Skip to content

Commit 27e8b4c

Browse files
authored
release 3.5.9 (#4056)
* release 3.5.9 * fix: change log * fix: seeCssPropertiesOnElements verification condition (#4057) * fix: seeCssPropertiesOnElements verification condition * fix: UTs * fix: UTs * fix: UTs * fix: UTs * update changelog
1 parent 64aa4f9 commit 27e8b4c

File tree

9 files changed

+217
-39
lines changed

9 files changed

+217
-39
lines changed

.github/workflows/playwright.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,5 @@ jobs:
5050
run: "BROWSER=firefox node ./bin/codecept.js run -c test/acceptance/codecept.Playwright.js --grep @Playwright --debug"
5151
- name: run webkit tests
5252
run: "BROWSER=webkit node ./bin/codecept.js run -c test/acceptance/codecept.Playwright.js --grep @Playwright --debug"
53-
- name: run unit tests
53+
- name: run chromium unit tests
5454
run: ./node_modules/.bin/mocha test/helper/Playwright_test.js --timeout 5000

CHANGELOG.md

+160-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,170 @@
1+
## 3.5.9
2+
3+
❤️ Thanks all to those who contributed to make this release! ❤️
4+
5+
🛩️ *Features*
6+
* feat: expose WebElement (#4043) - by @KobeNguyenT
7+
```
8+
Now we expose the WebElements that are returned by the WebHelper and you could make the subsequence actions on them.
9+
10+
// Playwright helper would return the Locator
11+
12+
I.amOnPage('/form/focus_blur_elements');
13+
const webElements = await I.grabWebElements('#button');
14+
webElements[0].click();
15+
```
16+
* feat(playwright): support HAR replaying (#3990) - by @KobeNguyenT
17+
```
18+
Replaying from HAR
19+
20+
// Replay API requests from HAR.
21+
// Either use a matching response from the HAR,
22+
// or abort the request if nothing matches.
23+
I.replayFromHar('./output/har/something.har', { url: "*/**/api/v1/fruits" });
24+
I.amOnPage('https://demo.playwright.dev/api-mocking');
25+
I.see('CodeceptJS');
26+
[Parameters]
27+
harFilePath [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) Path to recorded HAR file
28+
opts [object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)? [Options for replaying from HAR](https://playwright.dev/docs/api/class-page#page-route-from-har)
29+
```
30+
* feat(playwright): support HAR recording (#3986) - by @KobeNguyenT
31+
```
32+
A HAR file is an HTTP Archive file that contains a record of all the network requests that are made when a page is loaded.
33+
It contains information about the request and response headers, cookies, content, timings, and more.
34+
You can use HAR files to mock network requests in your tests. HAR will be saved to output/har.
35+
More info could be found here https://playwright.dev/docs/api/class-browser#browser-new-context-option-record-har.
36+
37+
...
38+
recordHar: {
39+
mode: 'minimal', // possible values: 'minimal'|'full'.
40+
content: 'embed' // possible values: "omit"|"embed"|"attach".
41+
}
42+
...
43+
```
44+
* improvement(playwright): support partial string for option (#4016) - by @KobeNguyenT
45+
```
46+
await I.amOnPage('/form/select');
47+
await I.selectOption('Select your age', '21-');
48+
```
49+
50+
🐛 *Bug Fixes*
51+
* fix(playwright): proceedSee could not find the element (#4006) - by @hatufacci
52+
* fix(appium): remove the vendor prefix of 'bstack:options' (#4053) - by @mojtabaalavi
53+
* fix(workers): event improvements (#3953) - by @KobeNguyenT
54+
```
55+
Emit the new event: event.workers.result.
56+
57+
CodeceptJS also exposes the env var `process.env.RUNS_WITH_WORKERS` when running tests with run-workers command so that you could handle the events better in your plugins/helpers.
58+
59+
const { event } = require('codeceptjs');
60+
61+
module.exports = function() {
62+
// this event would trigger the `_publishResultsToTestrail` when running `run-workers` command
63+
event.dispatcher.on(event.workers.result, async () => {
64+
await _publishResultsToTestrail();
65+
});
66+
67+
// this event would not trigger the `_publishResultsToTestrail` multiple times when running `run-workers` command
68+
event.dispatcher.on(event.all.result, async () => {
69+
// when running `run` command, this env var is undefined
70+
if (!process.env.RUNS_WITH_WORKERS) await _publishResultsToTestrail();
71+
});
72+
}
73+
```
74+
* fix: ai html updates (#3962) - by @davert
75+
```
76+
replaced minify library with a modern and more secure fork. Fixes [email protected] Regular Expression Denial of Service vulnerability #3829
77+
AI class is implemented as singleton
78+
refactored heal.js plugin to work on edge cases
79+
add configuration params on number of fixes performed by ay heal
80+
improved recorder class to add more verbose log
81+
improved recorder class to ignore some of errors
82+
```
83+
* fix(appium): closeApp supports both Android/iOS (#4046) - by @KobeNguyenT
84+
* fix: some security vulnerability of some packages (#4045) - by @KobeNguyenT
85+
* fix: seeAttributesOnElements check condition (#4029) - by @KobeNguyenT
86+
* fix: waitForText locator issue (#4039) - by @KobeNguyenT
87+
```
88+
Fixed this error:
89+
90+
locator.isVisible: Unexpected token "s" while parsing selector ":has-text('Were you able to resolve the resident's issue?') >> nth=0"
91+
at Playwright.waitForText (node_modules\codeceptjs\lib\helper\Playwright.js:2584:79)
92+
```
93+
* fix: move to sha256 (#4038) - by @KobeNguyenT
94+
* fix: respect retries from retryfailedstep plugin in helpers (#4028) - by @KobeNguyenT
95+
```
96+
Currently inside the _before() of helpers for example Playwright, the retries is set there, however, when retryFailedStep plugin is enabled, the retries of recorder is still using the value from _before() not the value from retryFailedStep plugin.
97+
98+
Fix:
99+
100+
- introduce the process.env.FAILED_STEP_RETIRES which could be access everywhere as the helper won't know anything about the plugin.
101+
- set default retries of Playwright to 3 to be on the same page with Puppeteer.
102+
```
103+
* fix: examples in test title (#4030) - by @KobeNguyenT
104+
```
105+
When test title doesn't have the data in examples:
106+
107+
Feature: Faker examples
108+
109+
Scenario Outline: Below are the users
110+
Examples:
111+
| user | role |
112+
| John | admin |
113+
| Tim | client |
114+
115+
Faker examples --
116+
[1] Starting recording promises
117+
Timeouts:
118+
Below are the users {"user":"John","role":"admin"}
119+
✔ OK in 4ms
120+
121+
Below are the users {"user":"Tim","role":"client"}
122+
✔ OK in 1ms
123+
124+
When test title includes the data in examples:
125+
126+
127+
Feature: Faker examples
128+
129+
Scenario Outline: Below are the users - <user> - <role>
130+
Examples:
131+
| user | role |
132+
| John | admin |
133+
| Tim | client |
134+
135+
136+
Faker examples --
137+
[1] Starting recording promises
138+
Timeouts:
139+
Below are the users - John - admin
140+
✔ OK in 4ms
141+
142+
Below are the users - Tim - client
143+
✔ OK in 1ms
144+
```
145+
* fix: disable retryFailedStep when using with tryTo (#4022) - by @KobeNguyenT
146+
* fix: locator builder returns error when class name contains hyphen (#4024) - by @KobeNguyenT
147+
* fix: seeCssPropertiesOnElements failed when font-weight is a number (#4026) - by @KobeNguyenT
148+
* fix(appium): missing await on some steps of runOnIOS and runOnAndroid (#4018) - by @KobeNguyenT
149+
* fix(cli): no error of failed tests when using retry with scenario only (#4020) - by @KobeNguyenT
150+
* fix: set getPageTimeout to 30s (#4031) - by @KobeNguyenT
151+
* fix(appium): expose switchToContext (#4015) - by @KobeNguyenT
152+
* fix: promise issue (#4013) - by @KobeNguyenT
153+
* fix: seeCssPropertiesOnElements issue with improper condition (#4057) - by @KobeNguyenT
154+
155+
📖 *Documentation*
156+
* docs: Update clearCookie documentation for Playwright helper (#4005) - by @Hellosager
157+
* docs: improve the example code for autoLogin (#4019) - by @KobeNguyenT
158+
![Screenshot 2023-11-22 at 14 40 11](https://github.com/codeceptjs/CodeceptJS/assets/7845001/c05ac436-efd0-4bc0-a46c-386f915c0f17)
159+
1160
## 3.5.8
2161

3162
Thanks all to those who contributed to make this release!
4163

5164
🐛 *Bug Fixes*
6165
fix(appium): type of setNetworkConnection() (#3994) - by @mirao
7166
fix: improve the way to show deprecated appium v1 message (#3992) - by @KobeNguyenT
8-
fix: missing exit condition of some wait functions - by @kobenguyent
167+
fix: missing exit condition of some wait functions - by @KobeNguyenT
9168

10169
## 3.5.7
11170

lib/colorUtils.js

+10
Original file line numberDiff line numberDiff line change
@@ -226,15 +226,25 @@ function isColorProperty(prop) {
226226
'color',
227227
'background',
228228
'backgroundColor',
229+
'background-color',
229230
'borderColor',
231+
'border-color',
230232
'borderBottomColor',
233+
'border-bottom-color',
231234
'borderLeftColor',
235+
'border-left-color',
232236
'borderRightColor',
233237
'borderTopColor',
234238
'caretColor',
235239
'columnRuleColor',
236240
'outlineColor',
237241
'textDecorationColor',
242+
'border-right-color',
243+
'border-top-color',
244+
'caret-color',
245+
'column-rule-color',
246+
'outline-color',
247+
'text-decoration-color',
238248
].indexOf(prop) > -1;
239249
}
240250

lib/helper/Playwright.js

+7-10
Original file line numberDiff line numberDiff line change
@@ -2119,29 +2119,26 @@ class Playwright extends Helper {
21192119

21202120
const cssPropertiesCamelCase = convertCssPropertiesToCamelCase(cssProperties);
21212121
const elemAmount = res.length;
2122-
const commands = [];
21232122
let props = [];
21242123

21252124
for (const element of res) {
2126-
const cssProperties = await element.evaluate((el) => getComputedStyle(el));
2127-
2128-
Object.keys(cssPropertiesCamelCase).forEach(prop => {
2125+
for (const prop of Object.keys(cssProperties)) {
2126+
const cssProp = await this.grabCssPropertyFrom(locator, prop);
21292127
if (isColorProperty(prop)) {
2130-
props.push(convertColorToRGBA(cssProperties[prop]));
2128+
props.push(convertColorToRGBA(cssProp));
21312129
} else {
2132-
props.push(cssProperties[prop]);
2130+
props.push(cssProp);
21332131
}
2134-
});
2132+
}
21352133
}
21362134

21372135
const values = Object.keys(cssPropertiesCamelCase).map(key => cssPropertiesCamelCase[key]);
21382136
if (!Array.isArray(props)) props = [props];
21392137
let chunked = chunkArray(props, values.length);
21402138
chunked = chunked.filter((val) => {
21412139
for (let i = 0; i < val.length; ++i) {
2142-
const _acutal = Number.isNaN(val[i]) || (typeof values[i]) === 'string' ? val[i] : Number.parseInt(val[i], 10);
2143-
const _expected = Number.isNaN(values[i]) || (typeof values[i]) === 'string' ? values[i] : Number.parseInt(values[i], 10);
2144-
if (_acutal !== _expected) return false;
2140+
// eslint-disable-next-line eqeqeq
2141+
if (val[i] != values[i]) return false;
21452142
}
21462143
return true;
21472144
});

lib/helper/Puppeteer.js

+15-20
Original file line numberDiff line numberDiff line change
@@ -1770,31 +1770,26 @@ class Puppeteer extends Helper {
17701770

17711771
const cssPropertiesCamelCase = convertCssPropertiesToCamelCase(cssProperties);
17721772
const elemAmount = res.length;
1773-
const commands = [];
1774-
res.forEach((el) => {
1775-
Object.keys(cssPropertiesCamelCase).forEach((prop) => {
1776-
commands.push(el.executionContext()
1777-
.evaluate((el) => {
1778-
const style = window.getComputedStyle ? getComputedStyle(el) : el.currentStyle;
1779-
return JSON.parse(JSON.stringify(style));
1780-
}, el)
1781-
.then((props) => {
1782-
if (isColorProperty(prop)) {
1783-
return convertColorToRGBA(props[prop]);
1784-
}
1785-
return props[prop];
1786-
}));
1787-
});
1788-
});
1789-
let props = await Promise.all(commands);
1773+
let props = [];
1774+
1775+
for (const element of res) {
1776+
for (const prop of Object.keys(cssProperties)) {
1777+
const cssProp = await this.grabCssPropertyFrom(locator, prop);
1778+
if (isColorProperty(prop)) {
1779+
props.push(convertColorToRGBA(cssProp));
1780+
} else {
1781+
props.push(cssProp);
1782+
}
1783+
}
1784+
}
1785+
17901786
const values = Object.keys(cssPropertiesCamelCase).map(key => cssPropertiesCamelCase[key]);
17911787
if (!Array.isArray(props)) props = [props];
17921788
let chunked = chunkArray(props, values.length);
17931789
chunked = chunked.filter((val) => {
17941790
for (let i = 0; i < val.length; ++i) {
1795-
const _acutal = Number.isNaN(val[i]) || (typeof values[i]) === 'string' ? val[i] : Number.parseInt(val[i], 10);
1796-
const _expected = Number.isNaN(values[i]) || (typeof values[i]) === 'string' ? values[i] : Number.parseInt(values[i], 10);
1797-
if (_acutal !== _expected) return false;
1791+
// eslint-disable-next-line eqeqeq
1792+
if (val[i] != values[i]) return false;
17981793
}
17991794
return true;
18001795
});

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codeceptjs",
3-
"version": "3.5.8",
3+
"version": "3.5.9",
44
"description": "Supercharged End 2 End Testing Framework for NodeJS",
55
"keywords": [
66
"acceptance",
@@ -59,7 +59,8 @@
5959
"publish:site": "./runok.js publish:site",
6060
"update-contributor-faces": "./runok.js contributor:faces",
6161
"dtslint": "dtslint typings --localTs './node_modules/typescript/lib'",
62-
"prepare": "husky install"
62+
"prepare": "husky install",
63+
"prepare-release": "./runok.js versioning && ./runok.js get:commit-log"
6364
},
6465
"dependencies": {
6566
"@codeceptjs/configure": "0.10.0",

runok.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -429,14 +429,14 @@ title: ${name}
429429
const changelog = fs.readFileSync(file).toString();
430430

431431
const _changelog = `## ${newVersion}\n
432-
Thanks all to those who contributed to make this release!
432+
❤️ Thanks all to those who contributed to make this release! ❤️
433+
434+
🛩️ *Features*
433435
434436
🐛 *Bug Fixes*
435437
436438
📖 *Documentation*
437439
438-
🛩️ *Features*
439-
440440
${changelog}`;
441441

442442
fs.writeFileSync(`./${file}`, _changelog);
@@ -448,7 +448,7 @@ ${changelog}`;
448448

449449
async getCommitLog() {
450450
console.log('Gathering commits...');
451-
const logs = await exec('git log --pretty=\'format:%s - by %aN\' $(git describe --abbrev=0 --tags)..HEAD');
451+
const logs = await exec('git log --pretty=\'format:* %s - by @%aN\' $(git describe --abbrev=0 --tags)..HEAD');
452452
console.log(logs.data.stdout);
453453
},
454454

test/helper/Playwright_test.js

+16
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ describe('Playwright', function () {
3333
I = new Playwright({
3434
url: siteUrl,
3535
windowSize: '500x700',
36+
browser: process.env.BROWSER || 'chromium',
3637
show: false,
3738
waitForTimeout: 5000,
3839
waitForAction: 500,
@@ -112,6 +113,17 @@ describe('Playwright', function () {
112113
});
113114
});
114115

116+
describe('#seeCssPropertiesOnElements', () => {
117+
it('should check background-color css property for given element', async () => {
118+
try {
119+
await I.amOnPage('https://codecept.io/helpers/Playwright/');
120+
await I.seeCssPropertiesOnElements('.navbar', { 'background-color': 'rgb(128, 90, 213)' });
121+
} catch (e) {
122+
e.message.should.include('expected element (.navbar) to have CSS property { \'background-color\': \'rgb(128, 90, 213)\' }');
123+
}
124+
});
125+
});
126+
115127
webApiTests.tests();
116128

117129
describe('#click', () => {
@@ -1051,6 +1063,7 @@ describe('Playwright', function () {
10511063

10521064
describe('#startRecordingWebSocketMessages, #grabWebSocketMessages, #stopRecordingWebSocketMessages', () => {
10531065
it('should throw error when calling grabWebSocketMessages before startRecordingWebSocketMessages', () => {
1066+
if (process.env.BROWSER === 'firefox') this.skip();
10541067
try {
10551068
I.amOnPage('https://websocketstest.com/');
10561069
I.waitForText('Work for You!');
@@ -1061,6 +1074,7 @@ describe('Playwright', function () {
10611074
});
10621075

10631076
it('should flush the WS messages', async () => {
1077+
if (process.env.BROWSER === 'firefox') this.skip();
10641078
await I.startRecordingWebSocketMessages();
10651079
I.amOnPage('https://websocketstest.com/');
10661080
I.waitForText('Work for You!');
@@ -1070,6 +1084,7 @@ describe('Playwright', function () {
10701084
});
10711085

10721086
it('should see recording WS messages', async () => {
1087+
if (process.env.BROWSER === 'firefox') this.skip();
10731088
await I.startRecordingWebSocketMessages();
10741089
await I.amOnPage('https://websocketstest.com/');
10751090
I.waitForText('Work for You!');
@@ -1078,6 +1093,7 @@ describe('Playwright', function () {
10781093
});
10791094

10801095
it('should not see recording WS messages', async () => {
1096+
if (process.env.BROWSER === 'firefox') this.skip();
10811097
await I.startRecordingWebSocketMessages();
10821098
await I.amOnPage('https://websocketstest.com/');
10831099
I.waitForText('Work for You!');

0 commit comments

Comments
 (0)