-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathindex.ts
176 lines (164 loc) · 7.54 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import { ElementFinder, ElementArrayFinder } from 'protractor';
import { promise as wdpromise } from 'selenium-webdriver';
export class BaseFragment extends ElementFinder {
/**
* Extend this class, to describe single custom fragment on your page
*
* @param {ElementFinder} elementFinder ElementFinder that you want to extend
*/
constructor(elementFinder: ElementFinder) {
// Basically we are recreating ElementFinder again with same parameters
super(elementFinder.browser_, elementFinder.elementArrayFinder_);
}
}
export class BaseArrayFragment<T extends ElementFinder> extends ElementArrayFinder {
// Internal reference to class that will be used to wrap ElementFinders in ElementArrayFinder
protected class_;
// Internal reference to unwrapped ElementArrayFinder
protected elementArrayFinder_: ElementArrayFinder;
/**
* Extend this class, to describe collection of custom fragments on your page
*
* @param {ElementArrayFinder} elementArrayFinder your ElementArrayFinder that you want to extend
* @param {any} class_ constructor, that will be used to wrap each element of collection
*/
constructor(elementArrayFinder: ElementArrayFinder, class_: any) {
super(elementArrayFinder.browser_, elementArrayFinder.getWebElements, elementArrayFinder.locator(), elementArrayFinder.actionResults_);
this.elementArrayFinder_ = elementArrayFinder;
this.class_ = class_;
}
/**
* Get an element within the ElementArrayFinder by index. The index starts at 0.
* Negative indices are wrapped (i.e. -i means ith element from last)
*
* This does not actually retrieve the underlying element.
*
* See documentation for ElementArrayFinder.get function
* http://www.protractortest.org/#/api?view=ElementArrayFinder.prototype.get
*
* @param {number} index
*
* @returns {T} fragment by specified index
*/
get(index: number): T {
return new this.class_(super.get(index));
}
/*
Since .first() and .last() are using .get() inside, it is not necessary to override them
But in case using TypeScript - this override will provide additional suggestions for your code.
*/
/**
* @returns {T} first fragment in collection
*/
first(): T {
return super.first() as T;
}
/**
* @returns {T} last fragment in collection
*/
last(): T {
return super.last() as T;
}
/**
* Allows to apply provided function to each element in this collection.
* Provided function will receive your custom fragment as first parameter.
*
* BUG: Exception on attempt to return ElementFinder from provided function:
* https://github.com/angular/protractor/issues/2227
*
* See documentation for ElementArrayFinder.map function
* http://www.protractortest.org/#/api?view=ElementArrayFinder.prototype.map
*
* @param {Function} mapFn Will receive your custom fragment as first parameter
*
* @returns {wdpromise.Promise<any[]>} Promise, that will be resolved to array with results.
*/
map(mapFn: (elementFinder?: T, index?: number) => any): wdpromise.Promise<any[]> {
return super.map((elementFinder, index) => {
return mapFn(new this.class_(elementFinder), index);
});
}
/**
* Allows to apply provided function to each element in this collection.
* Provided function will receive your custom fragment as first parameter.
* If provided function returns false for some element in collection - this element will be excluded from collection.
*
* See documentation for ElementArrayFinder.filter function
* http://www.protractortest.org/#/api?view=ElementArrayFinder.prototype.filter
*
* @param {Function} filterFn Will receive your custom fragment as first parameter
*
* @returns {T} new object that contains filtered values
*/
filter(filterFn: (elementFinder?: T, index?: number) => boolean | wdpromise.Promise<boolean> | Promise<boolean>): this {
// recreating same object, but with different elements inside it by calling constructor again
// Super-magic here, using 'any' for filter function to allow native promises to be returned
// So you can use async functions as filterFn
return new (this.constructor as any)(
super.filter(
(elementFinder, index): any => {
return filterFn(new this.class_(elementFinder), index);
}
),
this.class_
);
}
/**
* Allows to reduce collection into single value.
*
* See documentation for ElementArrayFinder.reduce function
* http://www.protractortest.org/#/api?view=ElementArrayFinder.prototype.reduce
*
* @param {Function} reduceFn Will receive your custom fragment as second parameter
* @param {any} initialValue Initial value of the accumulator
* @returns {wdpromise.Promise<any>} Promise that will be resolved to final value of the accumulator
*/
reduce(reduceFn: (value?: any, elementFinder?: T, index?: number, arr?: any) => any, initialValue: any): wdpromise.Promise<any> {
return super.reduce((value, elementFinder, index, arr) => {
return reduceFn(value, new this.class_(elementFinder), index, arr);
}, initialValue);
}
/**
* Determines whether all the members of an BaseArrayFragment satisfy the specified test.
* Works the same as native Array.every(): return true for an empty BaseArrayFragment
* @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array.
* @returns {wdpromise.Promise<boolean>} Promise that will be resolved to test result
*/
every(
callbackfn: (elementFinder?: T, index?: number, array?: T[]) => boolean | wdpromise.Promise<boolean> | Promise<boolean>
): wdpromise.Promise<boolean> {
return this.reduce(async (value, elementFinder, index, arr) => {
const callbackResult = await callbackfn(elementFinder, index, arr);
return value && callbackResult;
}, true);
}
/**
* Determines whether the specified callback function returns true for any element of an BaseArrayFragment.
* Works the same as native Array.some(): return false for an empty BaseArrayFragment
* @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array.
* @returns {wdpromise.Promise<boolean>} Promise that will be resolved to test result
*/
some(
callbackfn: (elementFinder?: T, index?: number, array?: T[]) => boolean | wdpromise.Promise<boolean> | Promise<boolean>
): wdpromise.Promise<boolean> {
return this.reduce(async (value, elementFinder, index, arr) => {
const callbackResult = await callbackfn(elementFinder, index, arr);
return value || callbackResult;
}, false);
}
/**
* Returns the value of the first element in the BaseArrayFragment where predicate is true, and undefined
* otherwise.
* @param predicate find calls predicate once for each element of the BaseArrayFragment, in ascending
* order, until it finds one where predicate returns true. Otherwise, find returns undefined.
* @returns {Promise<T | undefined>} Promise that will be resolved to first found <T extends ElementFinder> or undefined
*/
async find(
predicate: (elementFinder?: T, index?: number, array?: T[]) => boolean | wdpromise.Promise<boolean> | Promise<boolean>
): Promise<T | undefined> {
const result = this.filter(async (elementFinder, index) => {
return predicate(elementFinder, index);
});
return (await result.count()) ? result.first() : undefined;
}
}