1 | import './setup';
|
2 | import {Container} from 'aurelia-dependency-injection';
|
3 | import {HtmlBehaviorResource} from '../src/html-behavior';
|
4 | import {CompositionEngine} from '../src/composition-engine';
|
5 | import {CompositionTransactionOwnershipToken} from '../src/composition-transaction';
|
6 | import {ViewResources} from '../src/view-resources';
|
7 | import {DOM} from 'aurelia-pal';
|
8 | import { ViewSlot } from '../src/view-slot';
|
9 |
|
10 | describe('CompositionEngine', () => {
|
11 |
|
12 | let container;
|
13 | let mockModule;
|
14 |
|
15 | let compositionEngine;
|
16 |
|
17 | function createCompositionContext(viewModel) {
|
18 | let host = document.createElement('div');
|
19 | let compositionContext = new CompositionContext({
|
20 | host: host,
|
21 | viewSlot: new ViewSlot(host, true),
|
22 | container: container,
|
23 | viewModel: viewModel
|
24 | });
|
25 | return compositionContext;
|
26 | }
|
27 |
|
28 | beforeEach(() => {
|
29 | container = new Container();
|
30 | compositionEngine = container.get(CompositionEngine);
|
31 | });
|
32 |
|
33 | describe('ensureViewModel()', () => {
|
34 |
|
35 | it('ensures view model when view model\'s a string', done => {
|
36 | class MyClass {
|
37 | message = 'My class';
|
38 | }
|
39 |
|
40 | mockModule = {
|
41 | MyClass: MyClass
|
42 | };
|
43 | spyOn(compositionEngine.viewEngine.loader, 'loadModule')
|
44 | .and
|
45 | .callFake(() => new Promise(resolve => setTimeout(() => resolve(mockModule), 50)));
|
46 |
|
47 | let compositionContext = createCompositionContext('');
|
48 | container.registerInstance(DOM.Element, compositionContext.host);
|
49 |
|
50 | compositionEngine.ensureViewModel(compositionContext).then((context) => {
|
51 | expect(context).toBe(compositionContext);
|
52 | expect(context.viewModel instanceof MyClass).toBe(true);
|
53 | done();
|
54 | });
|
55 | });
|
56 |
|
57 | it('ensures view model when view model is a class', done => {
|
58 | class MyClass {
|
59 | message = 'My class';
|
60 | }
|
61 |
|
62 | let compositionContext = createCompositionContext(MyClass);
|
63 | container.registerInstance(DOM.Element, compositionContext.host);
|
64 |
|
65 | compositionEngine.ensureViewModel(compositionContext).then((context) => {
|
66 | expect(context).toBe(compositionContext);
|
67 | expect(context.viewModel instanceof MyClass).toBe(true);
|
68 | }).then(done).catch(done.fail);
|
69 | });
|
70 |
|
71 | it('registers instances with the "childContainer" only', done => {
|
72 |
|
73 | class MyClass {
|
74 | message = 'My class';
|
75 | }
|
76 |
|
77 | Promise.all([
|
78 | compositionEngine.ensureViewModel(createCompositionContext(MyClass)),
|
79 | compositionEngine.ensureViewModel(createCompositionContext(MyClass))
|
80 | ]).then(contexts => {
|
81 | let childContainerOne = contexts[0].childContainer;
|
82 | let childContainerTwo = contexts[1].childContainer;
|
83 |
|
84 | expect(childContainerOne.hasResolver(MyClass)).toBe(true);
|
85 | expect(childContainerTwo.hasResolver(MyClass)).toBe(true);
|
86 | expect(container.hasResolver(MyClass)).toBe(false);
|
87 | expect(childContainerOne.get(MyClass)).not.toBe(childContainerTwo.get(MyClass));
|
88 | done();
|
89 | }).catch(done.fail);
|
90 | });
|
91 |
|
92 | it('ensures view model when view model is an object', done => {
|
93 | class MyClass {
|
94 | message = 'My class';
|
95 | }
|
96 |
|
97 | let compositionContext = createCompositionContext(new MyClass());
|
98 | container.registerInstance(DOM.Element, compositionContext.host);
|
99 |
|
100 | compositionEngine.ensureViewModel(compositionContext).then((context) => {
|
101 | expect(context).toBe(compositionContext);
|
102 | expect(context.viewModel).toBe(compositionContext.viewModel);
|
103 | expect(container.hasResolver(MyClass)).toBe(false);
|
104 | expect(context.viewModel instanceof MyClass).toBe(true);
|
105 | done();
|
106 | });
|
107 | });
|
108 | });
|
109 |
|
110 | describe('compose', () => {
|
111 |
|
112 | describe('when viewModel is specified', () => {
|
113 |
|
114 | it('composes', done => {
|
115 | class MyClass {
|
116 | static $view = '<template></template>';
|
117 | }
|
118 |
|
119 | compositionEngine
|
120 | .compose(createCompositionContext(MyClass))
|
121 | .then(controller => {
|
122 | expect(controller.viewModel instanceof MyClass).toBe(true);
|
123 | done();
|
124 | })
|
125 | .catch(done.fail);
|
126 | });
|
127 |
|
128 | it('waits for composition transaction to complete before binding. Fixes https://github.com/aurelia/templating/issues/632', done => {
|
129 | let track = 0;
|
130 |
|
131 | const originalWait = CompositionTransactionOwnershipToken.prototype.waitForCompositionComplete;
|
132 | CompositionTransactionOwnershipToken.prototype.waitForCompositionComplete = function() {
|
133 | track = 1;
|
134 | return originalWait.apply(this, arguments);
|
135 | }
|
136 |
|
137 | class MyClass {
|
138 | static $view = '<template></template>';
|
139 |
|
140 | bind() {
|
141 | expect(track).toBe(1);
|
142 | }
|
143 | }
|
144 |
|
145 | compositionEngine
|
146 | .compose(createCompositionContext(MyClass))
|
147 | .then(controller => {
|
148 | CompositionTransactionOwnershipToken.prototype.waitForCompositionComplete = originalWait;
|
149 | expect(track).not.toBe(0);
|
150 | done();
|
151 | })
|
152 | .catch((ex) => {
|
153 | CompositionTransactionOwnershipToken.prototype.waitForCompositionComplete = originalWait;
|
154 | done.fail(ex);
|
155 | })
|
156 | });
|
157 | });
|
158 | });
|
159 |
|
160 |
|
161 | |
162 |
|
163 |
|
164 | class CompositionContext {
|
165 | |
166 |
|
167 |
|
168 | constructor(context) {
|
169 |
|
170 | |
171 |
|
172 |
|
173 |
|
174 | this.container = undefined;
|
175 |
|
176 | |
177 |
|
178 |
|
179 |
|
180 | this.childContainer = undefined;
|
181 |
|
182 | |
183 |
|
184 |
|
185 | this.bindingContext = undefined;
|
186 |
|
187 | |
188 |
|
189 |
|
190 |
|
191 | this.overrideContext = undefined;
|
192 |
|
193 | |
194 |
|
195 |
|
196 |
|
197 | this.viewModel = undefined;
|
198 |
|
199 | |
200 |
|
201 |
|
202 | this.model = undefined;
|
203 |
|
204 | |
205 |
|
206 |
|
207 |
|
208 | this.viewModelResource = undefined;
|
209 |
|
210 | |
211 |
|
212 |
|
213 |
|
214 | this.viewResources = undefined;
|
215 |
|
216 | |
217 |
|
218 |
|
219 |
|
220 | this.owningView = undefined;
|
221 |
|
222 | |
223 |
|
224 |
|
225 |
|
226 | this.view = undefined;
|
227 |
|
228 | |
229 |
|
230 |
|
231 |
|
232 | this.viewSlot = undefined;
|
233 |
|
234 | |
235 |
|
236 |
|
237 | this.skipActivation = false;
|
238 |
|
239 | |
240 |
|
241 |
|
242 |
|
243 |
|
244 | this.host = null;
|
245 | Object.assign(this, context);
|
246 | }
|
247 | }
|
248 | });
|