blob: a5238549a0dff122be5b4d0916f7f3cbf29fa978 [file] [log] [blame]
// 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:unittest/html_individual_config.dart';
import 'package:unittest/unittest.dart';
import '../utils.dart';
var invocations = [];
class Foo extends HtmlElement {
factory Foo() => null;
Foo.created() : super.created();
void createdCallback() {
invocations.add('created');
}
void enteredView() {
invocations.add('entered');
}
void leftView() {
invocations.add('left');
}
void attributeChanged(String name, String oldValue, String newValue) {
invocations.add('attribute changed');
}
}
// Pump custom events polyfill events.
void customElementsTakeRecords() {
if (js.context.hasProperty('CustomElements')) {
js.context['CustomElements'].callMethod('takeRecords');
}
}
main() {
useHtmlIndividualConfiguration();
// Adapted from Blink's
// fast/dom/custom/entered-left-document.html test.
var docA = document;
var docB = document.implementation.createHtmlDocument('');
var nullSanitizer = new NullTreeSanitizer();
var registeredTypes = false;
setUp(() {
return loadPolyfills().then((_) {
if (registeredTypes) {
return;
}
registeredTypes = true;
document.register('x-a', Foo);
});
});
group('standard_events', () {
var a;
setUp(() {
invocations = [];
});
test('Created', () {
a = new Element.tag('x-a');
expect(invocations, ['created']);
});
test('entered', () {
document.body.append(a);
customElementsTakeRecords();
expect(invocations, ['entered']);
});
test('left', () {
a.remove();
customElementsTakeRecords();
expect(invocations, ['left']);
});
var div = new DivElement();
test('nesting does not trigger entered', () {
div.append(a);
customElementsTakeRecords();
expect(invocations, []);
});
test('nested entering triggers entered', () {
document.body.append(div);
customElementsTakeRecords();
expect(invocations, ['entered']);
});
test('nested leaving triggers left', () {
div.remove();
customElementsTakeRecords();
expect(invocations, ['left']);
});
});
group('viewless_document', () {
var a;
setUp(() {
invocations = [];
});
test('Created, owned by a document without a view', () {
a = docB.createElement('x-a');
expect(a.document, 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', () {
docB.body.append(a);
expect(invocations, [],
reason: 'entered callback should not be invoked when entering a '
'document without a view');
});
/*
test('Attribute changed in document without a view', () {
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', () {
document.body.append(a);
customElementsTakeRecords();
expect(invocations, ['entered'],
reason: 'entered callback should be invoked when entering a document '
'with a view');
});
test('Left document with a view', () {
a.remove();
customElementsTakeRecords();
expect(invocations, ['left'],
reason: 'left callback should be invoked when leaving a document '
'with a view');
});
test('Created in a document without a view', () {
docB.body.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
Platform.upgradeCustomElements(docB.body);
expect(invocations, ['created'],
reason: 'only created callback should be invoked when parsing a '
'custom element in a document without a view');
});
});
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', () {
s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
Platform.upgradeCustomElements(s);
expect(invocations, ['created'],
reason: 'the entered callback should not be invoked when entering a '
'Shadow DOM subtree not in the document');
});
test('Leaves Shadow DOM that is not in a document', () {
s.innerHtml = '';
expect(invocations, [],
reason: 'the left callback should not be invoked when leaving a '
'Shadow DOM subtree not in the document');
});
test('Enters a document with a view as a constituent of Shadow DOM', () {
s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
Platform.upgradeCustomElements(s);
document.body.append(div);
customElementsTakeRecords();
expect(invocations, ['created', 'entered'],
reason: 'the entered callback should be invoked when inserted into '
'a document with a view as part of Shadow DOM');
div.remove();
customElementsTakeRecords();
expect(invocations, ['created', 'entered', 'left'],
reason: 'the left callback should be invoked when removed from a '
'document with a view as part of Shadow DOM');
});
});
group('disconnected_subtree', () {
var div = new DivElement();
setUp(() {
invocations = [];
});
test('Enters a disconnected subtree of DOM', () {
div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
Platform.upgradeCustomElements(div);
expect(invocations, ['created'],
reason: 'the entered callback should not be invoked when inserted '
'into a disconnected subtree');
});
test('Leaves a disconnected subtree of DOM', () {
div.innerHtml = '';
expect(invocations, [],
reason: 'the left callback should not be invoked when removed from a '
'disconnected subtree');
});
test('Enters a document with a view as a constituent of a subtree', () {
div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
Platform.upgradeCustomElements(div);
invocations = [];
document.body.append(div);
customElementsTakeRecords();
expect(invocations, ['entered'],
reason: 'the entered callback should be invoked when inserted into a '
'document with a view as part of a subtree');
});
});
}