import { assign } from '@ember/polyfills'; import { moduleFor, AutobootApplicationTestCase } from 'internal-test-helpers'; import Application from '..'; moduleFor( 'Application initializers', class extends AutobootApplicationTestCase { get fixture() { return `<div id="one">ONE</div> <div id="two">TWO</div> `; } get applicationOptions() { return assign(super.applicationOptions, { rootElement: '#one', }); } createSecondApplication(options, MyApplication = Application) { let myOptions = assign( this.applicationOptions, { rootElement: '#two', }, options ); let secondApp = (this.secondApp = MyApplication.create(myOptions)); return secondApp; } teardown() { super.teardown(); if (this.secondApp) { this.runTask(() => this.secondApp.destroy()); } } [`@test initializers require proper 'name' and 'initialize' properties`]() { let MyApplication = Application.extend(); expectAssertion(() => { MyApplication.initializer({ name: 'initializer' }); }); expectAssertion(() => { MyApplication.initializer({ initialize() {} }); }); } [`@test initializers that throw errors cause the boot promise to reject with the error`]( assert ) { assert.expect(2); let MyApplication = Application.extend(); MyApplication.initializer({ name: 'initializer', initialize() { throw new Error('boot failure'); }, }); this.runTask(() => { this.createApplication( { autoboot: false, }, MyApplication ); }); let app = this.application; try { this.runTask(() => { app.boot().then( () => { assert.ok(false, 'The boot promise should not resolve when there is a boot error'); }, error => { assert.ok(error instanceof Error, 'The boot promise should reject with an error'); assert.equal(error.message, 'boot failure'); } ); }); } catch (error) { assert.ok(false, 'The boot method should not throw'); throw error; } } [`@test initializers are passed an App`](assert) { let MyApplication = Application.extend(); MyApplication.initializer({ name: 'initializer', initialize(App) { assert.ok(App instanceof Application, 'initialize is passed an Application'); }, }); this.runTask(() => this.createApplication({}, MyApplication)); } [`@test initializers can be registered in a specified order`](assert) { let order = []; let MyApplication = Application.extend(); MyApplication.initializer({ name: 'fourth', after: 'third', initialize() { order.push('fourth'); }, }); MyApplication.initializer({ name: 'second', after: 'first', before: 'third', initialize() { order.push('second'); }, }); MyApplication.initializer({ name: 'fifth', after: 'fourth', before: 'sixth', initialize() { order.push('fifth'); }, }); MyApplication.initializer({ name: 'first', before: 'second', initialize() { order.push('first'); }, }); MyApplication.initializer({ name: 'third', initialize() { order.push('third'); }, }); MyApplication.initializer({ name: 'sixth', initialize() { order.push('sixth'); }, }); this.runTask(() => this.createApplication({}, MyApplication)); assert.deepEqual(order, ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']); } [`@test initializers can be registered in a specified order as an array`](assert) { let order = []; let MyApplication = Application.extend(); MyApplication.initializer({ name: 'third', initialize() { order.push('third'); }, }); MyApplication.initializer({ name: 'second', after: 'first', before: ['third', 'fourth'], initialize() { order.push('second'); }, }); MyApplication.initializer({ name: 'fourth', after: ['second', 'third'], initialize() { order.push('fourth'); }, }); MyApplication.initializer({ name: 'fifth', after: 'fourth', before: 'sixth', initialize() { order.push('fifth'); }, }); MyApplication.initializer({ name: 'first', before: ['second'], initialize() { order.push('first'); }, }); MyApplication.initializer({ name: 'sixth', initialize() { order.push('sixth'); }, }); this.runTask(() => this.createApplication({}, MyApplication)); assert.deepEqual(order, ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']); } [`@test initializers can have multiple dependencies`](assert) { let order = []; let MyApplication = Application.extend(); let a = { name: 'a', before: 'b', initialize() { order.push('a'); }, }; let b = { name: 'b', initialize() { order.push('b'); }, }; let c = { name: 'c', after: 'b', initialize() { order.push('c'); }, }; let afterB = { name: 'after b', after: 'b', initialize() { order.push('after b'); }, }; let afterC = { name: 'after c', after: 'c', initialize() { order.push('after c'); }, }; MyApplication.initializer(b); MyApplication.initializer(a); MyApplication.initializer(afterC); MyApplication.initializer(afterB); MyApplication.initializer(c); this.runTask(() => this.createApplication({}, MyApplication)); assert.ok(order.indexOf(a.name) < order.indexOf(b.name), 'a < b'); assert.ok(order.indexOf(b.name) < order.indexOf(c.name), 'b < c'); assert.ok(order.indexOf(b.name) < order.indexOf(afterB.name), 'b < afterB'); assert.ok(order.indexOf(c.name) < order.indexOf(afterC.name), 'c < afterC'); } [`@test initializers set on Application subclasses are not shared between apps`](assert) { let firstInitializerRunCount = 0; let secondInitializerRunCount = 0; let FirstApp = Application.extend(); FirstApp.initializer({ name: 'first', initialize() { firstInitializerRunCount++; }, }); let SecondApp = Application.extend(); SecondApp.initializer({ name: 'second', initialize() { secondInitializerRunCount++; }, }); this.runTask(() => this.createApplication({}, FirstApp)); assert.equal(firstInitializerRunCount, 1, 'first initializer only was run'); assert.equal(secondInitializerRunCount, 0, 'first initializer only was run'); this.runTask(() => this.createSecondApplication({}, SecondApp)); assert.equal(firstInitializerRunCount, 1, 'second initializer only was run'); assert.equal(secondInitializerRunCount, 1, 'second initializer only was run'); } [`@test initializers are concatenated`](assert) { let firstInitializerRunCount = 0; let secondInitializerRunCount = 0; let FirstApp = Application.extend(); FirstApp.initializer({ name: 'first', initialize() { firstInitializerRunCount++; }, }); let SecondApp = FirstApp.extend(); SecondApp.initializer({ name: 'second', initialize() { secondInitializerRunCount++; }, }); this.runTask(() => this.createApplication({}, FirstApp)); assert.equal( firstInitializerRunCount, 1, 'first initializer only was run when base class created' ); assert.equal( secondInitializerRunCount, 0, 'first initializer only was run when base class created' ); firstInitializerRunCount = 0; this.runTask(() => this.createSecondApplication({}, SecondApp)); assert.equal(firstInitializerRunCount, 1, 'first initializer was run when subclass created'); assert.equal( secondInitializerRunCount, 1, 'second initializers was run when subclass created' ); } [`@test initializers are per-app`](assert) { assert.expect(2); let FirstApp = Application.extend(); FirstApp.initializer({ name: 'abc', initialize() {}, }); expectAssertion(() => { FirstApp.initializer({ name: 'abc', initialize() {}, }); }); let SecondApp = Application.extend(); SecondApp.instanceInitializer({ name: 'abc', initialize() {}, }); assert.ok(true, 'Two apps can have initializers named the same.'); } [`@test initializers are executed in their own context`](assert) { assert.expect(1); let MyApplication = Application.extend(); MyApplication.initializer({ name: 'coolInitializer', myProperty: 'cool', initialize() { assert.equal(this.myProperty, 'cool', 'should have access to its own context'); }, }); this.runTask(() => this.createApplication({}, MyApplication)); } } );