Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(411)

Side by Side Diff: appengine/config_service/ui/bower_components/test-fixture/test-fixture.html

Issue 2923973003: Added base template for config ui. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 <!--
2 @license
3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
4 This code may only be used under the BSD style license found at http://polymer.g ithub.io/LICENSE.txt
5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6 The complete set of contributors may be found at http://polymer.github.io/CONTRI BUTORS.txt
7 Code distributed by Google as part of the polymer project is also
8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN TS.txt
9 -->
10
11 <!--
12
13 The `<test-fixture>` element can simplify the exercise of consistently
14 resetting a test suite's DOM. To use it, wrap the test suite's DOM as a template :
15
16 ```html
17 <test-fixture id="SomeElementFixture">
18 <template>
19 <some-element id="SomeElementForTesting"></some-element>
20 </template>
21 </test-fixture>
22 ```
23
24 Now, the `<test-fixture>` element can be used to generate a copy of its
25 template:
26
27 ```html
28 <script>
29 describe('<some-element>', function () {
30 var someElement;
31
32 beforeEach(function () {
33 document.getElementById('SomeElementFixture').create();
34 someElement = document.getElementById('SomeElementForTesting');
35 });
36 });
37 </script>
38 ```
39
40 Fixtured elements can be cleaned up by calling `restore` on the `<test-fixture>` :
41
42 ```javascript
43 afterEach(function () {
44 document.getElementById('SomeElementFixture').restore();
45 // <some-element id='SomeElementForTesting'> has been removed
46 });
47 ```
48
49 `<test-fixture>` will create fixtures from all of its immediate `<template>`
50 children. The DOM structure of fixture templates can be as simple or as complex
51 as the situation calls for.
52
53 ## Even simpler usage in Mocha
54
55 In Mocha, usage can be simplified even further. Include `test-fixture-mocha.js`
56 after Mocha in the `<head>` of your document and then fixture elements like so:
57
58 ```html
59 <script>
60 describe('<some-element>', function () {
61 var someElement;
62
63 beforeEach(function () {
64 someElement = fixture('SomeElementFixture');
65 });
66 });
67 </script>
68 ```
69
70 Fixtured elements will be automatically restored in the `afterEach` phase of the
71 current Mocha `Suite`.
72
73 ## Data-bound templates
74
75 Data-binding systems are also supported, as long as your (custom) template
76 elements define a `stamp(model)` method that returns a document fragment. This
77 allows you to stamp out templates w/ custom models for your fixtures.
78
79 For example, using Polymer 0.8's `dom-template`:
80
81 ```html
82 <test-fixture id="bound">
83 <template is="dom-template">
84 <span>{{greeting}}</span>
85 </template>
86 </test-fixture>
87 ```
88
89 You can pass an optional context argument to `create()` or `fixture()` to pass
90 the model:
91
92 ```js
93 var bound = fixture('bound', {greeting: 'ohai thurr'});
94 ```
95
96 ## The problem being addressed
97
98 Consider the following `web-component-tester` test suite:
99
100 ```html
101 <!doctype html>
102 <html>
103 <head>
104 <title>some-element test suite</title>
105
106 <link rel="import" href="../some-element.html">
107 </head>
108 <body>
109 <some-element id="SomeElementForTesting"></some-element>
110 <script>
111 describe('<some-element>', function () {
112 var someElement;
113
114 beforeEach(function () {
115 someElement = document.getElementById('SomeElementForTesting');
116 });
117
118 it('can receive property `foo`', function () {
119 someElement.foo = 'bar';
120 expect(someElement.foo).to.be.equal('bar');
121 });
122
123 it('has a default `foo` value of `undefined`', function () {
124 expect(someElement.foo).to.be.equal(undefined);
125 });
126 });
127 </script>
128 </body>
129 </html>
130 ```
131
132 In this contrived example, the suite will pass or fail depending on which order
133 the tests are run in. It is non-deterministic because `someElement` has
134 internal state that is not properly reset at the end of each test.
135
136 It would be trivial in the above example to simply reset `someElement.foo` to
137 the expected default value of `undefined` in an `afterEach` hook. However, for
138 non-contrived test suites that target complex elements, this can result in a
139 large quantity of ever-growing set-up and tear-down boilerplate.
140
141 @pseudoElement test-fixture
142 -->
143
144 <script>
145
146 (function () {
147 var TestFixturePrototype = Object.create(HTMLElement.prototype);
148 var TestFixtureExtension = {
149 _fixtureTemplates: null,
150
151 _elementsFixtured: false,
152
153 get elementsFixtured () {
154 return this._elementsFixtured;
155 },
156
157 get fixtureTemplates () {
158 if (!this._fixtureTemplates) {
159 // Copy fixtures to a true Array for Safari 7. This prevents their
160 // `content` property from being improperly garbage collected.
161 this._fixtureTemplates = Array.prototype.slice.apply(this.querySelectorA ll('template'));
162 }
163
164 return this._fixtureTemplates;
165 },
166
167 create: function (model) {
168 var generatedDoms = [];
169
170 this.restore();
171
172 this.removeElements(this.fixtureTemplates);
173
174 this.forElements(this.fixtureTemplates, function (fixtureTemplate) {
175 generatedDoms.push(
176 this.createFrom(fixtureTemplate, model)
177 );
178 }, this);
179
180 this.forcePolyfillAttachedStateSynchrony();
181
182 if (generatedDoms.length < 2) {
183 return generatedDoms[0];
184 }
185
186 return generatedDoms;
187 },
188
189 createFrom: function (fixtureTemplate, model) {
190 var fixturedFragment;
191 var fixturedElements;
192 var fixturedElement;
193
194 if (!(fixtureTemplate &&
195 fixtureTemplate.tagName === 'TEMPLATE')) {
196 return;
197 }
198
199 try {
200 fixturedFragment = this.stamp(fixtureTemplate, model);
201 } catch (error) {
202 console.error('Error stamping', fixtureTemplate, error);
203 throw error;
204 }
205
206 fixturedElements = this.collectElementChildren(fixturedFragment);
207
208 this.appendChild(fixturedFragment);
209 this._elementsFixtured = true;
210
211 if (fixturedElements.length < 2) {
212 return fixturedElements[0];
213 }
214
215 return fixturedElements;
216 },
217
218 restore: function () {
219 if (!this._elementsFixtured) {
220 return;
221 }
222
223 this.removeElements(this.children);
224
225 this.forElements(this.fixtureTemplates, function (fixtureTemplate) {
226 this.appendChild(fixtureTemplate);
227 }, this);
228
229 this.generatedDomStack = [];
230
231 this._elementsFixtured = false;
232
233 this.forcePolyfillAttachedStateSynchrony();
234 },
235
236 forcePolyfillAttachedStateSynchrony: function () {
237 // Force synchrony in attachedCallback and detachedCallback where
238 // implemented, in the event that we are dealing with one of these async
239 // polyfills:
240 // 1. Web Components CustomElements polyfill (v1 or v0).
241 if (window.customElements && window.customElements.flush) {
242 window.customElements.flush();
243 } else if (window.CustomElements && window.CustomElements.takeRecords) {
244 window.CustomElements.takeRecords();
245 }
246 // 2. ShadyDOM polyfill.
247 if (window.ShadyDOM && window.ShadyDOM.flush) {
248 window.ShadyDOM.flush();
249 }
250 },
251
252 collectElementChildren: function (parent) {
253 // Note: Safari 7.1 does not support `firstElementChild` or
254 // `nextElementSibling`, so we do things the old-fashioned way:
255 var elements = [];
256 var child = parent.firstChild;
257
258 while (child) {
259 if (child.nodeType === Node.ELEMENT_NODE) {
260 elements.push(child);
261 }
262
263 child = child.nextSibling;
264 }
265
266 return elements;
267 },
268
269 removeElements: function (elements) {
270 this.forElements(elements, function (element) {
271 this.removeChild(element);
272 }, this);
273 },
274
275 forElements: function (elements, iterator, context) {
276 Array.prototype.slice.call(elements)
277 .forEach(iterator, context);
278 },
279
280 stamp: function (fixtureTemplate, model) {
281 var stamped;
282 // Check if we are dealing with a "stampable" `<template>`. This is a
283 // vaguely defined special case of a `<template>` that is a custom
284 // element with a public `stamp` method that implements some manner of
285 // data binding.
286 if (fixtureTemplate.stamp) {
287 stamped = fixtureTemplate.stamp(model);
288 // We leak Polymer specifics a little; if there is an element `root`, we
289 // want that to be returned.
290 stamped = stamped.root || stamped;
291
292 // Otherwise, we fall back to standard HTML templates, which do not have
293 // any sort of binding support.
294 } else {
295 if (model) {
296 console.warn(this, 'was given a model to stamp, but the template is no t of a bindable type');
297 }
298
299 stamped = document.importNode(fixtureTemplate.content, true);
300
301 // Immediately upgrade the subtree if we are dealing with async
302 // Web Components polyfill.
303 // https://github.com/Polymer/polymer/blob/0.8-preview/src/features/mini /template.html#L52
304 if (window.CustomElements && window.CustomElements.upgradeSubtree) {
305 window.CustomElements.upgradeSubtree(stamped);
306 }
307 }
308
309 return stamped;
310 }
311 };
312
313 Object.getOwnPropertyNames(TestFixtureExtension)
314 .forEach(function (property) {
315 Object.defineProperty(
316 TestFixturePrototype,
317 property,
318 Object.getOwnPropertyDescriptor(TestFixtureExtension, property)
319 );
320 });
321
322 try {
323 if (window.customElements) {
324 function TestFixture() {
325 return ((window.Reflect && Reflect.construct) ?
326 Reflect.construct(HTMLElement, [], TestFixture)
327 : HTMLElement.call(this)) || this;
328 }
329 TestFixture.prototype = TestFixturePrototype;
330 // `constructor` is not writable on Safari 9, but is configurable.
331 Object.defineProperty(TestFixture.prototype, 'constructor', {
332 configurable: true,
333 enumerable: true,
334 writable: true,
335 value: TestFixture,
336 });
337 window.customElements.define('test-fixture', TestFixture);
338 } else {
339 document.registerElement('test-fixture', {
340 prototype: TestFixturePrototype
341 });
342 }
343 } catch (e) {
344 if (window.WCT) {
345 console.warn('if you are using WCT, you do not need to manually import tes t-fixture.html');
346 } else {
347 console.warn('test-fixture has already been registered!');
348 }
349 }
350 })();
351 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698