[3.0 alpha] Remove dart:html's deprecated document.registerElement & registerElement2 APIs

Change-Id: I07fc124c55d1aeb678f39a4d72d3b4f581025a10
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/273541
Reviewed-by: Srujan Gaddam <srujzs@google.com>
Commit-Queue: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
Sigmund Cherem 2022-12-09 16:02:02 +00:00 committed by Commit Queue
parent 98eedc6f22
commit c91b73eaf7
76 changed files with 325 additions and 5257 deletions

View file

@ -1,3 +1,14 @@
## 3.0.0
### Libraries
#### `dart:html`
- **Breaking change**: As previously announced, the deprecated `registerElement`
and `registerElement2` methods in `Document` and `HtmlDocument` have been
removed. See [#49536](https://github.com/dart-lang/sdk/issues/49536) for
details.
## 2.19.0
### Language

View file

@ -1,64 +0,0 @@
// 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.7
// Test of the graph segmentation algorithm used by deferred loading
// to determine which elements can be deferred and which libraries
// much be included in the initial download (loaded eagerly).
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/compiler.dart';
import 'package:expect/expect.dart';
import 'package:compiler/src/util/memory_compiler.dart';
void main() {
asyncTest(() async {
print('--test from kernel------------------------------------------------');
await runTest();
});
}
runTest() async {
CompilationResult result =
await runCompiler(memorySourceFiles: MEMORY_SOURCE_FILES);
Compiler compiler = result.compiler;
var closedWorld = compiler.backendClosedWorldForTesting;
var outputUnitForMember = closedWorld.outputUnitData.outputUnitForMember;
var outputUnitForClass = closedWorld.outputUnitData.outputUnitForClass;
var mainOutputUnit = closedWorld.outputUnitData.mainOutputUnit;
var elementEnvironment = closedWorld.elementEnvironment;
dynamic lib = elementEnvironment.lookupLibrary(Uri.parse("memory:lib.dart"));
var customType = elementEnvironment.lookupClass(lib, "CustomType");
var foo = elementEnvironment.lookupLibraryMember(lib, "foo");
Expect.notEquals(mainOutputUnit, outputUnitForMember(foo));
// Native elements are not deferred
Expect.equals(mainOutputUnit, outputUnitForClass(customType));
}
// The main library imports a file defining a custom element.
// Registering this class implicitly causes the constructors to be
// live. Check that this is handled.
const Map<String, String> MEMORY_SOURCE_FILES = const {
"main.dart": """
import "lib.dart" deferred as a;
import 'dart:html';
main() {
document.registerElement("foo-tag", a.a);
a.foo();
}
""",
"lib.dart": """
import 'dart:html';
var a = CustomType;
class CustomType extends HtmlElement {
factory CustomType() => null;
CustomType.created() : super.created() ;
}
foo() {}
""",
};

View file

@ -10112,22 +10112,6 @@ class Document extends Node {
String queryCommandValue(String commandId) native;
@deprecated
Function registerElement2(String type, [Map? options]) {
if (options != null) {
var options_1 = convertDartToNative_Dictionary(options);
return _registerElement2_1(type, options_1);
}
return _registerElement2_2(type);
}
@JSName('registerElement')
@deprecated
Function _registerElement2_1(type, options) native;
@JSName('registerElement')
@deprecated
Function _registerElement2_2(type) native;
@JSName('webkitExitFullscreen')
@SupportedBrowser(SupportedBrowser.CHROME)
@SupportedBrowser(SupportedBrowser.SAFARI)
@ -10424,29 +10408,6 @@ class Document extends Node {
ElementList<T> querySelectorAll<T extends Element>(String selectors) =>
new _FrozenElementList<T>._wrap(_querySelectorAll(selectors));
/// Checks if [registerElement] is supported on the current platform.
@deprecated
bool get supportsRegisterElement {
return JS('bool', '("registerElement" in #)', this);
}
/// *Deprecated*: use [supportsRegisterElement] instead.
@deprecated
bool get supportsRegister => supportsRegisterElement;
/// **Deprecated**: This is a legacy API based on a deprecated Web Components
/// v0.5 specification. Web Components v0.5 doesn't work on modern browsers
/// and can only be used with a polyfill.
///
/// The latest Web Components specification is supported indirectly via
/// JSInterop and doesn't have an explicit API in the `dart:html` library.
@deprecated
void registerElement(String tag, Type customElementClass,
{String? extendsTag}) {
registerElement2(
tag, {'prototype': customElementClass, 'extends': extendsTag});
}
@pragma('dart2js:tryInline') // Almost all call sites have one argument.
Element createElement(String tagName, [String? typeExtension]) {
return (typeExtension == null)
@ -17840,67 +17801,6 @@ class HtmlDocument extends Document {
_webkitExitFullscreen();
}
/**
* **Deprecated**: This is a legacy API based on a deprecated Web Components
* v0.5 specification. This method doesn't work on modern browsers and can
* only be used with a polyfill.
*
* The latest Web Components specification is supported indirectly via
* JSInterop and doesn't have an explicit API in the `dart:html` library.
*
* *Original documentation before deprecation*:
*
* Register a custom subclass of Element to be instantiatable by the DOM.
*
* This is necessary to allow the construction of any custom elements.
*
* The class being registered must either subclass HtmlElement or SvgElement.
* If they subclass these directly then they can be used as:
*
* class FooElement extends HtmlElement{
* void created() {
* print('FooElement created!');
* }
* }
*
* main() {
* document.registerElement('x-foo', FooElement);
* var myFoo = new Element.tag('x-foo');
* // prints 'FooElement created!' to the console.
* }
*
* The custom element can also be instantiated via HTML using the syntax
* `<x-foo></x-foo>`
*
* Other elements can be subclassed as well:
*
* class BarElement extends InputElement{
* void created() {
* print('BarElement created!');
* }
* }
*
* main() {
* document.registerElement('x-bar', BarElement);
* var myBar = new Element.tag('input', 'x-bar');
* // prints 'BarElement created!' to the console.
* }
*
* This custom element can also be instantiated via HTML using the syntax
* `<input is="x-bar"></input>`
*
*/
@deprecated
Function registerElement2(String tag, [Map? options]) {
return _registerCustomElement(JS('', 'window'), this, tag, options);
}
/** *Deprecated*: use [registerElement] instead. */
@deprecated
void register(String tag, Type customElementClass, {String? extendsTag}) {
return registerElement(tag, customElementClass, extendsTag: extendsTag);
}
/**
* Static factory designed to expose `visibilitychange` events to event
* handlers that are not necessarily instances of [Document].

View file

@ -1,120 +0,0 @@
// 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.
library attribute_changed_callback_test;
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class A extends HtmlElement {
static final tag = 'x-a';
factory A() => new Element.tag(tag) as A;
A.created() : super.created();
static var attributeChangedInvocations = 0;
void attributeChanged(name, oldValue, newValue) {
attributeChangedInvocations++;
}
}
class B extends HtmlElement {
static final tag = 'x-b';
factory B() => new Element.tag(tag) as B;
B.created() : super.created() {
invocations.add('created');
}
static var invocations = [];
Completer? completer;
void attributeChanged(name, oldValue, newValue) {
invocations.add('$name: $oldValue => $newValue');
if (completer != null) {
completer!.complete('value changed to $newValue');
completer = null;
}
}
}
// Pump custom events polyfill events.
void customElementsTakeRecords() {
if (js.context.hasProperty('CustomElements')) {
js.context['CustomElements'].callMethod('takeRecords');
}
}
main() async {
// Adapted from Blink's fast/dom/custom/attribute-changed-callback test.
await customElementsReady;
document.registerElement2(A.tag, {'prototype': A});
document.registerElement2(B.tag, {'prototype': B});
group('fully_supported', () {
test('transfer attribute changed callback', () {
var element = new A();
element.attributes['a'] = 'b';
expect(A.attributeChangedInvocations, 1);
});
test('add, change and remove an attribute', () {
var b = new B();
B.invocations = [];
b.attributes['data-s'] = 't';
expect(B.invocations, ['data-s: null => t']);
b.attributes['data-v'] = 'w';
B.invocations = [];
b.attributes['data-v'] = 'x';
expect(B.invocations, ['data-v: w => x']);
B.invocations = [];
b.attributes['data-v'] = 'x';
expect(B.invocations, []);
b.attributes.remove('data-v');
expect(B.invocations, ['data-v: x => null']);
});
test('add, change ID', () {
B.invocations = [];
var b = new B();
var completer = new Completer();
b.completer = completer;
b.id = 'x';
return completer.future
.then((_) => expect(B.invocations, ['created', 'id: null => x']))
.then((_) {
B.invocations = [];
var secondCompleter = new Completer();
b.completer = secondCompleter;
b.attributes.remove('id');
return secondCompleter.future;
}).then((_) => expect(B.invocations, ['id: x => null']));
});
});
group('unsupported_on_polyfill', () {
// If these tests start passing, don't remove the status suppression. Move
// the tests to the fullYy_supported group.
test('add, change classes', () {
var b = new B();
B.invocations = [];
b.classes.toggle('u');
expect(B.invocations, ['class: null => u']);
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> attribute_changed_callback_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running attribute_changed_callback_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,296 +0,0 @@
// 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.
library created_callback_test;
import 'dart:html';
import 'dart:js' as js;
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class A extends HtmlElement {
static final tag = 'x-a';
factory A() => new Element.tag(tag) as A;
A.created() : super.created() {
createdInvocations++;
}
static int createdInvocations = 0;
}
class B extends HtmlElement {
static final tag = 'x-b';
factory B() => new Element.tag(tag) as B;
B.created() : super.created();
}
class C extends HtmlElement {
static final tag = 'x-c';
factory C() => new Element.tag(tag) as C;
C.created() : super.created() {
createdInvocations++;
if (this.id != 'u') {
return;
}
var t = div.querySelector('#t');
var v = div.querySelector('#v');
var w = div.querySelector('#w');
expect(querySelector('x-b:not(:unresolved)'), this);
expect(querySelectorAll(':unresolved'), [v, w]);
// As per:
// http://www.w3.org/TR/2013/WD-custom-elements-20130514/#serializing-and-parsing
// creation order is t, u, v, w (postorder).
expect(t is C, isTrue);
// Note, this is different from JavaScript where this would be false.
expect(v is C, isTrue);
}
static int createdInvocations = 0;
static var div;
}
main() async {
// Adapted from Blink's
// fast/dom/custom/created-callback test.
await customElementsReady;
document.registerElement2(B.tag, {'prototype': B});
document.registerElement2(C.tag, {'prototype': C});
ErrorConstructorElement.register();
test('transfer created callback', () {
document.registerElement2(A.tag, {'prototype': A as dynamic});
var x = new A();
expect(A.createdInvocations, 1);
});
test('unresolved and created callback timing', () {
var div = new DivElement();
C.div = div;
div.setInnerHtml("""
<x-c id="t"></x-c>
<x-b id="u"></x-b>
<x-c id="v"></x-c>
<x-b id="w"></x-b>
""", treeSanitizer: NodeTreeSanitizer.trusted);
upgradeCustomElements(div);
expect(C.createdInvocations, 2);
expect(div.querySelector('#w') is B, isTrue);
});
test('nesting of constructors', NestedElement.test);
test('access while upgrading gets unupgraded element',
AccessWhileUpgradingElement.test);
test('cannot call created constructor', () {
expect(() {
new B.created();
}, throws);
});
test('cannot register without created', () {
expect(() {
document.registerElement2(
MissingCreatedElement.tag, {'prototype': MissingCreatedElement});
}, throws);
});
test('throw on createElement does not upgrade', () {
ErrorConstructorElement.callCount = 0;
var e;
expectGlobalError(() {
e = new Element.tag(ErrorConstructorElement.tag);
});
expect(ErrorConstructorElement.callCount, 1);
expect(e is HtmlElement, isTrue);
expect(e is ErrorConstructorElement, isFalse);
var dummy = new DivElement();
dummy.append(e);
e = dummy.firstChild;
expect(ErrorConstructorElement.callCount, 1);
});
test('throw on innerHtml does not upgrade', () {
ErrorConstructorElement.callCount = 0;
var dummy = new DivElement();
var tag = ErrorConstructorElement.tag;
expectGlobalError(() {
dummy.setInnerHtml('<$tag></$tag>',
treeSanitizer: NodeTreeSanitizer.trusted);
});
expect(ErrorConstructorElement.callCount, 1);
var e = dummy.firstChild;
// Accessing should not re-run the constructor.
expect(ErrorConstructorElement.callCount, 1);
expect(e is HtmlElement, isTrue);
expect(e is ErrorConstructorElement, isFalse);
});
test('cannot register created with params', () {
expect(() {
document.registerElement2(
'x-created-with-params', {'prototype': CreatedWithParametersElement});
}, throws);
});
test('created cannot be called from nested constructor',
NestedCreatedConstructorElement.test);
// TODO(vsm): Port additional test from upstream here:
// http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/dom/custom/created-callback.html?r1=156141&r2=156185
}
class NestedElement extends HtmlElement {
static final tag = 'x-nested';
final Element b = new B();
factory NestedElement() => new Element.tag(tag) as NestedElement;
NestedElement.created() : super.created();
static void register() {
document.registerElement2(tag, {'prototype': NestedElement});
}
static void test() {
register();
var e = new NestedElement();
expect(e.b, isNotNull);
expect(e.b is B, isTrue);
expect(e is NestedElement, isTrue);
}
}
class AccessWhileUpgradingElement extends HtmlElement {
static final tag = 'x-access-while-upgrading';
static late Element upgradingContext;
static late Element upgradingContextChild;
final foo = runInitializerCode();
factory AccessWhileUpgradingElement() =>
new Element.tag(tag) as AccessWhileUpgradingElement;
AccessWhileUpgradingElement.created() : super.created();
static runInitializerCode() {
upgradingContextChild = upgradingContext.firstChild as Element;
return 666;
}
static void register() {
document.registerElement2(tag, {'prototype': AccessWhileUpgradingElement});
}
static void test() {
register();
upgradingContext = new DivElement();
upgradingContext.setInnerHtml('<$tag></$tag>',
treeSanitizer: new NullTreeSanitizer());
dynamic child = upgradingContext.firstChild;
expect(child.foo, 666);
expect(upgradingContextChild is HtmlElement, isFalse);
expect(upgradingContextChild is AccessWhileUpgradingElement, isFalse,
reason: 'Elements accessed while upgrading should not be upgraded.');
}
}
class MissingCreatedElement extends HtmlElement {
static final tag = 'x-missing-created';
factory MissingCreatedElement() =>
new Element.tag(tag) as MissingCreatedElement;
}
class ErrorConstructorElement extends HtmlElement {
static final tag = 'x-throws-in-constructor';
static int callCount = 0;
factory ErrorConstructorElement() =>
new Element.tag(tag) as ErrorConstructorElement;
ErrorConstructorElement.created() : super.created() {
++callCount;
throw new Exception('Just messin with ya');
}
static void register() {
document.registerElement2(tag, {'prototype': ErrorConstructorElement});
}
}
class NestedCreatedConstructorElement extends HtmlElement {
static final tag = 'x-nested-created-constructor';
// Should not be able to call this here.
final B b = constructB();
static B? constructedB;
factory NestedCreatedConstructorElement() =>
new Element.tag(tag) as NestedCreatedConstructorElement;
NestedCreatedConstructorElement.created() : super.created();
static void register() {
document
.registerElement2(tag, {'prototype': NestedCreatedConstructorElement});
}
// Try to run the created constructor, and record the results.
static constructB() {
// This should throw an exception.
constructedB = new B.created();
return constructedB;
}
static void test() {
register();
// Exception should have occurred on upgrade.
var e;
expectGlobalError(() {
e = new Element.tag(tag);
});
expect(e is NestedCreatedConstructorElement, isFalse);
expect(e is HtmlElement, isTrue);
// Should not have been set.
expect(constructedB, isNull);
}
}
class CreatedWithParametersElement extends HtmlElement {
CreatedWithParametersElement.created(ignoredParam) : super.created();
}
void expectGlobalError(Function test) {
js.context['testExpectsGlobalError'] = true;
try {
test();
} catch (e) {
rethrow;
} finally {
js.context['testExpectsGlobalError'] = false;
}
var errors = js.context['testSuppressedGlobalErrors'];
expect(errors['length'], 1);
// Clear out the errors;
js.context['testSuppressedGlobalErrors']['length'] = 0;
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> created_callback_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running created_callback_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,145 +0,0 @@
// 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.
library document_register_basic_test;
import 'dart:html';
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class Foo extends HtmlElement {
static final tag = 'x-foo';
factory Foo() => new Element.tag(tag) as Foo;
Foo.created() : super.created();
get thisIsACustomClass => true;
}
class Bar extends HtmlElement {
static final tag = 'x-bar';
factory Bar() => new Element.tag(tag) as Bar;
Bar.created() : super.created();
get thisIsACustomClass => true;
}
class Baz extends Foo {
static final tag = 'x-baz';
factory Baz() => new Element.tag(tag) as Baz;
Baz.created() : super.created();
get thisIsAlsoACustomClass => true;
}
class BadB {}
abstract class BadC extends HtmlElement {
BadC.created() : super.created();
}
main() async {
// Adapted from Blink's fast/dom/custom/document-register-basic test.
await customElementsReady;
test('Testing document.registerElement2() basic behaviors', () {
document.registerElement2(Foo.tag, {'prototype': Foo});
// Cannot register an existing dart:html type.
expect(
() => document.registerElement2('x-bad-a', {'prototype': HtmlElement}),
throws);
// Invalid user type. Doesn't inherit from HtmlElement.
expect(() => document.registerElement2('x-bad-b', {'prototype': BadB}),
throws);
// Cannot register abstract class.
expect(() => document.registerElement2('x-bad-c', {'prototype': BadC}),
throws);
// Not a type.
expect(() => document.registerElement2('x-bad-d', {'prototype': null}),
throws);
// Cannot register system type.
expect(() => document.registerElement2('x-bad-e', {'prototype': Object}),
throws);
// Constructor initiated instantiation
var createdFoo = new Foo();
expect(createdFoo.thisIsACustomClass, isTrue);
// Dart type correctness
expect(createdFoo is HtmlElement, isTrue);
expect(createdFoo is Foo, isTrue);
expect(createdFoo.runtimeType, Foo);
// Native getter
expect(createdFoo.tagName, "X-FOO");
// Native setter
createdFoo.innerHtml = "Hello";
expect(createdFoo.text, "Hello");
// Native method
var childDiv = new DivElement();
createdFoo.append(childDiv);
expect(createdFoo.lastChild, childDiv);
// Parser initiated instantiation
var container = new DivElement()..id = "container";
document.body!.append(container);
container.setInnerHtml("<x-foo></x-foo>",
treeSanitizer: new NullTreeSanitizer());
upgradeCustomElements(container);
var parsedFoo = container.firstChild;
expect(parsedFoo is Foo, isTrue);
expect((parsedFoo as Foo).tagName, "X-FOO");
// Ensuring the wrapper is retained
var someProperty = new Expando();
someProperty[parsedFoo] = "hello";
expect(container.firstChild, parsedFoo);
expect(someProperty[container.firstChild!], someProperty[parsedFoo]);
// Having another constructor
document.registerElement2(Bar.tag, {'prototype': Bar});
var createdBar = new Bar();
expect(createdBar is Bar, isTrue);
expect(createdBar is Foo, isFalse);
expect(createdBar.tagName, "X-BAR");
// Having a subclass
document.registerElement2(Baz.tag, {'prototype': Baz});
var createdBaz = new Baz();
expect(createdBaz.tagName, "X-BAZ");
expect(createdBaz.thisIsACustomClass, isTrue);
expect(createdBaz.thisIsAlsoACustomClass, isTrue);
// With irregular cases
var createdUpperBar = new Element.tag("X-BAR");
var createdMixedBar = new Element.tag("X-Bar");
expect(createdUpperBar is Bar, isTrue);
expect(createdUpperBar.tagName, "X-BAR");
expect(createdMixedBar is Bar, isTrue);
expect(createdMixedBar.tagName, "X-BAR");
container.setInnerHtml("<X-BAR></X-BAR><X-Bar></X-Bar>",
treeSanitizer: new NullTreeSanitizer());
upgradeCustomElements(container);
expect(container.firstChild is Bar, isTrue);
expect((container.firstChild as Bar).tagName, "X-BAR");
expect(container.lastChild is Bar, isTrue);
expect((container.lastChild as Bar).tagName, "X-BAR");
// Constructors shouldn't interfere with each other
expect((new Foo()).tagName, "X-FOO");
expect((new Bar()).tagName, "X-BAR");
expect((new Baz()).tagName, "X-BAZ");
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> document_register_basic_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running document_register_basic_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,27 +0,0 @@
// Copyright (c) 2020, 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.
import 'dart:html';
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
main() async {
await customElementsReady;
test('can register custom template with webcomponents-lite polyfill', () {
document.registerElement2(
'my-element', {'prototype': MyElement, 'extends': 'template'});
dynamic e = new Element.tag('template', 'my-element');
document.body!.append(e);
expect(e is TemplateElement, isTrue);
expect(e.method(), 'value');
});
}
class MyElement extends TemplateElement {
MyElement.created() : super.created();
method() => 'value';
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> document_register_basic_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents-lite.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running document_register_basic_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,323 +0,0 @@
// 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.
import 'dart:html';
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class Foo extends HtmlElement {
static const tag = 'x-foo';
static final List<String> outerHtmlStrings = [
'<x-foo></x-foo>',
'<?XML:NAMESPACE PREFIX = PUBLIC NS = "URN:COMPONENT" /><x-foo></x-foo>'
];
factory Foo() => new Element.tag(tag) as Foo;
Foo.created() : super.created();
}
class Bar extends InputElement {
static const tag = 'x-bar';
static const outerHtmlString = '<input is="x-bar">';
factory Bar() => new Element.tag('input', tag) as Bar;
Bar.created() : super.created();
}
class Baz extends Foo {
static const tag = 'x-baz';
static final List<String> outerHtmlStrings = [
'<x-baz></x-baz>',
'<?XML:NAMESPACE PREFIX = PUBLIC NS = "URN:COMPONENT" /><x-baz></x-baz>'
];
factory Baz() => new Element.tag(tag) as Baz;
Baz.created() : super.created();
}
class Qux extends Bar {
static const tag = 'x-qux';
factory Qux() => new Element.tag('input', tag) as Qux;
Qux.created() : super.created();
}
class FooBad extends DivElement {
static const tag = 'x-foo';
factory FooBad() => new Element.tag('div', tag) as FooBad;
FooBad.created() : super.created();
}
class MyCanvas extends CanvasElement {
static const tag = 'my-canvas';
factory MyCanvas() => new Element.tag('canvas', tag) as MyCanvas;
MyCanvas.created() : super.created();
void fillAsRed() {
width = 100;
height = 100;
CanvasRenderingContext2D context =
this.getContext('2d') as CanvasRenderingContext2D;
context.fillStyle = 'red';
context.fillRect(0, 0, width!, height!);
context.fill();
var data = context.getImageData(0, 0, 1, 1).data;
expect(data, [255, 0, 0, 255]);
}
}
class CustomDiv extends DivElement {
CustomDiv.created() : super.created();
}
class CustomCustomDiv extends CustomDiv {
static const tag = 'custom-custom';
CustomCustomDiv.created() : super.created();
}
main() async {
// Adapted from Blink's fast/dom/custom/document-register-type-extension test.
var testForm = new FormElement()..id = 'testForm';
document.body!.append(testForm);
var isFormControl = (element) {
testForm.append(element);
return element.form == testForm;
};
var registeredTypes = false;
void registerTypes() {
if (registeredTypes) {
return;
}
registeredTypes = true;
document.registerElement2(Foo.tag, {'prototype': Foo});
document.registerElement2(Bar.tag, {'prototype': Bar, 'extends': 'input'});
document.registerElement2(Baz.tag, {'prototype': Baz});
document.registerElement2(Qux.tag, {'prototype': Qux, 'extends': 'input'});
document.registerElement2(
MyCanvas.tag, {'prototype': MyCanvas, 'extends': 'canvas'});
document.registerElement2(
CustomCustomDiv.tag, {'prototype': CustomCustomDiv, 'extends': 'div'});
}
await customElementsReady;
group('registration', () {
test('cannot register twice', () {
registerTypes();
expect(
() => document.registerElement2(
FooBad.tag, {'prototype': Foo, 'extends': 'div'}),
throws);
});
test('cannot register for non-matching tag', () {
registerTypes();
expect(() {
document.registerElement2(
'x-input-div', {'prototype': Bar, 'extends': 'div'});
}, throws);
});
test('cannot register type extension for custom tag', () {
registerTypes();
expect(() {
document
.registerElement2('x-custom-tag', {'prototype': CustomCustomDiv});
}, throws);
});
});
group('construction', () {
group('constructors', () {
registerTypes();
test('custom tag', () {
var fooNewed = new Foo();
expect(fooNewed.outerHtml, anyOf(Foo.outerHtmlStrings));
expect(fooNewed is Foo, isTrue);
expect(fooNewed is HtmlElement, isTrue);
expect(fooNewed is UnknownElement, isFalse);
});
test('type extension', () {
var barNewed = new Bar();
expect(barNewed.outerHtml, Bar.outerHtmlString);
expect(barNewed is Bar, isTrue);
expect(barNewed is InputElement, isTrue);
expect(isFormControl(barNewed), isTrue);
});
test('custom tag deriving from custom tag', () {
var bazNewed = new Baz();
expect(bazNewed.outerHtml, anyOf(Baz.outerHtmlStrings));
expect(bazNewed is Baz, isTrue);
expect(bazNewed is HtmlElement, isTrue);
expect(bazNewed is UnknownElement, isFalse);
});
test('type extension deriving from custom tag', () {
var quxNewed = new Qux();
var quxOuterHtml = '<input is="x-qux">';
expect(quxNewed.outerHtml, quxOuterHtml);
expect(quxNewed is Qux, isTrue);
expect(quxNewed is InputElement, isTrue);
expect(isFormControl(quxNewed), isTrue);
});
});
group('single-parameter createElement', () {
registerTypes();
test('custom tag', () {
var fooCreated = new Element.tag('x-foo');
expect(fooCreated.outerHtml, anyOf(Foo.outerHtmlStrings));
expect(fooCreated is Foo, isTrue);
});
test('does not upgrade type extension', () {
var barCreated = new Element.tag('x-bar');
expect(barCreated is Bar, isFalse);
expect(barCreated.outerHtml, "<x-bar></x-bar>");
expect(barCreated is UnknownElement, isFalse);
expect(barCreated is HtmlElement, isTrue);
});
test('custom tag deriving from custom tag', () {
var bazCreated = new Element.tag('x-baz');
expect(bazCreated.outerHtml, anyOf(Baz.outerHtmlStrings));
expect(bazCreated is Baz, isTrue);
expect(bazCreated is UnknownElement, isFalse);
});
test('type extension deriving from custom tag', () {
var quxCreated = new Element.tag('x-qux');
expect(quxCreated.outerHtml, "<x-qux></x-qux>");
expect(quxCreated is Qux, isFalse);
expect(quxCreated is UnknownElement, isFalse);
expect(quxCreated is HtmlElement, isTrue);
});
});
group('createElement with type extension', () {
registerTypes();
test('does not upgrade extension of custom tag', () {
var divFooCreated = new Element.tag("div", Foo.tag);
expect(divFooCreated.outerHtml, '<div is="x-foo"></div>');
expect(divFooCreated is Foo, isFalse);
expect(divFooCreated is DivElement, isTrue);
});
test('upgrades valid extension', () {
var inputBarCreated = new Element.tag("input", Bar.tag);
expect(inputBarCreated.outerHtml, Bar.outerHtmlString);
expect(inputBarCreated is Bar, isTrue);
expect(inputBarCreated is UnknownElement, isFalse);
expect(isFormControl(inputBarCreated), isTrue);
});
test('type extension of incorrect tag', () {
var divBarCreated = new Element.tag("div", Bar.tag);
expect(divBarCreated.outerHtml, '<div is="x-bar"></div>');
expect(divBarCreated is Bar, isFalse);
expect(divBarCreated is DivElement, isTrue);
});
test('incorrect extension of custom tag', () {
var fooBarCreated = new Element.tag(Foo.tag, Bar.tag);
expect(
fooBarCreated.outerHtml,
anyOf([
'<x-foo is="x-bar"></x-foo>',
'<?XML:NAMESPACE PREFIX = PUBLIC NS = "URN:COMPONENT" />'
'<x-foo is="x-bar"></x-foo>'
]));
expect(fooBarCreated is Foo, isTrue);
});
test('incorrect extension of type extension', () {
var barFooCreated = new Element.tag(Bar.tag, Foo.tag);
expect(barFooCreated.outerHtml, '<x-bar is="x-foo"></x-bar>');
expect(barFooCreated is UnknownElement, isFalse);
expect(barFooCreated is HtmlElement, isTrue);
});
test('null type extension', () {
var fooCreatedNull = new Element.tag(Foo.tag, null);
expect(fooCreatedNull.outerHtml, anyOf(Foo.outerHtmlStrings));
expect(fooCreatedNull is Foo, isTrue);
});
test('empty type extension', () {
var fooCreatedEmpty = new Element.tag(Foo.tag, "");
expect(fooCreatedEmpty.outerHtml, anyOf(Foo.outerHtmlStrings));
expect(fooCreatedEmpty is Foo, isTrue);
});
});
});
group('namespaces', () {
test('createElementNS', () {
registerTypes();
var fooCreatedNS = document.createElementNS(
"http://www.w3.org/1999/xhtml", Foo.tag, null);
expect(fooCreatedNS.outerHtml, anyOf(Foo.outerHtmlStrings));
expect(fooCreatedNS is Foo, isTrue);
var barCreatedNS = document.createElementNS(
"http://www.w3.org/1999/xhtml", "input", Bar.tag);
expect(barCreatedNS.outerHtml, Bar.outerHtmlString);
expect(barCreatedNS is Bar, isTrue);
expect(isFormControl(barCreatedNS), isTrue);
expect(
() => document.createElementNS(
'http://example.com/2013/no-such-namespace', 'xml:lang', 'x-bar'),
throws);
});
});
group('parsing', () {
test('parsing', () {
registerTypes();
createElementFromHtml(html) {
var container = new DivElement()
..setInnerHtml(html, treeSanitizer: new NullTreeSanitizer());
upgradeCustomElements(container);
return container.firstChild;
}
var fooParsed = createElementFromHtml('<x-foo>');
expect(fooParsed is Foo, isTrue);
var barParsed = createElementFromHtml('<input is=x-bar>');
expect(barParsed is Bar, isTrue);
expect(isFormControl(barParsed), isTrue);
var divFooParsed = createElementFromHtml('<div is=x-foo>');
expect(divFooParsed is Foo, isFalse);
expect(divFooParsed is DivElement, isTrue);
var namedBarParsed = createElementFromHtml('<x-bar>');
expect(namedBarParsed is Bar, isFalse);
// Polyfill does not convert parsed unregistered custom elements to
// HtmlElement.
// expect(namedBarParsed is UnknownElement, isFalse);
expect(namedBarParsed is HtmlElement, isTrue);
var divBarParsed = createElementFromHtml('<div is=x-bar>');
expect(divBarParsed is Bar, isFalse);
expect(divBarParsed is DivElement, isTrue);
});
});
group('functional', () {
test('canvas', () {
registerTypes();
var canvas = new MyCanvas();
canvas.fillAsRed();
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> document_register_type_extensions_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running document_register_type_extensions_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,53 +0,0 @@
// Copyright (c) 2014, 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.
import 'dart:html';
import 'dart:js' as js;
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class FooElement extends HtmlElement {
static final tag = 'x-foo';
final int initializedField = 666;
late js.JsObject _proxy = new js.JsObject.fromBrowserObject(this);
factory FooElement() => new Element.tag(tag) as FooElement;
FooElement.created() : super.created();
String doSomething() => _proxy.callMethod('doSomething');
bool get fooCreated => _proxy['fooCreated'];
}
main() async {
await customElementsReady;
var upgrader = document.createElementUpgrader(FooElement);
js.context['upgradeListener'] = (e) {
upgrader.upgrade(e);
};
test('cannot create upgrader for interfaces', () {
expect(() {
// TODO(srujzs): Determine if this should be a static error.
document.createElementUpgrader(HtmlElementInterface);
}, throws);
});
test('cannot upgrade interfaces', () {
expect(() {
upgrader.upgrade(new HtmlElementInterface());
// ^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT
}, throws);
});
}
class HtmlElementInterface implements HtmlElement {
// ^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER
HtmlElementInterface.created();
}

View file

@ -1,104 +0,0 @@
// Copyright (c) 2014, 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.
import 'dart:html';
import 'dart:js' as js;
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class FooElement extends HtmlElement {
static final tag = 'x-foo';
final int initializedField = 666;
late js.JsObject _proxy = new js.JsObject.fromBrowserObject(this);
factory FooElement() => new Element.tag(tag) as FooElement;
FooElement.created() : super.created();
String doSomething() => _proxy.callMethod('doSomething');
bool get fooCreated => _proxy['fooCreated'];
}
main() async {
await customElementsReady;
var upgrader = document.createElementUpgrader(FooElement);
js.context['upgradeListener'] = (e) {
upgrader.upgrade(e);
};
document.registerElement2('custom-element', {'prototype': CustomElement});
test('created gets proxied', () {
var element = document.createElement(FooElement.tag);
expect(element is FooElement, isTrue);
expect((element as FooElement).initializedField, 666);
expect(element.text, 'constructed');
js.context.callMethod('validateIsFoo', [element]);
expect(element.doSomething(), 'didSomething');
expect(element.fooCreated, true);
});
test('dart constructor works', () {
var element = new FooElement();
expect(element is FooElement, isTrue);
expect(element.text, 'constructed');
js.context.callMethod('validateIsFoo', [element]);
expect(element.doSomething(), 'didSomething');
});
test('cannot upgrade more than once', () {
var fooElement = new FooElement();
expect(() {
upgrader.upgrade(fooElement);
}, throws);
});
test('cannot upgrade non-matching elements', () {
expect(() {
upgrader.upgrade(new DivElement());
}, throws);
});
test('cannot upgrade custom elements', () {
var custom = new CustomElement();
expect(() {
upgrader.upgrade(custom);
}, throws);
});
test('can upgrade with extendsTag', () {
var upgrader = document.createElementUpgrader(CustomDiv, extendsTag: 'div');
var div = new DivElement();
var customDiv = upgrader.upgrade(div);
expect(customDiv is CustomDiv, isTrue);
var htmlElement = document.createElement('not-registered');
expect(() {
upgrader.upgrade(htmlElement);
}, throws);
});
test('cannot create upgrader for built-in types', () {
expect(() {
document.createElementUpgrader(HtmlElement);
}, throws);
});
}
class CustomDiv extends DivElement {
CustomDiv.created() : super.created();
}
class CustomElement extends HtmlElement {
factory CustomElement() =>
document.createElement('custom-element') as CustomElement;
CustomElement.created() : super.created();
}

View file

@ -1,49 +0,0 @@
<!DOCTYPE html>
<meta name="dart.unittest" content="full-stack-traces">
<title> element_upgrade_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
<body>
<h1> Running element_upgrade_test </h1>
<script>
var Foo = function() {};
Foo.prototype = Object.create(HTMLElement.prototype);
Foo.prototype.createdCallback = function() {
this.fooCreated = true;
this.textContent = 'constructed';
// Tell the Dart side that this was created.
// For testing purposes, for real code this would use a different mechanism.
window.upgradeListener(this);
};
Foo.prototype.doSomething = function() {
this.textContent = 'didSomething';
return 'didSomething';
};
Foo = document.registerElement('x-foo', Foo);
function validateIsFoo(element) {
if (!(element instanceof Foo)) {
throw Error('Element is not a Foo');
}
if (!element.fooCreated) {
throw Error('Expected fooCreated to be set');
}
}
</script>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>

View file

@ -1,57 +0,0 @@
// Copyright (c) 2020 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.
library entered_left_view_test;
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'entered_left_view_util.dart';
import 'package:async_helper/async_minitest.dart';
import '../utils.dart';
main() async {
await setupFunc();
group('disconnected_subtree', () {
var div = new DivElement();
setUp() {
invocations = [];
}
test('Enters a disconnected subtree of DOM', () {
setUp();
div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
upgradeCustomElements(div);
expect(invocations, ['created'],
reason: 'the attached callback should not be invoked when inserted '
'into a disconnected subtree');
});
test('Leaves a disconnected subtree of DOM', () {
setUp();
div.innerHtml = '';
expect(invocations, [],
reason:
'the detached callback should not be invoked when removed from a '
'disconnected subtree');
});
test('Enters a document with a view as a constituent of a subtree', () {
setUp();
div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
upgradeCustomElements(div);
invocations = [];
document.body!.append(div);
customElementsTakeRecords();
expect(invocations, ['attached'],
reason:
'the attached callback should be invoked when inserted into a '
'document with a view as part of a subtree');
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> disconnected_subtree_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running disconnected_subtree_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,66 +0,0 @@
// Copyright (c) 2020 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.
library entered_left_view_test;
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'entered_left_view_util.dart';
import 'package:async_helper/async_minitest.dart';
import '../utils.dart';
main() async {
await setupFunc();
group('standard_events', () {
var a;
setUp() {
invocations = [];
}
test('Created', () {
setUp();
a = new Element.tag('x-a');
expect(invocations, ['created']);
});
test('attached', () {
setUp();
document.body!.append(a);
customElementsTakeRecords();
expect(invocations, ['attached']);
});
test('detached', () {
setUp();
a.remove();
customElementsTakeRecords();
expect(invocations, ['detached']);
});
var div = new DivElement();
test('nesting does not trigger attached', () {
setUp();
div.append(a);
customElementsTakeRecords();
expect(invocations, []);
});
test('nested entering triggers attached', () {
setUp();
document.body!.append(div);
customElementsTakeRecords();
expect(invocations, ['attached']);
});
test('nested leaving triggers detached', () {
setUp();
div.remove();
customElementsTakeRecords();
expect(invocations, ['detached']);
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> entered_left_view_standard_events_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running entered_left_view_standard_events_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,75 +0,0 @@
// 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.
library entered_left_view_test;
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'package:async_helper/async_minitest.dart';
import '../utils.dart';
var invocations = [];
class Foo extends HtmlElement {
Foo.created() : super.created() {
invocations.add('created');
}
void attached() {
invocations.add('attached');
}
void enteredView() {
// Deprecated name. Should never be called since we override "attached".
invocations.add('enteredView');
}
void detached() {
invocations.add('detached');
}
void leftView() {
// Deprecated name. Should never be called since we override "detached".
invocations.add('leftView');
}
void attributeChanged(String name, String oldValue, String newValue) {
invocations.add('attribute changed');
}
}
// Test that the deprecated callbacks still work.
class FooOldCallbacks extends HtmlElement {
FooOldCallbacks.created() : super.created() {
invocations.add('created');
}
void enteredView() {
invocations.add('enteredView');
}
void leftView() {
invocations.add('leftView');
}
void attributeChanged(String name, String oldValue, String newValue) {
invocations.add('attribute changed');
}
}
var docA = document;
var docB = document.implementation!.createHtmlDocument('');
var nullSanitizer = new NullTreeSanitizer();
setupFunc() {
// Adapted from Blink's
// fast/dom/custom/attached-detached-document.html test.
return customElementsReady.then((_) {
document.registerElement2('x-a', {'prototype': Foo});
document.registerElement2('x-a-old', {'prototype': FooOldCallbacks});
});
}

View file

@ -1,71 +0,0 @@
// Copyright (c) 2020 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.
library entered_left_view_test;
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'entered_left_view_util.dart';
import 'package:async_helper/async_minitest.dart';
import '../utils.dart';
main() async {
await setupFunc();
group('shadow_dom', () {
var div;
var s;
setUp() {
invocations = [];
div = new DivElement();
s = div.createShadowRoot();
}
tearDown() {
customElementsTakeRecords();
}
test('Created in Shadow DOM that is not in a document', () {
setUp();
s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
upgradeCustomElements(s);
expect(invocations, ['created'],
reason: 'the attached callback should not be invoked when entering a '
'Shadow DOM subtree not in the document');
tearDown();
});
test('Leaves Shadow DOM that is not in a document', () {
setUp();
s.innerHtml = '';
expect(invocations, [],
reason: 'the detached callback should not be invoked when leaving a '
'Shadow DOM subtree not in the document');
tearDown();
});
test('Enters a document with a view as a constituent of Shadow DOM', () {
setUp();
s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
upgradeCustomElements(s);
document.body!.append(div);
customElementsTakeRecords();
expect(invocations, ['created', 'attached'],
reason: 'the attached callback should be invoked when inserted into '
'a document with a view as part of Shadow DOM');
div.remove();
customElementsTakeRecords();
expect(invocations, ['created', 'attached', 'detached'],
reason: 'the detached callback should be invoked when removed from a '
'document with a view as part of Shadow DOM');
tearDown();
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> shadow_dom_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running shadow_dom_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,67 +0,0 @@
// Copyright (c) 2020 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.
library entered_left_view_test;
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'entered_left_view_util.dart';
import 'package:async_helper/async_minitest.dart';
import '../utils.dart';
main() async {
await setupFunc();
// TODO(jmesserly): remove after deprecation period.
group('standard_events_old_callback_names', () {
var a;
setUp() {
invocations = [];
}
test('Created', () {
setUp();
a = new Element.tag('x-a-old');
expect(invocations, ['created']);
});
test('enteredView', () {
setUp();
document.body!.append(a);
customElementsTakeRecords();
expect(invocations, ['enteredView']);
});
test('leftView', () {
setUp();
a.remove();
customElementsTakeRecords();
expect(invocations, ['leftView']);
});
var div = new DivElement();
test('nesting does not trigger enteredView', () {
setUp();
div.append(a);
customElementsTakeRecords();
expect(invocations, []);
});
test('nested entering triggers enteredView', () {
setUp();
document.body!.append(div);
customElementsTakeRecords();
expect(invocations, ['enteredView']);
});
test('nested leaving triggers leftView', () {
setUp();
div.remove();
customElementsTakeRecords();
expect(invocations, ['leftView']);
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> standard_events_old_callback_names_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running standard_events_old_callback_names_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,79 +0,0 @@
// Copyright (c) 2020 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.
library entered_left_view_test;
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'entered_left_view_util.dart';
import 'package:async_helper/async_minitest.dart';
import '../utils.dart';
main() async {
await setupFunc();
group('viewless_document', () {
var a;
setUp() {
invocations = [];
}
test('Created, owned by a document without a view', () {
setUp();
a = docB.createElement('x-a');
expect(a.ownerDocument, docB,
reason: 'new instance should be owned by the document the definition '
'was registered with');
expect(invocations, ['created'],
reason: 'calling the constructor should invoke the created callback');
});
test('Entered document without a view', () {
setUp();
docB.body!.append(a);
expect(invocations, [],
reason: 'attached callback should not be invoked when entering a '
'document without a view');
});
test('Attribute changed in document without a view', () {
setUp();
a.setAttribute('data-foo', 'bar');
expect(invocations, ['attribute changed'],
reason: 'changing an attribute should invoke the callback, even in a '
'document without a view');
});
test('Entered document with a view', () {
setUp();
document.body!.append(a);
customElementsTakeRecords();
expect(invocations, ['attached'],
reason:
'attached callback should be invoked when entering a document '
'with a view');
});
test('Left document with a view', () {
setUp();
a.remove();
customElementsTakeRecords();
expect(invocations, ['detached'],
reason: 'detached callback should be invoked when leaving a document '
'with a view');
});
test('Created in a document without a view', () {
setUp();
docB.body!.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
upgradeCustomElements(docB.body!);
expect(invocations, ['created'],
reason: 'only created callback should be invoked when parsing a '
'custom element in a document without a view');
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> viewless_document_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running viewless_document_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,24 +0,0 @@
// 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.
// Regression test for CL 194523002.
import 'dart:html';
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class A extends HtmlElement {
static final tag = 'x-a';
factory A() => new Element.tag(tag) as A;
A.created() : super.created();
}
main() async {
// Adapted from Blink's
// fast/dom/custom/constructor-calls-created-synchronously test.
await customElementsReady;
document.registerElement2(A.tag, {'prototype': A});
}

View file

@ -1,224 +0,0 @@
// Copyright (c) 2020, 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.
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'dart:typed_data';
import 'package:expect/minitest.dart';
/**
* Verifies that [actual] has the same graph structure as [expected].
* Detects cycles and DAG structure in Maps and Lists.
*/
verifyGraph(expected, actual) {
var eItems = [];
var aItems = [];
message(path, reason) => path == ''
? reason
: reason == null ? "path: $path" : "path: $path, $reason";
walk(path, expected, actual) {
if (expected is String || expected is num || expected == null) {
expect(actual, equals(expected), reason: message(path, 'not equal'));
return;
}
// Cycle or DAG?
for (int i = 0; i < eItems.length; i++) {
if (identical(expected, eItems[i])) {
expect(actual, same(aItems[i]),
reason: message(path, 'missing back or side edge'));
return;
}
}
for (int i = 0; i < aItems.length; i++) {
if (identical(actual, aItems[i])) {
expect(expected, same(eItems[i]),
reason: message(path, 'extra back or side edge'));
return;
}
}
eItems.add(expected);
aItems.add(actual);
if (expected is Blob) {
expect(actual is Blob, isTrue, reason: '$actual is Blob');
expect(expected.type, equals(actual.type),
reason: message(path, '.type'));
expect(expected.size, equals(actual.size),
reason: message(path, '.size'));
return;
}
if (expected is ByteBuffer) {
expect(actual is ByteBuffer, isTrue, reason: '$actual is ByteBuffer');
expect(expected.lengthInBytes, equals(actual.lengthInBytes),
reason: message(path, '.lengthInBytes'));
// TODO(antonm): one can create a view on top of those
// and check if contents identical. Let's do it later.
return;
}
if (expected is DateTime) {
expect(actual is DateTime, isTrue, reason: '$actual is DateTime');
expect(expected.millisecondsSinceEpoch,
equals(actual.millisecondsSinceEpoch),
reason: message(path, '.millisecondsSinceEpoch'));
return;
}
if (expected is ImageData) {
expect(actual is ImageData, isTrue, reason: '$actual is ImageData');
expect(expected.width, equals(actual.width),
reason: message(path, '.width'));
expect(expected.height, equals(actual.height),
reason: message(path, '.height'));
walk('$path.data', expected.data, actual.data);
return;
}
if (expected is TypedData) {
expect(actual is TypedData, isTrue, reason: '$actual is TypedData');
walk('$path/.buffer', expected.buffer, actual.buffer);
expect(expected.offsetInBytes, equals(actual.offsetInBytes),
reason: message(path, '.offsetInBytes'));
expect(expected.lengthInBytes, equals(actual.lengthInBytes),
reason: message(path, '.lengthInBytes'));
// And also fallback to elements check below.
}
if (expected is List) {
expect(actual, predicate((v) => v is List),
reason: message(path, '$actual is List'));
expect(actual.length, expected.length,
reason: message(path, 'different list lengths'));
for (var i = 0; i < expected.length; i++) {
walk('$path[$i]', expected[i], actual[i]);
}
return;
}
if (expected is Map) {
expect(actual, predicate((v) => v is Map),
reason: message(path, '$actual is Map'));
for (var key in expected.keys) {
if (!actual.containsKey(key)) {
expect(false, isTrue, reason: message(path, 'missing key "$key"'));
}
walk('$path["$key"]', expected[key], actual[key]);
}
for (var key in actual.keys) {
if (!expected.containsKey(key)) {
expect(false, isTrue, reason: message(path, 'extra key "$key"'));
}
}
return;
}
expect(false, isTrue, reason: 'Unhandled type: $expected');
}
walk('', expected, actual);
}
/**
* Sanitizer which does nothing.
*/
class NullTreeSanitizer implements NodeTreeSanitizer {
void sanitizeTree(Node node) {}
}
/**
* Validate that two DOM trees are equivalent.
*/
void validateNodeTree(Node a, Node b, [String path = '']) {
path = '${path}${a.runtimeType}';
expect(a.nodeType, b.nodeType, reason: '$path nodeTypes differ');
expect(a.nodeValue, b.nodeValue, reason: '$path nodeValues differ');
expect(a.text, b.text, reason: '$path texts differ');
expect(a.nodes.length, b.nodes.length, reason: '$path nodes.lengths differ');
if (a is Element) {
Element bE = b as Element;
Element aE = a;
expect(aE.tagName, bE.tagName, reason: '$path tagNames differ');
expect(aE.attributes.length, bE.attributes.length,
reason: '$path attributes.lengths differ');
for (var key in aE.attributes.keys) {
expect(aE.attributes[key], bE.attributes[key],
reason: '$path attribute [$key] values differ');
}
}
for (var i = 0; i < a.nodes.length; ++i) {
validateNodeTree(a.nodes[i], b.nodes[i], '$path[$i].');
}
}
/**
* Upgrade all custom elements in the subtree which have not been upgraded.
*
* This is needed to cover timing scenarios which the custom element polyfill
* does not cover.
*/
void upgradeCustomElements(Node node) {
if (js.context.hasProperty('CustomElements') &&
js.context['CustomElements'].hasProperty('upgradeAll')) {
js.context['CustomElements'].callMethod('upgradeAll', [node]);
}
}
/**
* A future that completes once all custom elements in the initial HTML page
* have been upgraded.
*
* This is needed because the native implementation can update the elements
* while parsing the HTML document, but the custom element polyfill cannot,
* so it completes this future once all elements are upgraded.
*/
// TODO(jmesserly): rename to webComponentsReady to match the event?
Future customElementsReady = () {
if (_isReady) return new Future.value();
// Not upgraded. Wait for the polyfill to fire the WebComponentsReady event.
// Note: we listen on document (not on document.body) to allow this polyfill
// to be loaded in the HEAD element.
return document.on['WebComponentsReady'].first;
}();
// Return true if we are using the polyfill and upgrade is complete, or if we
// have native document.register and therefore the browser took care of it.
// Otherwise return false, including the case where we can't find the polyfill.
bool get _isReady {
// If we don't have dart:js, assume things are ready
if (js.context == null) return true;
var customElements = js.context['CustomElements'];
if (customElements == null) {
// Return true if native document.register, otherwise false.
// (Maybe the polyfill isn't loaded yet. Wait for it.)
return document.supportsRegisterElement;
}
return customElements['ready'] == true;
}
/**
* *Note* this API is primarily intended for tests. In other code it is better
* to write it in a style that works with or without the polyfill, rather than
* using this method.
*
* Synchronously trigger evaluation of pending lifecycle events, which otherwise
* need to wait for a [MutationObserver] to signal the changes in the polyfill.
* This method can be used to resolve differences in timing between native and
* polyfilled custom elements.
*/
void customElementsTakeRecords([Node? node]) {
var customElements = js.context['CustomElements'];
if (customElements == null) return;
customElements.callMethod('takeRecords', [node]);
}

View file

@ -1,43 +0,0 @@
// Copyright (c) 2015, 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.
library custom_elements_method_clash;
import 'dart:async';
import 'dart:html';
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class CustomElement extends HtmlElement {
factory CustomElement() => new Element.tag('x-custom') as CustomElement;
CustomElement.created() : super.created() {}
// Try to clash with native 'appendChild' method.
void appendChild() {
throw 'Gotcha!';
}
}
main() async {
await customElementsReady;
group('test', () {
test('test', () {
document.registerElement2('x-custom', {'prototype': CustomElement});
CustomElement custom = new CustomElement();
document.body!.children.add(custom);
// Will call appendChild in JS.
custom.children.add(new DivElement()..text = 'Hello world!');
try {
custom.appendChild(); // Make sure method is not tree shaken.
fail('appendChild did not throw');
} catch (e) {
expect(e, equals('Gotcha!'));
}
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> custom_element_method_clash_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running custom_element_method_clash_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,33 +0,0 @@
// Copyright (c) 2015, 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.
library custom_elements_name_clash;
import 'dart:async';
import 'dart:html';
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class CustomElement extends HtmlElement {
factory CustomElement() => new Element.tag('x-custom') as CustomElement;
CustomElement.created() : super.created() {}
// Try to clash with native 'appendChild' method.
var appendChild = 123;
}
main() async {
await customElementsReady;
group('test', () {
test('test', () {
document.registerElement2('x-custom', {'prototype': CustomElement});
CustomElement custom = new CustomElement();
document.body!.children.add(custom);
// Will call appendChild in JS.
custom.children.add(new DivElement()..text = 'Hello world!');
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> custom_element_name_clash_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running custom_element_name_clash_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,131 +0,0 @@
// Copyright (c) 2015, 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.
// Regression test for http://dartbug.com/23127
// Tests super calls to a custom element upgrade constructor with various
// combinations of parameters and type arguments.
library custom_elements_23127_test;
import 'dart:async';
import 'dart:html';
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
abstract class B1 extends HtmlElement {
void action();
B1.created() : super.created() {
action();
}
}
abstract class B1T<T> extends HtmlElement {
void action();
var qq = false;
B1T.created() : super.created() {
action();
qq = this is T;
}
}
abstract class B2 extends HtmlElement {
void action();
var qq;
B2.created([a = 1, b = 2, c = 3])
: qq = callTwice(() => ++a * ++b), // [a] and [b] are boxed.
super.created() {
action();
qq = [qq, a, b, c];
}
}
abstract class B2T<T> extends HtmlElement {
void action();
var qq;
B2T.created([a = 1, b = 2, c = 3])
: qq = callTwice(() => ++a * ++b),
super.created() {
action();
qq = [this is T, qq, a, b, c];
}
}
class C1 extends B1 {
int z = 0;
C1.created() : super.created();
action() {
z = 3;
}
}
class C1T extends B1T {
int z = 0;
C1T.created() : super.created();
action() {
z = 3;
}
}
class C2 extends B2 {
int z = 0;
C2.created() : super.created(20);
action() {
z = 3;
}
}
class C2T extends B2T {
int z = 0;
C2T.created() : super.created(20);
action() {
z = 3;
}
}
var callTwice;
main() async {
await customElementsReady;
callTwice = (f) {
f();
return f();
};
group('baseline', () {
test('C1', () {
document.register('x-c1', C1);
C1 e = document.createElement('x-c1') as C1;
expect(e.z, 3);
});
});
group('c1t', () {
test('C1T', () {
document.register('x-c1t', C1T);
C1T e = document.createElement('x-c1t') as C1T;
expect(e.z, 3);
expect(e.qq, true);
});
});
group('c2', () {
test('C2', () {
document.register('x-c2', C2);
C2 e = document.createElement('x-c2') as C2;
expect(e.z, 3);
expect(e.qq, [88, 22, 4, 3]);
});
});
group('c2t', () {
test('C2T', () {
document.register('x-c2t', C2T);
C2T e = document.createElement('x-c2t') as C2T;
expect(e.z, 3);
expect(e.qq, [true, 88, 22, 4, 3]);
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> custom_elements_23127_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running custom_elements_23127_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,179 +0,0 @@
// 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.
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;
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 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);
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> custom_elements_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running custom_elements_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -2,17 +2,159 @@
// 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.
/// The test runner for DDC does not handle tests that import files using
/// relative imports that reach outside of the directory containing the test
/// (i.e. "../" imports). Since tests both in this directory and in "custom/"
/// use utils.dart, it needs to be accessible from both places.
///
/// We could have every test outside of "custom/" import "custom/utils.dart",
/// but that feels weird since "utils.dart" doesn't have anything to do with
/// custom elements.
///
/// Instead, it lives there, but is exported from here for the tests in this
/// directory to import.
// TODO(rnystrom): If the DDC test runner is fixed to use a different module
// root that handles "../" imports, move "custom/utils.dart" to here.
export 'custom/utils.dart';
import 'dart:html';
import 'dart:typed_data';
import 'package:expect/minitest.dart';
/**
* Verifies that [actual] has the same graph structure as [expected].
* Detects cycles and DAG structure in Maps and Lists.
*/
verifyGraph(expected, actual) {
var eItems = [];
var aItems = [];
message(path, reason) => path == ''
? reason
: reason == null
? "path: $path"
: "path: $path, $reason";
walk(path, expected, actual) {
if (expected is String || expected is num || expected == null) {
expect(actual, equals(expected), reason: message(path, 'not equal'));
return;
}
// Cycle or DAG?
for (int i = 0; i < eItems.length; i++) {
if (identical(expected, eItems[i])) {
expect(actual, same(aItems[i]),
reason: message(path, 'missing back or side edge'));
return;
}
}
for (int i = 0; i < aItems.length; i++) {
if (identical(actual, aItems[i])) {
expect(expected, same(eItems[i]),
reason: message(path, 'extra back or side edge'));
return;
}
}
eItems.add(expected);
aItems.add(actual);
if (expected is Blob) {
expect(actual is Blob, isTrue, reason: '$actual is Blob');
expect(expected.type, equals(actual.type),
reason: message(path, '.type'));
expect(expected.size, equals(actual.size),
reason: message(path, '.size'));
return;
}
if (expected is ByteBuffer) {
expect(actual is ByteBuffer, isTrue, reason: '$actual is ByteBuffer');
expect(expected.lengthInBytes, equals(actual.lengthInBytes),
reason: message(path, '.lengthInBytes'));
// TODO(antonm): one can create a view on top of those
// and check if contents identical. Let's do it later.
return;
}
if (expected is DateTime) {
expect(actual is DateTime, isTrue, reason: '$actual is DateTime');
expect(expected.millisecondsSinceEpoch,
equals(actual.millisecondsSinceEpoch),
reason: message(path, '.millisecondsSinceEpoch'));
return;
}
if (expected is ImageData) {
expect(actual is ImageData, isTrue, reason: '$actual is ImageData');
expect(expected.width, equals(actual.width),
reason: message(path, '.width'));
expect(expected.height, equals(actual.height),
reason: message(path, '.height'));
walk('$path.data', expected.data, actual.data);
return;
}
if (expected is TypedData) {
expect(actual is TypedData, isTrue, reason: '$actual is TypedData');
walk('$path/.buffer', expected.buffer, actual.buffer);
expect(expected.offsetInBytes, equals(actual.offsetInBytes),
reason: message(path, '.offsetInBytes'));
expect(expected.lengthInBytes, equals(actual.lengthInBytes),
reason: message(path, '.lengthInBytes'));
// And also fallback to elements check below.
}
if (expected is List) {
expect(actual, predicate((v) => v is List),
reason: message(path, '$actual is List'));
expect(actual.length, expected.length,
reason: message(path, 'different list lengths'));
for (var i = 0; i < expected.length; i++) {
walk('$path[$i]', expected[i], actual[i]);
}
return;
}
if (expected is Map) {
expect(actual, predicate((v) => v is Map),
reason: message(path, '$actual is Map'));
for (var key in expected.keys) {
if (!actual.containsKey(key)) {
expect(false, isTrue, reason: message(path, 'missing key "$key"'));
}
walk('$path["$key"]', expected[key], actual[key]);
}
for (var key in actual.keys) {
if (!expected.containsKey(key)) {
expect(false, isTrue, reason: message(path, 'extra key "$key"'));
}
}
return;
}
expect(false, isTrue, reason: 'Unhandled type: $expected');
}
walk('', expected, actual);
}
/**
* Sanitizer which does nothing.
*/
class NullTreeSanitizer implements NodeTreeSanitizer {
void sanitizeTree(Node node) {}
}
/**
* Validate that two DOM trees are equivalent.
*/
void validateNodeTree(Node a, Node b, [String path = '']) {
path = '${path}${a.runtimeType}';
expect(a.nodeType, b.nodeType, reason: '$path nodeTypes differ');
expect(a.nodeValue, b.nodeValue, reason: '$path nodeValues differ');
expect(a.text, b.text, reason: '$path texts differ');
expect(a.nodes.length, b.nodes.length, reason: '$path nodes.lengths differ');
if (a is Element) {
Element bE = b as Element;
Element aE = a;
expect(aE.tagName, bE.tagName, reason: '$path tagNames differ');
expect(aE.attributes.length, bE.attributes.length,
reason: '$path attributes.lengths differ');
for (var key in aE.attributes.keys) {
expect(aE.attributes[key], bE.attributes[key],
reason: '$path attribute [$key] values differ');
}
}
for (var i = 0; i < a.nodes.length; ++i) {
validateNodeTree(a.nodes[i], b.nodes[i], '$path[$i].');
}
}

View file

@ -1,122 +0,0 @@
// 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 attribute_changed_callback_test;
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class A extends HtmlElement {
static final tag = 'x-a';
factory A() => new Element.tag(tag);
A.created() : super.created();
static var attributeChangedInvocations = 0;
void attributeChanged(name, oldValue, newValue) {
attributeChangedInvocations++;
}
}
class B extends HtmlElement {
static final tag = 'x-b';
factory B() => new Element.tag(tag);
B.created() : super.created() {
invocations.add('created');
}
static var invocations = [];
Completer completer;
void attributeChanged(name, oldValue, newValue) {
invocations.add('$name: $oldValue => $newValue');
if (completer != null) {
completer.complete('value changed to $newValue');
completer = null;
}
}
}
// Pump custom events polyfill events.
void customElementsTakeRecords() {
if (js.context.hasProperty('CustomElements')) {
js.context['CustomElements'].callMethod('takeRecords');
}
}
main() async {
// Adapted from Blink's fast/dom/custom/attribute-changed-callback test.
await customElementsReady;
document.registerElement2(A.tag, {'prototype': A});
document.registerElement2(B.tag, {'prototype': B});
group('fully_supported', () {
test('transfer attribute changed callback', () {
var element = new A();
element.attributes['a'] = 'b';
expect(A.attributeChangedInvocations, 1);
});
test('add, change and remove an attribute', () {
var b = new B();
B.invocations = [];
b.attributes['data-s'] = 't';
expect(B.invocations, ['data-s: null => t']);
b.attributes['data-v'] = 'w';
B.invocations = [];
b.attributes['data-v'] = 'x';
expect(B.invocations, ['data-v: w => x']);
B.invocations = [];
b.attributes['data-v'] = 'x';
expect(B.invocations, []);
b.attributes.remove('data-v');
expect(B.invocations, ['data-v: x => null']);
});
test('add, change ID', () {
B.invocations = [];
var b = new B();
var completer = new Completer();
b.completer = completer;
b.id = 'x';
return completer.future
.then((_) => expect(B.invocations, ['created', 'id: null => x']))
.then((_) {
B.invocations = [];
var secondCompleter = new Completer();
b.completer = secondCompleter;
b.attributes.remove('id');
return secondCompleter.future;
}).then((_) => expect(B.invocations, ['id: x => null']));
});
});
group('unsupported_on_polyfill', () {
// If these tests start passing, don't remove the status suppression. Move
// the tests to the fullYy_supported group.
test('add, change classes', () {
var b = new B();
B.invocations = [];
b.classes.toggle('u');
expect(B.invocations, ['class: null => u']);
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> attribute_changed_callback_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running attribute_changed_callback_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,294 +0,0 @@
// 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 created_callback_test;
import 'dart:html';
import 'dart:js' as js;
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class A extends HtmlElement {
static final tag = 'x-a';
factory A() => new Element.tag(tag);
A.created() : super.created() {
createdInvocations++;
}
static int createdInvocations = 0;
}
class B extends HtmlElement {
static final tag = 'x-b';
factory B() => new Element.tag(tag);
B.created() : super.created();
}
class C extends HtmlElement {
static final tag = 'x-c';
factory C() => new Element.tag(tag);
C.created() : super.created() {
createdInvocations++;
if (this.id != 'u') {
return;
}
var t = div.querySelector('#t');
var v = div.querySelector('#v');
var w = div.querySelector('#w');
expect(querySelector('x-b:not(:unresolved)'), this);
expect(querySelectorAll(':unresolved'), [v, w]);
// As per:
// http://www.w3.org/TR/2013/WD-custom-elements-20130514/#serializing-and-parsing
// creation order is t, u, v, w (postorder).
expect(t is C, isTrue);
// Note, this is different from JavaScript where this would be false.
expect(v is C, isTrue);
}
static int createdInvocations = 0;
static var div;
}
main() async {
// Adapted from Blink's
// fast/dom/custom/created-callback test.
await customElementsReady;
document.registerElement2(B.tag, {'prototype': B});
document.registerElement2(C.tag, {'prototype': C});
ErrorConstructorElement.register();
test('transfer created callback', () {
document.registerElement2(A.tag, {'prototype': A as dynamic});
var x = new A();
expect(A.createdInvocations, 1);
});
test('unresolved and created callback timing', () {
var div = new DivElement();
C.div = div;
div.setInnerHtml("""
<x-c id="t"></x-c>
<x-b id="u"></x-b>
<x-c id="v"></x-c>
<x-b id="w"></x-b>
""", treeSanitizer: NodeTreeSanitizer.trusted);
upgradeCustomElements(div);
expect(C.createdInvocations, 2);
expect(div.querySelector('#w') is B, isTrue);
});
test('nesting of constructors', NestedElement.test);
test('access while upgrading gets unupgraded element',
AccessWhileUpgradingElement.test);
test('cannot call created constructor', () {
expect(() {
new B.created();
}, throws);
});
test('cannot register without created', () {
expect(() {
document.registerElement2(
MissingCreatedElement.tag, {'prototype': MissingCreatedElement});
}, throws);
});
test('throw on createElement does not upgrade', () {
ErrorConstructorElement.callCount = 0;
var e;
expectGlobalError(() {
e = new Element.tag(ErrorConstructorElement.tag);
});
expect(ErrorConstructorElement.callCount, 1);
expect(e is HtmlElement, isTrue);
expect(e is ErrorConstructorElement, isFalse);
var dummy = new DivElement();
dummy.append(e);
e = dummy.firstChild;
expect(ErrorConstructorElement.callCount, 1);
});
test('throw on innerHtml does not upgrade', () {
ErrorConstructorElement.callCount = 0;
var dummy = new DivElement();
var tag = ErrorConstructorElement.tag;
expectGlobalError(() {
dummy.setInnerHtml('<$tag></$tag>',
treeSanitizer: NodeTreeSanitizer.trusted);
});
expect(ErrorConstructorElement.callCount, 1);
var e = dummy.firstChild;
// Accessing should not re-run the constructor.
expect(ErrorConstructorElement.callCount, 1);
expect(e is HtmlElement, isTrue);
expect(e is ErrorConstructorElement, isFalse);
});
test('cannot register created with params', () {
expect(() {
document.registerElement2(
'x-created-with-params', {'prototype': CreatedWithParametersElement});
}, throws);
});
test('created cannot be called from nested constructor',
NestedCreatedConstructorElement.test);
// TODO(vsm): Port additional test from upstream here:
// http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/dom/custom/created-callback.html?r1=156141&r2=156185
}
class NestedElement extends HtmlElement {
static final tag = 'x-nested';
final Element b = new B();
factory NestedElement() => new Element.tag(tag);
NestedElement.created() : super.created();
static void register() {
document.registerElement2(tag, {'prototype': NestedElement});
}
static void test() {
register();
var e = new NestedElement();
expect(e.b, isNotNull);
expect(e.b is B, isTrue);
expect(e is NestedElement, isTrue);
}
}
class AccessWhileUpgradingElement extends HtmlElement {
static final tag = 'x-access-while-upgrading';
static Element upgradingContext;
static Element upgradingContextChild;
final foo = runInitializerCode();
factory AccessWhileUpgradingElement() => new Element.tag(tag);
AccessWhileUpgradingElement.created() : super.created();
static runInitializerCode() {
upgradingContextChild = upgradingContext.firstChild;
return 666;
}
static void register() {
document.registerElement2(tag, {'prototype': AccessWhileUpgradingElement});
}
static void test() {
register();
upgradingContext = new DivElement();
upgradingContext.setInnerHtml('<$tag></$tag>',
treeSanitizer: new NullTreeSanitizer());
dynamic child = upgradingContext.firstChild;
expect(child.foo, 666);
expect(upgradingContextChild is HtmlElement, isFalse);
expect(upgradingContextChild is AccessWhileUpgradingElement, isFalse,
reason: 'Elements accessed while upgrading should not be upgraded.');
}
}
class MissingCreatedElement extends HtmlElement {
static final tag = 'x-missing-created';
factory MissingCreatedElement() => new Element.tag(tag);
}
class ErrorConstructorElement extends HtmlElement {
static final tag = 'x-throws-in-constructor';
static int callCount = 0;
factory ErrorConstructorElement() => new Element.tag(tag);
ErrorConstructorElement.created() : super.created() {
++callCount;
throw new Exception('Just messin with ya');
}
static void register() {
document.registerElement2(tag, {'prototype': ErrorConstructorElement});
}
}
class NestedCreatedConstructorElement extends HtmlElement {
static final tag = 'x-nested-created-constructor';
// Should not be able to call this here.
final B b = constructB();
static B constructedB;
factory NestedCreatedConstructorElement() => new Element.tag(tag);
NestedCreatedConstructorElement.created() : super.created();
static void register() {
document
.registerElement2(tag, {'prototype': NestedCreatedConstructorElement});
}
// Try to run the created constructor, and record the results.
static constructB() {
// This should throw an exception.
constructedB = new B.created();
return constructedB;
}
static void test() {
register();
// Exception should have occurred on upgrade.
var e;
expectGlobalError(() {
e = new Element.tag(tag);
});
expect(e is NestedCreatedConstructorElement, isFalse);
expect(e is HtmlElement, isTrue);
// Should not have been set.
expect(constructedB, isNull);
}
}
class CreatedWithParametersElement extends HtmlElement {
CreatedWithParametersElement.created(ignoredParam) : super.created();
}
void expectGlobalError(Function test) {
js.context['testExpectsGlobalError'] = true;
try {
test();
} catch (e) {
rethrow;
} finally {
js.context['testExpectsGlobalError'] = false;
}
var errors = js.context['testSuppressedGlobalErrors'];
expect(errors['length'], 1);
// Clear out the errors;
js.context['testSuppressedGlobalErrors']['length'] = 0;
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> created_callback_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running created_callback_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,147 +0,0 @@
// 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 document_register_basic_test;
import 'dart:html';
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class Foo extends HtmlElement {
static final tag = 'x-foo';
factory Foo() => new Element.tag(tag);
Foo.created() : super.created();
get thisIsACustomClass => true;
}
class Bar extends HtmlElement {
static final tag = 'x-bar';
factory Bar() => new Element.tag(tag);
Bar.created() : super.created();
get thisIsACustomClass => true;
}
class Baz extends Foo {
static final tag = 'x-baz';
factory Baz() => new Element.tag(tag);
Baz.created() : super.created();
get thisIsAlsoACustomClass => true;
}
class BadB {}
abstract class BadC extends HtmlElement {
BadC.created() : super.created();
}
main() async {
// Adapted from Blink's fast/dom/custom/document-register-basic test.
await customElementsReady;
test('Testing document.registerElement2() basic behaviors', () {
document.registerElement2(Foo.tag, {'prototype': Foo});
// Cannot register an existing dart:html type.
expect(
() => document.registerElement2('x-bad-a', {'prototype': HtmlElement}),
throws);
// Invalid user type. Doesn't inherit from HtmlElement.
expect(() => document.registerElement2('x-bad-b', {'prototype': BadB}),
throws);
// Cannot register abstract class.
expect(() => document.registerElement2('x-bad-c', {'prototype': BadC}),
throws);
// Not a type.
expect(() => document.registerElement2('x-bad-d', {'prototype': null}),
throws);
// Cannot register system type.
expect(() => document.registerElement2('x-bad-e', {'prototype': Object}),
throws);
// Constructor initiated instantiation
var createdFoo = new Foo();
expect(createdFoo.thisIsACustomClass, isTrue);
// Dart type correctness
expect(createdFoo is HtmlElement, isTrue);
expect(createdFoo is Foo, isTrue);
expect(createdFoo.runtimeType, Foo);
// Native getter
expect(createdFoo.tagName, "X-FOO");
// Native setter
createdFoo.innerHtml = "Hello";
expect(createdFoo.text, "Hello");
// Native method
var childDiv = new DivElement();
createdFoo.append(childDiv);
expect(createdFoo.lastChild, childDiv);
// Parser initiated instantiation
var container = new DivElement()..id = "container";
document.body.append(container);
container.setInnerHtml("<x-foo></x-foo>",
treeSanitizer: new NullTreeSanitizer());
upgradeCustomElements(container);
var parsedFoo = container.firstChild;
expect(parsedFoo is Foo, isTrue);
expect((parsedFoo as Foo).tagName, "X-FOO");
// Ensuring the wrapper is retained
var someProperty = new Expando();
someProperty[parsedFoo] = "hello";
expect(container.firstChild, parsedFoo);
expect(someProperty[container.firstChild], someProperty[parsedFoo]);
// Having another constructor
document.registerElement2(Bar.tag, {'prototype': Bar});
var createdBar = new Bar();
expect(createdBar is Bar, isTrue);
expect(createdBar is Foo, isFalse);
expect(createdBar.tagName, "X-BAR");
// Having a subclass
document.registerElement2(Baz.tag, {'prototype': Baz});
var createdBaz = new Baz();
expect(createdBaz.tagName, "X-BAZ");
expect(createdBaz.thisIsACustomClass, isTrue);
expect(createdBaz.thisIsAlsoACustomClass, isTrue);
// With irregular cases
var createdUpperBar = new Element.tag("X-BAR");
var createdMixedBar = new Element.tag("X-Bar");
expect(createdUpperBar is Bar, isTrue);
expect(createdUpperBar.tagName, "X-BAR");
expect(createdMixedBar is Bar, isTrue);
expect(createdMixedBar.tagName, "X-BAR");
container.setInnerHtml("<X-BAR></X-BAR><X-Bar></X-Bar>",
treeSanitizer: new NullTreeSanitizer());
upgradeCustomElements(container);
expect(container.firstChild is Bar, isTrue);
expect((container.firstChild as Bar).tagName, "X-BAR");
expect(container.lastChild is Bar, isTrue);
expect((container.lastChild as Bar).tagName, "X-BAR");
// Constructors shouldn't interfere with each other
expect((new Foo()).tagName, "X-FOO");
expect((new Bar()).tagName, "X-BAR");
expect((new Baz()).tagName, "X-BAZ");
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> document_register_basic_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running document_register_basic_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,25 +0,0 @@
// @dart = 2.9
import 'dart:html';
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
main() async {
await customElementsReady;
test('can register custom template with webcomponents-lite polyfill', () {
document.registerElement2(
'my-element', {'prototype': MyElement, 'extends': 'template'});
dynamic e = new Element.tag('template', 'my-element');
document.body.append(e);
expect(e is TemplateElement, isTrue);
expect(e.method(), 'value');
});
}
class MyElement extends TemplateElement {
MyElement.created() : super.created();
method() => 'value';
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> document_register_basic_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents-lite.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running document_register_basic_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,318 +0,0 @@
// 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
import 'dart:html';
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class Foo extends HtmlElement {
static const tag = 'x-foo';
static final List outerHtmlStrings = [
'<x-foo></x-foo>',
'<?XML:NAMESPACE PREFIX = PUBLIC NS = "URN:COMPONENT" /><x-foo></x-foo>'
];
factory Foo() => new Element.tag(tag);
Foo.created() : super.created();
}
class Bar extends InputElement {
static const tag = 'x-bar';
static const outerHtmlString = '<input is="x-bar">';
factory Bar() => new Element.tag('input', tag);
Bar.created() : super.created();
}
class Baz extends Foo {
static const tag = 'x-baz';
static final List outerHtmlStrings = [
'<x-baz></x-baz>',
'<?XML:NAMESPACE PREFIX = PUBLIC NS = "URN:COMPONENT" /><x-baz></x-baz>'
];
factory Baz() => new Element.tag(tag);
Baz.created() : super.created();
}
class Qux extends Bar {
static const tag = 'x-qux';
factory Qux() => new Element.tag('input', tag);
Qux.created() : super.created();
}
class FooBad extends DivElement {
static const tag = 'x-foo';
factory FooBad() => new Element.tag('div', tag);
FooBad.created() : super.created();
}
class MyCanvas extends CanvasElement {
static const tag = 'my-canvas';
factory MyCanvas() => new Element.tag('canvas', tag);
MyCanvas.created() : super.created();
void fillAsRed() {
width = 100;
height = 100;
CanvasRenderingContext2D context = this.getContext('2d');
context.fillStyle = 'red';
context.fillRect(0, 0, width, height);
context.fill();
var data = context.getImageData(0, 0, 1, 1).data;
expect(data, [255, 0, 0, 255]);
}
}
class CustomDiv extends DivElement {
CustomDiv.created() : super.created();
}
class CustomCustomDiv extends CustomDiv {
static const tag = 'custom-custom';
CustomCustomDiv.created() : super.created();
}
main() async {
// Adapted from Blink's fast/dom/custom/document-register-type-extension test.
var testForm = new FormElement()..id = 'testForm';
document.body.append(testForm);
var isFormControl = (element) {
testForm.append(element);
return element.form == testForm;
};
var registeredTypes = false;
void registerTypes() {
if (registeredTypes) {
return;
}
registeredTypes = true;
document.registerElement2(Foo.tag, {'prototype': Foo});
document.registerElement2(Bar.tag, {'prototype': Bar, 'extends': 'input'});
document.registerElement2(Baz.tag, {'prototype': Baz});
document.registerElement2(Qux.tag, {'prototype': Qux, 'extends': 'input'});
document.registerElement2(MyCanvas.tag, {'prototype': MyCanvas, 'extends': 'canvas'});
document.registerElement2(CustomCustomDiv.tag, {'prototype': CustomCustomDiv,
'extends': 'div'});
}
await customElementsReady;
group('registration', () {
test('cannot register twice', () {
registerTypes();
expect(() => document.registerElement2(FooBad.tag, {'prototype': Foo, 'extends': 'div'}),
throws);
});
test('cannot register for non-matching tag', () {
registerTypes();
expect(() {
document.registerElement2('x-input-div', {'prototype': Bar, 'extends': 'div'});
}, throws);
});
test('cannot register type extension for custom tag', () {
registerTypes();
expect(() {
document.registerElement2('x-custom-tag', {'prototype': CustomCustomDiv});
}, throws);
});
});
group('construction', () {
group('constructors', () {
registerTypes();
test('custom tag', () {
var fooNewed = new Foo();
expect(fooNewed.outerHtml, anyOf(Foo.outerHtmlStrings));
expect(fooNewed is Foo, isTrue);
expect(fooNewed is HtmlElement, isTrue);
expect(fooNewed is UnknownElement, isFalse);
});
test('type extension', () {
var barNewed = new Bar();
expect(barNewed.outerHtml, Bar.outerHtmlString);
expect(barNewed is Bar, isTrue);
expect(barNewed is InputElement, isTrue);
expect(isFormControl(barNewed), isTrue);
});
test('custom tag deriving from custom tag', () {
var bazNewed = new Baz();
expect(bazNewed.outerHtml, anyOf(Baz.outerHtmlStrings));
expect(bazNewed is Baz, isTrue);
expect(bazNewed is HtmlElement, isTrue);
expect(bazNewed is UnknownElement, isFalse);
});
test('type extension deriving from custom tag', () {
var quxNewed = new Qux();
var quxOuterHtml = '<input is="x-qux">';
expect(quxNewed.outerHtml, quxOuterHtml);
expect(quxNewed is Qux, isTrue);
expect(quxNewed is InputElement, isTrue);
expect(isFormControl(quxNewed), isTrue);
});
});
group('single-parameter createElement', () {
registerTypes();
test('custom tag', () {
var fooCreated = new Element.tag('x-foo');
expect(fooCreated.outerHtml, anyOf(Foo.outerHtmlStrings));
expect(fooCreated is Foo, isTrue);
});
test('does not upgrade type extension', () {
var barCreated = new Element.tag('x-bar');
expect(barCreated is Bar, isFalse);
expect(barCreated.outerHtml, "<x-bar></x-bar>");
expect(barCreated is UnknownElement, isFalse);
expect(barCreated is HtmlElement, isTrue);
});
test('custom tag deriving from custom tag', () {
var bazCreated = new Element.tag('x-baz');
expect(bazCreated.outerHtml, anyOf(Baz.outerHtmlStrings));
expect(bazCreated is Baz, isTrue);
expect(bazCreated is UnknownElement, isFalse);
});
test('type extension deriving from custom tag', () {
var quxCreated = new Element.tag('x-qux');
expect(quxCreated.outerHtml, "<x-qux></x-qux>");
expect(quxCreated is Qux, isFalse);
expect(quxCreated is UnknownElement, isFalse);
expect(quxCreated is HtmlElement, isTrue);
});
});
group('createElement with type extension', () {
registerTypes();
test('does not upgrade extension of custom tag', () {
var divFooCreated = new Element.tag("div", Foo.tag);
expect(divFooCreated.outerHtml, '<div is="x-foo"></div>');
expect(divFooCreated is Foo, isFalse);
expect(divFooCreated is DivElement, isTrue);
});
test('upgrades valid extension', () {
var inputBarCreated = new Element.tag("input", Bar.tag);
expect(inputBarCreated.outerHtml, Bar.outerHtmlString);
expect(inputBarCreated is Bar, isTrue);
expect(inputBarCreated is UnknownElement, isFalse);
expect(isFormControl(inputBarCreated), isTrue);
});
test('type extension of incorrect tag', () {
var divBarCreated = new Element.tag("div", Bar.tag);
expect(divBarCreated.outerHtml, '<div is="x-bar"></div>');
expect(divBarCreated is Bar, isFalse);
expect(divBarCreated is DivElement, isTrue);
});
test('incorrect extension of custom tag', () {
var fooBarCreated = new Element.tag(Foo.tag, Bar.tag);
expect(
fooBarCreated.outerHtml,
anyOf([
'<x-foo is="x-bar"></x-foo>',
'<?XML:NAMESPACE PREFIX = PUBLIC NS = "URN:COMPONENT" />'
'<x-foo is="x-bar"></x-foo>']));
expect(fooBarCreated is Foo, isTrue);
});
test('incorrect extension of type extension', () {
var barFooCreated = new Element.tag(Bar.tag, Foo.tag);
expect(barFooCreated.outerHtml, '<x-bar is="x-foo"></x-bar>');
expect(barFooCreated is UnknownElement, isFalse);
expect(barFooCreated is HtmlElement, isTrue);
});
test('null type extension', () {
var fooCreatedNull = new Element.tag(Foo.tag, null);
expect(fooCreatedNull.outerHtml, anyOf(Foo.outerHtmlStrings));
expect(fooCreatedNull is Foo, isTrue);
});
test('empty type extension', () {
var fooCreatedEmpty = new Element.tag(Foo.tag, "");
expect(fooCreatedEmpty.outerHtml, anyOf(Foo.outerHtmlStrings));
expect(fooCreatedEmpty is Foo, isTrue);
});
});
});
group('namespaces', () {
test('createElementNS', () {
registerTypes();
var fooCreatedNS = document.createElementNS(
"http://www.w3.org/1999/xhtml", Foo.tag, null);
expect(fooCreatedNS.outerHtml, anyOf(Foo.outerHtmlStrings));
expect(fooCreatedNS is Foo, isTrue);
var barCreatedNS = document.createElementNS(
"http://www.w3.org/1999/xhtml", "input", Bar.tag);
expect(barCreatedNS.outerHtml, Bar.outerHtmlString);
expect(barCreatedNS is Bar, isTrue);
expect(isFormControl(barCreatedNS), isTrue);
expect(
() => document.createElementNS(
'http://example.com/2013/no-such-namespace', 'xml:lang', 'x-bar'),
throws);
});
});
group('parsing', () {
test('parsing', () {
registerTypes();
createElementFromHtml(html) {
var container = new DivElement()
..setInnerHtml(html, treeSanitizer: new NullTreeSanitizer());
upgradeCustomElements(container);
return container.firstChild;
}
var fooParsed = createElementFromHtml('<x-foo>');
expect(fooParsed is Foo, isTrue);
var barParsed = createElementFromHtml('<input is=x-bar>');
expect(barParsed is Bar, isTrue);
expect(isFormControl(barParsed), isTrue);
var divFooParsed = createElementFromHtml('<div is=x-foo>');
expect(divFooParsed is Foo, isFalse);
expect(divFooParsed is DivElement, isTrue);
var namedBarParsed = createElementFromHtml('<x-bar>');
expect(namedBarParsed is Bar, isFalse);
// Polyfill does not convert parsed unregistered custom elements to
// HtmlElement.
// expect(namedBarParsed is UnknownElement, isFalse);
expect(namedBarParsed is HtmlElement, isTrue);
var divBarParsed = createElementFromHtml('<div is=x-bar>');
expect(divBarParsed is Bar, isFalse);
expect(divBarParsed is DivElement, isTrue);
});
});
group('functional', () {
test('canvas', () {
registerTypes();
var canvas = new MyCanvas();
canvas.fillAsRed();
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> document_register_type_extensions_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running document_register_type_extensions_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,58 +0,0 @@
// Copyright (c) 2014, 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
import 'dart:html';
import 'dart:js' as js;
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class FooElement extends HtmlElement {
static final tag = 'x-foo';
final int initializedField = 666;
js.JsObject _proxy;
factory FooElement() => new Element.tag(tag);
FooElement.created() : super.created() {
_proxy = new js.JsObject.fromBrowserObject(this);
}
String doSomething() => _proxy.callMethod('doSomething');
bool get fooCreated => _proxy['fooCreated'];
}
main() async {
await customElementsReady;
var upgrader = document.createElementUpgrader(FooElement);
js.context['upgradeListener'] = (e) {
upgrader.upgrade(e);
};
test('cannot create upgrader for interfaces', () {
expect(() {
// TODO(srujzs): Determine if this should be a static error.
document.createElementUpgrader(HtmlElementInterface);
}, throws);
});
test('cannot upgrade interfaces', () {
expect(() {
upgrader.upgrade(new HtmlElementInterface());
// ^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT
}, throws);
});
}
class HtmlElementInterface implements HtmlElement {
// ^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER
HtmlElementInterface.created();
}

View file

@ -1,107 +0,0 @@
// Copyright (c) 2014, 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
import 'dart:html';
import 'dart:js' as js;
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class FooElement extends HtmlElement {
static final tag = 'x-foo';
final int initializedField = 666;
js.JsObject _proxy;
factory FooElement() => new Element.tag(tag);
FooElement.created() : super.created() {
_proxy = new js.JsObject.fromBrowserObject(this);
}
String doSomething() => _proxy.callMethod('doSomething');
bool get fooCreated => _proxy['fooCreated'];
}
main() async {
await customElementsReady;
var upgrader = document.createElementUpgrader(FooElement);
js.context['upgradeListener'] = (e) {
upgrader.upgrade(e);
};
document.registerElement2('custom-element', {'prototype': CustomElement});
test('created gets proxied', () {
var element = document.createElement(FooElement.tag);
expect(element is FooElement, isTrue);
expect((element as FooElement).initializedField, 666);
expect(element.text, 'constructed');
js.context.callMethod('validateIsFoo', [element]);
expect((element as FooElement).doSomething(), 'didSomething');
expect((element as FooElement).fooCreated, true);
});
test('dart constructor works', () {
var element = new FooElement();
expect(element is FooElement, isTrue);
expect(element.text, 'constructed');
js.context.callMethod('validateIsFoo', [element]);
expect(element.doSomething(), 'didSomething');
});
test('cannot upgrade more than once', () {
var fooElement = new FooElement();
expect(() {
upgrader.upgrade(fooElement);
}, throws);
});
test('cannot upgrade non-matching elements', () {
expect(() {
upgrader.upgrade(new DivElement());
}, throws);
});
test('cannot upgrade custom elements', () {
var custom = new CustomElement();
expect(() {
upgrader.upgrade(custom);
}, throws);
});
test('can upgrade with extendsTag', () {
var upgrader = document.createElementUpgrader(CustomDiv, extendsTag: 'div');
var div = new DivElement();
var customDiv = upgrader.upgrade(div);
expect(customDiv is CustomDiv, isTrue);
var htmlElement = document.createElement('not-registered');
expect(() {
upgrader.upgrade(htmlElement);
}, throws);
});
test('cannot create upgrader for built-in types', () {
expect(() {
document.createElementUpgrader(HtmlElement);
}, throws);
});
}
class CustomDiv extends DivElement {
CustomDiv.created() : super.created();
}
class CustomElement extends HtmlElement {
factory CustomElement() => document.createElement('custom-element');
CustomElement.created() : super.created();
}

View file

@ -1,49 +0,0 @@
<!DOCTYPE html>
<meta name="dart.unittest" content="full-stack-traces">
<title> element_upgrade_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
<body>
<h1> Running element_upgrade_test </h1>
<script>
var Foo = function() {};
Foo.prototype = Object.create(HTMLElement.prototype);
Foo.prototype.createdCallback = function() {
this.fooCreated = true;
this.textContent = 'constructed';
// Tell the Dart side that this was created.
// For testing purposes, for real code this would use a different mechanism.
window.upgradeListener(this);
};
Foo.prototype.doSomething = function() {
this.textContent = 'didSomething';
return 'didSomething';
};
Foo = document.registerElement('x-foo', Foo);
function validateIsFoo(element) {
if (!(element instanceof Foo)) {
throw Error('Element is not a Foo');
}
if (!element.fooCreated) {
throw Error('Expected fooCreated to be set');
}
}
</script>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>

View file

@ -1,59 +0,0 @@
// Copyright (c) 2020 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 entered_left_view_test;
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'entered_left_view_util.dart';
import 'package:async_helper/async_minitest.dart';
import '../utils.dart';
main() async {
await setupFunc();
group('disconnected_subtree', () {
var div = new DivElement();
setUp() {
invocations = [];
}
test('Enters a disconnected subtree of DOM', () {
setUp();
div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
upgradeCustomElements(div);
expect(invocations, ['created'],
reason: 'the attached callback should not be invoked when inserted '
'into a disconnected subtree');
});
test('Leaves a disconnected subtree of DOM', () {
setUp();
div.innerHtml = '';
expect(invocations, [],
reason:
'the detached callback should not be invoked when removed from a '
'disconnected subtree');
});
test('Enters a document with a view as a constituent of a subtree', () {
setUp();
div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
upgradeCustomElements(div);
invocations = [];
document.body.append(div);
customElementsTakeRecords();
expect(invocations, ['attached'],
reason:
'the attached callback should be invoked when inserted into a '
'document with a view as part of a subtree');
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> disconnected_subtree_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running disconnected_subtree_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,68 +0,0 @@
// Copyright (c) 2020 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 entered_left_view_test;
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'entered_left_view_util.dart';
import 'package:async_helper/async_minitest.dart';
import '../utils.dart';
main() async {
await setupFunc();
group('standard_events', () {
var a;
setUp() {
invocations = [];
}
test('Created', () {
setUp();
a = new Element.tag('x-a');
expect(invocations, ['created']);
});
test('attached', () {
setUp();
document.body.append(a);
customElementsTakeRecords();
expect(invocations, ['attached']);
});
test('detached', () {
setUp();
a.remove();
customElementsTakeRecords();
expect(invocations, ['detached']);
});
var div = new DivElement();
test('nesting does not trigger attached', () {
setUp();
div.append(a);
customElementsTakeRecords();
expect(invocations, []);
});
test('nested entering triggers attached', () {
setUp();
document.body.append(div);
customElementsTakeRecords();
expect(invocations, ['attached']);
});
test('nested leaving triggers detached', () {
setUp();
div.remove();
customElementsTakeRecords();
expect(invocations, ['detached']);
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> entered_left_view_standard_events_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running entered_left_view_standard_events_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,79 +0,0 @@
// 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 entered_left_view_test;
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'package:async_helper/async_minitest.dart';
import '../utils.dart';
var invocations = [];
class Foo extends HtmlElement {
factory Foo() => null;
Foo.created() : super.created() {
invocations.add('created');
}
void attached() {
invocations.add('attached');
}
void enteredView() {
// Deprecated name. Should never be called since we override "attached".
invocations.add('enteredView');
}
void detached() {
invocations.add('detached');
}
void leftView() {
// Deprecated name. Should never be called since we override "detached".
invocations.add('leftView');
}
void attributeChanged(String name, String oldValue, String newValue) {
invocations.add('attribute changed');
}
}
// Test that the deprecated callbacks still work.
class FooOldCallbacks extends HtmlElement {
factory FooOldCallbacks() => null;
FooOldCallbacks.created() : super.created() {
invocations.add('created');
}
void enteredView() {
invocations.add('enteredView');
}
void leftView() {
invocations.add('leftView');
}
void attributeChanged(String name, String oldValue, String newValue) {
invocations.add('attribute changed');
}
}
var docA = document;
var docB = document.implementation.createHtmlDocument('');
var nullSanitizer = new NullTreeSanitizer();
setupFunc() {
// Adapted from Blink's
// fast/dom/custom/attached-detached-document.html test.
return customElementsReady.then((_) {
document.registerElement2('x-a', {'prototype': Foo});
document.registerElement2('x-a-old', {'prototype': FooOldCallbacks});
});
}

View file

@ -1,73 +0,0 @@
// Copyright (c) 2020 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 entered_left_view_test;
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'entered_left_view_util.dart';
import 'package:async_helper/async_minitest.dart';
import '../utils.dart';
main() async {
await setupFunc();
group('shadow_dom', () {
var div;
var s;
setUp() {
invocations = [];
div = new DivElement();
s = div.createShadowRoot();
}
tearDown() {
customElementsTakeRecords();
}
test('Created in Shadow DOM that is not in a document', () {
setUp();
s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
upgradeCustomElements(s);
expect(invocations, ['created'],
reason: 'the attached callback should not be invoked when entering a '
'Shadow DOM subtree not in the document');
tearDown();
});
test('Leaves Shadow DOM that is not in a document', () {
setUp();
s.innerHtml = '';
expect(invocations, [],
reason: 'the detached callback should not be invoked when leaving a '
'Shadow DOM subtree not in the document');
tearDown();
});
test('Enters a document with a view as a constituent of Shadow DOM', () {
setUp();
s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
upgradeCustomElements(s);
document.body.append(div);
customElementsTakeRecords();
expect(invocations, ['created', 'attached'],
reason: 'the attached callback should be invoked when inserted into '
'a document with a view as part of Shadow DOM');
div.remove();
customElementsTakeRecords();
expect(invocations, ['created', 'attached', 'detached'],
reason: 'the detached callback should be invoked when removed from a '
'document with a view as part of Shadow DOM');
tearDown();
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> shadow_dom_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running shadow_dom_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,69 +0,0 @@
// Copyright (c) 2020 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 entered_left_view_test;
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'entered_left_view_util.dart';
import 'package:async_helper/async_minitest.dart';
import '../utils.dart';
main() async {
await setupFunc();
// TODO(jmesserly): remove after deprecation period.
group('standard_events_old_callback_names', () {
var a;
setUp() {
invocations = [];
}
test('Created', () {
setUp();
a = new Element.tag('x-a-old');
expect(invocations, ['created']);
});
test('enteredView', () {
setUp();
document.body.append(a);
customElementsTakeRecords();
expect(invocations, ['enteredView']);
});
test('leftView', () {
setUp();
a.remove();
customElementsTakeRecords();
expect(invocations, ['leftView']);
});
var div = new DivElement();
test('nesting does not trigger enteredView', () {
setUp();
div.append(a);
customElementsTakeRecords();
expect(invocations, []);
});
test('nested entering triggers enteredView', () {
setUp();
document.body.append(div);
customElementsTakeRecords();
expect(invocations, ['enteredView']);
});
test('nested leaving triggers leftView', () {
setUp();
div.remove();
customElementsTakeRecords();
expect(invocations, ['leftView']);
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> standard_events_old_callback_names_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running standard_events_old_callback_names_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,81 +0,0 @@
// Copyright (c) 2020 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 entered_left_view_test;
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'entered_left_view_util.dart';
import 'package:async_helper/async_minitest.dart';
import '../utils.dart';
main() async {
await setupFunc();
group('viewless_document', () {
var a;
setUp() {
invocations = [];
}
test('Created, owned by a document without a view', () {
setUp();
a = docB.createElement('x-a');
expect(a.ownerDocument, docB,
reason: 'new instance should be owned by the document the definition '
'was registered with');
expect(invocations, ['created'],
reason: 'calling the constructor should invoke the created callback');
});
test('Entered document without a view', () {
setUp();
docB.body.append(a);
expect(invocations, [],
reason: 'attached callback should not be invoked when entering a '
'document without a view');
});
test('Attribute changed in document without a view', () {
setUp();
a.setAttribute('data-foo', 'bar');
expect(invocations, ['attribute changed'],
reason: 'changing an attribute should invoke the callback, even in a '
'document without a view');
});
test('Entered document with a view', () {
setUp();
document.body.append(a);
customElementsTakeRecords();
expect(invocations, ['attached'],
reason:
'attached callback should be invoked when entering a document '
'with a view');
});
test('Left document with a view', () {
setUp();
a.remove();
customElementsTakeRecords();
expect(invocations, ['detached'],
reason: 'detached callback should be invoked when leaving a document '
'with a view');
});
test('Created in a document without a view', () {
setUp();
docB.body.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
upgradeCustomElements(docB.body);
expect(invocations, ['created'],
reason: 'only created callback should be invoked when parsing a '
'custom element in a document without a view');
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> viewless_document_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running viewless_document_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,26 +0,0 @@
// 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
// Regression test for CL 194523002.
import 'dart:html';
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class A extends HtmlElement {
static final tag = 'x-a';
factory A() => new Element.tag(tag);
A.created() : super.created();
}
main() async {
// Adapted from Blink's
// fast/dom/custom/constructor-calls-created-synchronously test.
await customElementsReady;
document.registerElement2(A.tag, {'prototype': A});
}

View file

@ -1,222 +0,0 @@
// @dart = 2.9
import 'dart:async';
import 'dart:html';
import 'dart:js' as js;
import 'dart:typed_data';
import 'package:expect/minitest.dart';
/**
* Verifies that [actual] has the same graph structure as [expected].
* Detects cycles and DAG structure in Maps and Lists.
*/
verifyGraph(expected, actual) {
var eItems = [];
var aItems = [];
message(path, reason) => path == ''
? reason
: reason == null ? "path: $path" : "path: $path, $reason";
walk(path, expected, actual) {
if (expected is String || expected is num || expected == null) {
expect(actual, equals(expected), reason: message(path, 'not equal'));
return;
}
// Cycle or DAG?
for (int i = 0; i < eItems.length; i++) {
if (identical(expected, eItems[i])) {
expect(actual, same(aItems[i]),
reason: message(path, 'missing back or side edge'));
return;
}
}
for (int i = 0; i < aItems.length; i++) {
if (identical(actual, aItems[i])) {
expect(expected, same(eItems[i]),
reason: message(path, 'extra back or side edge'));
return;
}
}
eItems.add(expected);
aItems.add(actual);
if (expected is Blob) {
expect(actual is Blob, isTrue, reason: '$actual is Blob');
expect(expected.type, equals(actual.type),
reason: message(path, '.type'));
expect(expected.size, equals(actual.size),
reason: message(path, '.size'));
return;
}
if (expected is ByteBuffer) {
expect(actual is ByteBuffer, isTrue, reason: '$actual is ByteBuffer');
expect(expected.lengthInBytes, equals(actual.lengthInBytes),
reason: message(path, '.lengthInBytes'));
// TODO(antonm): one can create a view on top of those
// and check if contents identical. Let's do it later.
return;
}
if (expected is DateTime) {
expect(actual is DateTime, isTrue, reason: '$actual is DateTime');
expect(expected.millisecondsSinceEpoch,
equals(actual.millisecondsSinceEpoch),
reason: message(path, '.millisecondsSinceEpoch'));
return;
}
if (expected is ImageData) {
expect(actual is ImageData, isTrue, reason: '$actual is ImageData');
expect(expected.width, equals(actual.width),
reason: message(path, '.width'));
expect(expected.height, equals(actual.height),
reason: message(path, '.height'));
walk('$path.data', expected.data, actual.data);
return;
}
if (expected is TypedData) {
expect(actual is TypedData, isTrue, reason: '$actual is TypedData');
walk('$path/.buffer', expected.buffer, actual.buffer);
expect(expected.offsetInBytes, equals(actual.offsetInBytes),
reason: message(path, '.offsetInBytes'));
expect(expected.lengthInBytes, equals(actual.lengthInBytes),
reason: message(path, '.lengthInBytes'));
// And also fallback to elements check below.
}
if (expected is List) {
expect(actual, predicate((v) => v is List),
reason: message(path, '$actual is List'));
expect(actual.length, expected.length,
reason: message(path, 'different list lengths'));
for (var i = 0; i < expected.length; i++) {
walk('$path[$i]', expected[i], actual[i]);
}
return;
}
if (expected is Map) {
expect(actual, predicate((v) => v is Map),
reason: message(path, '$actual is Map'));
for (var key in expected.keys) {
if (!actual.containsKey(key)) {
expect(false, isTrue, reason: message(path, 'missing key "$key"'));
}
walk('$path["$key"]', expected[key], actual[key]);
}
for (var key in actual.keys) {
if (!expected.containsKey(key)) {
expect(false, isTrue, reason: message(path, 'extra key "$key"'));
}
}
return;
}
expect(false, isTrue, reason: 'Unhandled type: $expected');
}
walk('', expected, actual);
}
/**
* Sanitizer which does nothing.
*/
class NullTreeSanitizer implements NodeTreeSanitizer {
void sanitizeTree(Node node) {}
}
/**
* Validate that two DOM trees are equivalent.
*/
void validateNodeTree(Node a, Node b, [String path = '']) {
path = '${path}${a.runtimeType}';
expect(a.nodeType, b.nodeType, reason: '$path nodeTypes differ');
expect(a.nodeValue, b.nodeValue, reason: '$path nodeValues differ');
expect(a.text, b.text, reason: '$path texts differ');
expect(a.nodes.length, b.nodes.length, reason: '$path nodes.lengths differ');
if (a is Element) {
Element bE = b;
Element aE = a;
expect(aE.tagName, bE.tagName, reason: '$path tagNames differ');
expect(aE.attributes.length, bE.attributes.length,
reason: '$path attributes.lengths differ');
for (var key in aE.attributes.keys) {
expect(aE.attributes[key], bE.attributes[key],
reason: '$path attribute [$key] values differ');
}
}
for (var i = 0; i < a.nodes.length; ++i) {
validateNodeTree(a.nodes[i], b.nodes[i], '$path[$i].');
}
}
/**
* Upgrade all custom elements in the subtree which have not been upgraded.
*
* This is needed to cover timing scenarios which the custom element polyfill
* does not cover.
*/
void upgradeCustomElements(Node node) {
if (js.context.hasProperty('CustomElements') &&
js.context['CustomElements'].hasProperty('upgradeAll')) {
js.context['CustomElements'].callMethod('upgradeAll', [node]);
}
}
/**
* A future that completes once all custom elements in the initial HTML page
* have been upgraded.
*
* This is needed because the native implementation can update the elements
* while parsing the HTML document, but the custom element polyfill cannot,
* so it completes this future once all elements are upgraded.
*/
// TODO(jmesserly): rename to webComponentsReady to match the event?
Future customElementsReady = () {
if (_isReady) return new Future.value();
// Not upgraded. Wait for the polyfill to fire the WebComponentsReady event.
// Note: we listen on document (not on document.body) to allow this polyfill
// to be loaded in the HEAD element.
return document.on['WebComponentsReady'].first;
}();
// Return true if we are using the polyfill and upgrade is complete, or if we
// have native document.register and therefore the browser took care of it.
// Otherwise return false, including the case where we can't find the polyfill.
bool get _isReady {
// If we don't have dart:js, assume things are ready
if (js.context == null) return true;
var customElements = js.context['CustomElements'];
if (customElements == null) {
// Return true if native document.register, otherwise false.
// (Maybe the polyfill isn't loaded yet. Wait for it.)
return document.supportsRegisterElement;
}
return customElements['ready'] == true;
}
/**
* *Note* this API is primarily intended for tests. In other code it is better
* to write it in a style that works with or without the polyfill, rather than
* using this method.
*
* Synchronously trigger evaluation of pending lifecycle events, which otherwise
* need to wait for a [MutationObserver] to signal the changes in the polyfill.
* This method can be used to resolve differences in timing between native and
* polyfilled custom elements.
*/
void customElementsTakeRecords([Node node]) {
var customElements = js.context['CustomElements'];
if (customElements == null) return;
customElements.callMethod('takeRecords', [node]);
}

View file

@ -1,45 +0,0 @@
// Copyright (c) 2015, 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_method_clash;
import 'dart:async';
import 'dart:html';
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class CustomElement extends HtmlElement {
factory CustomElement() => new Element.tag('x-custom');
CustomElement.created() : super.created() {}
// Try to clash with native 'appendChild' method.
void appendChild() {
throw 'Gotcha!';
}
}
main() async {
await customElementsReady;
group('test', () {
test('test', () {
document.registerElement2('x-custom', {'prototype': CustomElement});
CustomElement custom = new CustomElement();
document.body.children.add(custom);
// Will call appendChild in JS.
custom.children.add(new DivElement()..text = 'Hello world!');
try {
custom.appendChild(); // Make sure method is not tree shaken.
fail('appendChild did not throw');
} catch (e) {
expect(e, equals('Gotcha!'));
}
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> custom_element_method_clash_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running custom_element_method_clash_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,35 +0,0 @@
// Copyright (c) 2015, 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_name_clash;
import 'dart:async';
import 'dart:html';
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
class CustomElement extends HtmlElement {
factory CustomElement() => new Element.tag('x-custom');
CustomElement.created() : super.created() {}
// Try to clash with native 'appendChild' method.
var appendChild = 123;
}
main() async {
await customElementsReady;
group('test', () {
test('test', () {
document.registerElement2('x-custom', {'prototype': CustomElement});
CustomElement custom = new CustomElement();
document.body.children.add(custom);
// Will call appendChild in JS.
custom.children.add(new DivElement()..text = 'Hello world!');
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> custom_element_name_clash_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running custom_element_name_clash_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,133 +0,0 @@
// Copyright (c) 2015, 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
// Regression test for http://dartbug.com/23127
// Tests super calls to a custom element upgrade constructor with various
// combinations of parameters and type arguments.
library custom_elements_23127_test;
import 'dart:async';
import 'dart:html';
import 'package:async_helper/async_minitest.dart';
import 'utils.dart';
abstract class B1 extends HtmlElement {
void action();
B1.created() : super.created() {
action();
}
}
abstract class B1T<T> extends HtmlElement {
void action();
var qq = false;
B1T.created() : super.created() {
action();
qq = this is T;
}
}
abstract class B2 extends HtmlElement {
void action();
var qq;
B2.created([a = 1, b = 2, c = 3])
: qq = callTwice(() => ++a * ++b), // [a] and [b] are boxed.
super.created() {
action();
qq = [qq, a, b, c];
}
}
abstract class B2T<T> extends HtmlElement {
void action();
var qq;
B2T.created([a = 1, b = 2, c = 3])
: qq = callTwice(() => ++a * ++b),
super.created() {
action();
qq = [this is T, qq, a, b, c];
}
}
class C1 extends B1 {
int z;
C1.created() : super.created();
action() {
z = 3;
}
}
class C1T extends B1T {
int z;
C1T.created() : super.created();
action() {
z = 3;
}
}
class C2 extends B2 {
int z;
C2.created() : super.created(20);
action() {
z = 3;
}
}
class C2T extends B2T {
int z;
C2T.created() : super.created(20);
action() {
z = 3;
}
}
var callTwice;
main() async {
await customElementsReady;
callTwice = (f) {
f();
return f();
};
group('baseline', () {
test('C1', () {
document.register('x-c1', C1);
C1 e = document.createElement('x-c1');
expect(e.z, 3);
});
});
group('c1t', () {
test('C1T', () {
document.register('x-c1t', C1T);
C1T e = document.createElement('x-c1t');
expect(e.z, 3);
expect(e.qq, true);
});
});
group('c2', () {
test('C2', () {
document.register('x-c2', C2);
C2 e = document.createElement('x-c2');
expect(e.z, 3);
expect(e.qq, [88, 22, 4, 3]);
});
});
group('c2t', () {
test('C2T', () {
document.register('x-c2t', C2T);
C2T e = document.createElement('x-c2t');
expect(e.z, 3);
expect(e.qq, [true, 88, 22, 4, 3]);
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> custom_elements_23127_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running custom_elements_23127_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,188 +0,0 @@
// 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);
});
});
}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="dart.unittest" content="full-stack-traces">
<title> custom_elements_test </title>
<style>
.unittest-table { font-family:monospace; border:1px; }
.unittest-pass { background: #6b3;}
.unittest-fail { background: #d55;}
.unittest-error { background: #a11;}
</style>
<script src="/packages/web_components/webcomponents.js"></script>
<script src="/packages/web_components/dart_support.js"></script>
</head>
<body>
<h1> Running custom_elements_test </h1>
<script type="text/javascript"
src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
%TEST_SCRIPTS%
</body>
</html>

View file

@ -1,16 +1,157 @@
/// The test runner for DDC does not handle tests that import files using
/// relative imports that reach outside of the directory containing the test
/// (i.e. "../" imports). Since tests both in this directory and in "custom/"
/// use utils.dart, it needs to be accessible from both places.
///
/// We could have every test outside of "custom/" import "custom/utils.dart",
/// but that feels weird since "utils.dart" doesn't have anything to do with
/// custom elements.
///
/// Instead, it lives there, but is exported from here for the tests in this
/// directory to import.
// TODO(rnystrom): If the DDC test runner is fixed to use a different module
// root that handles "../" imports, move "custom/utils.dart" to here.
// @dart = 2.9
export 'custom/utils.dart';
import 'dart:html';
import 'dart:typed_data';
import 'package:expect/minitest.dart';
/**
* Verifies that [actual] has the same graph structure as [expected].
* Detects cycles and DAG structure in Maps and Lists.
*/
verifyGraph(expected, actual) {
var eItems = [];
var aItems = [];
message(path, reason) => path == ''
? reason
: reason == null
? "path: $path"
: "path: $path, $reason";
walk(path, expected, actual) {
if (expected is String || expected is num || expected == null) {
expect(actual, equals(expected), reason: message(path, 'not equal'));
return;
}
// Cycle or DAG?
for (int i = 0; i < eItems.length; i++) {
if (identical(expected, eItems[i])) {
expect(actual, same(aItems[i]),
reason: message(path, 'missing back or side edge'));
return;
}
}
for (int i = 0; i < aItems.length; i++) {
if (identical(actual, aItems[i])) {
expect(expected, same(eItems[i]),
reason: message(path, 'extra back or side edge'));
return;
}
}
eItems.add(expected);
aItems.add(actual);
if (expected is Blob) {
expect(actual is Blob, isTrue, reason: '$actual is Blob');
expect(expected.type, equals(actual.type),
reason: message(path, '.type'));
expect(expected.size, equals(actual.size),
reason: message(path, '.size'));
return;
}
if (expected is ByteBuffer) {
expect(actual is ByteBuffer, isTrue, reason: '$actual is ByteBuffer');
expect(expected.lengthInBytes, equals(actual.lengthInBytes),
reason: message(path, '.lengthInBytes'));
// TODO(antonm): one can create a view on top of those
// and check if contents identical. Let's do it later.
return;
}
if (expected is DateTime) {
expect(actual is DateTime, isTrue, reason: '$actual is DateTime');
expect(expected.millisecondsSinceEpoch,
equals(actual.millisecondsSinceEpoch),
reason: message(path, '.millisecondsSinceEpoch'));
return;
}
if (expected is ImageData) {
expect(actual is ImageData, isTrue, reason: '$actual is ImageData');
expect(expected.width, equals(actual.width),
reason: message(path, '.width'));
expect(expected.height, equals(actual.height),
reason: message(path, '.height'));
walk('$path.data', expected.data, actual.data);
return;
}
if (expected is TypedData) {
expect(actual is TypedData, isTrue, reason: '$actual is TypedData');
walk('$path/.buffer', expected.buffer, actual.buffer);
expect(expected.offsetInBytes, equals(actual.offsetInBytes),
reason: message(path, '.offsetInBytes'));
expect(expected.lengthInBytes, equals(actual.lengthInBytes),
reason: message(path, '.lengthInBytes'));
// And also fallback to elements check below.
}
if (expected is List) {
expect(actual, predicate((v) => v is List),
reason: message(path, '$actual is List'));
expect(actual.length, expected.length,
reason: message(path, 'different list lengths'));
for (var i = 0; i < expected.length; i++) {
walk('$path[$i]', expected[i], actual[i]);
}
return;
}
if (expected is Map) {
expect(actual, predicate((v) => v is Map),
reason: message(path, '$actual is Map'));
for (var key in expected.keys) {
if (!actual.containsKey(key)) {
expect(false, isTrue, reason: message(path, 'missing key "$key"'));
}
walk('$path["$key"]', expected[key], actual[key]);
}
for (var key in actual.keys) {
if (!expected.containsKey(key)) {
expect(false, isTrue, reason: message(path, 'extra key "$key"'));
}
}
return;
}
expect(false, isTrue, reason: 'Unhandled type: $expected');
}
walk('', expected, actual);
}
/**
* Sanitizer which does nothing.
*/
class NullTreeSanitizer implements NodeTreeSanitizer {
void sanitizeTree(Node node) {}
}
/**
* Validate that two DOM trees are equivalent.
*/
void validateNodeTree(Node a, Node b, [String path = '']) {
path = '${path}${a.runtimeType}';
expect(a.nodeType, b.nodeType, reason: '$path nodeTypes differ');
expect(a.nodeValue, b.nodeValue, reason: '$path nodeValues differ');
expect(a.text, b.text, reason: '$path texts differ');
expect(a.nodes.length, b.nodes.length, reason: '$path nodes.lengths differ');
if (a is Element) {
Element bE = b;
Element aE = a;
expect(aE.tagName, bE.tagName, reason: '$path tagNames differ');
expect(aE.attributes.length, bE.attributes.length,
reason: '$path attributes.lengths differ');
for (var key in aE.attributes.keys) {
expect(aE.attributes[key], bE.attributes[key],
reason: '$path attribute [$key] values differ');
}
}
for (var i = 0; i < a.nodes.length; ++i) {
validateNodeTree(a.nodes[i], b.nodes[i], '$path[$i].');
}
}

View file

@ -6737,9 +6737,11 @@
"readyState": {},
"referrer": {},
"registerElement": {
"dart_action": "suppress",
"support_level": "deprecated"
},
"registerElement2": {
"dart_action": "suppress",
"support_level": "deprecated"
},
"rootElement": {

View file

@ -27,28 +27,6 @@ $!MEMBERS
ElementList<T> querySelectorAll<T extends Element>(String selectors) =>
new _FrozenElementList<T>._wrap(_querySelectorAll(selectors));
/// Checks if [registerElement] is supported on the current platform.
@deprecated
bool get supportsRegisterElement {
return JS('bool', '("registerElement" in #)', this);
}
/// *Deprecated*: use [supportsRegisterElement] instead.
@deprecated
bool get supportsRegister => supportsRegisterElement;
/// **Deprecated**: This is a legacy API based on a deprecated Web Components
/// v0.5 specification. Web Components v0.5 doesn't work on modern browsers
/// and can only be used with a polyfill.
///
/// The latest Web Components specification is supported indirectly via
/// JSInterop and doesn't have an explicit API in the `dart:html` library.
@deprecated
void registerElement(String tag, Type customElementClass,
{String$NULLABLE extendsTag}) {
registerElement2(tag, {'prototype': customElementClass, 'extends': extendsTag});
}
@pragma('dart2js:tryInline') // Almost all call sites have one argument.
Element createElement(String tagName, [String$NULLABLE typeExtension]) {
return (typeExtension == null)

View file

@ -62,68 +62,6 @@ $!MEMBERS
}
/**
* **Deprecated**: This is a legacy API based on a deprecated Web Components
* v0.5 specification. This method doesn't work on modern browsers and can
* only be used with a polyfill.
*
* The latest Web Components specification is supported indirectly via
* JSInterop and doesn't have an explicit API in the `dart:html` library.
*
* *Original documentation before deprecation*:
*
* Register a custom subclass of Element to be instantiatable by the DOM.
*
* This is necessary to allow the construction of any custom elements.
*
* The class being registered must either subclass HtmlElement or SvgElement.
* If they subclass these directly then they can be used as:
*
* class FooElement extends HtmlElement{
* void created() {
* print('FooElement created!');
* }
* }
*
* main() {
* document.registerElement('x-foo', FooElement);
* var myFoo = new Element.tag('x-foo');
* // prints 'FooElement created!' to the console.
* }
*
* The custom element can also be instantiated via HTML using the syntax
* `<x-foo></x-foo>`
*
* Other elements can be subclassed as well:
*
* class BarElement extends InputElement{
* void created() {
* print('BarElement created!');
* }
* }
*
* main() {
* document.registerElement('x-bar', BarElement);
* var myBar = new Element.tag('input', 'x-bar');
* // prints 'BarElement created!' to the console.
* }
*
* This custom element can also be instantiated via HTML using the syntax
* `<input is="x-bar"></input>`
*
*/
@deprecated
Function registerElement2(String tag, [Map$NULLABLE options]) {
return _registerCustomElement(JS('', 'window'), this, tag, options);
}
/** *Deprecated*: use [registerElement] instead. */
@deprecated
void register(String tag, Type customElementClass,
{String$NULLABLE extendsTag}) {
return registerElement(tag, customElementClass, extendsTag: extendsTag);
}
/**
* Static factory designed to expose `visibilitychange` events to event
* handlers that are not necessarily instances of [Document].