From 68107589bbaa912946da3d205b509662ec862b85 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Thu, 19 Nov 2020 17:02:23 -0500 Subject: [PATCH] refactor: Scope service into core addon and desktop routes Ensure top-level scopes route within ui/admin and ui/desktop are exactly the same in preparation for future refactor. feat: Add projects/targets route chore: yarn:format output in ui/desktop test: Add basic acceptance tests for projects and targets --- addons/api/addon/services/storage.js | 4 +- addons/core/README.md | 19 ++- .../core/addon}/services/scope.js | 2 +- addons/core/app/services/scope.js | 1 + addons/core/tests/unit/.gitkeep | 0 addons/core/tests/unit/services/scope-test.js | 18 ++ ui/admin/tests/unit/services/scope-test.js | 12 -- ui/desktop/app/router.js | 4 +- ui/desktop/app/routes/scopes/scope.js | 55 +++--- ui/desktop/app/routes/scopes/scope/index.js | 2 +- .../app/routes/scopes/scope/projects.js | 28 ++++ .../scopes/scope/{ => projects}/targets.js | 6 +- .../scopes/scope/projects/targets/index.js | 3 + .../app/routes/scopes/scope/targets/index.js | 3 - ui/desktop/app/services/scope.js | 20 --- .../app/templates/scopes/scope/projects.hbs | 1 + .../scopes/scope/{ => projects}/targets.hbs | 0 .../scope/{ => projects}/targets/index.hbs | 0 ui/desktop/ember-cli-build.js | 6 +- ui/desktop/tests/acceptance/projects-test.js | 156 +++++++++++++++++ ui/desktop/tests/acceptance/targets-test.js | 158 ++++++++++++++++++ .../{targets-test.js => projects-test.js} | 4 +- .../targets-test.js} | 4 +- .../scope/projects/targets/index-test.js | 11 ++ ui/desktop/tests/unit/services/scope-test.js | 12 -- 25 files changed, 439 insertions(+), 90 deletions(-) rename {ui/admin/app => addons/core/addon}/services/scope.js (89%) create mode 100644 addons/core/app/services/scope.js delete mode 100644 addons/core/tests/unit/.gitkeep create mode 100644 addons/core/tests/unit/services/scope-test.js delete mode 100644 ui/admin/tests/unit/services/scope-test.js create mode 100644 ui/desktop/app/routes/scopes/scope/projects.js rename ui/desktop/app/routes/scopes/scope/{ => projects}/targets.js (82%) create mode 100644 ui/desktop/app/routes/scopes/scope/projects/targets/index.js delete mode 100644 ui/desktop/app/routes/scopes/scope/targets/index.js delete mode 100644 ui/desktop/app/services/scope.js create mode 100644 ui/desktop/app/templates/scopes/scope/projects.hbs rename ui/desktop/app/templates/scopes/scope/{ => projects}/targets.hbs (100%) rename ui/desktop/app/templates/scopes/scope/{ => projects}/targets/index.hbs (100%) create mode 100644 ui/desktop/tests/acceptance/projects-test.js create mode 100644 ui/desktop/tests/acceptance/targets-test.js rename ui/desktop/tests/unit/routes/scopes/scope/{targets-test.js => projects-test.js} (56%) rename ui/desktop/tests/unit/routes/scopes/scope/{targets/index-test.js => projects/targets-test.js} (53%) create mode 100644 ui/desktop/tests/unit/routes/scopes/scope/projects/targets/index-test.js delete mode 100644 ui/desktop/tests/unit/services/scope-test.js diff --git a/addons/api/addon/services/storage.js b/addons/api/addon/services/storage.js index 3f4be864f..ea1b7138d 100644 --- a/addons/api/addon/services/storage.js +++ b/addons/api/addon/services/storage.js @@ -4,7 +4,7 @@ import { get } from '@ember/object'; /** * A dead simple memory storage class used by `StorageService` when it - * is configued for memory-only. + * is configured for memory-only. */ class MemoryStorage { /** @@ -42,7 +42,7 @@ class MemoryStorage { /** * The storage service provides a simple way to persist data in the browser. - * Most of the time localStorage is used. Appplications may specify in-memory + * Most of the time localStorage is used. Applications may specify in-memory * storage via the config, for example: * * ENV.storage = { diff --git a/addons/core/README.md b/addons/core/README.md index 2822b86f7..3b913d4d3 100644 --- a/addons/core/README.md +++ b/addons/core/README.md @@ -69,7 +69,7 @@ export default class ExampleRoute extends Route { } ``` -In the application template, interate over confirmations, yielding the +In the application template, iterate over confirmations, yielding the confirmation instance as well as accept and deny functions which, when called, update the confirmation status. @@ -108,6 +108,23 @@ async myAction() { } ``` +## Scope Service + +This addon exposes a service to hold all active scopes (org and project where available). + +To make use of the service, import it and initialize it using service injection. + +```js +import { inject as service } from '@ember/service'; + +export default class ExampleRoute extends Route { + @service scope; + async myAction() { + // do something + } +} +``` + ## Yarn Commands List of available project commands. `yarn run ` diff --git a/ui/admin/app/services/scope.js b/addons/core/addon/services/scope.js similarity index 89% rename from ui/admin/app/services/scope.js rename to addons/core/addon/services/scope.js index 9128b704d..fa17bee48 100644 --- a/ui/admin/app/services/scope.js +++ b/addons/core/addon/services/scope.js @@ -3,7 +3,7 @@ import { tracked } from '@glimmer/tracking'; /** * This simple non-functional service is used to retain references to - * the currently active scope or scopes. + * the current active scope(s). */ export default class ScopeService extends Service { // =attributes diff --git a/addons/core/app/services/scope.js b/addons/core/app/services/scope.js new file mode 100644 index 000000000..619b8617e --- /dev/null +++ b/addons/core/app/services/scope.js @@ -0,0 +1 @@ +export { default } from 'core/services/scope'; diff --git a/addons/core/tests/unit/.gitkeep b/addons/core/tests/unit/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/addons/core/tests/unit/services/scope-test.js b/addons/core/tests/unit/services/scope-test.js new file mode 100644 index 000000000..596ddbfcd --- /dev/null +++ b/addons/core/tests/unit/services/scope-test.js @@ -0,0 +1,18 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Service | scope', function (hooks) { + setupTest(hooks); + + test('it can contain org scope', function (assert) { + let service = this.owner.lookup('service:scope'); + service.org = {}; + assert.ok(service.org, 'Service contains org scope'); + }); + + test('it can contain project scope', function (assert) { + let service = this.owner.lookup('service:scope'); + service.project = {}; + assert.ok(service.project, 'Service contains project scope'); + }); +}); diff --git a/ui/admin/tests/unit/services/scope-test.js b/ui/admin/tests/unit/services/scope-test.js deleted file mode 100644 index df15e7547..000000000 --- a/ui/admin/tests/unit/services/scope-test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Service | scope', function (hooks) { - setupTest(hooks); - - // TODO: Replace this with your real tests. - test('it exists', function (assert) { - let service = this.owner.lookup('service:scope'); - assert.ok(service); - }); -}); diff --git a/ui/desktop/app/router.js b/ui/desktop/app/router.js index 3ebda9c66..9480e547d 100644 --- a/ui/desktop/app/router.js +++ b/ui/desktop/app/router.js @@ -9,10 +9,12 @@ export default class Router extends EmberRouter { Router.map(function () { this.route('scopes', function () { this.route('scope', { path: ':scope_id' }, function () { - this.route('targets', function () {}); this.route('authenticate', function () { this.route('method', { path: ':auth_method_id' }); }); + this.route('projects', function () { + this.route('targets', function () {}); + }); }); }); this.route('origin'); diff --git a/ui/desktop/app/routes/scopes/scope.js b/ui/desktop/app/routes/scopes/scope.js index a5d3a7dab..914aa2904 100644 --- a/ui/desktop/app/routes/scopes/scope.js +++ b/ui/desktop/app/routes/scopes/scope.js @@ -5,6 +5,7 @@ import { A } from '@ember/array'; export default class ScopesScopeRoute extends Route { // =services + @service intl; @service session; @service scope; @@ -25,10 +26,12 @@ export default class ScopesScopeRoute extends Route { // from ID because global has a fixed ID. const type = id === 'global' ? 'global' : 'org'; return this.store.findRecord('scope', id).catch(() => { - console.error('caught error'); const maybeExistingScope = this.store.peekRecord('scope', id); - const scopeOptions = { id, type }; + /* istanbul ignore else */ + if (type === 'global') { + scopeOptions.name = this.intl.t('titles.global'); + } return ( maybeExistingScope || this.store.createRecord('scope', scopeOptions) ); @@ -41,36 +44,25 @@ export default class ScopesScopeRoute extends Route { * a project. These are used for scope navigation. */ async afterModel(model) { - // Load all orgs - let orgs; + // First, load orgs and, if necessary, projects + let orgs, projects; orgs = await this.store .query('scope', { scope_id: 'global' }) .catch(() => A([])); - - // Then pull out the "selected" org, if relevant - let selectedOrg; - if (model.isGlobal || model.isOrg) selectedOrg = model; - - let projects; - if (model.isOrg) { - projects = await this.store.query('scope', { scope_id: model.id }); + if (model.isProject) { + projects = await this.store.query('scope', { scope_id: model.scopeID }); + } + // Then pull out the "selected" scopes, if relevant + let selectedOrg, selectedProject; + if (model.isGlobal || model.isOrg) selectedOrg = model; + if (model.isProject) { + selectedProject = model; + selectedOrg = this.store.peekRecord('scope', model.scopeID); } - // Update the scope service with the current scope(s); this.scope.org = selectedOrg; - this.scope.projects = projects; - this.scopes = { orgs, selectedOrg }; - } - - /** - * - */ - redirect(model) { - const { isAuthenticated } = this.session; - const { isGlobal } = model; - if (isAuthenticated && isGlobal && this.scopes.orgs?.length) { - this.replaceWith('scopes.scope', this.scopes.orgs.firstObject.id); - } + this.scope.project = selectedProject; + this.scopes = { orgs, projects, selectedOrg, selectedProject }; } /** @@ -96,4 +88,15 @@ export default class ScopesScopeRoute extends Route { outlet: 'header-nav', }); } + + /** + * In global scope, redirect to first org on authentication. + */ + redirect(model) { + const { isAuthenticated } = this.session; + const { isGlobal } = model; + if (isAuthenticated && isGlobal && this.scopes.orgs?.length) { + this.replaceWith('scopes.scope', this.scopes.orgs.firstObject.id); + } + } } diff --git a/ui/desktop/app/routes/scopes/scope/index.js b/ui/desktop/app/routes/scopes/scope/index.js index 1713c1c58..5df8ead9e 100644 --- a/ui/desktop/app/routes/scopes/scope/index.js +++ b/ui/desktop/app/routes/scopes/scope/index.js @@ -17,7 +17,7 @@ export default class ScopesScopeIndexRoute extends Route { if (!this.session.isAuthenticated) { this.replaceWith('scopes.scope.authenticate'); } else { - this.replaceWith('scopes.scope.targets'); + this.replaceWith('scopes.scope.projects.targets'); } } } diff --git a/ui/desktop/app/routes/scopes/scope/projects.js b/ui/desktop/app/routes/scopes/scope/projects.js new file mode 100644 index 000000000..fb77550fd --- /dev/null +++ b/ui/desktop/app/routes/scopes/scope/projects.js @@ -0,0 +1,28 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeProjectsRoute extends Route { + // =services + + @service session; + + // =methods + + /** + * If arriving here unauthenticated, redirect to index for further processing. + */ + beforeModel() { + if (!this.session.isAuthenticated) this.transitionTo('index'); + } + + /** + * Loads project scopes for the current scope. + * @return {Promise + */ + model() { + const currentScope = this.modelFor('scopes.scope'); + return this.store.query('scope', { + scope_id: currentScope.id, + }); + } +} diff --git a/ui/desktop/app/routes/scopes/scope/targets.js b/ui/desktop/app/routes/scopes/scope/projects/targets.js similarity index 82% rename from ui/desktop/app/routes/scopes/scope/targets.js rename to ui/desktop/app/routes/scopes/scope/projects/targets.js index b12b4099e..393a7d11d 100644 --- a/ui/desktop/app/routes/scopes/scope/targets.js +++ b/ui/desktop/app/routes/scopes/scope/projects/targets.js @@ -2,11 +2,10 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; import { all } from 'rsvp'; -export default class ScopesScopeTargetsRoute extends Route { +export default class ScopesScopeProjectsTargetsRoute extends Route { // =services @service session; - @service scope; // =methods @@ -22,8 +21,9 @@ export default class ScopesScopeTargetsRoute extends Route { * @return {Promise{[TargetModel]}} */ async model() { + const projects = this.modelFor('scopes.scope.projects'); let projectTargets = await all( - this.scope.projects.map(({ id: scope_id }) => + projects.map(({ id: scope_id }) => this.store.query('target', { scope_id }) ) ); diff --git a/ui/desktop/app/routes/scopes/scope/projects/targets/index.js b/ui/desktop/app/routes/scopes/scope/projects/targets/index.js new file mode 100644 index 000000000..0d0c9a76c --- /dev/null +++ b/ui/desktop/app/routes/scopes/scope/projects/targets/index.js @@ -0,0 +1,3 @@ +import Route from '@ember/routing/route'; + +export default class ScopesScopeProjectsTargetsIndexRoute extends Route {} diff --git a/ui/desktop/app/routes/scopes/scope/targets/index.js b/ui/desktop/app/routes/scopes/scope/targets/index.js deleted file mode 100644 index 2b4412f53..000000000 --- a/ui/desktop/app/routes/scopes/scope/targets/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Route from '@ember/routing/route'; - -export default class ScopesScopeTargetsIndexRoute extends Route {} diff --git a/ui/desktop/app/services/scope.js b/ui/desktop/app/services/scope.js deleted file mode 100644 index abf3c508a..000000000 --- a/ui/desktop/app/services/scope.js +++ /dev/null @@ -1,20 +0,0 @@ -import Service from '@ember/service'; -import { tracked } from '@glimmer/tracking'; - -/** - * This simple non-functional service is used to retain references to - * the currently active scope or scopes. - */ -export default class ScopeService extends Service { - // =attributes - - /** - * @type {ScopeModel} - */ - @tracked org; - - /** - * @type {[ScopeModel]} - */ - @tracked projects; -} diff --git a/ui/desktop/app/templates/scopes/scope/projects.hbs b/ui/desktop/app/templates/scopes/scope/projects.hbs new file mode 100644 index 000000000..c24cd6895 --- /dev/null +++ b/ui/desktop/app/templates/scopes/scope/projects.hbs @@ -0,0 +1 @@ +{{outlet}} diff --git a/ui/desktop/app/templates/scopes/scope/targets.hbs b/ui/desktop/app/templates/scopes/scope/projects/targets.hbs similarity index 100% rename from ui/desktop/app/templates/scopes/scope/targets.hbs rename to ui/desktop/app/templates/scopes/scope/projects/targets.hbs diff --git a/ui/desktop/app/templates/scopes/scope/targets/index.hbs b/ui/desktop/app/templates/scopes/scope/projects/targets/index.hbs similarity index 100% rename from ui/desktop/app/templates/scopes/scope/targets/index.hbs rename to ui/desktop/app/templates/scopes/scope/projects/targets/index.hbs diff --git a/ui/desktop/ember-cli-build.js b/ui/desktop/ember-cli-build.js index b3af84373..7cfb137f6 100644 --- a/ui/desktop/ember-cli-build.js +++ b/ui/desktop/ember-cli-build.js @@ -19,10 +19,8 @@ module.exports = function (defaults) { importCss: false, }, svg: { - paths: [ - '../../addons/core/public' - ] - } + paths: ['../../addons/core/public'], + }, }); // Use `app.import` to add additional libraries to the generated diff --git a/ui/desktop/tests/acceptance/projects-test.js b/ui/desktop/tests/acceptance/projects-test.js new file mode 100644 index 000000000..a973db904 --- /dev/null +++ b/ui/desktop/tests/acceptance/projects-test.js @@ -0,0 +1,156 @@ +import { module, test } from 'qunit'; +import { + visit, + currentURL, + //fillIn, + //click, + //find, + //findAll, + //getRootElement + //setupOnerror, +} from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +//import { Response } from 'miragejs'; +//import a11yAudit from 'ember-a11y-testing/test-support/audit'; +import { + currentSession, + authenticateSession, + invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | projects', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + let mockIPC; + let messageHandler; + + const instances = { + scopes: { + global: null, + org: null, + project: null, + }, + authMethods: { + global: null, + }, + target: null, + }; + + const stubs = { + global: null, + org: null, + }; + + const urls = { + index: '/', + origin: '/origin', + scopes: { + global: null, + org: null, + }, + authenticate: { + global: null, + methods: { + global: null, + }, + }, + projects: null, + }; + + const setDefaultOrigin = (test) => { + const origin = window.location.origin; + const session = test.owner.lookup('service:session'); + session.set('data.origin', origin); + }; + + hooks.beforeEach(function () { + authenticateSession(); + + // create scopes + instances.scopes.global = this.server.create('scope', { id: 'global' }); + stubs.global = { id: 'global', type: 'global' }; + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: stubs.global, + }); + stubs.org = { id: instances.scopes.org.id, type: 'org' }; + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: stubs.org, + }); + stubs.project = { id: instances.scopes.project.id, type: 'project' }; + + instances.authMethods.global = this.server.create('auth-method', { + scope: instances.scopes.global, + }); + + instances.hostCatalog = this.server.create( + 'host-catalog', + { scope: instances.scopes.project }, + 'withChildren' + ); + instances.target = this.server.create( + 'target', + { scope: instances.scopes.project }, + 'withRandomHostSets' + ); + + urls.scopes.global = `/scopes/${instances.scopes.global.id}`; + urls.scopes.org = `/scopes/${instances.scopes.org.id}`; + urls.authenticate.global = `${urls.scopes.global}/authenticate`; + urls.authenticate.methods.global = `${urls.authenticate.global}/${instances.authMethods.global.id}`; + urls.projects = `${urls.scopes.org}/projects`; + + class MockIPC { + origin = null; + + invoke(method, payload) { + return this[method](payload); + } + + getOrigin() { + return this.origin; + } + + setOrigin(origin) { + this.origin = origin; + return this.origin; + } + } + + mockIPC = new MockIPC(); + messageHandler = async function (event) { + if (event.origin !== window.location.origin) return; + const { method, payload } = event.data; + if (method) { + const response = await mockIPC.invoke(method, payload); + event.ports[0].postMessage(response); + } + }; + + window.addEventListener('message', messageHandler); + setDefaultOrigin(this); + }); + + hooks.afterEach(function () { + window.removeEventListener('message', messageHandler); + }); + + test('visiting index while unauthenticated redirects to global authenticate method', async function (assert) { + invalidateSession(); + assert.expect(2); + await visit(urls.projects); + //await a11yAudit(); + assert.notOk(currentSession().isAuthenticated); + assert.equal(currentURL(), urls.authenticate.methods.global); + }); + + test('visiting index', async function (assert) { + assert.expect(1); + await visit(urls.projects); + //await a11yAudit(); + assert.equal(currentURL(), urls.projects); + }); +}); diff --git a/ui/desktop/tests/acceptance/targets-test.js b/ui/desktop/tests/acceptance/targets-test.js new file mode 100644 index 000000000..6f7cd30e4 --- /dev/null +++ b/ui/desktop/tests/acceptance/targets-test.js @@ -0,0 +1,158 @@ +import { module, test } from 'qunit'; +import { + visit, + currentURL, + //fillIn, + //click, + //find, + //findAll, + //getRootElement + //setupOnerror, +} from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +//import { Response } from 'miragejs'; +//import a11yAudit from 'ember-a11y-testing/test-support/audit'; +import { + currentSession, + authenticateSession, + invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | targets', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + let mockIPC; + let messageHandler; + + const instances = { + scopes: { + global: null, + org: null, + project: null, + }, + authMethods: { + global: null, + }, + target: null, + }; + + const stubs = { + global: null, + org: null, + }; + + const urls = { + index: '/', + origin: '/origin', + scopes: { + global: null, + org: null, + }, + authenticate: { + global: null, + methods: { + global: null, + }, + }, + projects: null, + targets: null, + }; + + const setDefaultOrigin = (test) => { + const origin = window.location.origin; + const session = test.owner.lookup('service:session'); + session.set('data.origin', origin); + }; + + hooks.beforeEach(function () { + authenticateSession(); + + // create scopes + instances.scopes.global = this.server.create('scope', { id: 'global' }); + stubs.global = { id: 'global', type: 'global' }; + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: stubs.global, + }); + stubs.org = { id: instances.scopes.org.id, type: 'org' }; + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: stubs.org, + }); + stubs.project = { id: instances.scopes.project.id, type: 'project' }; + + instances.authMethods.global = this.server.create('auth-method', { + scope: instances.scopes.global, + }); + + instances.hostCatalog = this.server.create( + 'host-catalog', + { scope: instances.scopes.project }, + 'withChildren' + ); + instances.target = this.server.create( + 'target', + { scope: instances.scopes.project }, + 'withRandomHostSets' + ); + + urls.scopes.global = `/scopes/${instances.scopes.global.id}`; + urls.scopes.org = `/scopes/${instances.scopes.org.id}`; + urls.authenticate.global = `${urls.scopes.global}/authenticate`; + urls.authenticate.methods.global = `${urls.authenticate.global}/${instances.authMethods.global.id}`; + urls.projects = `${urls.scopes.org}/projects`; + urls.targets = `${urls.projects}/targets`; + + class MockIPC { + origin = null; + + invoke(method, payload) { + return this[method](payload); + } + + getOrigin() { + return this.origin; + } + + setOrigin(origin) { + this.origin = origin; + return this.origin; + } + } + + mockIPC = new MockIPC(); + messageHandler = async function (event) { + if (event.origin !== window.location.origin) return; + const { method, payload } = event.data; + if (method) { + const response = await mockIPC.invoke(method, payload); + event.ports[0].postMessage(response); + } + }; + + window.addEventListener('message', messageHandler); + setDefaultOrigin(this); + }); + + hooks.afterEach(function () { + window.removeEventListener('message', messageHandler); + }); + + test('visiting index while unauthenticated redirects to global authenticate method', async function (assert) { + invalidateSession(); + assert.expect(2); + await visit(urls.targets); + //await a11yAudit(); + assert.notOk(currentSession().isAuthenticated); + assert.equal(currentURL(), urls.authenticate.methods.global); + }); + + test('visiting index', async function (assert) { + assert.expect(1); + await visit(urls.targets); + //await a11yAudit(); + assert.equal(currentURL(), urls.targets); + }); +}); diff --git a/ui/desktop/tests/unit/routes/scopes/scope/targets-test.js b/ui/desktop/tests/unit/routes/scopes/scope/projects-test.js similarity index 56% rename from ui/desktop/tests/unit/routes/scopes/scope/targets-test.js rename to ui/desktop/tests/unit/routes/scopes/scope/projects-test.js index 0d357c6b8..127213dac 100644 --- a/ui/desktop/tests/unit/routes/scopes/scope/targets-test.js +++ b/ui/desktop/tests/unit/routes/scopes/scope/projects-test.js @@ -1,11 +1,11 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; -module('Unit | Route | scopes/scope/targets', function (hooks) { +module('Unit | Route | scopes/scope/projects', function (hooks) { setupTest(hooks); test('it exists', function (assert) { - let route = this.owner.lookup('route:scopes/scope/targets'); + let route = this.owner.lookup('route:scopes/scope/projects'); assert.ok(route); }); }); diff --git a/ui/desktop/tests/unit/routes/scopes/scope/targets/index-test.js b/ui/desktop/tests/unit/routes/scopes/scope/projects/targets-test.js similarity index 53% rename from ui/desktop/tests/unit/routes/scopes/scope/targets/index-test.js rename to ui/desktop/tests/unit/routes/scopes/scope/projects/targets-test.js index 74d495fcb..fc7169572 100644 --- a/ui/desktop/tests/unit/routes/scopes/scope/targets/index-test.js +++ b/ui/desktop/tests/unit/routes/scopes/scope/projects/targets-test.js @@ -1,11 +1,11 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; -module('Unit | Route | scopes/scope/targets/index', function (hooks) { +module('Unit | Route | scopes/scope/projects/targets', function (hooks) { setupTest(hooks); test('it exists', function (assert) { - let route = this.owner.lookup('route:scopes/scope/targets/index'); + let route = this.owner.lookup('route:scopes/scope/projects/targets'); assert.ok(route); }); }); diff --git a/ui/desktop/tests/unit/routes/scopes/scope/projects/targets/index-test.js b/ui/desktop/tests/unit/routes/scopes/scope/projects/targets/index-test.js new file mode 100644 index 000000000..be503187c --- /dev/null +++ b/ui/desktop/tests/unit/routes/scopes/scope/projects/targets/index-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/projects/targets/index', function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let route = this.owner.lookup('route:scopes/scope/projects/targets/index'); + assert.ok(route); + }); +}); diff --git a/ui/desktop/tests/unit/services/scope-test.js b/ui/desktop/tests/unit/services/scope-test.js deleted file mode 100644 index df15e7547..000000000 --- a/ui/desktop/tests/unit/services/scope-test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Service | scope', function (hooks) { - setupTest(hooks); - - // TODO: Replace this with your real tests. - test('it exists', function (assert) { - let service = this.owner.lookup('service:scope'); - assert.ok(service); - }); -});