Index: third_party/pkg/angular/test/_specs.dart |
diff --git a/third_party/pkg/angular/test/_specs.dart b/third_party/pkg/angular/test/_specs.dart |
index 88b46e6e95d925229fc52e321adac3b9c4fdf935..75b19770b6ffafd217809d87238c0e315d86788f 100644 |
--- a/third_party/pkg/angular/test/_specs.dart |
+++ b/third_party/pkg/angular/test/_specs.dart |
@@ -1,58 +1,51 @@ |
library ng_specs; |
-import 'dart:html'; |
-import 'package:unittest/unittest.dart' as unit; |
+import 'dart:html' hide Animation; |
+ |
import 'package:angular/angular.dart'; |
import 'package:angular/mock/module.dart'; |
-import 'package:collection/wrappers.dart' show DelegatingList; |
+import 'package:unittest/unittest.dart' as unit; |
-import 'jasmine_syntax.dart'; |
+import 'jasmine_syntax.dart' as jasmine_syntax; |
-export 'dart:html'; |
-export 'jasmine_syntax.dart' hide main; |
+export 'dart:html' hide Animation; |
export 'package:unittest/unittest.dart'; |
-export 'package:unittest/mock.dart'; |
+export 'package:mock/mock.dart'; |
+export 'package:di/di.dart'; |
export 'package:di/dynamic_injector.dart'; |
export 'package:angular/angular.dart'; |
+export 'package:angular/application.dart'; |
+export 'package:angular/introspection.dart'; |
+export 'package:angular/core/annotation.dart'; |
+export 'package:angular/core/registry.dart'; |
+export 'package:angular/core/module_internal.dart'; |
+export 'package:angular/core_dom/module_internal.dart'; |
+export 'package:angular/core/parser/parser.dart'; |
+export 'package:angular/core/parser/lexer.dart'; |
+export 'package:angular/directive/module.dart'; |
+export 'package:angular/formatter/module.dart'; |
+export 'package:angular/routing/module.dart'; |
+export 'package:angular/animate/module.dart'; |
export 'package:angular/mock/module.dart'; |
export 'package:perf_api/perf_api.dart'; |
es(String html) { |
var div = new DivElement(); |
div.setInnerHtml(html, treeSanitizer: new NullTreeSanitizer()); |
- return div.nodes; |
+ return new List.from(div.nodes); |
} |
e(String html) => es(html).first; |
-renderedText(n, [bool notShadow = false]) { |
- if (n is List) { |
- return n.map((nn) => renderedText(nn)).join(""); |
- } |
- |
- if (n is Comment) return ''; |
- |
- if (!notShadow && n is Element && n.shadowRoot != null) { |
- var shadowText = n.shadowRoot.text; |
- var domText = renderedText(n, true); |
- return shadowText.replaceFirst("SHADOW-CONTENT", domText); |
- } |
- |
- if (n.nodes == null || n.nodes.length == 0) return n.text; |
- |
- return n.nodes.map((cn) => renderedText(cn)).join(""); |
-} |
- |
Expect expect(actual, [unit.Matcher matcher = null]) { |
- if (matcher != null) { |
- unit.expect(actual, matcher); |
- } |
+ if (matcher != null) unit.expect(actual, matcher); |
return new Expect(actual); |
} |
class Expect { |
var actual; |
- var not; |
+ NotExpect not; |
+ |
Expect(this.actual) { |
not = new NotExpect(this); |
} |
@@ -61,67 +54,152 @@ class Expect { |
toContain(expected) => unit.expect(actual, unit.contains(expected)); |
toBe(expected) => unit.expect(actual, |
unit.predicate((actual) => identical(expected, actual), '$expected')); |
- toThrow([exception]) => unit.expect(actual, exception == null ? unit.throws : unit.throwsA(new ExceptionContains(exception))); |
- toBeFalsy() => unit.expect(actual, (v) => v == null ? true : v is bool ? v == false : false); |
- toBeTruthy() => unit.expect(actual, (v) => v is bool ? v == true : true); |
- toBeDefined() => unit.expect(actual, (v) => v != null); |
+ toThrow([exception]) => unit.expect(actual, exception == null ? |
+ unit.throws: |
+ unit.throwsA(new ExceptionContains(exception))); |
+ toBeFalsy() => unit.expect(actual, _isFalsy, |
+ reason: '"$actual" is not Falsy'); |
+ toBeTruthy() => unit.expect(actual, (v) => !_isFalsy(v), |
+ reason: '"$actual" is not Truthy'); |
+ toBeDefined() => unit.expect(actual, unit.isNotNull); |
toBeNull() => unit.expect(actual, unit.isNull); |
toBeNotNull() => unit.expect(actual, unit.isNotNull); |
- toHaveBeenCalled() => unit.expect(actual.called, true, reason: 'method not called'); |
- toHaveBeenCalledOnce() => unit.expect(actual.count, 1, reason: 'method invoked ${actual.count} expected once'); |
+ toHaveHtml(expected) => unit.expect(_toHtml(actual), unit.equals(expected)); |
+ toHaveText(expected) => |
+ unit.expect(_elementText(actual), unit.equals(expected)); |
+ |
+ toHaveBeenCalled() => |
+ unit.expect(actual.called, true, reason: 'method not called'); |
+ toHaveBeenCalledOnce() => unit.expect(actual.count, 1, |
+ reason: 'method invoked ${actual.count} expected once'); |
toHaveBeenCalledWith([a,b,c,d,e,f]) => |
unit.expect(actual.firstArgsMatch(a,b,c,d,e,f), true, |
- reason: 'method invoked with correct arguments'); |
+ reason: 'method invoked with correct arguments'); |
toHaveBeenCalledOnceWith([a,b,c,d,e,f]) => |
unit.expect(actual.count == 1 && actual.firstArgsMatch(a,b,c,d,e,f), |
- true, |
- reason: 'method invoked once with correct arguments. (Called ${actual.count} times)'); |
- |
- toHaveClass(cls) => unit.expect(actual.classes.contains(cls), true, reason: ' Expected ${actual} to have css class ${cls}'); |
+ true, |
+ reason: 'method invoked once with correct arguments. ' |
+ '(Called ${actual.count} times)'); |
+ |
+ toHaveClass(cls) => unit.expect(actual.classes.contains(cls), true, |
+ reason: ' Expected ${actual} to have css class ${cls}'); |
+ |
+ toHaveAttribute(name, [value = null]) { |
+ unit.expect(actual.attributes.containsKey(name), true, |
+ reason: 'Epxected $actual to have attribute $name'); |
+ if (value != null) { |
+ unit.expect(actual.attributes[name], value, |
+ reason: 'Epxected $actual attribute "$name" to be "$value"'); |
+ } |
+ } |
toEqualSelect(options) { |
var actualOptions = []; |
for (var option in actual.querySelectorAll('option')) { |
- if (option.selected) { |
- actualOptions.add([option.value]); |
- } else { |
- actualOptions.add(option.value); |
- } |
+ actualOptions.add(option.selected ? [option.value] : option.value); |
} |
return unit.expect(actualOptions, options); |
} |
- toEqualValid() { |
- // TODO: implement onece we have forms |
- } |
- toEqualInvalid() { |
- // TODO: implement onece we have forms |
- } |
- toEqualPristine() { |
- // TODO: implement onece we have forms |
+ toBeValid() => unit.expect(actual.valid && !actual.invalid, true, |
+ reason: 'Form is not valid'); |
+ toBePristine() => |
+ unit.expect(actual.pristine && !actual.dirty, true, |
+ reason: 'Form is dirty'); |
+ |
+ _isFalsy(v) => v == null ? true: v is bool ? v == false : false; |
+ |
+ _toHtml(node, [bool outer = false]) { |
+ if (node is Comment) { |
+ return '<!--${node.text}-->'; |
+ } else if (node is DocumentFragment) { |
+ var acc = ''; |
+ node.childNodes.forEach((n) { acc += _toHtml(n, true); }); |
+ return acc; |
+ } else if (node is List) { |
+ var acc = ''; |
+ node.forEach((n) { acc += _toHtml(n); }); |
+ return acc; |
+ } else if (node is Element) { |
+ // Remove all the "ng-binding" internal classes |
+ node = node.clone(true) as Element; |
+ node.classes.remove('ng-binding'); |
+ node.querySelectorAll(".ng-binding").forEach((Element e) { |
+ e.classes.remove('ng-binding'); |
+ }); |
+ var htmlString = outer ? node.outerHtml : node.innerHtml; |
+ // Strip out empty class attributes. This seems like a Dart bug... |
+ return htmlString.replaceAll(' class=""', '').trim(); |
+ } else if (node is Text) { |
+ return node.text; |
+ } else { |
+ throw "JQuery._toHtml not implemented for node type [${node.nodeType}]"; |
+ } |
} |
- toEqualDirty() { |
- // TODO: implement onece we have forms |
+ |
+ _elementText(n, [bool notShadow = false]) { |
+ if (n is Iterable) { |
+ return n.map((nn) => _elementText(nn)).join(""); |
+ } |
+ |
+ if (n is Comment) return ''; |
+ |
+ if (!notShadow && n is Element && n.shadowRoot != null) { |
+ var cShadows = n.shadowRoot.nodes.map((n) => n.clone(true)).toList(); |
+ for (var i = 0, ii = cShadows.length; i < ii; i++) { |
+ var n = cShadows[i]; |
+ if (n is Element) { |
+ var updateElement = (e) { |
+ var text = new Text('SHADOW-CONTENT'); |
+ if (e.parent == null) { |
+ cShadows[i] = text; |
+ } else { |
+ e.parent.insertBefore(text, e); |
+ } |
+ e.nodes = []; |
+ }; |
+ if (n is ContentElement) { updateElement(n); } |
+ n.querySelectorAll('content').forEach(updateElement); |
+ } |
+ }; |
+ var shadowText = _elementText(cShadows, true); |
+ var domText = _elementText(n, true); |
+ |
+ return shadowText.replaceFirst("SHADOW-CONTENT", domText); |
+ } |
+ |
+ if (n.nodes == null || n.nodes.length == 0) return n.text; |
+ |
+ return n.nodes.map((cn) => _elementText(cn)).join(""); |
} |
} |
class NotExpect { |
- Expect expect; |
- get actual => expect.actual; |
- NotExpect(this.expect); |
+ Expect _expect; |
+ get actual => _expect.actual; |
+ |
+ NotExpect(this._expect); |
- toHaveBeenCalled() => unit.expect(actual.called, false, reason: 'method called'); |
+ toHaveBeenCalled() => |
+ unit.expect(actual.called, false, reason: 'method called'); |
toThrow() => actual(); |
- toHaveClass(cls) => unit.expect(actual.classes.contains(cls), false, reason: ' Expected ${actual} to not have css class ${cls}'); |
+ toHaveClass(cls) => unit.expect(actual.classes.contains(cls), false, |
+ reason: ' Expected ${actual} to not have css class ${cls}'); |
+ toHaveAttribute(name) => unit.expect(actual.attributes.containsKey(name), |
+ false, reason: ' Expected $actual to not have attribute "$name"'); |
toBe(expected) => unit.expect(actual, |
unit.predicate((actual) => !identical(expected, actual), 'not $expected')); |
toEqual(expected) => unit.expect(actual, |
unit.predicate((actual) => expected != actual, 'not $expected')); |
toContain(expected) => unit.expect(actual, |
unit.predicate((actual) => !actual.contains(expected), 'not $expected')); |
+ toBePristine() => unit.expect(actual.pristine && !actual.dirty, false, |
+ reason: 'Form is pristine'); |
+ toBeValid() => unit.expect(actual.valid && !actual.invalid, false, |
+ reason: 'Form is valid'); |
} |
class ExceptionContains extends unit.Matcher { |
@@ -147,92 +225,31 @@ class ExceptionContains extends unit.Matcher { |
} |
} |
-$(selector) { |
- return new JQuery(selector); |
-} |
- |
- |
-class GetterSetter { |
- Getter getter(String key) => null; |
- Setter setter(String key) => null; |
+_injectify(fn) { |
+ // The function does two things: |
+ // First: if the it() passed a function, we wrap it in |
+ // the "sync" FunctionComposition. |
+ // Second: when we are calling the FunctionComposition, |
+ // we inject "inject" into the middle of the |
+ // composition. |
+ if (fn is! FunctionComposition) fn = sync(fn); |
+ return fn.outer(inject(fn.inner)); |
} |
-var getterSetter = new GetterSetter(); |
- |
-class JQuery extends DelegatingList<Node> { |
- JQuery([selector]) : super([]) { |
- if (selector == null) { |
- // do nothing; |
- } else if (selector is String) { |
- addAll(es(selector)); |
- } else if (selector is List) { |
- addAll(selector); |
- } else if (selector is Node) { |
- add(selector); |
- } else { |
- throw selector; |
- } |
- } |
- |
- _toHtml(node, [bool outer = false]) { |
- if (node is Comment) { |
- return '<!--${node.text}-->'; |
- } else { |
- return outer ? node.outerHtml : node.innerHtml; |
- } |
- } |
- accessor(Function getter, Function setter, [value, single=false]) { |
- // TODO(dart): ?value does not work, since value was passed. :-( |
- var setterMode = value != null; |
- var result = setterMode ? this : ''; |
- forEach((node) { |
- if (setterMode) { |
- setter(node, value); |
- } else { |
- result = single ? getter(node) : '$result${getter(node)}'; |
- } |
- }); |
- return result; |
- } |
- |
- html([String html]) => accessor( |
- (n) => _toHtml(n), |
- (n, v) => n.setInnerHtml(v, treeSanitizer: new NullTreeSanitizer()), |
- html); |
- val([String text]) => accessor((n) => n.value, (n, v) => n.value = v); |
- text([String text]) => accessor((n) => n.text, (n, v) => n.text = v, text); |
- contents() => fold(new JQuery(), (jq, node) => jq..addAll(node.nodes)); |
- toString() => fold('', (html, node) => '$html${_toHtml(node, true)}'); |
- eq(num childIndex) => $(this[childIndex]); |
- remove(_) => forEach((n) => n.remove()); |
- attr([String name, String value]) => accessor( |
- (n) => n.attributes[name], |
- (n, v) => n.attributes[name] = v, |
- value, |
- true); |
- prop([String name]) => accessor( |
- (n) => getterSetter.getter(name)(n), |
- (n, v) => getterSetter.setter(name)(n, v), |
- null, |
- true); |
- textWithShadow() => fold('', (t, n) => '${t}${renderedText(n)}'); |
- find(selector) => fold(new JQuery(), (jq, n) => jq..addAll( |
- (n is Element ? (n as Element).querySelectorAll(selector) : []))); |
- hasClass(String name) => fold(false, (hasClass, node) => |
- hasClass || (node is Element && (node as Element).classes.contains(name))); |
- addClass(String name) => forEach((node) => |
- (node is Element) ? (node as Element).classes.add(name) : null); |
- removeClass(String name) => forEach((node) => |
- (node is Element) ? (node as Element).classes.remove(name) : null); |
- css(String name, [String value]) => accessor( |
- (Element n) => n.style.getPropertyValue(name), |
- (Element n, v) => n.style.setProperty(name, value), value); |
- children() => new JQuery(this[0].childNodes); |
-} |
+// Jasmine syntax |
+beforeEachModule(fn) => jasmine_syntax.beforeEach(module(fn), priority:1); |
+beforeEach(fn) => jasmine_syntax.beforeEach(_injectify(fn)); |
+afterEach(fn) => jasmine_syntax.afterEach(_injectify(fn)); |
+it(name, fn) => jasmine_syntax.it(name, _injectify(fn)); |
+iit(name, fn) => jasmine_syntax.iit(name, _injectify(fn)); |
+xit(name, fn) => jasmine_syntax.xit(name, fn); |
+xdescribe(name, fn) => jasmine_syntax.xdescribe(name, fn); |
+ddescribe(name, fn) => jasmine_syntax.ddescribe(name, fn); |
+describe(name, fn) => jasmine_syntax.describe(name, fn); |
+var jasmine = jasmine_syntax.jasmine; |
main() { |
- beforeEach(setUpInjector); |
- beforeEach(() => wrapFn(sync)); |
- afterEach(tearDownInjector); |
+ jasmine_syntax.beforeEach(setUpInjector, priority:3); |
+ jasmine_syntax.afterEach(tearDownInjector); |
} |