1 | import './setup';
|
2 | import {metadata} from 'aurelia-metadata';
|
3 | import { Logger } from 'aurelia-logging';
|
4 | import {bindingMode, valueConverter, bindingBehavior, ValueConverterResource, BindingBehaviorResource} from 'aurelia-binding';
|
5 | import {Container} from 'aurelia-dependency-injection';
|
6 | import { customElement, customAttribute, bindable } from '../src/decorators';
|
7 | import {ViewResources} from '../src/view-resources';
|
8 | import { HtmlBehaviorResource } from '../src/html-behavior';
|
9 | import { viewEngineHooks } from '../src/view-engine-hooks-resource';
|
10 |
|
11 | describe('ViewResources', () => {
|
12 |
|
13 | let container;
|
14 |
|
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 |
|
241 |
|
242 |
|
243 |
|
244 |
|
245 |
|
246 |
|
247 |
|
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
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 |
|
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 | });
|