capybara-ng 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,899 +0,0 @@
1
- module Angular
2
- #
3
- # TODO KI NOT USED
4
- #
5
- # Build the helper 'element' function for a given instance of Protractor.
6
- #
7
- # @private
8
- # @param {Protractor} ptor
9
- # @return {function(webdriver.Locator): ElementFinder}
10
- class ElementHelper
11
- def by_binding
12
- end
13
- end
14
- end
15
-
16
- <<-JS
17
-
18
- var buildElementHelper = function(ptor) {
19
-
20
- /**
21
- * ElementArrayFinder is used for operations on an array of elements (as opposed
22
- * to a single element).
23
- *
24
- * The ElementArrayFinder is used to set up a chain of conditions that identify
25
- * an array of elements. In particular, you can call all(locator) and
26
- * filter(filterFn) to return a new ElementArrayFinder modified by the
27
- * conditions, and you can call get(index) to return a single ElementFinder at
28
- * position 'index'.
29
- *
30
- * Similar to jquery, ElementArrayFinder will search all branches of the DOM
31
- * to find the elements that satify the conditions (i.e. all, filter, get).
32
- * However, an ElementArrayFinder will not actually retrieve the elements until
33
- * an action is called, which means it can be set up in helper files (i.e.
34
- * page objects) before the page is available, and reused as the page changes.
35
- *
36
- * You can treat an ElementArrayFinder as an array of WebElements for most
37
- * purposes, in particular, you may perform actions (i.e. click, getText) on
38
- * them as you would an array of WebElements. The action will apply to
39
- * every element identified by the ElementArrayFinder. ElementArrayFinder
40
- * extends Promise, and once an action is performed on an ElementArrayFinder,
41
- * the latest result can be accessed using then, and will be returned as an
42
- * array of the results; the array has length equal to the length of the
43
- * elements found by the ElementArrayFinder and each result represents the
44
- * result of performing the action on the element. Unlike a WebElement, an
45
- * ElementArrayFinder will wait for the angular app to settle before
46
- * performing finds or actions.
47
- *
48
- * @alias element.all(locator)
49
- * @view
50
- * <ul class="items">
51
- * <li>First</li>
52
- * <li>Second</li>
53
- * <li>Third</li>
54
- * </ul>
55
- *
56
- * @example
57
- * element.all(by.css('.items li')).then(function(items) {
58
- * expect(items.length).toBe(3);
59
- * expect(items[0].getText()).toBe('First');
60
- * });
61
- *
62
- * @constructor
63
- * @param {function(): Array.<webdriver.WebElement>} getWebElements A function
64
- * that returns a list of the underlying Web Elements.
65
- * @param {webdriver.Locator} locator The most relevant locator. It is only
66
- * used for error reporting and ElementArrayFinder.locator.
67
- * @param {Array.<webdriver.promise.Promise>} opt_actionResults An array
68
- * of promises which will be retrieved with then. Resolves to the latest
69
- * action result, or null if no action has been called.
70
- * @return {ElementArrayFinder}
71
- */
72
- var ElementArrayFinder = function(getWebElements, locator, opt_actionResults) {
73
- this.getWebElements = getWebElements || null;
74
- this.actionResults_ = opt_actionResults;
75
- this.locator_ = locator;
76
-
77
- var self = this;
78
- WEB_ELEMENT_FUNCTIONS.forEach(function(fnName) {
79
- self[fnName] = function() {
80
- var callerError = new Error();
81
- var args = arguments;
82
- var actionFn = function(webElem) {
83
- return webElem[fnName].apply(webElem, args).then(null, function(e) {
84
- e.stack = e.stack + '\n' + callerError.stack;
85
- throw e;
86
- });
87
- };
88
- return self.applyAction_(actionFn);
89
- };
90
- });
91
- };
92
- util.inherits(ElementArrayFinder, webdriver.promise.Promise);
93
-
94
- /**
95
- * Calls to ElementArrayFinder may be chained to find an array of elements
96
- * using the current elements in this ElementArrayFinder as the starting point.
97
- * This function returns a new ElementArrayFinder which would contain the
98
- * children elements found (and could also be empty).
99
- *
100
- * @alias element.all(locator).all(locator)
101
- * @view
102
- * <div id='id1' class="parent">
103
- * <ul>
104
- * <li class="foo">1a</li>
105
- * <li class="baz">1b</li>
106
- * </ul>
107
- * </div>
108
- * <div id='id2' class="parent">
109
- * <ul>
110
- * <li class="foo">2a</li>
111
- * <li class="bar">2b</li>
112
- * </ul>
113
- * </div>
114
- *
115
- * @example
116
- * var foo = element.all(by.css('.parent')).all(by.css('.foo'))
117
- * expect(foo.getText()).toEqual(['1a', '2a'])
118
- * var baz = element.all(by.css('.parent')).all(by.css('.baz'))
119
- * expect(baz.getText()).toEqual(['1b'])
120
- * var nonexistent = element.all(by.css('.parent')).all(by.css('.NONEXISTENT'))
121
- * expect(nonexistent.getText()).toEqual([''])
122
- *
123
- * @param {webdriver.Locator} subLocator
124
- * @return {ElementArrayFinder}
125
- */
126
- ElementArrayFinder.prototype.all = function(locator) {
127
- var self = this;
128
- var getWebElements = function() {
129
- if (self.getWebElements === null) {
130
- // This is the first time we are looking for an element
131
- return ptor.waitForAngular().then(function() {
132
- if (locator.findElementsOverride) {
133
- return locator.findElementsOverride(ptor.driver);
134
- } else {
135
- return ptor.driver.findElements(locator);
136
- }
137
- });
138
- } else {
139
- return self.getWebElements().then(function(parentWebElements) {
140
- var childrenPromiseList = [];
141
- // For each parent web element, find their children and construct a
142
- // list of Promise<List<child_web_element>>
143
- parentWebElements.forEach(function(parentWebElement) {
144
- var childrenPromise = locator.findElementsOverride ?
145
- locator.findElementsOverride(ptor.driver, parentWebElement) :
146
- parentWebElement.findElements(locator);
147
- childrenPromiseList.push(childrenPromise);
148
- });
149
-
150
-
151
- // Resolve the list of Promise<List<child_web_elements>> and merge into
152
- // a single list
153
- return webdriver.promise.all(childrenPromiseList).then(
154
- function(resolved) {
155
- var childrenList = [];
156
- resolved.forEach(function(resolvedE) {
157
- childrenList = childrenList.concat(resolvedE);
158
- });
159
- return childrenList;
160
- });
161
- });
162
- }
163
- };
164
- return new ElementArrayFinder(getWebElements, locator);
165
- };
166
-
167
- /**
168
- * Apply a filter function to each element within the ElementArrayFinder. Returns
169
- * a new ElementArrayFinder with all elements that pass the filter function. The
170
- * filter function receives the ElementFinder as the first argument
171
- * and the index as a second arg.
172
- * This does not actually retrieve the underlying list of elements, so it can
173
- * be used in page objects.
174
- *
175
- * @alias element.all(locator).filter(filterFn)
176
- * @view
177
- * <ul class="items">
178
- * <li class="one">First</li>
179
- * <li class="two">Second</li>
180
- * <li class="three">Third</li>
181
- * </ul>
182
- *
183
- * @example
184
- * element.all(by.css('.items li')).filter(function(elem, index) {
185
- * return elem.getText().then(function(text) {
186
- * return text === 'Third';
187
- * });
188
- * }).then(function(filteredElements) {
189
- * filteredElements[0].click();
190
- * });
191
- *
192
- * @param {function(ElementFinder, number): webdriver.WebElement.Promise} filterFn
193
- * Filter function that will test if an element should be returned.
194
- * filterFn can either return a boolean or a promise that resolves to a boolean.
195
- * @return {!ElementArrayFinder} A ElementArrayFinder that represents an array
196
- * of element that satisfy the filter function.
197
- */
198
- ElementArrayFinder.prototype.filter = function(filterFn) {
199
- var self = this;
200
- var getWebElements = function() {
201
- return self.getWebElements().then(function(parentWebElements) {
202
- var list = [];
203
- parentWebElements.forEach(function(parentWebElement, index) {
204
- var elementFinder = self.get(index); // Wrap in ElementFinder
205
- var filterResults = filterFn(elementFinder, index);
206
- if (filterResults instanceof webdriver.promise.Promise) {
207
- filterResults.then(function(satisfies) {
208
- if (satisfies) {
209
- list.push(parentWebElements[index]);
210
- }
211
- });
212
- } else if (filterResults) {
213
- list.push(parentWebElements[index]);
214
- }
215
- });
216
- return list;
217
- });
218
- };
219
- return new ElementArrayFinder(getWebElements, this.locator_);
220
- };
221
-
222
- /**
223
- * Get an element within the ElementArrayFinder by index. The index starts at 0.
224
- * This does not actually retrieve the underlying element.
225
- *
226
- * @alias element.all(locator).get(index)
227
- * @view
228
- * <ul class="items">
229
- * <li>First</li>
230
- * <li>Second</li>
231
- * <li>Third</li>
232
- * </ul>
233
- *
234
- * @example
235
- * var list = element.all(by.css('.items li'));
236
- * expect(list.get(0).getText()).toBe('First');
237
- * expect(list.get(1).getText()).toBe('Second');
238
- *
239
- * @param {number} index Element index.
240
- * @return {ElementFinder} finder representing element at the given index.
241
- */
242
- ElementArrayFinder.prototype.get = function(index) {
243
- var self = this;
244
- var getWebElements = function() {
245
- return self.getWebElements().then(function(parentWebElements) {
246
- if (index === -1) {
247
- // -1 is special and means last
248
- index = parentWebElements.length - 1;
249
- }
250
- if (index >= parentWebElements.length) {
251
- throw new Error('Index out of bound. Trying to access element at ' +
252
- 'index:' + index + ', but there are only ' +
253
- parentWebElements.length + ' elements');
254
- }
255
- return [parentWebElements[index]];
256
- });
257
- };
258
- return new ElementArrayFinder(getWebElements, this.locator_).toElementFinder_();
259
- };
260
-
261
- /**
262
- * Get the first matching element for the ElementArrayFinder. This does not
263
- * actually retrieve the underlying element.
264
- *
265
- * @alias element.all(locator).first()
266
- * @view
267
- * <ul class="items">
268
- * <li>First</li>
269
- * <li>Second</li>
270
- * <li>Third</li>
271
- * </ul>
272
- *
273
- * @example
274
- * var first = element.all(by.css('.items li')).first();
275
- * expect(first.getText()).toBe('First');
276
- *
277
- * @return {ElementFinder} finder representing the first matching element
278
- */
279
- ElementArrayFinder.prototype.first = function() {
280
- return this.get(0);
281
- };
282
-
283
- /**
284
- * Get the last matching element for the ElementArrayFinder. This does not
285
- * actually retrieve the underlying element.
286
- *
287
- * @alias element.all(locator).last()
288
- * @view
289
- * <ul class="items">
290
- * <li>First</li>
291
- * <li>Second</li>
292
- * <li>Third</li>
293
- * </ul>
294
- *
295
- * @example
296
- * var last = element.all(by.css('.items li')).last();
297
- * expect(last.getText()).toBe('Third');
298
- *
299
- * @return {ElementFinder} finder representing the last matching element
300
- */
301
- ElementArrayFinder.prototype.last = function() {
302
- return this.get(-1);
303
- };
304
-
305
- /**
306
- * Shorthand function for finding arrays of elements by css.
307
- *
308
- * @type {function(string): ElementArrayFinder}
309
- */
310
- ElementArrayFinder.prototype.$$ = function(selector) {
311
- return this.all(webdriver.By.css(selector));
312
- };
313
-
314
- /**
315
- * Returns an ElementFinder representation of ElementArrayFinder. It ensures
316
- * that the ElementArrayFinder resolves to one and only one underlying element.
317
- *
318
- * @return {ElementFinder} An ElementFinder representation
319
- * @private
320
- */
321
- ElementArrayFinder.prototype.toElementFinder_ = function() {
322
- return new ElementFinder(this);
323
- };
324
-
325
- /**
326
- * Count the number of elements represented by the ElementArrayFinder.
327
- *
328
- * @alias element.all(locator).count()
329
- * @view
330
- * <ul class="items">
331
- * <li>First</li>
332
- * <li>Second</li>
333
- * <li>Third</li>
334
- * </ul>
335
- *
336
- * @example
337
- * var list = element.all(by.css('.items li'));
338
- * expect(list.count()).toBe(3);
339
- *
340
- * @return {!webdriver.promise.Promise} A promise which resolves to the
341
- * number of elements matching the locator.
342
- */
343
- ElementArrayFinder.prototype.count = function() {
344
- return this.getWebElements().then(function(arr) {
345
- return arr.length;
346
- }, function(err) {
347
- if (err.code == webdriver.error.ErrorCode.NO_SUCH_ELEMENT) {
348
- return 0;
349
- } else {
350
- throw err;
351
- }
352
- });
353
- };
354
-
355
- /**
356
- * Returns the most relevant locator.
357
- * i.e.
358
- * $('#ID1').locator() returns by.css('#ID1')
359
- * $('#ID1').$('#ID2').locator() returns by.css('#ID2')
360
- * $$('#ID1').filter(filterFn).get(0).click().locator() returns by.css('#ID1')
361
- * @return {webdriver.Locator}
362
- */
363
- ElementArrayFinder.prototype.locator = function() {
364
- return this.locator_;
365
- };
366
-
367
- /**
368
- * Apply an action function to every element in the ElementArrayFinder,
369
- * and return a new ElementArrayFinder that contains the results of the actions.
370
- *
371
- * @param {function(ElementFinder)} actionFn
372
- *
373
- * @return {ElementArrayFinder}
374
- * @private
375
- */
376
- ElementArrayFinder.prototype.applyAction_ = function(actionFn) {
377
- var actionResults = this.getWebElements().then(function(arr) {
378
- var list = [];
379
- arr.forEach(function(webElem) {
380
- list.push(actionFn(webElem));
381
- });
382
- return webdriver.promise.all(list);
383
- });
384
- return new ElementArrayFinder(this.getWebElements, this.locator_, actionResults);
385
- };
386
-
387
- /**
388
- * Represents the ElementArrayFinder as an array of ElementFinders.
389
- *
390
- * @return {Array.<ElementFinder>} Return a promise, which resolves to a list
391
- * of ElementFinders specified by the locator.
392
- */
393
- ElementArrayFinder.prototype.asElementFinders_ = function() {
394
- var self = this;
395
- return this.getWebElements().then(function(arr) {
396
- var list = [];
397
- arr.forEach(function(webElem, index) {
398
- list.push(self.get(index));
399
- });
400
- return list;
401
- });
402
- };
403
-
404
- /**
405
- * Retrieve the elements represented by the ElementArrayFinder. The input
406
- * function is passed to the resulting promise, which resolves to an
407
- * array of ElementFinders.
408
- *
409
- * @alias element.all(locator).then(thenFunction)
410
- * @view
411
- * <ul class="items">
412
- * <li>First</li>
413
- * <li>Second</li>
414
- * <li>Third</li>
415
- * </ul>
416
- *
417
- * @example
418
- * element.all(by.css('.items li')).then(function(arr) {
419
- * expect(arr.length).toEqual(3);
420
- * });
421
- *
422
- * @param {function(Array.<ElementFinder>)} fn
423
- * @param {function(Error)} errorFn
424
- *
425
- * @type {webdriver.promise.Promise} a promise which will resolve to
426
- * an array of ElementFinders represented by the ElementArrayFinder.
427
- */
428
- ElementArrayFinder.prototype.then = function(fn, errorFn) {
429
- if (this.actionResults_) {
430
- return this.actionResults_.then(fn, errorFn);
431
- } else {
432
- return this.asElementFinders_().then(fn, errorFn);
433
- }
434
- };
435
-
436
- /**
437
- * Calls the input function on each ElementFinder represented by the ElementArrayFinder.
438
- *
439
- * @alias element.all(locator).each(eachFunction)
440
- * @view
441
- * <ul class="items">
442
- * <li>First</li>
443
- * <li>Second</li>
444
- * <li>Third</li>
445
- * </ul>
446
- *
447
- * @example
448
- * element.all(by.css('.items li')).each(function(element) {
449
- * // Will print First, Second, Third.
450
- * element.getText().then(console.log);
451
- * });
452
- *
453
- * @param {function(ElementFinder)} fn Input function
454
- */
455
- ElementArrayFinder.prototype.each = function(fn) {
456
- return this.asElementFinders_().then(function(arr) {
457
- arr.forEach(function(elementFinder, index) {
458
- fn(elementFinder, index);
459
- });
460
- });
461
- };
462
-
463
- /**
464
- * Apply a map function to each element within the ElementArrayFinder. The
465
- * callback receives the ElementFinder as the first argument and the index as
466
- * a second arg.
467
- *
468
- * @alias element.all(locator).map(mapFunction)
469
- * @view
470
- * <ul class="items">
471
- * <li class="one">First</li>
472
- * <li class="two">Second</li>
473
- * <li class="three">Third</li>
474
- * </ul>
475
- *
476
- * @example
477
- * var items = element.all(by.css('.items li')).map(function(elm, index) {
478
- * return {
479
- * index: index,
480
- * text: elm.getText(),
481
- * class: elm.getAttribute('class')
482
- * };
483
- * });
484
- * expect(items).toEqual([
485
- * {index: 0, text: 'First', class: 'one'},
486
- * {index: 1, text: 'Second', class: 'two'},
487
- * {index: 2, text: 'Third', class: 'three'}
488
- * ]);
489
- *
490
- * @param {function(ElementFinder, number)} mapFn Map function that
491
- * will be applied to each element.
492
- * @return {!webdriver.promise.Promise} A promise that resolves to an array
493
- * of values returned by the map function.
494
- */
495
- ElementArrayFinder.prototype.map = function(mapFn) {
496
- return this.asElementFinders_().then(function(arr) {
497
- var list = [];
498
- arr.forEach(function(elementFinder, index) {
499
- var mapResult = mapFn(elementFinder, index);
500
- // All nested arrays and objects will also be fully resolved.
501
- webdriver.promise.fullyResolved(mapResult).then(function(resolved) {
502
- list.push(resolved);
503
- });
504
- });
505
- return list;
506
- });
507
- };
508
-
509
- /**
510
- * Apply a reduce function against an accumulator and every element found
511
- * using the locator (from left-to-right). The reduce function has to reduce
512
- * every element into a single value (the accumulator). Returns promise of
513
- * the accumulator. The reduce function receives the accumulator, current
514
- * ElementFinder, the index, and the entire array of ElementFinders,
515
- * respectively.
516
- *
517
- * @alias element.all(locator).reduce(reduceFn)
518
- * @view
519
- * <ul class="items">
520
- * <li class="one">First</li>
521
- * <li class="two">Second</li>
522
- * <li class="three">Third</li>
523
- * </ul>
524
- *
525
- * @example
526
- * var value = element.all(by.css('.items li')).reduce(function(acc, elem) {
527
- * return elem.getText().then(function(text) {
528
- * return acc + text + ' ';
529
- * });
530
- * });
531
- *
532
- * expect(value).toEqual('First Second Third ');
533
- *
534
- * @param {function(number, ElementFinder, number, Array.<ElementFinder>)}
535
- * reduceFn Reduce function that reduces every element into a single value.
536
- * @param {*} initialValue Initial value of the accumulator.
537
- * @return {!webdriver.promise.Promise} A promise that resolves to the final
538
- * value of the accumulator.
539
- */
540
- ElementArrayFinder.prototype.reduce = function(reduceFn, initialValue) {
541
- var valuePromise = webdriver.promise.fulfilled(initialValue);
542
- return this.asElementFinders_().then(function(arr) {
543
- arr.forEach(function(elementFinder, index) {
544
- valuePromise = valuePromise.then(function(value) {
545
- return reduceFn(value, elementFinder, index, arr);
546
- });
547
- });
548
- return valuePromise;
549
- });
550
- };
551
-
552
- /**
553
- * Evaluates the input as if it were on the scope of the current underlying
554
- * elements.
555
- * @param {string} expression
556
- *
557
- * @return {ElementArrayFinder} which resolves to the
558
- * evaluated expression for each underlying element.
559
- * The result will be resolved as in
560
- * {@link webdriver.WebDriver.executeScript}. In summary - primitives will
561
- * be resolved as is, functions will be converted to string, and elements
562
- * will be returned as a WebElement.
563
- */
564
- ElementArrayFinder.prototype.evaluate = function(expression) {
565
- var evaluationFn = function(webElem) {
566
- return webElem.getDriver().executeScript(
567
- clientSideScripts.evaluate, webElem, expression);
568
- };
569
- return this.applyAction_(evaluationFn);
570
- };
571
-
572
- /**
573
- * Determine if animation is allowed on the current underlying elements.
574
- * @param {string} value
575
- *
576
- * @return {ElementArrayFinder} which resolves to whether animation is allowed.
577
- */
578
- ElementArrayFinder.prototype.allowAnimations = function(value) {
579
- var allowAnimationsTestFn = function(webElem) {
580
- return webElem.getDriver().executeScript(
581
- clientSideScripts.allowAnimations, webElem, value);
582
- };
583
- return this.applyAction_(allowAnimationsTestFn);
584
- };
585
-
586
- /**
587
- * The ElementFinder simply represents a single element of an
588
- * ElementArrayFinder (and is more like a convenience object). As a result,
589
- * anything that can be done with an ElementFinder, can also be done using
590
- * an ElementArrayFinder.
591
- *
592
- * The ElementFinder can be treated as a WebElement for most purposes, in
593
- * particular, you may perform actions (i.e. click, getText) on them as you
594
- * would a WebElement. ElementFinders extend Promise, and once an action
595
- * is performed on an ElementFinder, the latest result from the chain can be
596
- * accessed using then. Unlike a WebElement, an ElementFinder will wait for
597
- * angular to settle before performing finds or actions.
598
- *
599
- * ElementFinder can be used to build a chain of locators that is used to find
600
- * an element. An ElementFinder does not actually attempt to find the element
601
- * until an action is called, which means they can be set up in helper files
602
- * before the page is available.
603
- *
604
- * @alias element(locator)
605
- * @view
606
- * <span>{{person.name}}</span>
607
- * <span ng-bind="person.email"></span>
608
- * <input type="text" ng-model="person.name"/>
609
- *
610
- * @example
611
- * // Find element with {{scopeVar}} syntax.
612
- * element(by.binding('person.name')).getText().then(function(name) {
613
- * expect(name).toBe('Foo');
614
- * });
615
- *
616
- * // Find element with ng-bind="scopeVar" syntax.
617
- * expect(element(by.binding('person.email')).getText()).toBe('foo@bar.com');
618
- *
619
- * // Find by model.
620
- * var input = element(by.model('person.name'));
621
- * input.sendKeys('123');
622
- * expect(input.getAttribute('value')).toBe('Foo123');
623
- *
624
- * @constructor
625
- * @param {ElementArrayFinder} elementArrayFinder The ElementArrayFinder
626
- * that this is branched from.
627
- * @return {ElementFinder}
628
- */
629
- var ElementFinder = function(elementArrayFinder) {
630
- if (!elementArrayFinder) {
631
- throw new Error('BUG: elementArrayFinder cannot be empty');
632
- }
633
- this.parentElementArrayFinder = elementArrayFinder;
634
-
635
- // This filter verifies that there is only 1 element returned by the
636
- // elementArrayFinder. It will warn if there are more than 1 element and
637
- // throw an error if there are no elements.
638
- var getWebElements = function() {
639
- return elementArrayFinder.getWebElements().then(function(webElements) {
640
- if (webElements.length === 0) {
641
- throw new webdriver.error.Error(
642
- webdriver.error.ErrorCode.NO_SUCH_ELEMENT,
643
- 'No element found using locator: ' +
644
- elementArrayFinder.locator_.toString());
645
- } else {
646
- if (webElements.length > 1) {
647
- console.log('warning: more than one element found for locator ' +
648
- elementArrayFinder.locator_.toString() +
649
- ' - you may need to be more specific');
650
- }
651
- return [webElements[0]];
652
- }
653
- });
654
- };
655
-
656
- // Store a copy of the underlying elementArrayFinder, but with the more
657
- // restrictive getWebElements (which checks that there is only 1 element).
658
- this.elementArrayFinder_ = new ElementArrayFinder(
659
- getWebElements, elementArrayFinder.locator_,
660
- elementArrayFinder.actionResults_);
661
-
662
- // Decorate ElementFinder with webdriver functions. Simply calls the
663
- // underlying elementArrayFinder to perform these functions.
664
- var self = this;
665
- WEB_ELEMENT_FUNCTIONS.forEach(function(fnName) {
666
- self[fnName] = function() {
667
- return self.elementArrayFinder_[fnName].
668
- apply(self.elementArrayFinder_, arguments).toElementFinder_();
669
- };
670
- });
671
- };
672
- util.inherits(ElementFinder, webdriver.promise.Promise);
673
-
674
- /**
675
- * See ElementArrayFinder.prototype.locator
676
- * @return {webdriver.Locator}
677
- */
678
- ElementFinder.prototype.locator = function() {
679
- return this.elementArrayFinder_.locator();
680
- };
681
-
682
- /**
683
- * Returns the WebElement represented by this ElementFinder.
684
- * Throws the WebDriver error if the element doesn't exist.
685
- *
686
- * @example
687
- * The following three expressions are equivalent.
688
- * - element(by.css('.parent')).getWebElement();
689
- * - browser.waitForAngular(); browser.driver.findElement(by.css('.parent'));
690
- * - browser.findElement(by.css('.parent'))
691
- *
692
- * @alias element(locator).getWebElement()
693
- * @return {webdriver.WebElement}
694
- */
695
- ElementFinder.prototype.getWebElement = function() {
696
- var id = this.elementArrayFinder_.getWebElements().then(
697
- function(parentWebElements) {
698
- return parentWebElements[0];
699
- });
700
- return new webdriver.WebElementPromise(ptor.driver, id);
701
- };
702
-
703
- /**
704
- * Access the underlying actionResult of ElementFinder. Implementation allows
705
- * ElementFinder to be used as a webdriver.promise.Promise
706
- * @param {function(webdriver.promise.Promise)} fn Function which takes
707
- * the value of the underlying actionResult.
708
- *
709
- * @return {webdriver.promise.Promise} Promise which contains the results of
710
- * evaluating fn.
711
- */
712
- ElementFinder.prototype.then = function(fn, errorFn) {
713
- return this.elementArrayFinder_.then(function(actionResults) {
714
- return fn(actionResults[0]);
715
- }, errorFn);
716
- };
717
-
718
- /**
719
- * Calls to element may be chained to find an array of elements within a parent.
720
- *
721
- * @alias element(locator).all(locator)
722
- * @view
723
- * <div class="parent">
724
- * <ul>
725
- * <li class="one">First</li>
726
- * <li class="two">Second</li>
727
- * <li class="three">Third</li>
728
- * </ul>
729
- * </div>
730
- *
731
- * @example
732
- * var items = element(by.css('.parent')).all(by.tagName('li'))
733
- *
734
- * @param {webdriver.Locator} subLocator
735
- * @return {ElementArrayFinder}
736
- */
737
- ElementFinder.prototype.all = function(subLocator) {
738
- return this.elementArrayFinder_.all(subLocator);
739
- };
740
-
741
- /**
742
- * Calls to element may be chained to find elements within a parent.
743
- *
744
- * @alias element(locator).element(locator)
745
- * @view
746
- * <div class="parent">
747
- * <div class="child">
748
- * Child text
749
- * <div>{{person.phone}}</div>
750
- * </div>
751
- * </div>
752
- *
753
- * @example
754
- * // Chain 2 element calls.
755
- * var child = element(by.css('.parent')).
756
- * element(by.css('.child'));
757
- * expect(child.getText()).toBe('Child text\n555-123-4567');
758
- *
759
- * // Chain 3 element calls.
760
- * var triple = element(by.css('.parent')).
761
- * element(by.css('.child')).
762
- * element(by.binding('person.phone'));
763
- * expect(triple.getText()).toBe('555-123-4567');
764
- *
765
- * @param {webdriver.Locator} subLocator
766
- * @return {ElementFinder}
767
- */
768
- ElementFinder.prototype.element = function(subLocator) {
769
- return this.all(subLocator).toElementFinder_();
770
- };
771
-
772
- /**
773
- * Shortcut for querying the document directly with css.
774
- *
775
- * @alias $$(cssSelector)
776
- * @view
777
- * <div class="count">
778
- * <span class="one">First</span>
779
- * <span class="two">Second</span>
780
- * </div>
781
- *
782
- * @example
783
- * // The following protractor expressions are equivalent.
784
- * var list = element.all(by.css('.count span'));
785
- * expect(list.count()).toBe(2);
786
- *
787
- * list = $$('.count span');
788
- * expect(list.count()).toBe(2);
789
- * expect(list.get(0).getText()).toBe('First');
790
- * expect(list.get(1).getText()).toBe('Second');
791
- *
792
- * @param {string} selector a css selector
793
- * @return {ElementArrayFinder} which identifies the
794
- * array of the located {@link webdriver.WebElement}s.
795
- */
796
- ElementFinder.prototype.$$ = function(selector) {
797
- return this.all(webdriver.By.css(selector));
798
- };
799
-
800
- /**
801
- * Shortcut for querying the document directly with css.
802
- *
803
- * @alias $(cssSelector)
804
- * @view
805
- * <div class="count">
806
- * <span class="one">First</span>
807
- * <span class="two">Second</span>
808
- * </div>
809
- *
810
- * @example
811
- * var item = $('.count .two');
812
- * expect(item.getText()).toBe('Second');
813
- *
814
- * @param {string} selector A css selector
815
- * @return {ElementFinder} which identifies the located
816
- * {@link webdriver.WebElement}
817
- */
818
- ElementFinder.prototype.$ = function(selector) {
819
- return this.element(webdriver.By.css(selector));
820
- };
821
-
822
- /**
823
- * Determine whether the element is present on the page.
824
- *
825
- * @view
826
- * <span>{{person.name}}</span>
827
- *
828
- * @example
829
- * // Element exists.
830
- * expect(element(by.binding('person.name')).isPresent()).toBe(true);
831
- *
832
- * // Element not present.
833
- * expect(element(by.binding('notPresent')).isPresent()).toBe(false);
834
- *
835
- * @return {ElementFinder} which resolves to whether
836
- * the element is present on the page.
837
- */
838
- ElementFinder.prototype.isPresent = function() {
839
- return this.parentElementArrayFinder.count().then(function(count) {
840
- return !!count;
841
- });
842
- };
843
-
844
- /**
845
- * Override for WebElement.prototype.isElementPresent so that protractor waits
846
- * for Angular to settle before making the check.
847
- *
848
- * @see ElementFinder.isPresent
849
- *
850
- * @param {webdriver.Locator} subLocator Locator for element to look for.
851
- * @return {ElementFinder} which resolves to whether
852
- * the element is present on the page.
853
- */
854
- ElementFinder.prototype.isElementPresent = function(subLocator) {
855
- return this.element(subLocator).isPresent();
856
- };
857
-
858
- /**
859
- * Evaluates the input as if it were on the scope of the current element.
860
- * @param {string} expression
861
- *
862
- * @return {ElementFinder} which resolves to the evaluated expression.
863
- */
864
- ElementFinder.prototype.evaluate = function(expression) {
865
- return this.elementArrayFinder_.evaluate(expression).toElementFinder_();
866
- };
867
-
868
- /**
869
- * See ElementArrayFinder.prototype.allowAnimations.
870
- * @param {string} value
871
- *
872
- * @return {ElementFinder} which resolves to whether animation is allowed.
873
- */
874
- ElementFinder.prototype.allowAnimations = function(value) {
875
- return this.elementArrayFinder_.allowAnimations(value).toElementFinder_();
876
- };
877
-
878
- /**
879
- * Webdriver relies on this function to be present on Promises, so adding
880
- * this dummy function as we inherited from webdriver.promise.Promise, but
881
- * this function is irrelevant to our usage
882
- *
883
- * @return {boolean} Always false as ElementFinder is never in pending state.
884
- */
885
- ElementFinder.prototype.isPending = function() {
886
- return false;
887
- };
888
-
889
- var element = function(locator) {
890
- return new ElementArrayFinder().all(locator).toElementFinder_();
891
- };
892
-
893
- element.all = function(locator) {
894
- return new ElementArrayFinder().all(locator);
895
- };
896
-
897
- return element;
898
- };
899
- JS