UNPKG

8.39 kBJavaScriptView Raw
1import './setup';
2import {metadata} from 'aurelia-metadata';
3import { Logger } from 'aurelia-logging';
4import {bindingMode, valueConverter, bindingBehavior, ValueConverterResource, BindingBehaviorResource} from 'aurelia-binding';
5import {Container} from 'aurelia-dependency-injection';
6import { customElement, customAttribute, bindable } from '../src/decorators';
7import {ViewResources} from '../src/view-resources';
8import { HtmlBehaviorResource } from '../src/html-behavior';
9import { viewEngineHooks } from '../src/view-engine-hooks-resource';
10
11describe('ViewResources', () => {
12 /**@type {Container} */
13 let container;
14 /**@type {ViewResources} */
15 let resources;
16
17 beforeEach(() => {
18 container = new Container();
19 resources = new ViewResources();
20 });
21
22 describe('convention', () => {
23 it('recognizes convention', () => {
24 class El {
25 static $resource() {
26 return 'el1';
27 }
28 }
29
30 let meta = ViewResources.convention(El);
31 expect(meta.elementName).toBe('el1');
32
33 class A {
34 static $resource = {
35 type: 'attribute',
36 }
37 }
38
39 meta = ViewResources.convention(A);
40 expect(meta.attributeName).toBe('a');
41
42 class ElOrA {
43 static $resource = {
44 type: 'element',
45 bindables: ['b', 'c', { name: 'd', defaultBindingMode: 'twoWay' }]
46 }
47 }
48 meta = ViewResources.convention(ElOrA);
49 expect(meta.properties.length).toBe(3);
50 expect(meta.attributes.d.defaultBindingMode).toBe(bindingMode.twoWay);
51
52 class Vc {
53 static $resource = {
54 type: 'valueConverter'
55 }
56 }
57 meta = ViewResources.convention(Vc);
58 expect(meta instanceof ValueConverterResource).toBe(true);
59 expect(meta.name).toBe('vc');
60
61 class Bb {
62 static $resource = {
63 type: 'bindingBehavior'
64 }
65 }
66 meta = ViewResources.convention(Bb);
67 expect(meta instanceof BindingBehaviorResource).toBe(true);
68 expect(meta.name).toBe('bb');
69 });
70
71 it('warns when using uppercase letters in custom element / attribute name', () => {
72 let spy = spyOn(Logger.prototype, 'warn').and.callThrough();
73 class ElEl {
74 static $resource() {
75 return 'ElEl';
76 }
77 }
78
79 let meta = ViewResources.convention(ElEl);
80 expect(meta.elementName).toBe('el-el');
81 expect(spy).toHaveBeenCalledWith(`'ElEl' is not a valid custom element name and has been converted to 'el-el'. Upper-case letters are not allowed because the DOM is not case-sensitive.`);
82 });
83
84 it('invokes static method with correct context', () => {
85 class Base {
86 static get elName() {
87 return 'base';
88 }
89 static $resource() {
90 return this.elName;
91 }
92 }
93
94 class El extends Base {
95
96 }
97 let meta = ViewResources.convention(El);
98 expect(meta.elementName).toBe('base');
99
100 class El1 extends Base {
101 static get elName() {
102 return 'el';
103 }
104 }
105 meta = ViewResources.convention(El1);
106 expect(meta.elementName).toBe('el');
107 });
108
109 it('does not reapply convention', () => {
110 class El {
111 static $resource = {
112 bindables: ['value']
113 }
114 }
115 let meta = metadata.getOrCreateOwn(metadata.resource, HtmlBehaviorResource, El);
116 ViewResources.convention(El, meta);
117 expect(meta.elementName).toBe('el');
118 expect(meta.properties.length).toBe(1);
119 expect(meta.__au_resource__).toBe(true);
120
121 El.$resource.bindables.push('name', 'label', 'type');
122 ViewResources.convention(El, meta);
123 expect(meta.properties.length).toBe(1);
124 });
125 });
126
127 it('auto register', () => {
128 let resourceMetaType;
129 class El {}
130
131 let eMeta = resources.autoRegister(container, El);
132 resourceMetaType = metadata.get(metadata.resource, El);
133
134 expect(eMeta).toBe(resourceMetaType);
135 expect(resourceMetaType.target).toBe(El);
136 expect(resourceMetaType instanceof HtmlBehaviorResource).toBe(true);
137
138 class ElCustomElement {}
139 expect(() => resources.autoRegister(container, ElCustomElement)).toThrow();
140
141 @customElement('el')
142 class Ell {}
143 expect(() => resources.autoRegister(container, Ell)).toThrow();
144
145 // =========
146
147 class ACustomAttribute {}
148
149 let aMeta = resources.autoRegister(container, ACustomAttribute);
150 resourceMetaType = metadata.get(metadata.resource, ACustomAttribute);
151
152 expect(aMeta).toBe(resourceMetaType);
153 expect(aMeta.target).toBe(ACustomAttribute);
154 expect(aMeta instanceof HtmlBehaviorResource).toBe(true);
155
156 @customAttribute('a')
157 class AA {}
158
159 expect(() => resources.autoRegister(container, AA)).toThrow();
160
161 // =========
162
163 class VValueConverter {}
164 let vMeta = resources.autoRegister(container, VValueConverter);
165 resourceMetaType = metadata.get(metadata.resource, VValueConverter);
166
167 expect(vMeta).toBe(resourceMetaType);
168
169 @valueConverter('v')
170 class V {}
171 expect(() => resources.autoRegister(container, V)).toThrow();
172
173 // =========
174
175 class BBindingBehavior {}
176 let bMeta = resources.autoRegister(container, BBindingBehavior);
177 resourceMetaType = metadata.get(metadata.resource, BBindingBehavior);
178
179 expect(bMeta).toBe(resourceMetaType);
180
181 @bindingBehavior('b')
182 class B {}
183
184 expect(() => resources.autoRegister(container, B)).toThrow();
185
186 // ========
187
188 class HViewEngineHooks {
189 beforeCompile() {}
190 }
191 let hMeta = resources.autoRegister(container, HViewEngineHooks);
192 resourceMetaType = metadata.get(metadata.resource, HViewEngineHooks);
193
194 expect(hMeta).toBe(resourceMetaType);
195 expect(resources.beforeCompile).toBe(true);
196
197 @viewEngineHooks()
198 class H {
199 beforeCompile() {}
200 afterCompile() {}
201 }
202 resources.autoRegister(container, H);
203
204 expect(resources.afterCompile).toBe(true);
205 expect(resources.beforeCompile1).toBeDefined();
206 expect(resources.beforeCompile2).toBeDefined();
207
208 });
209
210 it('auto register with static `resource` convention ', () => {
211 class El3 {
212 static $resource = 'el3'
213 }
214 resources.autoRegister(container, El3);
215 expect(resources.getElement('el3').target).toBe(El3);
216 });
217
218 describe('interop', () => {
219 it('uses existing HtmlBehaviorResource metadata for naming', () => {
220
221 @customElement('a')
222 class El {
223 static $resource = 'b'
224 }
225
226 resources.autoRegister(container, El);
227 expect(resources.getElement('a').target).toBe(El);
228
229 @customAttribute('b')
230 class At {
231 static $resource = {
232 type: 'attribute',
233 name: 'c'
234 }
235 }
236 resources.autoRegister(container, At);
237 expect(resources.getAttribute('b').target).toBe(At)
238 });
239
240 // it('adds bindables', () => {
241
242 // class El {
243 // static $resource() {
244 // return {
245 // bindables: ['name', 'value']
246 // }
247 // }
248 // @bindable() name
249 // @bindable() value
250 // }
251 // resources.autoRegister(container, El);
252 // expect(resources.getElement('el').properties.length).toBe(4);
253 // });
254
255 describe('with inheritance', () => {
256
257 it('works with base class using static config and derived class using decorator', () => {
258 class Base {
259 static $resource = {
260 bindables: ['name', 'value']
261 }
262 }
263
264 class Field extends Base {
265 @bindable()
266 label;
267 }
268
269 resources.autoRegister(container, Field);
270 expect(resources.getElement('field').properties.length).toBe(3);
271 });
272
273 it('works with base class using decorators and derivde class using static config', () => {
274 class Base {
275 @bindable() name
276 @bindable() value;
277 }
278
279 class Field extends Base {
280 static $resource = {
281 bindables: ['label']
282 }
283 }
284
285 const meta = resources.autoRegister(container, Field);
286 expect(resources.getElement('field').properties.length).toBe(3);
287 // Just a little check to ensure metadata are
288 expect(resources.getElement('base')).toBeFalsy();
289 expect(meta).toBe(resources.getElement('field'));
290 expect(metadata.getOwn(metadata.resource, Base)).not.toBe(meta);
291 });
292
293 });
294 });
295});