Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
775 changes: 70 additions & 705 deletions .github/workflows/dart.yml

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions _tests/dart_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ presets:
browser:
platforms:
- chrome
compilers:
- dart2js
- dart2wasm
paths:
- test/bootstrap
- test/common
Expand Down
2 changes: 1 addition & 1 deletion _tests/lib/compiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ Future<void> _testBuilder(
inputIds,
reader,
writer,
AnalyzerResolvers(),
AnalyzerResolvers.custom(),
logger: logger,
),
['non-nullable'],
Expand Down
109 changes: 92 additions & 17 deletions _tests/lib/matchers.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import 'dart:html';
import 'dart:js_interop';

import 'package:ngdart/angular.dart';
import 'package:test/test.dart';
import 'package:web/web.dart';

/// Matches textual content of an element including children.
Matcher hasTextContent(String expected) => _HasTextContent(expected);

/// Matches DOMTokenList.
Matcher hasDomTokenList(List<String> expected) => _HasDomTokenList(expected);

/// Matches textual content of an element including children.
Matcher hasInnerHtml(String expected) => _HasInnerHtml(expected);

final throwsNoProviderError = throwsA(_isNoProviderError);
final _isNoProviderError = const TypeMatcher<NoProviderError>();

Expand All @@ -15,7 +22,8 @@ class _HasTextContent extends Matcher {
const _HasTextContent(this.expectedText);

@override
bool matches(Object? item, void _) => _elementText(item) == expectedText;
bool matches(Object? item, void _) =>
_elementText(item as JSAny?) == expectedText;

@override
Description describe(Description description) =>
Expand All @@ -29,33 +37,100 @@ class _HasTextContent extends Matcher {
void __,
) {
mismatchDescription.add('Text content of element: '
'\'${_elementText(item)}\'');
'\'${_elementText(item as JSAny?)}\'');
return mismatchDescription;
}
}

String? _elementText(Object? n) {
if (n is Iterable) {
return n.map(_elementText).join('');
} else if (n is Node) {
if (n is Comment) {
String? _elementText(JSAny? node) {
if (node.isA<NodeList>()) {
return <String?>[
for (var i = 0; i < (node as NodeList).length; i++)
_elementText(node.item(i))
].join('');
}

if (node.isA<Node>()) {
if (node.isA<Comment>()) {
return '';
}

if (n is ContentElement) {
return _elementText(n.getDistributedNodes());
if (node.isA<Element>() && (node as Element).shadowRoot != null) {
return _elementText(node.shadowRoot!.childNodes);
}

if ((node as Node).childNodes.length != 0) {
return _elementText(node.childNodes);
}

if (n is Element && n.shadowRoot != null) {
return _elementText(n.shadowRoot!.nodes);
return node.textContent;
}

return null;
}

class _HasDomTokenList extends Matcher {
final List<String?> expectedTokens;

const _HasDomTokenList(this.expectedTokens);

@override
bool matches(Object? item, void _) {
final tokens = item as DOMTokenList;

if (tokens.length != expectedTokens.length) {
return false;
}

if (n.nodes.isNotEmpty) {
return _elementText(n.nodes);
for (var i = 0; i < expectedTokens.length; i++) {
if (tokens.item(i) != expectedTokens[i]) {
return false;
}
}

return n.text;
} else {
return '$n';
return true;
}

@override
Description describe(Description description) {
return description.add(expectedTokens.join(','));
}

@override
Description describeMismatch(
item,
Description mismatchDescription,
void _,
void __,
) {
mismatchDescription.add('DOMTokenList: \'$item}\'');
return mismatchDescription;
}
}

class _HasInnerHtml extends Matcher {
final String expectedHtml;

const _HasInnerHtml(this.expectedHtml);

@override
bool matches(Object? item, void _) {
return ((item as Element).innerHTML as JSString).toDart == expectedHtml;
}

@override
Description describe(Description description) =>
description.add(expectedHtml);

@override
Description describeMismatch(
item,
Description mismatchDescription,
void _,
void __,
) {
mismatchDescription.add('Inner HTML of element: '
'\'${_elementText(item as Element)}\'');
return mismatchDescription;
}
}
6 changes: 3 additions & 3 deletions _tests/mono_pkg.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
sdk:
- pubspec
- dev
- stable
# - dev

stages:
- build:
- command: dart run build_runner build --fail-on-severe
- command: dart run build_runner build --delete-conflicting-outputs --fail-on-severe
- unit_test:
- command: dart test -P vm
- command: dart run build_runner test --fail-on-severe -- -P browser
- command: dart run build_runner test --delete-conflicting-outputs --fail-on-severe -- -P browser
2 changes: 1 addition & 1 deletion _tests/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ dependencies:
build_test: ^2.2.2
collection: ^1.19.1
glob: ^2.1.2
js: ^0.7.1
logging: ^1.3.0
ngcompiler: ^3.0.0-dev.3
ngdart: ^8.0.0-dev.4
ngtest: ^5.0.0-dev.2
source_gen: ^1.5.0
test: ^1.25.9
web: ^1.1.1

dev_dependencies:
analyzer: ^6.5.0
Expand Down
30 changes: 13 additions & 17 deletions _tests/test/bootstrap/run_app_test.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
@JS()
library angular.test.bootstrap.run_app_test;

import 'dart:async';
import 'dart:html';
import 'dart:js_interop';

import 'package:js/js.dart';
import 'package:ngdart/angular.dart';
import 'package:test/test.dart';
import 'package:web/web.dart';

import 'run_app_test.template.dart' as ng;

Expand All @@ -27,9 +24,9 @@ void main() {

/// Verify that the DOM of the page represents the component.
void verifyDomAndStyles({String innerText = 'Hello World!'}) {
expect(rootDomContainer.text, innerText);
expect(rootDomContainer.textContent, innerText);
final h1 = rootDomContainer.querySelector('h1');
expect(h1!.getComputedStyle().height, '100px');
expect(window.getComputedStyle(h1!).height, '100px');
}

/// Verify the `Testability` interface is working for this application.
Expand All @@ -38,21 +35,21 @@ void main() {
void verifyTestability() {
expect(component.injector.get(Testability), isNotNull);
var jsTestability = getAngularTestability(
rootDomContainer.children.first,
rootDomContainer.children.item(0)!,
);
expect(getAllAngularTestabilities(), isNot(hasLength(0)));
expect(getAllAngularTestabilities().length, isNot(equals(0)));
expect(jsTestability.isStable(), isTrue, reason: 'Expected stability');
jsTestability.whenStable(allowInterop(expectAsync0(() {
jsTestability.whenStable(expectAsync0(() {
Future(expectAsync0(() {
verifyDomAndStyles(innerText: 'Hello Universe!');
}));
})));
}).toJS);
runInApp(() => HelloWorldComponent.doAsyncTaskAndThenRename('Universe'));
}

setUp(() {
rootDomContainer = DivElement()..id = 'test-root-dom';
rootDomContainer.append(Element.tag('hello-world'));
rootDomContainer = HTMLDivElement()..id = 'test-root-dom';
rootDomContainer.append(document.createElement('hello-world'));
document.body!.append(rootDomContainer);
HelloWorldComponent.name = 'World';
});
Expand Down Expand Up @@ -166,10 +163,9 @@ class StubExceptionHandler implements ExceptionHandler {
external JsTestability getAngularTestability(Element e);

@JS()
external List<JsTestability> getAllAngularTestabilities();
external JSArray<JsTestability> getAllAngularTestabilities();

@JS()
abstract class JsTestability {
extension type JsTestability._(JSObject _) implements JSObject {
external bool isStable();
external void whenStable(void Function() fn);
external void whenStable(JSFunction fn);
}
12 changes: 5 additions & 7 deletions _tests/test/common/directives/for_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
library angular2.test.common.directives.for_test;

import 'dart:async';

import 'package:_tests/matchers.dart';
Expand Down Expand Up @@ -298,7 +296,7 @@ void main() {
await testFixture.update((component) {
component.child!.items = ['a', 'b', 'c'];
});
expect(testFixture.text, hasTextContent('0: a;1: b;2: c;'));
expect(testFixture.text, equals('0: a;1: b;2: c;'));
});

test('should use a default template if a custom one is null', () async {
Expand All @@ -308,7 +306,7 @@ void main() {
await testFixture.update((NgForCustomTemplateNullTest component) {
component.child!.items = ['a', 'b', 'c'];
});
expect(testFixture.text, hasTextContent('0: a;1: b;2: c;'));
expect(testFixture.text, equals('0: a;1: b;2: c;'));
});

test(
Expand All @@ -320,7 +318,7 @@ void main() {
await testFixture.update((NgForCustomTemplatePrecedenceTest component) {
component.child!.items = ['a', 'b', 'c'];
});
expect(testFixture.text, hasTextContent('0: a;1: b;2: c;'));
expect(testFixture.text, equals('0: a;1: b;2: c;'));
});

group('track by', () {
Expand Down Expand Up @@ -380,8 +378,8 @@ void main() {
];
});
var endElements = testFixture.rootElement.querySelectorAll('p');
expect(startElements[0], endElements[1]);
expect(startElements[1], endElements[0]);
expect(startElements.item(0), endElements.item(1));
expect(startElements.item(1), endElements.item(0));
});

test(
Expand Down
21 changes: 12 additions & 9 deletions _tests/test/common/directives/if_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:js_interop';

import 'package:ngdart/angular.dart';
import 'package:ngdart/src/runtime/check_binding.dart';
import 'package:ngtest/angular_test.dart';
Expand All @@ -15,7 +17,7 @@ void main() {
var testFixture = await testBed.create();
var element = testFixture.rootElement;
expect(element.querySelectorAll('copy-me'), hasLength(1));
expect(element.innerHtml, contains('hello2'));
expect(element.innerHTML, contains('hello2'));
});

test('should toggle node when condition changes', () async {
Expand Down Expand Up @@ -50,31 +52,31 @@ void main() {
component.booleanCondition = false;
});
expect(element.querySelectorAll('copy-me'), hasLength(0));
expect(element.innerHtml!.contains('hello'), false);
expect((element.innerHTML as JSString).toDart.contains('hello'), isFalse);

await testFixture.update((NgIfNestedTestComponent component) {
component.booleanCondition = true;
});
expect(element.querySelectorAll('copy-me'), hasLength(1));
expect(element.innerHtml!.contains('hello'), true);
expect((element.innerHTML as JSString).toDart.contains('hello'), isTrue);

await testFixture.update((NgIfNestedTestComponent component) {
component.nestedBooleanCondition = false;
});
expect(element.querySelectorAll('copy-me'), hasLength(0));
expect(element.innerHtml!.contains('hello'), false);
expect((element.innerHTML as JSString).toDart.contains('hello'), isFalse);

await testFixture.update((NgIfNestedTestComponent component) {
component.nestedBooleanCondition = true;
});
expect(element.querySelectorAll('copy-me'), hasLength(1));
expect(element.innerHtml!.contains('hello'), true);
expect((element.innerHTML as JSString).toDart.contains('hello'), isTrue);

await testFixture.update((NgIfNestedTestComponent component) {
component.booleanCondition = false;
});
expect(element.querySelectorAll('copy-me'), hasLength(0));
expect(element.innerHtml!.contains('hello'), false);
expect((element.innerHTML as JSString).toDart.contains('hello'), isFalse);
});

test('should update multiple bindings', () async {
Expand All @@ -84,20 +86,21 @@ void main() {
var element = testFixture.rootElement;
// Check startup.
expect(element.querySelectorAll('copy-me'), hasLength(3));
expect(element.text, 'helloNumberhelloStringhelloFunction');
expect(
element.textContent, equals('helloNumberhelloStringhelloFunction'));

await testFixture.update((NgIfMultiUpdateTestComponent component) {
component.numberCondition = 0;
});
expect(element.querySelectorAll('copy-me'), hasLength(1));
expect(element.text, 'helloString');
expect(element.textContent, equals('helloString'));

await testFixture.update((NgIfMultiUpdateTestComponent component) {
component.numberCondition = 1;
component.stringCondition = 'bar';
});
expect(element.querySelectorAll('copy-me'), hasLength(1));
expect(element.text, 'helloNumber');
expect(element.textContent, equals('helloNumber'));
await testFixture.update((NgIfMultiUpdateTestComponent component) {
component.booleanCondition = false;
});
Expand Down
Loading