Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/command-line/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ testplane --repl --grep 'my test name' --browser chrome
- `--keep-browser-on-fail` - the same as the `--keep-browser` option, but the browser will only remain open if the tests fail.

Example of console output with connection information to the browser:

```
[15:44:38 +0700] Testplane run has finished, but the browser won't be closed, because you passed the --keep-browser argument.
[15:44:38 +0700] You may attach to this browser using the following capabilities:
Expand Down
151 changes: 151 additions & 0 deletions docs/commands/browser/restoreState.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import Admonition from "@theme/Admonition";

# restoreState

## Overview {#overview}

Browser command that restores session state (cookies, local and session storages) from a file or variable.

## Usage {#usage}

You can restore the browser state from either a file (using the `path` parameter) or directly from an object (using the `data` parameter).

**Important:** If you provide both `path` and `data` parameters, the file specified in `path` will take priority.

You can optionally specify which storage types to restore using the `cookies`, `localStorage`, and `sessionStorage` parameters. This allows you to restore only the specific data you need.

The state data for restoration can be obtained from the [saveState](../saveState) command.

<Admonition type="warning">
You must be on the exact same page from which the cookies were originally saved. You need to
navigate to the page first, use the [url](../url) command before restoring state.
</Admonition>

```typescript
await browser.restoreState({
path: "./stateDump.json",
data: stateDump,
cookies: true,
localStorage: true,
sessionStorage: true,
});
```

## Command Parameters {#parameters}

<table>
<thead>
<tr>
<td>**Name**</td>
<td>**Type**</td>
<td>**Default**</td>
<td>**Description**</td>
</tr>
</thead>
<tbody>
<tr>
<td>path</td>
<td>`string`</td>
<td>`-`</td>
<td>Path to file with state.</td>
</tr>
<tr>
<td>data</td>
<td>`SaveStateData`</td>
<td>`-`</td>
<td>Object with state.</td>
</tr>
<tr>
<td>cookies</td>
<td>`boolean`</td>
<td>`true`</td>
<td>Enable restore cookies (true by default).</td>
</tr>
<tr>
<td>localStorage</td>
<td>`boolean`</td>
<td>`true`</td>
<td>Enable restore localStorage (true by default).</td>
</tr>
<tr>
<td>sessionStorage</td>
<td>`boolean`</td>
<td>`true`</td>
<td>Enable restore sessionStorage (true by default).</td>
</tr>
<tr>
<td>cookieFilter</td>
<td>`(cookie: Cookie) => boolean`</td>
<td>`-`</td>
<td>
Function for filtering cookies, receiving cookie objects, and returning boolean.
</td>
</tr>
</tbody>
</table>

## Usage Examples {#examples}

Restore state from file.

```typescript
it("test", async ({ browser }) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use example from below here as well. Not necessarily replacing yours, you can just add it as a second one.

await browser.url("https://github.com/gemini-testing/testplane");

await browser.restoreState({
path: "./stateDump.json",
cookieFilter: ({ domain }) => domain === ".example.com",
});

// Reload page for see auth result.
await browser.refresh();
});
```

Example of implementing authentication in tests with saveState/restoreState and beforeAll hook.

```typescript
import { ConfigInput, WdioBrowser } from "testplane";
import { launchBrowser } from "testplane/unstable";

export default {
gridUrl: "local",
beforeAll: async ({ config }) => {
const b = await launchBrowser(config.browsers["chrome"]!);

await b.url("https://our-site.com");
await b.$("input.login").setValue("[email protected]");
await b.$("input.password").setValue("password123");

await b.saveState({ path: "./.testplane/state.json" });
await b.deleteSession();
},
sets: {
/* ... */
},
browsers: {
chrome: {
headless: false,
desiredCapabilities: {
browserName: "chrome",
},
},
},
plugins: {
/* ... */
"@testplane/global-hook": {
enabled: true,
beforeEach: async ({ browser }: { browser: WdioBrowser }) => {
await browser.url("https://our-site.com");
await browser.restoreState({ path: "./.testplane/state.json" });
},
},
},
} satisfies ConfigInput;
```

## Related Commands {#related}

- [saveState](../saveState)
- [afterAll](../../../config/after-all)
- [beforeAll](../../../config/before-all)
92 changes: 92 additions & 0 deletions docs/commands/browser/saveState.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# saveState

## Overview {#overview}

Browser command that saves session state (cookies, local and session storages).

## Usage {#usage}

This command returns a state of the page state, including cookies, localStorage, and sessionStorage.
You can use parameters to exclude specific types of data if needed.

If you provide the `path` parameter, the state dump will be saved to a file.
The saved state can later be restored using the [restoreState](../restoreState) command.

```typescript
import type { SaveStateData } from "testplane";

const stateDump: SaveStateData = await browser.saveState({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be really nice to briefly comment what's exactly inside that SaveStateData object. Or, if the SaveStateData interface is simple enough, we can include it right in the example.

path: "./stateDump.json",
cookies: true,
localStorage: true,
sessionStorage: true,
});
```

## Command Parameters {#parameters}

<table>
<thead>
<tr>
<td>**Name**</td>
<td>**Type**</td>
<td>**Default**</td>
<td>**Description**</td>
</tr>
</thead>
<tbody>
<tr>
<td>path</td>
<td>`string`</td>
<td>`-`</td>
<td>Path to file where state will be saved.</td>
</tr>
<tr>
<td>cookies</td>
<td>`boolean`</td>
<td>`true`</td>
<td>Enable save cookies (true by default).</td>
</tr>
<tr>
<td>localStorage</td>
<td>`boolean`</td>
<td>`true`</td>
<td>Enable save localStorage (true by default).</td>
</tr>
<tr>
<td>sessionStorage</td>
<td>`boolean`</td>
<td>`true`</td>
<td>Enable save sessionStorage (true by default).</td>
</tr>
<tr>
<td>cookieFilter</td>
<td>`(cookie: Cookie) => boolean`</td>
<td>`-`</td>
<td>
Function for filtering cookies, receiving cookie objects, and returning boolean.
</td>
</tr>
</tbody>
</table>

## Usage Examples {#examples}

Save state in file.

```typescript
it("test", async ({ browser }) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a more comprehensive example would bring much more value. Here's what I needed to do to setup simple save/restore workflow:

import {ConfigInput, WdioBrowser} from "testplane";
import {launchBrowser} from "testplane/unstable";

export default {
    gridUrl: "local",
    beforeAll: async ({config}) => {
        const b = await launchBrowser(config.browsers['chrome']!);

        await b.url('https://our-site.com');
        await b.$('input.login').setValue('[email protected]');
        await b.$('input.password').setValue('password123');

        await b.saveState({path: './.testplane/state.json'});
        await b.deleteSession();
    },
    sets: {/* ... */},
    browsers: {
        chrome: {
            headless: false,
            desiredCapabilities: {
                browserName: "chrome"
            }
        }
    },
    plugins: {
        /* ... */
        "@testplane/global-hook": {
            enabled: true,
            beforeEach: async ({browser}: {browser: WdioBrowser}) => {
                await browser.url('https://our-site.com');
                await browser.restoreState({path: './.testplane/state.json'});
            }
        }
    },
} satisfies ConfigInput;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

await browser.url("https://github.com/gemini-testing/testplane");

await browser.saveState({
path: "./stateDump.json",
cookieFilter: ({ domain }) => domain === ".example.com",
});
});
```

## Related Commands {#related}

- [restoreState](../restoreState)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add references to the new hooks as well.

- [afterAll](../../../config/after-all)
- [beforeAll](../../../config/before-all)
26 changes: 26 additions & 0 deletions docs/config/after-all.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# afterAll

## Overview {#overview}

This parameter is a hook. The function specified for this parameter will be automatically called after tests are completed.

The context of the function is the Testplane config. Also function receive config in arguments.

## Usage Example {#example}

Here is an example of using this hook to remove a file with a page state.

```typescript title="testplane.config.ts"
import * as fs from "fs";

export default {
// ...
afterAll: async () => {
await fs.unlink("./dump.json");
},
};
```

## Related {#related}

- [beforeAll](../before-all)
54 changes: 54 additions & 0 deletions docs/config/before-all.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# beforeAll

## Overview {#overview}

This parameter is a hook. The function specified for this parameter will be automatically called before tests running.

The context of the function is the Testplane config. Also function receive config in arguments.

## Usage Example {#example}

Here is an example of using this hook for logging in and getting session data for use in tests.

```typescript title="testplane.config.ts"
import { launchBrowser } from "testplane/unstable";

export default {
// ...
browsers: {
chrome: {
headless: true,
desiredCapabilities: {
webSocketUrl: true,
browserName: "chrome",
},
},
firefox: {
headless: true,
desiredCapabilities: {
webSocketUrl: true,
browserName: "firefox",
},
},
},
beforeAll: async () => {
// launch a new browser with existing config
const browser = await launchBrowser(this.config.browsers.chrome);

await browser.url("https://example.com");

// do login things, type username/password etc.

// save dump with state (cookies, localStorage) for using in tests
await browser.saveState({
path: "./dump.json",
});

await browser.deleteSession();
},
};
```

## Related {#related}

- [afterAll](../after-all)
2 changes: 1 addition & 1 deletion docs/reference/testplane-standalone-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { launchBrowser } from "testplane/unstable";
// Launch a new browser with the given settings
const browser = await launchBrowser({
desiredCapabilities: {
browserName: 'chrome',
browserName: "chrome",
},
headless: false,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ testplane --repl --grep 'my test name' --browser chrome
- `--keep-browser-on-fail` - то же, что и опция `--keep-browser`, только браузер останется только в том случае, если тесты завершатся неуспешно

Пример вывода в консоли c информацией для подключения к браузеру

```
[15:44:38 +0700] Testplane run has finished, but the browser won't be closed, because you passed the --keep-browser argument.
[15:44:38 +0700] You may attach to this browser using the following capabilities:
Expand Down
Loading