diff --git a/.dockerignore b/.dockerignore index 5a266e8e1..0a5878cef 100644 --- a/.dockerignore +++ b/.dockerignore @@ -18,4 +18,5 @@ htmlcov .coverage coverage .cache +.npm-debug.log test/__pycache__ diff --git a/.gitignore b/.gitignore index d5d39119f..1a5d2c3a8 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ coverage htmlcov .tox .cache +.npm-debug.log diff --git a/karma.conf.js b/karma.conf.js index a63de3ca4..51836ffec 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -8,7 +8,6 @@ module.exports = function (config) { 'node_modules/angular/angular.js', 'node_modules/angular-animate/angular-animate.js', 'node_modules/angular-cookies/angular-cookies.js', - 'node_modules/angular-md5/angular-md5.js', 'node_modules/angular-mocks/angular-mocks.js', 'node_modules/angular-route/angular-route.js', 'node_modules/angular-sanitize/angular-sanitize.js', diff --git a/static/js/angular-route-builder.js b/static/js/angular-route-builder.js deleted file mode 100644 index d38ff7eca..000000000 --- a/static/js/angular-route-builder.js +++ /dev/null @@ -1,38 +0,0 @@ -var AngularRouteBuilder = function(routeProvider, pages, profiles, currentProfile) { - this.routeProvider = routeProvider; - this.pages = pages; - this.profiles = profiles; - - for (var i = 0; i < profiles.length; ++i) { - var current = profiles[i]; - if (current.id == currentProfile) { - this.profiles = this.profiles.slice(i); - break; - } - } -}; - -AngularRouteBuilder.prototype.otherwise = function(options) { - this.routeProvider.otherwise(options); -}; - -AngularRouteBuilder.prototype.route = function(path, pagename) { - // Lookup the page, matching our lists of profiles. - var pair = this.pages.get(pagename, this.profiles); - if (!pair) { - throw Error('Unknown page: ' + pagename); - } - - // Create the route. - var foundProfile = pair[0]; - var page = pair[1]; - var templateUrl = foundProfile.templatePath + page.templateName; - - var options = jQuery.extend({}, page.flags || {}); - options['templateUrl'] = templateUrl; - options['reloadOnSearch'] = false; - options['controller'] = page.controller; - - this.routeProvider.when(path, options); - return this; -}; \ No newline at end of file diff --git a/static/js/app.js b/static/js/app.js index ba49e6181..58170c42e 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -90,7 +90,8 @@ quayApp.config(['$compileProvider', function ($compileProvider) { }]); // Configure the routes. -quayApp.config(['$routeProvider', '$locationProvider', 'pages', function($routeProvider, $locationProvider, pages) { +quayApp.config(['$routeProvider', '$locationProvider', 'pages', 'RouteBuilderProvider', + function($routeProvider, $locationProvider, pages, RouteBuilderProvider) { $locationProvider.html5Mode(true); // WARNING WARNING WARNING @@ -101,7 +102,7 @@ quayApp.config(['$routeProvider', '$locationProvider', 'pages', function($routeP var layoutProfile = 'layout'; window.console.log('Using layout profile: ' + layoutProfile); - var routeBuilder = new AngularRouteBuilder($routeProvider, pages, [ + var routeBuilder = new RouteBuilderProvider.$get()($routeProvider, pages, [ // Start with the old pages (if we asked for it). {id: 'old-layout', templatePath: '/static/partials/'}, diff --git a/static/js/route-builder/route-builder.js b/static/js/route-builder/route-builder.js new file mode 100644 index 000000000..8a94706eb --- /dev/null +++ b/static/js/route-builder/route-builder.js @@ -0,0 +1,57 @@ +(function() { + 'use strict'; + + angular + .module("quay") + .factory('RouteBuilder', factory); + + factory.$inject = [ + + ]; + + function factory() { + function RouteBuilder(routeProvider, pages, profiles, currentProfile) { + this.routeProvider = routeProvider; + this.pages = pages; + this.profiles = profiles; + + for (var i = 0; i < profiles.length; ++i) { + if (profiles[i].id == currentProfile) { + this.profiles = this.profiles.slice(i); + break; + } + } + } + + RouteBuilder.prototype.otherwise = function(options) { + this.routeProvider.otherwise(options); + }; + + RouteBuilder.prototype.route = function(path, pagename) { + // Lookup the page, matching our lists of profiles. + var pair = this.pages.get(pagename, this.profiles); + if (!pair) { + throw Error('Unknown page: ' + pagename); + } + + // Create the route. + var foundProfile = pair[0]; + var page = pair[1]; + var templateUrl = foundProfile.templatePath + page.templateName; + + var options = jQuery.extend({}, page.flags || {}); + options['templateUrl'] = templateUrl; + options['reloadOnSearch'] = false; + options['controller'] = page.controller; + + this.routeProvider.when(path, options); + + return this; + }; + + return function(routeProvider, pages, profiles, currentProfile) { + return new RouteBuilder(routeProvider, pages, profiles, currentProfile); + } + } + +})(); \ No newline at end of file diff --git a/static/js/route-builder/route-builder.spec.js b/static/js/route-builder/route-builder.spec.js new file mode 100644 index 000000000..fa883cb02 --- /dev/null +++ b/static/js/route-builder/route-builder.spec.js @@ -0,0 +1,120 @@ +describe("Service: RouteBuilder", function() { + var RouteBuilder; + var routeProviderMock; + var pagesMock; + var profiles; + var currentProfile; + + beforeEach(module('quay')); + + beforeEach(inject(function($injector) { + profiles = [ + {id: 'old-layout', templatePath: '/static/partials/'}, + {id: 'layout', templatePath: '/static/partials/'} + ]; + currentProfile = 'layout'; + routeProviderMock = jasmine.createSpyObj('routeProvider', ['otherwise', 'when']); + pagesMock = jasmine.createSpyObj('pagesMock', ['get', 'create']); + RouteBuilder = $injector.get('RouteBuilder'); + })); + + describe("constructor", function() { + + it("returns a RouteBuilder object", function() { + var routeBuilder = new RouteBuilder(routeProviderMock, pagesMock, profiles, currentProfile); + + expect(routeBuilder).toBeDefined(); + }); + + it("initializes dependencies", function() { + var routeBuilder = new RouteBuilder(routeProviderMock, pagesMock, profiles, currentProfile); + + expect(routeBuilder.routeProvider).toEqual(routeProviderMock); + expect(routeBuilder.pages).toEqual(pagesMock); + expect(routeBuilder.profiles).toBeDefined(); + }); + + it("sets 'profiles' to all given profiles if given current profile does not match any of the given profiles' id", function() { + var routeBuilder = new RouteBuilder(routeProviderMock, pagesMock, profiles, 'fake-profile'); + + expect(routeBuilder.profiles).toEqual(profiles); + }); + + it("sets 'profiles' to the first given profile with id matching given current profile", function() { + var routeBuilder = new RouteBuilder(routeProviderMock, pagesMock, profiles, currentProfile); + + expect(routeBuilder.profiles).toEqual([profiles[1]]); + }); + }); + + describe("otherwise", function() { + var routeBuilder; + + beforeEach(function() { + routeBuilder = new RouteBuilder(routeProviderMock, pagesMock, profiles, currentProfile); + }); + + it("calls routeProvider to set fallback route with given options", function() { + var options = {1: "option"}; + routeBuilder.otherwise(options); + + expect(routeProviderMock.otherwise.calls.argsFor(0)[0]).toEqual(options); + }); + }); + + describe("route", function() { + var routeBuilder; + var path; + var pagename; + var page; + + beforeEach(function() { + path = '/repository/:namespace/:name'; + pagename = 'repo-view'; + page = { + templateName: 'repository.html', + reloadOnSearch: false, + controller: jasmine.createSpy('pageController'), + flags: {}, + }; + routeBuilder = new RouteBuilder(routeProviderMock, pagesMock, profiles, currentProfile); + }); + + it("calls pages with given pagename and 'profiles' to get matching page and profile pair", function() { + pagesMock.get.and.returnValue([profiles[1], page]); + routeBuilder.route(path, pagename); + + expect(pagesMock.get.calls.argsFor(0)[0]).toEqual(pagename); + expect(pagesMock.get.calls.argsFor(0)[1]).toEqual(routeBuilder.profiles); + }); + + it("throws error if no matching page/profile pair found", function() { + pagesMock.get.and.returnValue(); + try { + routeBuilder.route(path, pagename); + fail(); + } catch (error) { + expect(error.message).toEqual('Unknown page: ' + pagename); + } + }); + + it("calls routeProvider to set route for given path and options", function() { + pagesMock.get.and.returnValue([profiles[1], page]); + var expectedOptions = { + templateUrl: profiles[1].templatePath + page.templateName, + reloadOnSearch: false, + controller: page.controller, + }; + routeBuilder.route(path, pagename); + + expect(routeProviderMock.when.calls.argsFor(0)[0]).toEqual(path); + expect(routeProviderMock.when.calls.argsFor(0)[1]).toEqual(expectedOptions); + }); + + it("returns itself (the RouteBuilder instance)", function() { + pagesMock.get.and.returnValue([profiles[1], page]); + + expect(routeBuilder.route(path, pagename)).toEqual(routeBuilder); + }); + }); +}); \ No newline at end of file