Index: third_party/pkg/angular/test/directive/ng_repeat_spec.dart |
diff --git a/third_party/pkg/angular/test/directive/ng_repeat_spec.dart b/third_party/pkg/angular/test/directive/ng_repeat_spec.dart |
index eb0fa376c7ebd428c0673ee72a75599e1ca2c776..05b1ab34e205cba1819480d421f1b10f3aff32bf 100644 |
--- a/third_party/pkg/angular/test/directive/ng_repeat_spec.dart |
+++ b/third_party/pkg/angular/test/directive/ng_repeat_spec.dart |
@@ -2,283 +2,341 @@ library ng_repeat_spec; |
import '../_specs.dart'; |
+// Mock animate instance that throws on move |
+class MockAnimate extends Animate { |
+ Animation move(Iterable<Node> nodes, Node parent, |
+ {Node insertBefore}) { |
+ throw "Move should not be called"; |
+ } |
+} |
+ |
main() { |
describe('NgRepeater', () { |
- var element, $compile, scope, $exceptionHandler, directives; |
- |
- beforeEach(inject((Injector injector, Scope $rootScope, Compiler compiler, DirectiveMap _directives) { |
- $exceptionHandler = injector.get(ExceptionHandler); |
- scope = $rootScope; |
- $compile = (html) { |
- element = $(html); |
- var blockFactory = compiler(element, _directives); |
- var block = blockFactory(injector, element); |
+ Element element; |
+ var compile, scope, exceptionHandler, directives; |
+ |
+ beforeEach((Injector injector, Scope rootScope, Compiler compiler, DirectiveMap _directives) { |
+ exceptionHandler = injector.get(ExceptionHandler); |
+ scope = rootScope; |
+ compile = (html, [scope]) { |
+ element = e(html); |
+ var viewFactory = compiler([element], _directives); |
+ var blockInjector = injector; |
+ if (scope != null) { |
+ viewFactory.bind(injector)(scope); |
+ } else { |
+ viewFactory(injector, [element]); |
+ } |
return element; |
}; |
directives = _directives; |
- })); |
+ }); |
- it(r'should set create a list of items', inject((Scope scope, Compiler compiler, Injector injector) { |
- var element = $('<div><div ng-repeat="item in items">{{item}}</div></div>'); |
- BlockFactory blockFactory = compiler(element, directives); |
- Block block = blockFactory(injector, element); |
+ it(r'should set create a list of items', (Scope scope, Compiler compiler, Injector injector) { |
+ var element = es('<div><div ng-repeat="item in items">{{item}}</div></div>'); |
+ ViewFactory viewFactory = compiler(element, directives); |
+ View view = viewFactory(injector, element); |
scope.context['items'] = ['a', 'b']; |
scope.apply(); |
- expect(element.text()).toEqual('ab'); |
- })); |
+ expect(element).toHaveText('ab'); |
+ }); |
+ |
+ |
+ it(r'should set create a list of items', (Scope scope, Compiler compiler, Injector injector) { |
+ scope.context['items'] = []; |
+ scope.watch('1', (_, __) { |
+ scope.context['items'].add('a'); |
+ scope.context['items'].add('b'); |
+ }); |
+ var element = es('<div><div ng-repeat="item in items">{{item}}</div></div>'); |
+ ViewFactory viewFactory = compiler(element, directives); |
+ View view = viewFactory(injector, element); |
+ scope.apply(); |
+ expect(element).toHaveText('ab'); |
+ }); |
it(r'should set create a list of items from iterable', |
- inject((Scope scope, Compiler compiler, Injector injector) { |
- var element = $('<div><div ng-repeat="item in items">{{item}}</div></div>'); |
- BlockFactory blockFactory = compiler(element, directives); |
- Block block = blockFactory(injector, element); |
+ (Scope scope, Compiler compiler, Injector injector) { |
+ var element = es('<div><div ng-repeat="item in items">{{item}}</div></div>'); |
+ ViewFactory viewFactory = compiler(element, directives); |
+ View view = viewFactory(injector, element); |
scope.context['items'] = ['a', 'b'].map((i) => i); // makes an iterable |
scope.apply(); |
- expect(element.text()).toEqual('ab'); |
- })); |
+ expect(element).toHaveText('ab'); |
+ }); |
it(r'should iterate over an array of objects', () { |
- element = $compile( |
- '<ul>' + |
- '<li ng-repeat="item in items">{{item.name}};</li>' + |
+ element = compile( |
+ '<ul>' |
+ '<li ng-repeat="item in items">{{item.name}};</li>' |
'</ul>'); |
// INIT |
scope.context['items'] = [{"name": 'misko'}, {"name":'shyam'}]; |
scope.apply(); |
- expect(element.find('li').length).toEqual(2); |
- expect(element.text()).toEqual('misko;shyam;'); |
+ expect(element.querySelectorAll('li').length).toEqual(2); |
+ expect(element.text).toEqual('misko;shyam;'); |
// GROW |
scope.context['items'].add({"name": 'adam'}); |
scope.apply(); |
- expect(element.find('li').length).toEqual(3); |
- expect(element.text()).toEqual('misko;shyam;adam;'); |
+ expect(element.querySelectorAll('li').length).toEqual(3); |
+ expect(element.text).toEqual('misko;shyam;adam;'); |
// SHRINK |
scope.context['items'].removeLast(); |
scope.context['items'].removeAt(0); |
scope.apply(); |
- expect(element.find('li').length).toEqual(1); |
- expect(element.text()).toEqual('shyam;'); |
+ expect(element.querySelectorAll('li').length).toEqual(1); |
+ expect(element.text).toEqual('shyam;'); |
}); |
it(r'should gracefully handle nulls', () { |
- element = $compile( |
- '<div>' + |
- '<ul>' + |
- '<li ng-repeat="item in null">{{item.name}};</li>' + |
- '</ul>' + |
+ element = compile( |
+ '<div>' |
+ '<ul>' |
+ '<li ng-repeat="item in null">{{item.name}};</li>' |
+ '</ul>' |
'</div>'); |
scope.apply(); |
- expect(element.find('ul').length).toEqual(1); |
- expect(element.find('li').length).toEqual(0); |
+ expect(element.querySelectorAll('ul').length).toEqual(1); |
+ expect(element.querySelectorAll('li').length).toEqual(0); |
+ }); |
+ |
+ |
+ it('should support formatters', () { |
+ element = compile( |
+ '<div><span ng-repeat="item in items | filter:myFilter">{{item}}</span></div>'); |
+ scope.context['items'] = ['foo', 'bar', 'baz']; |
+ scope.context['myFilter'] = (String item) => item.startsWith('b'); |
+ scope.apply(); |
+ expect(element.querySelectorAll('span').length).toEqual(2); |
+ }); |
+ |
+ it('should support function as a formatter', () { |
+ scope.context['isEven'] = (num) => num % 2 == 0; |
+ var element = compile( |
+ '<div ng-show="true">' |
+ '<span ng-repeat="r in [1, 2] | filter:isEven">{{r}}</span>' |
+ '</div>'); |
+ scope.apply(); |
+ expect(element.text).toEqual('2'); |
}); |
describe('track by', () { |
it(r'should track using expression function', () { |
- element = $compile( |
- '<ul>' + |
- '<li ng-repeat="item in items track by item.id">{{item.name}};</li>' + |
+ element = compile( |
+ '<ul>' |
+ '<li ng-repeat="item in items track by item.id">{{item.name}};</li>' |
'</ul>'); |
scope.context['items'] = [{"id": 'misko'}, {"id": 'igor'}]; |
scope.apply(); |
- var li0 = element.find('li')[0]; |
- var li1 = element.find('li')[1]; |
+ var li0 = element.querySelectorAll('li')[0]; |
+ var li1 = element.querySelectorAll('li')[1]; |
scope.context['items'].add(scope.context['items'].removeAt(0)); |
scope.apply(); |
- expect(element.find('li')[0]).toBe(li1); |
- expect(element.find('li')[1]).toBe(li0); |
+ expect(element.querySelectorAll('li')[0]).toBe(li1); |
+ expect(element.querySelectorAll('li')[1]).toBe(li0); |
}); |
it(r'should track using build in $id function', () { |
- element = $compile( |
- '<ul>' + |
- r'<li ng-repeat="item in items track by $id(item)">{{item.name}};</li>' + |
+ element = compile( |
+ '<ul>' |
+ r'<li ng-repeat="item in items track by $id(item)">{{item.name}};</li>' |
'</ul>'); |
scope.context['items'] = [{"name": 'misko'}, {"name": 'igor'}]; |
scope.apply(); |
- var li0 = element.find('li')[0]; |
- var li1 = element.find('li')[1]; |
+ var li0 = element.querySelectorAll('li')[0]; |
+ var li1 = element.querySelectorAll('li')[1]; |
scope.context['items'].add(scope.context['items'].removeAt(0)); |
scope.apply(); |
- expect(element.find('li')[0]).toBe(li1); |
- expect(element.find('li')[1]).toBe(li0); |
+ expect(element.querySelectorAll('li')[0]).toBe(li1); |
+ expect(element.querySelectorAll('li')[1]).toBe(li0); |
}); |
it(r'should iterate over an array of primitives', () { |
- element = $compile( |
- r'<ul>' + |
- r'<li ng-repeat="item in items track by $index">{{item}};</li>' + |
+ element = compile( |
+ r'<ul>' |
+ r'<li ng-repeat="item in items track by $index">{{item}};</li>' |
r'</ul>'); |
// INIT |
scope.context['items'] = [true, true, true]; |
scope.apply(); |
- expect(element.find('li').length).toEqual(3); |
- expect(element.text()).toEqual('true;true;true;'); |
+ expect(element.querySelectorAll('li').length).toEqual(3); |
+ expect(element.text).toEqual('true;true;true;'); |
scope.context['items'] = [false, true, true]; |
scope.apply(); |
- expect(element.find('li').length).toEqual(3); |
- expect(element.text()).toEqual('false;true;true;'); |
+ expect(element.querySelectorAll('li').length).toEqual(3); |
+ expect(element.text).toEqual('false;true;true;'); |
scope.context['items'] = [false, true, false]; |
scope.apply(); |
- expect(element.find('li').length).toEqual(3); |
- expect(element.text()).toEqual('false;true;false;'); |
+ expect(element.querySelectorAll('li').length).toEqual(3); |
+ expect(element.text).toEqual('false;true;false;'); |
scope.context['items'] = [true]; |
scope.apply(); |
- expect(element.find('li').length).toEqual(1); |
- expect(element.text()).toEqual('true;'); |
+ expect(element.querySelectorAll('li').length).toEqual(1); |
+ expect(element.text).toEqual('true;'); |
scope.context['items'] = [true, true, false]; |
scope.apply(); |
- expect(element.find('li').length).toEqual(3); |
- expect(element.text()).toEqual('true;true;false;'); |
+ expect(element.querySelectorAll('li').length).toEqual(3); |
+ expect(element.text).toEqual('true;true;false;'); |
scope.context['items'] = [true, false, false]; |
scope.apply(); |
- expect(element.find('li').length).toEqual(3); |
- expect(element.text()).toEqual('true;false;false;'); |
+ expect(element.querySelectorAll('li').length).toEqual(3); |
+ expect(element.text).toEqual('true;false;false;'); |
// string |
scope.context['items'] = ['a', 'a', 'a']; |
scope.apply(); |
- expect(element.find('li').length).toEqual(3); |
- expect(element.text()).toEqual('a;a;a;'); |
+ expect(element.querySelectorAll('li').length).toEqual(3); |
+ expect(element.text).toEqual('a;a;a;'); |
scope.context['items'] = ['ab', 'a', 'a']; |
scope.apply(); |
- expect(element.find('li').length).toEqual(3); |
- expect(element.text()).toEqual('ab;a;a;'); |
+ expect(element.querySelectorAll('li').length).toEqual(3); |
+ expect(element.text).toEqual('ab;a;a;'); |
scope.context['items'] = ['test']; |
scope.apply(); |
- expect(element.find('li').length).toEqual(1); |
- expect(element.text()).toEqual('test;'); |
+ expect(element.querySelectorAll('li').length).toEqual(1); |
+ expect(element.text).toEqual('test;'); |
scope.context['items'] = ['same', 'value']; |
scope.apply(); |
- expect(element.find('li').length).toEqual(2); |
- expect(element.text()).toEqual('same;value;'); |
+ expect(element.querySelectorAll('li').length).toEqual(2); |
+ expect(element.text).toEqual('same;value;'); |
// number |
scope.context['items'] = [12, 12, 12]; |
scope.apply(); |
- expect(element.find('li').length).toEqual(3); |
- expect(element.text()).toEqual('12;12;12;'); |
+ expect(element.querySelectorAll('li').length).toEqual(3); |
+ expect(element.text).toEqual('12;12;12;'); |
scope.context['items'] = [53, 12, 27]; |
scope.apply(); |
- expect(element.find('li').length).toEqual(3); |
- expect(element.text()).toEqual('53;12;27;'); |
+ expect(element.querySelectorAll('li').length).toEqual(3); |
+ expect(element.text).toEqual('53;12;27;'); |
scope.context['items'] = [89]; |
scope.apply(); |
- expect(element.find('li').length).toEqual(1); |
- expect(element.text()).toEqual('89;'); |
+ expect(element.querySelectorAll('li').length).toEqual(1); |
+ expect(element.text).toEqual('89;'); |
scope.context['items'] = [89, 23]; |
scope.apply(); |
- expect(element.find('li').length).toEqual(2); |
- expect(element.text()).toEqual('89;23;'); |
+ expect(element.querySelectorAll('li').length).toEqual(2); |
+ expect(element.text).toEqual('89;23;'); |
}); |
}); |
it(r'should error on wrong parsing of ngRepeat', () { |
- element = $('<ul><li ng-repeat="i dont parse"></li></ul>'); |
expect(() { |
- $compile(element); |
- }).toThrow("[NgErr7] ngRepeat error! Expected expression in form of '_item_ in _collection_[ track by _id_]' but got 'i dont parse'."); |
+ compile('<ul><li ng-repeat="i dont parse"></li></ul>')(); |
+ }).toThrow("[NgErr7] ngRepeat error! Expected expression in form of " |
+ "'_item_ in _collection_[ track by _id_]' but got " |
+ "'i dont parse'."); |
}); |
it("should throw error when left-hand-side of ngRepeat can't be parsed", () { |
- element = $('<ul><li ng-repeat="i dont parse in foo"></li></ul>'); |
expect(() { |
- $compile(element); |
- }).toThrow("[NgErr8] ngRepeat error! '_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got 'i dont parse'."); |
+ compile('<ul><li ng-repeat="i dont parse in foo"></li></ul>')(); |
+ }).toThrow("[NgErr8] ngRepeat error! '_item_' in '_item_ in " |
+ "_collection_' should be an identifier or '(_key_, _value_)' " |
+ "expression, but got 'i dont parse'."); |
}); |
it(r'should expose iterator offset as $index when iterating over arrays', |
() { |
- element = $compile( |
+ element = compile( |
'<ul>' + |
'<li ng-repeat="item in items">{{item}}:{{\$index}}|</li>' + |
'</ul>'); |
scope.context['items'] = ['misko', 'shyam', 'frodo']; |
scope.apply(); |
- expect(element.text()).toEqual('misko:0|shyam:1|frodo:2|'); |
+ expect(element.text).toEqual('misko:0|shyam:1|frodo:2|'); |
}); |
it(r'should expose iterator position as $first, $middle and $last when iterating over arrays', |
() { |
- element = $compile( |
- '<ul>' + |
- '<li ng-repeat="item in items">{{item}}:{{\$first}}-{{\$middle}}-{{\$last}}|</li>' + |
+ element = compile( |
+ '<ul>' |
+ '<li ng-repeat="item in items">{{item}}:{{\$first}}-{{\$middle}}-{{\$last}}|</li>' |
'</ul>'); |
scope.context['items'] = ['misko', 'shyam', 'doug']; |
scope.apply(); |
- expect(element.text()). |
- toEqual('misko:true-false-false|shyam:false-true-false|doug:false-false-true|'); |
+ expect(element.text) |
+ .toEqual('misko:true-false-false|' |
+ 'shyam:false-true-false|' |
+ 'doug:false-false-true|'); |
scope.context['items'].add('frodo'); |
scope.apply(); |
- expect(element.text()). |
- toEqual('misko:true-false-false|' + |
- 'shyam:false-true-false|' + |
- 'doug:false-true-false|' + |
- 'frodo:false-false-true|'); |
+ expect(element.text) |
+ .toEqual('misko:true-false-false|' |
+ 'shyam:false-true-false|' |
+ 'doug:false-true-false|' |
+ 'frodo:false-false-true|'); |
scope.context['items'].removeLast(); |
scope.context['items'].removeLast(); |
scope.apply(); |
- expect(element.text()).toEqual('misko:true-false-false|shyam:false-false-true|'); |
+ expect(element.text).toEqual('misko:true-false-false|' |
+ 'shyam:false-false-true|'); |
scope.context['items'].removeLast(); |
scope.apply(); |
- expect(element.text()).toEqual('misko:true-false-true|'); |
+ expect(element.text).toEqual('misko:true-false-true|'); |
}); |
it(r'should report odd', () { |
- element = $compile( |
- '<ul>' + |
- '<li ng-repeat="item in items">{{item}}:{{\$odd}}-{{\$even}}|</li>' + |
+ element = compile( |
+ '<ul>' |
+ '<li ng-repeat="item in items">{{item}}:{{\$odd}}-{{\$even}}|</li>' |
'</ul>'); |
scope.context['items'] = ['misko', 'shyam', 'doug']; |
scope.apply(); |
- expect(element.text()).toEqual('misko:false-true|shyam:true-false|doug:false-true|'); |
+ expect(element.text).toEqual('misko:false-true|' |
+ 'shyam:true-false|' |
+ 'doug:false-true|'); |
scope.context['items'].add('frodo'); |
scope.apply(); |
- expect(element.text()).toEqual('misko:false-true|shyam:true-false|doug:false-true|frodo:true-false|'); |
+ expect(element.text).toEqual('misko:false-true|' |
+ 'shyam:true-false|' |
+ 'doug:false-true|' |
+ 'frodo:true-false|'); |
scope.context['items'].removeLast(); |
scope.context['items'].removeLast(); |
scope.apply(); |
- expect(element.text()).toEqual('misko:false-true|shyam:true-false|'); |
+ expect(element.text).toEqual('misko:false-true|shyam:true-false|'); |
scope.context['items'].removeLast(); |
scope.apply(); |
- expect(element.text()).toEqual('misko:false-true|'); |
+ expect(element.text).toEqual('misko:false-true|'); |
}); |
it(r'should repeat over nested arrays', () { |
- element = $compile( |
+ element = compile( |
'<ul>' + |
'<li ng-repeat="subgroup in groups">' + |
'<div ng-repeat="group in subgroup">{{group}}|</div>X' + |
@@ -287,7 +345,7 @@ main() { |
scope.context['groups'] = [['a', 'b'], ['c','d']]; |
scope.apply(); |
- expect(element.text()).toEqual('a|b|Xc|d|X'); |
+ expect(element.text).toEqual('a|b|Xc|d|X'); |
}); |
@@ -295,9 +353,9 @@ main() { |
var a, b, c, d, lis; |
beforeEach(() { |
- element = $compile( |
- '<ul>' + |
- '<li ng-repeat="item in items">{{key}}:{{val}}|></li>' + |
+ element = compile( |
+ '<ul>' |
+ '<li ng-repeat="item in items">{{key}}:{{val}}|></li>' |
'</ul>'); |
a = {}; |
b = {}; |
@@ -306,68 +364,34 @@ main() { |
scope.context['items'] = [a, b, c]; |
scope.apply(); |
- lis = element.find('li'); |
+ lis = element.querySelectorAll('li'); |
}); |
it(r'should preserve the order of elements', () { |
scope.context['items'] = [a, c, d]; |
scope.apply(); |
- var newElements = element.find('li'); |
+ var newElements = element.querySelectorAll('li'); |
expect(newElements[0]).toEqual(lis[0]); |
expect(newElements[1]).toEqual(lis[2]); |
- expect(newElements[2] == lis[1]).toEqual(false); |
+ expect(newElements[2]).not.toEqual(lis[1]); |
}); |
- |
- it(r'should throw error on adding existing duplicates and recover', () { |
+ it(r'should not throw an error on duplicates', () { |
scope.context['items'] = [a, a, a]; |
- expect(() { |
- scope.apply(); |
- }).toThrow("[NgErr50] ngRepeat error! Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: item in items, Duplicate key: {}"); |
- |
- // recover |
- scope.context['items'] = [a]; |
- scope.apply(); |
- var newElements = element.find('li'); |
- expect(newElements.length).toEqual(1); |
- expect(newElements[0]).toEqual(lis[0]); |
- |
- scope.context['items'] = []; |
- scope.apply(); |
- newElements = element.find('li'); |
- expect(newElements.length).toEqual(0); |
+ expect(() => scope.apply()).not.toThrow(); |
+ scope.context['items'].add(a); |
+ expect(() => scope.apply()).not.toThrow(); |
}); |
- |
- it(r'should throw error on new duplicates and recover', () { |
- scope.context['items'] = [d, d, d]; |
- expect(() { |
- scope.apply(); |
- }).toThrow("[NgErr50] ngRepeat error! Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: item in items, Duplicate key: {}"); |
- |
- // recover |
- scope.context['items'] = [a]; |
- scope.apply(); |
- var newElements = element.find('li'); |
- expect(newElements.length).toEqual(1); |
- expect(newElements[0]).toEqual(lis[0]); |
- |
- scope.context['items'] = []; |
- scope.apply(); |
- newElements = element.find('li'); |
- expect(newElements.length).toEqual(0); |
- }); |
- |
- |
it(r'should reverse items when the collection is reversed', () { |
scope.context['items'] = [a, b, c]; |
scope.apply(); |
- lis = element.find('li'); |
+ lis = element.querySelectorAll('li'); |
scope.context['items'] = [c, b, a]; |
scope.apply(); |
- var newElements = element.find('li'); |
+ var newElements = element.querySelectorAll('li'); |
expect(newElements.length).toEqual(3); |
expect(newElements[0]).toEqual(lis[2]); |
expect(newElements[1]).toEqual(lis[1]); |
@@ -376,17 +400,17 @@ main() { |
it(r'should reuse elements even when model is composed of primitives', () { |
- // rebuilding repeater from scratch can be expensive, we should try to avoid it even for |
- // model that is composed of primitives. |
+ // rebuilding repeater from scratch can be expensive, we should try to |
+ // avoid it even for model that is composed of primitives. |
scope.context['items'] = ['hello', 'cau', 'ahoj']; |
scope.apply(); |
- lis = element.find('li'); |
+ lis = element.querySelectorAll('li'); |
lis[2].id = 'yes'; |
scope.context['items'] = ['ahoj', 'hello', 'cau']; |
scope.apply(); |
- var newLis = element.find('li'); |
+ var newLis = element.querySelectorAll('li'); |
expect(newLis.length).toEqual(3); |
expect(newLis[0]).toEqual(lis[2]); |
expect(newLis[1]).toEqual(lis[0]); |
@@ -394,5 +418,56 @@ main() { |
}); |
}); |
+ |
+ it('should correctly handle detached state', () { |
+ scope.context['items'] = [1]; |
+ |
+ var parentScope = scope.createChild(new PrototypeMap(scope.context)); |
+ element = compile( |
+ '<ul>' |
+ '<li ng-repeat="item in items">{{item}}</li>' |
+ '</ul>', parentScope); |
+ |
+ parentScope.destroy(); |
+ expect(scope.apply).not.toThrow(); |
+ }); |
+ |
+ it(r'should not move blocks when elements only added or removed', |
+ inject((Injector injector) { |
+ var throwOnMove = new MockAnimate(); |
+ var child = injector.createChild( |
+ [new Module()..value(Animate, throwOnMove)]); |
+ |
+ child.invoke((Injector injector, Scope rootScope, Compiler compiler, |
+ DirectiveMap _directives) { |
+ exceptionHandler = injector.get(ExceptionHandler); |
+ scope = rootScope; |
+ compile = (html) { |
+ element = e(html); |
+ var viewFactory = compiler([element], _directives); |
+ viewFactory(injector, [element]); |
+ return element; |
+ }; |
+ directives = _directives; |
+ }); |
+ |
+ element = compile( |
+ '<ul>' |
+ '<li ng-repeat="item in items">{{item}}</li>' |
+ '</ul>'); |
+ |
+ scope..context['items'] = ['a', 'b', 'c'] |
+ ..apply() |
+ // grow |
+ ..context['items'].add('d') |
+ ..apply() |
+ // shrink |
+ ..context['items'].removeLast() |
+ ..apply() |
+ ..context['items'].removeAt(0) |
+ ..apply(); |
+ |
+ expect(element).toHaveText('bc'); |
+ })); |
}); |
} |