1 | import './setup';
|
2 | import {Container} from 'aurelia-dependency-injection';
|
3 | import {ViewSlot} from '../src/view-slot';
|
4 | import {TemplatingEngine} from '../src/templating-engine';
|
5 | import {View} from '../src/view';
|
6 | import {ViewResources} from '../src/view-resources';
|
7 | import {ViewFactory} from '../src/view-factory';
|
8 | import {ShadowDOM} from '../src/shadow-dom'
|
9 | import {DOM} from 'aurelia-pal';
|
10 |
|
11 | describe('view-slot', () => {
|
12 | let container;
|
13 | let templatingEngine;
|
14 | let viewSlot;
|
15 | let parent;
|
16 | let element;
|
17 | let comment;
|
18 |
|
19 | beforeEach(() => {
|
20 | container = new Container();
|
21 | parent = DOM.createElement('div');
|
22 | comment = DOM.createComment('testing');
|
23 | element = DOM.createElement('div');
|
24 | parent.appendChild(element);
|
25 | viewSlot = new ViewSlot(element, false);
|
26 | container.registerInstance(DOM.Element, element);
|
27 | templatingEngine = container.get(TemplatingEngine);
|
28 | });
|
29 |
|
30 | describe('when binding to a bindingContext', () => {
|
31 | let context = { name: 'Test Context' };
|
32 | let view;
|
33 | let compilerInstructions;
|
34 | let resources;
|
35 | let factory;
|
36 |
|
37 | beforeEach(() => {
|
38 | compilerInstructions = {};
|
39 | resources = container.get(ViewResources);
|
40 | factory = new ViewFactory(parent, compilerInstructions, resources);
|
41 | view = factory.create();
|
42 | });
|
43 |
|
44 | describe('.bind', () => {
|
45 | it('applies bindingContext if unbound', () => {
|
46 | viewSlot.bind(context);
|
47 | expect(viewSlot.bindingContext).toEqual(context);
|
48 | });
|
49 |
|
50 | it('applies new bindingContext if not matching old', () => {
|
51 | let newContext = { name: 'New Context' };
|
52 | viewSlot.bind(context);
|
53 | expect(viewSlot.bindingContext).toEqual(context);
|
54 | viewSlot.bind(newContext);
|
55 | expect(viewSlot.bindingContext).toEqual(newContext);
|
56 | });
|
57 |
|
58 | it('applies new bindingContext to all children', () => {
|
59 | viewSlot.add(view);
|
60 | viewSlot.bind(context);
|
61 | expect(view.bindingContext).toEqual(context)
|
62 | });
|
63 |
|
64 | it('applies override context', () => {
|
65 | viewSlot.bind(context, { $index: 0 });
|
66 | expect(viewSlot.overrideContext).toEqual({ $index: 0 });
|
67 | });
|
68 | });
|
69 |
|
70 | describe('.unbind', () => {
|
71 | it('removes bindingContext if already bound', () => {
|
72 | viewSlot.bind(context);
|
73 | viewSlot.unbind();
|
74 | expect(viewSlot.isBound).toEqual(false);
|
75 | expect(viewSlot.bindingContext).toEqual(null);
|
76 | });
|
77 |
|
78 | it('removes bindingContext from all children', () => {
|
79 | viewSlot.add(view);
|
80 | viewSlot.bind(context);
|
81 | expect(view.bindingContext).toEqual(context);
|
82 | viewSlot.unbind();
|
83 | expect(view.bindingContext).toEqual(null);
|
84 | });
|
85 |
|
86 | it('removes override context', () => {
|
87 | viewSlot.bind(context, { $index: 0 });
|
88 | expect(viewSlot.overrideContext).toEqual({ $index: 0 });
|
89 | viewSlot.unbind();
|
90 | expect(view.bindingContext).toEqual(null);
|
91 | expect(view.overrideContext).toEqual(null);
|
92 | });
|
93 | });
|
94 | });
|
95 |
|
96 | describe('when adding or removing views', () => {
|
97 | let view;
|
98 | let secondView;
|
99 | let thirdView;
|
100 | let compilerInstructions;
|
101 | let resources;
|
102 | let factory;
|
103 |
|
104 | beforeEach(() => {
|
105 | compilerInstructions = {};
|
106 | resources = container.get(ViewResources);
|
107 | factory = new ViewFactory(parent, compilerInstructions, resources);
|
108 | view = factory.create();
|
109 | secondView = factory.create();
|
110 | thirdView = factory.create();
|
111 | });
|
112 |
|
113 | describe('.add', () => {
|
114 | it('adds a new view to children', () => {
|
115 | expect(viewSlot.children.length).toEqual(0);
|
116 | viewSlot.add(view);
|
117 | expect(viewSlot.children.length).toEqual(1);
|
118 | });
|
119 |
|
120 | xit('returns a promise if is animatable', () => {
|
121 | viewSlot.add(comment)
|
122 | let result = viewSlot.add(view);
|
123 | expect(result.constructor.name).toEqual('Promise');
|
124 | });
|
125 | });
|
126 |
|
127 | describe('.insert', () => {
|
128 | it('inserts a new view to children when empty already', () => {
|
129 | viewSlot.insert(0, secondView);
|
130 | expect(viewSlot.children.length).toEqual(1);
|
131 | expect(viewSlot.children[0]).toEqual(secondView);
|
132 | });
|
133 |
|
134 | it('inserts a new view to children when contains 1 already', () => {
|
135 | viewSlot.add(view);
|
136 | viewSlot.insert(1, secondView);
|
137 | expect(viewSlot.children.length).toEqual(2);
|
138 | });
|
139 |
|
140 | it('inserts a new view to children when contains 2 already', () => {
|
141 | viewSlot.add(view);
|
142 | viewSlot.add(secondView);
|
143 | viewSlot.insert(1, thirdView);
|
144 | expect(viewSlot.children.length).toEqual(3);
|
145 | });
|
146 |
|
147 | xit('returns a promise if is animatable', () => {
|
148 | viewSlot.add(view);
|
149 | view.attached();
|
150 | let result = viewSlot.insert(1, view);
|
151 | expect(result.constructor.name).toEqual('Promise');
|
152 | });
|
153 | });
|
154 |
|
155 | describe('.move', () => {
|
156 | it('moves a view across children when contains 3 already', () => {
|
157 | viewSlot.add(view);
|
158 | viewSlot.add(secondView);
|
159 | viewSlot.add(thirdView);
|
160 | viewSlot.move(2, 1);
|
161 | expect(viewSlot.children.length).toEqual(3);
|
162 | expect(viewSlot.children[1]).toEqual(thirdView);
|
163 | expect(viewSlot.children[2]).toEqual(secondView);
|
164 | });
|
165 |
|
166 | it('moves a view to the beginning of children when contains 3 already', () => {
|
167 | viewSlot.add(view);
|
168 | viewSlot.add(secondView);
|
169 | viewSlot.add(thirdView);
|
170 | viewSlot.move(2, 0);
|
171 | expect(viewSlot.children.length).toEqual(3);
|
172 | expect(viewSlot.children[0]).toEqual(thirdView);
|
173 | expect(viewSlot.children[1]).toEqual(view);
|
174 | expect(viewSlot.children[2]).toEqual(secondView);
|
175 | });
|
176 |
|
177 | it('moves a view to the end of children when contains 3 already', () => {
|
178 | viewSlot.add(view);
|
179 | viewSlot.add(secondView);
|
180 | viewSlot.add(thirdView);
|
181 | viewSlot.move(0, 2);
|
182 | expect(viewSlot.children.length).toEqual(3);
|
183 | expect(viewSlot.children[0]).toEqual(secondView);
|
184 | expect(viewSlot.children[1]).toEqual(thirdView);
|
185 | expect(viewSlot.children[2]).toEqual(view);
|
186 | });
|
187 | });
|
188 |
|
189 | describe('.remove', () => {
|
190 | it('removes a view from children', () => {
|
191 | viewSlot.add(view);
|
192 | expect(viewSlot.children.length).toEqual(1);
|
193 | viewSlot.remove(view);
|
194 | expect(viewSlot.children.length).toEqual(0);
|
195 | });
|
196 |
|
197 | it('calls detached if already attached when removed', () => {
|
198 | spyOn(view, 'detached');
|
199 | viewSlot.add(view);
|
200 | viewSlot.attached();
|
201 | viewSlot.remove(view);
|
202 | expect(view.detached).toHaveBeenCalled();
|
203 | });
|
204 |
|
205 | describe('doesnt call return to cache when returnToCache', () => {
|
206 |
|
207 | it('is set to false', () => {
|
208 | spyOn(view, 'returnToCache');
|
209 | viewSlot.add(view);
|
210 | viewSlot.remove(view, false);
|
211 | expect(view.returnToCache).not.toHaveBeenCalled();
|
212 | });
|
213 |
|
214 | it('is not set', () => {
|
215 | spyOn(view, 'returnToCache');
|
216 | viewSlot.add(view);
|
217 | viewSlot.remove(view);
|
218 | expect(view.returnToCache).not.toHaveBeenCalled();
|
219 | });
|
220 | });
|
221 |
|
222 | it('calls return to cache when returnToCache is true', () => {
|
223 | spyOn(view, 'returnToCache');
|
224 | viewSlot.add(view);
|
225 | viewSlot.remove(view, true);
|
226 | expect(view.returnToCache).toHaveBeenCalled();
|
227 | });
|
228 | });
|
229 |
|
230 |
|
231 | describe('.remove with ShadowDOM', () => {
|
232 | let { distributeView, undistributeAll, undistributeView } = ShadowDOM;
|
233 | beforeAll(() => {
|
234 | ShadowDOM.distributeView = ShadowDOM.undistributeView = ShadowDOM.undistributeAll = () => {};
|
235 | });
|
236 | afterAll(() => {
|
237 | ShadowDOM.distributeView = distributeView;
|
238 | ShadowDOM.undistributeView = undistributeView;
|
239 | ShadowDOM.undistributeAll = undistributeAll;
|
240 | });
|
241 |
|
242 | beforeEach(() => {
|
243 | viewSlot.projectTo({ _default_: {} });
|
244 | });
|
245 |
|
246 | it('removes a view from children', () => {
|
247 | viewSlot.add(view);
|
248 | expect(viewSlot.children.length).toEqual(1);
|
249 | viewSlot.remove(view);
|
250 | expect(viewSlot.children.length).toEqual(0);
|
251 | });
|
252 |
|
253 | it('calls detached if already attached when removed', () => {
|
254 | spyOn(view, 'detached');
|
255 | viewSlot.add(view);
|
256 | viewSlot.attached();
|
257 | viewSlot.remove(view);
|
258 | expect(view.detached).toHaveBeenCalled();
|
259 | });
|
260 |
|
261 | describe('doesnt call return to cache when returnToCache', () => {
|
262 |
|
263 | it('is set to false', () => {
|
264 | spyOn(view, 'returnToCache');
|
265 | viewSlot.add(view);
|
266 | viewSlot.remove(view, false);
|
267 | expect(view.returnToCache).not.toHaveBeenCalled();
|
268 | });
|
269 |
|
270 | it('is not set', () => {
|
271 | spyOn(view, 'returnToCache');
|
272 | viewSlot.add(view);
|
273 | viewSlot.remove(view);
|
274 | expect(view.returnToCache).not.toHaveBeenCalled();
|
275 | });
|
276 | });
|
277 |
|
278 | it('calls return to cache when returnToCache is true', () => {
|
279 | spyOn(view, 'returnToCache');
|
280 | viewSlot.add(view);
|
281 | viewSlot.remove(view, true);
|
282 | expect(view.returnToCache).toHaveBeenCalled();
|
283 | });
|
284 | });
|
285 |
|
286 | describe('.removeAll', () => {
|
287 | it('removes all views from children', () => {
|
288 | viewSlot.add(view);
|
289 | viewSlot.add(secondView);
|
290 | expect(viewSlot.children.length).toEqual(2);
|
291 | viewSlot.removeAll();
|
292 | expect(viewSlot.children.length).toEqual(0);
|
293 | });
|
294 | });
|
295 |
|
296 | describe('.removeMany', () => {
|
297 | it('removes many views from children synchronously', () => {
|
298 | viewSlot.add(view);
|
299 | viewSlot.add(secondView);
|
300 | viewSlot.add(thirdView);
|
301 | expect(viewSlot.children.length).toEqual(3);
|
302 | viewSlot.removeMany([view, thirdView]);
|
303 | expect(viewSlot.children.length).toEqual(1);
|
304 | viewSlot.removeMany([secondView]);
|
305 | expect(viewSlot.children.length).toEqual(0);
|
306 | });
|
307 | });
|
308 |
|
309 | describe('.attached', () => {
|
310 | it('sets attached on the slot', () => {
|
311 | expect(viewSlot.isAttached).toEqual(false);
|
312 | viewSlot.attached();
|
313 | expect(viewSlot.isAttached).toEqual(true);
|
314 | });
|
315 |
|
316 | it('sets attached on children', () => {
|
317 | expect(view.isAttached).toEqual(false);
|
318 | viewSlot.add(view);
|
319 | viewSlot.attached();
|
320 | expect(view.isAttached).toEqual(true);
|
321 | });
|
322 | });
|
323 |
|
324 | describe('.detached', () => {
|
325 | it('sets detached on the slot', () => {
|
326 | viewSlot.attached();
|
327 | expect(viewSlot.isAttached).toEqual(true);
|
328 | viewSlot.detached();
|
329 | expect(viewSlot.isAttached).toEqual(false);
|
330 | });
|
331 |
|
332 | it('sets detached on children', () => {
|
333 | viewSlot.attached();
|
334 | expect(viewSlot.isAttached).toEqual(true);
|
335 | viewSlot.add(view);
|
336 | viewSlot.detached();
|
337 | expect(view.isAttached).toEqual(false);
|
338 | });
|
339 | });
|
340 | });
|
341 | });
|