| // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| // @dart = 2.9 |
| |
| library custom_elements_test; |
| |
| import 'dart:async'; |
| import 'dart:html'; |
| import 'package:async_helper/async_minitest.dart'; |
| import 'utils.dart'; |
| |
| class CustomMixin { |
| var mixinMethodCalled; |
| |
| void mixinMethod() { |
| mixinMethodCalled = true; |
| } |
| } |
| |
| class CustomType extends HtmlElement with CustomMixin { |
| bool createdCalled = false; |
| |
| factory CustomType() => null; |
| CustomType.created() : super.created() { |
| createdCalled = true; |
| customCreatedCount++; |
| } |
| |
| void invokeMixinMethod() { |
| mixinMethod(); |
| } |
| } |
| |
| int customCreatedCount = 0; |
| |
| int nextTagId = 0; |
| String get nextTag => 'x-type${nextTagId++}'; |
| |
| class NotAnElement {} |
| |
| main() async { |
| await customElementsReady; |
| |
| group('register', () { |
| test('register', () { |
| var tag = nextTag; |
| document.registerElement(tag, CustomType); |
| |
| var element = new Element.tag(tag) as CustomType; |
| expect(element, isNotNull); |
| expect(element is CustomType, isTrue); |
| expect(element.createdCalled, isTrue); |
| }); |
| |
| test('register twice', () { |
| var tag = nextTag; |
| document.registerElement(tag, CustomType); |
| expect(() { |
| document.registerElement(tag, CustomType); |
| }, throws, reason: 'Cannot register a tag more than once.'); |
| |
| var newTag = nextTag; |
| document.registerElement(newTag, CustomType); |
| |
| var element = new Element.tag(newTag) as CustomType; |
| expect(element, isNotNull); |
| expect(element is CustomType, isTrue); |
| }); |
| |
| test('register null', () { |
| expect(() { |
| document.registerElement(nextTag, null); |
| }, throws, reason: 'Cannot register a null type.'); |
| }); |
| |
| test('register native', () { |
| expect(() { |
| document.registerElement(nextTag, BodyElement); |
| }, throws, reason: 'Cannot register a native element.'); |
| }); |
| |
| test('register non-element', () { |
| expect(() { |
| document.registerElement(nextTag, NotAnElement); |
| }, throws, reason: 'Cannot register a non-element.'); |
| }); |
| }); |
| |
| // TODO(vsm): Modify this test once we agree on the proper semantics. |
| /* |
| group('preregister', () { |
| |
| test('pre-registration construction', () { |
| var tag = nextTag; |
| var dom = new Element.html('<div><$tag></$tag></div>'); |
| |
| var preElement = dom.children[0]; |
| expect(preElement, isNotNull); |
| expect(preElement is HtmlElement, isTrue); |
| expect(preElement is CustomType, isFalse); |
| var firedOnPre = false; |
| preElement.onFocus.listen((_) { |
| firedOnPre = true; |
| }); |
| |
| document.registerElement(tag, CustomType); |
| upgradeCustomElements(dom); |
| |
| var postElement = dom.children[0]; |
| expect(postElement, isNotNull); |
| expect(postElement is CustomType, isTrue); |
| expect(postElement.createdCalled, isTrue); |
| |
| // Element from first query remains an UnknownElement. |
| expect(preElement is HtmlElement, isTrue); |
| expect(preElement.parent, dom); |
| expect(dom.children.length, 1); |
| |
| var firedOnPost = false; |
| postElement.onFocus.listen((_) { |
| firedOnPost = true; |
| }); |
| // Event handlers persist on old and new element. |
| postElement.dispatchEvent(new Event('focus')); |
| expect(firedOnPre, isTrue); |
| expect(firedOnPost, isTrue); |
| }); |
| });*/ |
| |
| group('innerHtml', () { |
| test('query', () { |
| var tag = nextTag; |
| document.registerElement(tag, CustomType); |
| var element = new DivElement(); |
| element.setInnerHtml('<$tag></$tag>', |
| treeSanitizer: new NullTreeSanitizer()); |
| upgradeCustomElements(element); |
| document.body.nodes.add(element); |
| var queried = querySelector(tag) as CustomType; |
| |
| expect(queried, isNotNull); |
| expect(queried is CustomType, isTrue); |
| expect(queried.createdCalled, isTrue); |
| }); |
| |
| test('query id', () { |
| var tag = nextTag; |
| document.registerElement(tag, CustomType); |
| var element = new DivElement(); |
| element.setInnerHtml('<$tag id="someid"></$tag>', |
| treeSanitizer: new NullTreeSanitizer()); |
| upgradeCustomElements(element); |
| document.body.nodes.add(element); |
| var queried = querySelector('#someid') as CustomType; |
| |
| expect(queried, isNotNull); |
| expect(queried is CustomType, isTrue); |
| expect(queried.id, "someid"); |
| }); |
| }); |
| |
| group('lifecycle', () { |
| test('created', () { |
| int oldCount = customCreatedCount; |
| var tag = nextTag; |
| document.registerElement(tag, CustomType); |
| var element = new DivElement(); |
| element.setInnerHtml('<$tag></$tag>', |
| treeSanitizer: new NullTreeSanitizer()); |
| upgradeCustomElements(element); |
| document.body.nodes.add(element); |
| expect(customCreatedCount, oldCount + 1); |
| }); |
| }); |
| |
| group('mixins', () { |
| test('can invoke mixin methods', () { |
| var tag = nextTag; |
| document.registerElement(tag, CustomType); |
| |
| var element = new Element.tag(tag) as CustomType; |
| element.invokeMixinMethod(); |
| expect(element.mixinMethodCalled, isTrue); |
| }); |
| }); |
| } |