Skip to content

Commit 6f99119

Browse files
authored
feat(webapi): add waitForCookie (#4169)
1 parent 91c1840 commit 6f99119

File tree

8 files changed

+179
-1
lines changed

8 files changed

+179
-1
lines changed

docs/helpers/Playwright.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2398,6 +2398,21 @@ I.waitForClickable('.btn.continue', 5); // wait for 5 secs
23982398

23992399
Returns **void** automatically synchronized promise through #recorder
24002400

2401+
### waitForCookie
2402+
2403+
Waits for the specified cookie in the cookies.
2404+
2405+
```js
2406+
I.waitForCookie("token");
2407+
```
2408+
2409+
#### Parameters
2410+
2411+
- `name` **[string][9]** expected cookie name.
2412+
- `sec` **[number][20]** (optional, `3` by default) time in seconds to wait
2413+
2414+
Returns **void** automatically synchronized promise through #recorder
2415+
24012416
### waitForDetached
24022417

24032418
Waits for an element to become not attached to the DOM on a page (by default waits for 1sec).

docs/helpers/Puppeteer.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2003,6 +2003,21 @@ I.waitForClickable('.btn.continue', 5); // wait for 5 secs
20032003
20042004
Returns **void** automatically synchronized promise through #recorder
20052005
2006+
### waitForCookie
2007+
2008+
Waits for the specified cookie in the cookies.
2009+
2010+
```js
2011+
I.waitForCookie("token");
2012+
```
2013+
2014+
#### Parameters
2015+
2016+
- `name` **[string][6]** expected cookie name.
2017+
- `sec` **[number][10]** (optional, `3` by default) time in seconds to wait
2018+
2019+
Returns **void** automatically synchronized promise through #recorder
2020+
20062021
### waitForDetached
20072022
20082023
Waits for an element to become not attached to the DOM on a page (by default waits for 1sec).

docs/helpers/WebDriver.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2253,6 +2253,21 @@ I.waitForClickable('.btn.continue', 5); // wait for 5 secs
22532253
22542254
Returns **void** automatically synchronized promise through #recorder
22552255
2256+
### waitForCookie
2257+
2258+
Waits for the specified cookie in the cookies.
2259+
2260+
```js
2261+
I.waitForCookie("token");
2262+
```
2263+
2264+
#### Parameters
2265+
2266+
- `name` **[string][18]** expected cookie name.
2267+
- `sec` **[number][23]** (optional, `3` by default) time in seconds to wait
2268+
2269+
Returns **void** automatically synchronized promise through #recorder
2270+
22562271
### waitForDetached
22572272
22582273
Waits for an element to become not attached to the DOM on a page (by default waits for 1sec).

docs/webapi/waitForCookie.mustache

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Waits for the specified cookie in the cookies.
2+
3+
```js
4+
I.waitForCookie("token");
5+
```
6+
7+
@param {string} name expected cookie name.
8+
@param {number} [sec=3] (optional, `3` by default) time in seconds to wait
9+
@returns {void} automatically synchronized promise through #recorder

lib/helper/Playwright.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const fs = require('fs');
44
const Helper = require('@codeceptjs/helper');
55
const { v4: uuidv4 } = require('uuid');
66
const assert = require('assert');
7+
const promiseRetry = require('promise-retry');
78
const Locator = require('../locator');
89
const store = require('../store');
910
const recorder = require('../recorder');
@@ -50,6 +51,7 @@ const { createValueEngine, createDisabledEngine } = require('./extras/Playwright
5051
const {
5152
seeElementError, dontSeeElementError, dontSeeElementInDOMError, seeElementInDOMError,
5253
} = require('./errors/ElementAssertion');
54+
const { log } = require('../output');
5355

5456
const pathSeparator = path.sep;
5557

@@ -2890,6 +2892,38 @@ class Playwright extends Helper {
28902892
}
28912893
}
28922894

2895+
/**
2896+
* {{> waitForCookie }}
2897+
*/
2898+
async waitForCookie(name, sec) {
2899+
// by default, we will retry 3 times
2900+
let retries = 3;
2901+
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
2902+
2903+
if (sec) {
2904+
retries = sec;
2905+
} else {
2906+
retries = Math.ceil(waitTimeout / 1000) - 1;
2907+
}
2908+
2909+
return promiseRetry(async (retry, number) => {
2910+
const _grabCookie = async (name) => {
2911+
const cookies = await this.browserContext.cookies();
2912+
const cookie = cookies.filter(c => c.name === name);
2913+
if (cookie.length === 0) throw Error(`Cookie ${name} is not found after ${retries}s`);
2914+
};
2915+
2916+
this.debugSection('Wait for cookie: ', name);
2917+
if (number > 1) this.debugSection('Retrying... Attempt #', number);
2918+
2919+
try {
2920+
await _grabCookie(name);
2921+
} catch (e) {
2922+
retry(e);
2923+
}
2924+
}, { retries, maxTimeout: 1000 });
2925+
}
2926+
28932927
async _waitForAction() {
28942928
return this.wait(this.options.waitForAction / 1000);
28952929
}

lib/helper/Puppeteer.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const path = require('path');
55

66
const Helper = require('@codeceptjs/helper');
77
const { v4: uuidv4 } = require('uuid');
8+
const promiseRetry = require('promise-retry');
89
const Locator = require('../locator');
910
const recorder = require('../recorder');
1011
const store = require('../store');
@@ -1635,6 +1636,38 @@ class Puppeteer extends Helper {
16351636
if (cookie[0]) return cookie[0];
16361637
}
16371638

1639+
/**
1640+
* {{> waitForCookie }}
1641+
*/
1642+
async waitForCookie(name, sec) {
1643+
// by default, we will retry 3 times
1644+
let retries = 3;
1645+
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;
1646+
1647+
if (sec) {
1648+
retries = sec;
1649+
} else {
1650+
retries = Math.ceil(waitTimeout / 1000) - 1;
1651+
}
1652+
1653+
return promiseRetry(async (retry, number) => {
1654+
const _grabCookie = async (name) => {
1655+
const cookies = await this.page.cookies();
1656+
const cookie = cookies.filter(c => c.name === name);
1657+
if (cookie.length === 0) throw Error(`Cookie ${name} is not found after ${retries}s`);
1658+
};
1659+
1660+
this.debugSection('Wait for cookie: ', name);
1661+
if (number > 1) this.debugSection('Retrying... Attempt #', number);
1662+
1663+
try {
1664+
await _grabCookie(name);
1665+
} catch (e) {
1666+
retry(e);
1667+
}
1668+
}, { retries, maxTimeout: 1000 });
1669+
}
1670+
16381671
/**
16391672
* {{> clearCookie }}
16401673
*/

lib/helper/WebDriver.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const fs = require('fs');
66

77
const Helper = require('@codeceptjs/helper');
88
const crypto = require('crypto');
9+
const promiseRetry = require('promise-retry');
910
const stringIncludes = require('../assert/include').includes;
1011
const { urlEquals, equals } = require('../assert/equal');
1112
const { debug } = require('../output');
@@ -1860,6 +1861,37 @@ class WebDriver extends Helper {
18601861
return cookie[0];
18611862
}
18621863

1864+
/**
1865+
* {{> waitForCookie }}
1866+
*/
1867+
async waitForCookie(name, sec) {
1868+
// by default, we will retry 3 times
1869+
let retries = 3;
1870+
const waitTimeout = sec || this.options.waitForTimeoutInSeconds;
1871+
1872+
if (sec) {
1873+
retries = sec;
1874+
} else {
1875+
retries = waitTimeout - 1;
1876+
}
1877+
1878+
return promiseRetry(async (retry, number) => {
1879+
const _grabCookie = async (name) => {
1880+
const cookie = await this.browser.getCookies([name]);
1881+
if (cookie.length === 0) throw Error(`Cookie ${name} is not found after ${retries}s`);
1882+
};
1883+
1884+
this.debugSection('Wait for cookie: ', name);
1885+
if (number > 1) this.debugSection('Retrying... Attempt #', number);
1886+
1887+
try {
1888+
await _grabCookie(name);
1889+
} catch (e) {
1890+
retry(e);
1891+
}
1892+
}, { retries, maxTimeout: 1000 });
1893+
}
1894+
18631895
/**
18641896
* Accepts the active JavaScript native popup window, as created by window.alert|window.confirm|window.prompt.
18651897
* Don't confuse popups with modal windows, as created by [various

test/helper/webapi.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ module.exports.tests = function () {
842842
});
843843
});
844844

845-
describe('cookies : #setCookie, #clearCookies, #seeCookie', () => {
845+
describe('cookies : #setCookie, #clearCookies, #seeCookie, #waitForCookie', () => {
846846
it('should do all cookie stuff', async () => {
847847
await I.amOnPage('/');
848848
await I.setCookie({
@@ -889,6 +889,31 @@ module.exports.tests = function () {
889889
await I.clearCookie();
890890
await I.dontSeeCookie('auth');
891891
});
892+
893+
it('should wait for cookie and throw error when cookie not found', async () => {
894+
if (isHelper('TestCafe')) return;
895+
if (process.env.DevTools) return;
896+
897+
await I.amOnPage('https://google.com');
898+
try {
899+
await I.waitForCookie('auth', 2);
900+
} catch (e) {
901+
assert.equal(e.message, 'Cookie auth is not found after 2s');
902+
}
903+
});
904+
905+
it('should wait for cookie', async () => {
906+
if (isHelper('TestCafe')) return;
907+
if (process.env.DevTools) return;
908+
909+
await I.amOnPage('/');
910+
await I.setCookie({
911+
name: 'auth',
912+
value: '123456',
913+
url: 'http://localhost',
914+
});
915+
await I.waitForCookie('auth');
916+
});
892917
});
893918

894919
describe('#waitForText', () => {

0 commit comments

Comments
 (0)