4cc31f8f4f
There are no behavioral changes here, I just ran `dart format` on the `tests/lib/html/` directory. Change-Id: I221b2a370adc393e49621db1d37aa6eeb09b3015 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/425329 Reviewed-by: Srujan Gaddam <srujzs@google.com> Auto-Submit: Bob Nystrom <rnystrom@google.com> Commit-Queue: Bob Nystrom <rnystrom@google.com>
205 lines
5.5 KiB
Dart
205 lines
5.5 KiB
Dart
// 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 'dart:typed_data';
|
|
|
|
import 'package:expect/legacy/minitest.dart'; // ignore: deprecated_member_use_from_same_package
|
|
|
|
/**
|
|
* 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].');
|
|
}
|
|
}
|