Skip to content

Commit

Permalink
feat(webapi): add waitForCookie (#4169)
Browse files Browse the repository at this point in the history
  • Loading branch information
kobenguyent authored Feb 4, 2024
1 parent 91c1840 commit 6f99119
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 1 deletion.
15 changes: 15 additions & 0 deletions docs/helpers/Playwright.md
Original file line number Diff line number Diff line change
Expand Up @@ -2398,6 +2398,21 @@ I.waitForClickable('.btn.continue', 5); // wait for 5 secs

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

### waitForCookie

Waits for the specified cookie in the cookies.

```js
I.waitForCookie("token");
```

#### Parameters

- `name` **[string][9]** expected cookie name.
- `sec` **[number][20]** (optional, `3` by default) time in seconds to wait

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

### waitForDetached

Waits for an element to become not attached to the DOM on a page (by default waits for 1sec).
Expand Down
15 changes: 15 additions & 0 deletions docs/helpers/Puppeteer.md
Original file line number Diff line number Diff line change
Expand Up @@ -2003,6 +2003,21 @@ I.waitForClickable('.btn.continue', 5); // wait for 5 secs
Returns **void** automatically synchronized promise through #recorder
### waitForCookie
Waits for the specified cookie in the cookies.
```js
I.waitForCookie("token");
```
#### Parameters
- `name` **[string][6]** expected cookie name.
- `sec` **[number][10]** (optional, `3` by default) time in seconds to wait
Returns **void** automatically synchronized promise through #recorder
### waitForDetached
Waits for an element to become not attached to the DOM on a page (by default waits for 1sec).
Expand Down
15 changes: 15 additions & 0 deletions docs/helpers/WebDriver.md
Original file line number Diff line number Diff line change
Expand Up @@ -2253,6 +2253,21 @@ I.waitForClickable('.btn.continue', 5); // wait for 5 secs
Returns **void** automatically synchronized promise through #recorder
### waitForCookie
Waits for the specified cookie in the cookies.
```js
I.waitForCookie("token");
```
#### Parameters
- `name` **[string][18]** expected cookie name.
- `sec` **[number][23]** (optional, `3` by default) time in seconds to wait
Returns **void** automatically synchronized promise through #recorder
### waitForDetached
Waits for an element to become not attached to the DOM on a page (by default waits for 1sec).
Expand Down
9 changes: 9 additions & 0 deletions docs/webapi/waitForCookie.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Waits for the specified cookie in the cookies.

```js
I.waitForCookie("token");
```

@param {string} name expected cookie name.
@param {number} [sec=3] (optional, `3` by default) time in seconds to wait
@returns {void} automatically synchronized promise through #recorder
34 changes: 34 additions & 0 deletions lib/helper/Playwright.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const fs = require('fs');
const Helper = require('@codeceptjs/helper');
const { v4: uuidv4 } = require('uuid');
const assert = require('assert');
const promiseRetry = require('promise-retry');
const Locator = require('../locator');
const store = require('../store');
const recorder = require('../recorder');
Expand Down Expand Up @@ -50,6 +51,7 @@ const { createValueEngine, createDisabledEngine } = require('./extras/Playwright
const {
seeElementError, dontSeeElementError, dontSeeElementInDOMError, seeElementInDOMError,
} = require('./errors/ElementAssertion');
const { log } = require('../output');

const pathSeparator = path.sep;

Expand Down Expand Up @@ -2890,6 +2892,38 @@ class Playwright extends Helper {
}
}

/**
* {{> waitForCookie }}
*/
async waitForCookie(name, sec) {
// by default, we will retry 3 times
let retries = 3;
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;

if (sec) {
retries = sec;
} else {
retries = Math.ceil(waitTimeout / 1000) - 1;
}

return promiseRetry(async (retry, number) => {
const _grabCookie = async (name) => {
const cookies = await this.browserContext.cookies();
const cookie = cookies.filter(c => c.name === name);
if (cookie.length === 0) throw Error(`Cookie ${name} is not found after ${retries}s`);
};

this.debugSection('Wait for cookie: ', name);
if (number > 1) this.debugSection('Retrying... Attempt #', number);

try {
await _grabCookie(name);
} catch (e) {
retry(e);
}
}, { retries, maxTimeout: 1000 });
}

async _waitForAction() {
return this.wait(this.options.waitForAction / 1000);
}
Expand Down
33 changes: 33 additions & 0 deletions lib/helper/Puppeteer.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const path = require('path');

const Helper = require('@codeceptjs/helper');
const { v4: uuidv4 } = require('uuid');
const promiseRetry = require('promise-retry');
const Locator = require('../locator');
const recorder = require('../recorder');
const store = require('../store');
Expand Down Expand Up @@ -1635,6 +1636,38 @@ class Puppeteer extends Helper {
if (cookie[0]) return cookie[0];
}

/**
* {{> waitForCookie }}
*/
async waitForCookie(name, sec) {
// by default, we will retry 3 times
let retries = 3;
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout;

if (sec) {
retries = sec;
} else {
retries = Math.ceil(waitTimeout / 1000) - 1;
}

return promiseRetry(async (retry, number) => {
const _grabCookie = async (name) => {
const cookies = await this.page.cookies();
const cookie = cookies.filter(c => c.name === name);
if (cookie.length === 0) throw Error(`Cookie ${name} is not found after ${retries}s`);
};

this.debugSection('Wait for cookie: ', name);
if (number > 1) this.debugSection('Retrying... Attempt #', number);

try {
await _grabCookie(name);
} catch (e) {
retry(e);
}
}, { retries, maxTimeout: 1000 });
}

/**
* {{> clearCookie }}
*/
Expand Down
32 changes: 32 additions & 0 deletions lib/helper/WebDriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const fs = require('fs');

const Helper = require('@codeceptjs/helper');
const crypto = require('crypto');
const promiseRetry = require('promise-retry');
const stringIncludes = require('../assert/include').includes;
const { urlEquals, equals } = require('../assert/equal');
const { debug } = require('../output');
Expand Down Expand Up @@ -1860,6 +1861,37 @@ class WebDriver extends Helper {
return cookie[0];
}

/**
* {{> waitForCookie }}
*/
async waitForCookie(name, sec) {
// by default, we will retry 3 times
let retries = 3;
const waitTimeout = sec || this.options.waitForTimeoutInSeconds;

if (sec) {
retries = sec;
} else {
retries = waitTimeout - 1;
}

return promiseRetry(async (retry, number) => {
const _grabCookie = async (name) => {
const cookie = await this.browser.getCookies([name]);
if (cookie.length === 0) throw Error(`Cookie ${name} is not found after ${retries}s`);
};

this.debugSection('Wait for cookie: ', name);
if (number > 1) this.debugSection('Retrying... Attempt #', number);

try {
await _grabCookie(name);
} catch (e) {
retry(e);
}
}, { retries, maxTimeout: 1000 });
}

/**
* Accepts the active JavaScript native popup window, as created by window.alert|window.confirm|window.prompt.
* Don't confuse popups with modal windows, as created by [various
Expand Down
27 changes: 26 additions & 1 deletion test/helper/webapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -842,7 +842,7 @@ module.exports.tests = function () {
});
});

describe('cookies : #setCookie, #clearCookies, #seeCookie', () => {
describe('cookies : #setCookie, #clearCookies, #seeCookie, #waitForCookie', () => {
it('should do all cookie stuff', async () => {
await I.amOnPage('/');
await I.setCookie({
Expand Down Expand Up @@ -889,6 +889,31 @@ module.exports.tests = function () {
await I.clearCookie();
await I.dontSeeCookie('auth');
});

it('should wait for cookie and throw error when cookie not found', async () => {
if (isHelper('TestCafe')) return;
if (process.env.DevTools) return;

await I.amOnPage('https://google.com');
try {
await I.waitForCookie('auth', 2);
} catch (e) {
assert.equal(e.message, 'Cookie auth is not found after 2s');
}
});

it('should wait for cookie', async () => {
if (isHelper('TestCafe')) return;
if (process.env.DevTools) return;

await I.amOnPage('/');
await I.setCookie({
name: 'auth',
value: '123456',
url: 'http://localhost',
});
await I.waitForCookie('auth');
});
});

describe('#waitForText', () => {
Expand Down

0 comments on commit 6f99119

Please sign in to comment.