Skip to content

Commit 2534959

Browse files
DavertMikDavertMik
andauthored
Feat/els step options (#4781)
* added els step option * added comment for fn step class --------- Co-authored-by: DavertMik <[email protected]>
1 parent 2a242e4 commit 2534959

File tree

3 files changed

+265
-199
lines changed

3 files changed

+265
-199
lines changed

lib/els.js

Lines changed: 87 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,115 +1,124 @@
1-
const output = require('./output');
2-
const store = require('./store');
3-
const recorder = require('./recorder');
4-
const container = require('./container');
5-
const event = require('./event');
6-
const Step = require('./step');
7-
const { truth } = require('./assert/truth');
8-
const { isAsyncFunction, humanizeFunction } = require('./utils');
1+
const output = require('./output')
2+
const store = require('./store')
3+
const container = require('./container')
4+
const StepConfig = require('./step/config')
5+
const recordStep = require('./step/record')
6+
const FuncStep = require('./step/func')
7+
const { truth } = require('./assert/truth')
8+
const { isAsyncFunction, humanizeFunction } = require('./utils')
99

1010
function element(purpose, locator, fn) {
11-
if (!fn) {
12-
fn = locator;
13-
locator = purpose;
14-
purpose = 'first element';
11+
let stepConfig
12+
if (arguments[arguments.length - 1] instanceof StepConfig) {
13+
stepConfig = arguments[arguments.length - 1]
1514
}
1615

17-
const step = prepareStep(purpose, locator, fn);
18-
if (!step) return;
16+
if (!fn || fn === stepConfig) {
17+
fn = locator
18+
locator = purpose
19+
purpose = 'first element'
20+
}
1921

20-
return executeStep(step, async () => {
21-
const els = await step.helper._locate(locator);
22-
output.debug(`Found ${els.length} elements, using first element`);
22+
const step = prepareStep(purpose, locator, fn)
23+
if (!step) return
2324

24-
return fn(els[0]);
25-
});
25+
return executeStep(
26+
step,
27+
async () => {
28+
const els = await step.helper._locate(locator)
29+
output.debug(`Found ${els.length} elements, using first element`)
30+
31+
return fn(els[0])
32+
},
33+
stepConfig,
34+
)
2635
}
2736

2837
function eachElement(purpose, locator, fn) {
2938
if (!fn) {
30-
fn = locator;
31-
locator = purpose;
32-
purpose = 'for each element';
39+
fn = locator
40+
locator = purpose
41+
purpose = 'for each element'
3342
}
3443

35-
const step = prepareStep(purpose, locator, fn);
36-
if (!step) return;
44+
const step = prepareStep(purpose, locator, fn)
45+
if (!step) return
3746

3847
return executeStep(step, async () => {
39-
const els = await step.helper._locate(locator);
40-
output.debug(`Found ${els.length} elements for each elements to iterate`);
48+
const els = await step.helper._locate(locator)
49+
output.debug(`Found ${els.length} elements for each elements to iterate`)
4150

42-
const errs = [];
43-
let i = 0;
51+
const errs = []
52+
let i = 0
4453
for (const el of els) {
4554
try {
46-
await fn(el, i);
55+
await fn(el, i)
4756
} catch (err) {
48-
output.error(`eachElement: failed operation on element #${i} ${el}`);
49-
errs.push(err);
57+
output.error(`eachElement: failed operation on element #${i} ${el}`)
58+
errs.push(err)
5059
}
51-
i++;
60+
i++
5261
}
5362

5463
if (errs.length) {
55-
throw errs[0];
64+
throw errs[0]
5665
}
57-
});
66+
})
5867
}
5968

6069
function expectElement(locator, fn) {
61-
const step = prepareStep('expect element to be', locator, fn);
62-
if (!step) return;
70+
const step = prepareStep('expect element to be', locator, fn)
71+
if (!step) return
6372

6473
return executeStep(step, async () => {
65-
const els = await step.helper._locate(locator);
66-
output.debug(`Found ${els.length} elements, first will be used for assertion`);
74+
const els = await step.helper._locate(locator)
75+
output.debug(`Found ${els.length} elements, first will be used for assertion`)
6776

68-
const result = await fn(els[0]);
69-
const assertion = truth(`element (${locator})`, fn.toString());
70-
assertion.assert(result);
71-
});
77+
const result = await fn(els[0])
78+
const assertion = truth(`element (${locator})`, fn.toString())
79+
assertion.assert(result)
80+
})
7281
}
7382

7483
function expectAnyElement(locator, fn) {
75-
const step = prepareStep('expect any element to be', locator, fn);
76-
if (!step) return;
84+
const step = prepareStep('expect any element to be', locator, fn)
85+
if (!step) return
7786

7887
return executeStep(step, async () => {
79-
const els = await step.helper._locate(locator);
80-
output.debug(`Found ${els.length} elements, at least one should pass the assertion`);
88+
const els = await step.helper._locate(locator)
89+
output.debug(`Found ${els.length} elements, at least one should pass the assertion`)
8190

82-
const assertion = truth(`any element of (${locator})`, fn.toString());
91+
const assertion = truth(`any element of (${locator})`, fn.toString())
8392

84-
let found = false;
93+
let found = false
8594
for (const el of els) {
86-
const result = await fn(el);
95+
const result = await fn(el)
8796
if (result) {
88-
found = true;
89-
break;
97+
found = true
98+
break
9099
}
91100
}
92-
if (!found) throw assertion.getException();
93-
});
101+
if (!found) throw assertion.getException()
102+
})
94103
}
95104

96105
function expectAllElements(locator, fn) {
97-
const step = prepareStep('expect all elements', locator, fn);
98-
if (!step) return;
106+
const step = prepareStep('expect all elements', locator, fn)
107+
if (!step) return
99108

100109
return executeStep(step, async () => {
101-
const els = await step.helper._locate(locator);
102-
output.debug(`Found ${els.length} elements, all should pass the assertion`);
110+
const els = await step.helper._locate(locator)
111+
output.debug(`Found ${els.length} elements, all should pass the assertion`)
103112

104-
let i = 1;
113+
let i = 1
105114
for (const el of els) {
106-
output.debug(`checking element #${i}: ${el}`);
107-
const result = await fn(el);
108-
const assertion = truth(`element #${i} of (${locator})`, humanizeFunction(fn));
109-
assertion.assert(result);
110-
i++;
115+
output.debug(`checking element #${i}: ${el}`)
116+
const result = await fn(el)
117+
const assertion = truth(`element #${i} of (${locator})`, humanizeFunction(fn))
118+
assertion.assert(result)
119+
i++
111120
}
112-
});
121+
})
113122
}
114123

115124
module.exports = {
@@ -118,60 +127,32 @@ module.exports = {
118127
expectElement,
119128
expectAnyElement,
120129
expectAllElements,
121-
};
130+
}
122131

123132
function prepareStep(purpose, locator, fn) {
124-
if (store.dryRun) return;
125-
const helpers = Object.values(container.helpers());
133+
if (store.dryRun) return
134+
const helpers = Object.values(container.helpers())
126135

127-
const helper = helpers.filter(h => !!h._locate)[0];
136+
const helper = helpers.filter(h => !!h._locate)[0]
128137

129138
if (!helper) {
130-
throw new Error('No helper enabled with _locate method with returns a list of elements.');
139+
throw new Error('No helper enabled with _locate method with returns a list of elements.')
131140
}
132141

133142
if (!isAsyncFunction(fn)) {
134-
throw new Error('Async function should be passed into each element');
143+
throw new Error('Async function should be passed into each element')
135144
}
136145

137-
const isAssertion = purpose.startsWith('expect');
146+
const isAssertion = purpose.startsWith('expect')
138147

139-
const step = new Step(helper, `${purpose} within "${locator}" ${isAssertion ? 'to be' : 'to'}`);
140-
step.setActor('EL');
141-
step.setArguments([humanizeFunction(fn)]);
142-
step.helperMethod = '_locate';
148+
const step = new FuncStep(`${purpose} within "${locator}" ${isAssertion ? 'to be' : 'to'}`)
149+
step.setHelper(helper)
150+
step.setArguments([humanizeFunction(fn)]) // user defined function is a passed argument
143151

144-
return step;
152+
return step
145153
}
146154

147-
async function executeStep(step, action) {
148-
let error;
149-
const promise = recorder.add('register element wrapper', async () => {
150-
event.emit(event.step.started, step);
151-
152-
try {
153-
await action();
154-
} catch (err) {
155-
recorder.throw(err);
156-
event.emit(event.step.failed, step, err);
157-
event.emit(event.step.finished, step);
158-
// event.emit(event.step.after, step)
159-
error = err;
160-
// await recorder.promise();
161-
return;
162-
}
163-
164-
event.emit(event.step.after, step);
165-
event.emit(event.step.passed, step);
166-
event.emit(event.step.finished, step);
167-
});
168-
169-
// await recorder.promise();
170-
171-
// if (error) {
172-
// console.log('error', error.inspect())
173-
// return recorder.throw(error);
174-
// }
175-
176-
return promise;
155+
async function executeStep(step, action, stepConfig = {}) {
156+
step.setCallable(action)
157+
return recordStep(step, [stepConfig])
177158
}

lib/step/func.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const BaseStep = require('./base')
2+
const store = require('../store')
3+
4+
/**
5+
* Function executed as a step
6+
*/
7+
class FuncStep extends BaseStep {
8+
// this is actual function that should be executed within step
9+
setCallable(fn) {
10+
this.fn = fn
11+
}
12+
13+
// helper is optional, if we need to allow step to access helper methods
14+
setHelper(helper) {
15+
this.helper = helper
16+
}
17+
18+
run() {
19+
if (!this.fn) throw new Error('Function is not set')
20+
21+
// we wrap that function to track time and status
22+
// and disable it in dry run mode
23+
this.args = Array.prototype.slice.call(arguments)
24+
this.startTime = +Date.now()
25+
26+
if (store.dryRun) {
27+
this.setStatus('success')
28+
// should we add Proxy and dry run resolver here?
29+
return Promise.resolve(true)
30+
}
31+
32+
let result
33+
try {
34+
result = this.fn.apply(this.helper, this.args)
35+
this.setStatus('success')
36+
this.endTime = +Date.now()
37+
} catch (err) {
38+
this.endTime = +Date.now()
39+
this.setStatus('failed')
40+
throw err
41+
}
42+
return result
43+
}
44+
}
45+
46+
module.exports = FuncStep

0 commit comments

Comments
 (0)