Skip to content

Commit b6602c9

Browse files
added reuse session feature (#93)
* added reuse session feature
1 parent c04d762 commit b6602c9

File tree

13 files changed

+141
-55
lines changed

13 files changed

+141
-55
lines changed

.github/workflows/pull-request.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ jobs:
1818
node-version: ${{ matrix.version }}
1919
- run: npm ci
2020
- run: npm run build
21+
- run: npm run test
2122
- run: npm run install:browsers
2223
- run: npm run test:e2e
2324
- name: junit report

.gitignore

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,5 @@ lib/
33
coverage/
44
test-e2e/report.*
55
.idea/
6-
customDir/
7-
dirToStoreTraces/
8-
dirToStoreVideos/
6+
traces/
97
video/

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
88
:beetle: - bugfix
99
:x: - deprecation
1010

11+
## [0.41.1]
12+
- :rocket: added _reuseSession_ option to keep browser/application opened after test ends
13+
1114
## [0.41.0]
1215
- :rocket: introduced browserManager object to control all launched browser and electron instances
1316
- :rocket: added steps to start/stop/switch to other browser/electron instances

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,21 @@ To properly use globals exposed by @qavajs/steps-playwright add corresponding ty
136136
}
137137
```
138138

139+
## reuseSession
140+
reuseSession flag allows to share session between tests in frames of process. But setting of this flag
141+
transfers session control to user.
142+
143+
```javascript
144+
module.exports = {
145+
default: {
146+
browser: {
147+
reuseSession: true
148+
}
149+
}
150+
}
151+
```
152+
153+
139154
## Development and testing
140155
Install dependencies
141156
`npm install`

package-lock.json

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@qavajs/steps-playwright",
3-
"version": "0.41.0",
3+
"version": "0.41.1",
44
"description": "steps to interact with playwright",
55
"main": "./index.js",
66
"scripts": {
@@ -37,7 +37,7 @@
3737
"@types/express": "^4.17.21",
3838
"@vitest/coverage-v8": "^0.34.6",
3939
"@vitest/ui": "^0.34.6",
40-
"electron": "^27.1.2",
40+
"electron": "^27.1.3",
4141
"express": "^4.18.2",
4242
"ts-node": "^10.9.1",
4343
"typescript": "^5.3.2",

src/browserManager.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,16 @@ export class BrowserManager {
2929
this.setContext((driverInstance as any as ElectronApplication).context());
3030
this.setPage(await (driverInstance as any as ElectronApplication).firstWindow())
3131
} else {
32-
const context = await driverInstance.newContext(driverConfig);
32+
const firstContext = driverInstance.contexts()[0];
33+
const context = driverConfig.reuseSession && firstContext
34+
? firstContext
35+
: await driverInstance.newContext(driverConfig.capabilities);
3336
this.setContext(context);
34-
this.setPage(await context.newPage());
37+
const firstPage = this.context?.pages()[0];
38+
const page = driverConfig.reuseSession && firstPage
39+
? firstPage
40+
: await context.newPage();
41+
this.setPage(page);
3542
}
3643
(this.context as NamedContext).name = 'default';
3744
}
@@ -88,7 +95,9 @@ export class BrowserManager {
8895
/**
8996
* return to default state (1 browser, no contexts)
9097
*/
91-
async teardown() {
98+
async teardown({ reuseSession } = { reuseSession: false }) {
99+
this.setDriver(this.drivers['default']);
100+
if (reuseSession) return;
92101
for (const driverKey in this.drivers) {
93102
const driverInstance = this.drivers[driverKey] as any;
94103
if (driverInstance.firstWindow) {
@@ -97,7 +106,6 @@ export class BrowserManager {
97106
await this.browserTeardown(driverInstance, driverKey);
98107
}
99108
}
100-
this.driver = this.drivers['default'];
101109
}
102110

103111
async browserTeardown(driverInstance: Browser, driverKey: string) {
@@ -120,7 +128,11 @@ export class BrowserManager {
120128
async close() {
121129
for (const driverKey in this.drivers) {
122130
const driverInstance = this.drivers[driverKey] as any;
123-
await driverInstance.close();
131+
if (driverInstance.firstWindow) {
132+
await this.electronTeardown(driverInstance, driverKey);
133+
} else {
134+
await driverInstance.close();
135+
}
124136
delete this.drivers[driverKey];
125137
}
126138
};

src/hooks.ts

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,12 @@ import { po } from '@qavajs/po-playwright';
1414
import {
1515
saveScreenshotAfterStep,
1616
saveScreenshotBeforeStep,
17-
saveTrace,
18-
saveVideo,
19-
traceArchive
17+
saveVideo
2018
} from './utils/utils';
2119
import { readFile } from 'node:fs/promises';
2220
import { createJSEngine } from './selectorEngines';
2321
import browserManager, {BrowserManager} from './browserManager';
22+
import tracingManager from './utils/tracingManager';
2423

2524
declare global {
2625
var browser: Browser
@@ -47,12 +46,7 @@ Before({name: 'Init'}, async function () {
4746
config.driverConfig.capabilities.recordVideo = config.driverConfig.video;
4847
}
4948
await browserManager.launchDriver('default', config.driverConfig);
50-
if (config.driverConfig.trace) {
51-
await context.tracing.start({
52-
screenshots: true,
53-
snapshots: true
54-
});
55-
}
49+
await tracingManager.start(driverConfig);
5650
po.init(page, { timeout: config.driverConfig.timeout.present, logger: this });
5751
po.register(config.pageObject);
5852
global.browserManager = browserManager;
@@ -80,20 +74,19 @@ AfterStep(async function (step: ITestStepHookParameter) {
8074
});
8175

8276
After({name: 'Teardown'}, async function (scenario: ITestCaseHookParameter) {
83-
if (saveTrace(config.driverConfig, scenario)) {
84-
const path = traceArchive(config.driverConfig, scenario);
85-
await context.tracing.stop({ path });
86-
if (config.driverConfig?.trace.attach) {
87-
const zipBuffer: Buffer = await readFile(path);
88-
this.attach(zipBuffer.toString('base64'), 'base64:application/zip');
89-
}
90-
}
91-
await browserManager.teardown();
77+
await tracingManager.stop(config.driverConfig, this, scenario);
78+
await browserManager.teardown({ reuseSession: config.driverConfig.reuseSession });
9279
if (saveVideo(config.driverConfig, scenario)) {
9380
if (config.driverConfig?.video.attach) {
94-
const videoPath = await page.video()?.path() ?? '';
95-
const zipBuffer: Buffer = await readFile(videoPath);
96-
this.attach(zipBuffer.toString('base64'), 'base64:video/webm');
81+
const video = page.video();
82+
console.log(video)
83+
if (video) {
84+
const videoPath = await video.path();
85+
const zipBuffer: Buffer = await readFile(videoPath);
86+
this.attach(zipBuffer.toString('base64'), 'base64:video/webm');
87+
} else {
88+
console.warn('Video was not recorded');
89+
}
9790
}
9891
}
9992
});

src/multiBrowser.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,14 @@ When('I launch new driver as {string}', async function (driverName: string) {
1717
* @param {string} driverName - driver name
1818
* @param {string} config - json with browser config
1919
* @example
20-
* When I launch new driver as 'browser2'
20+
* When I launch new driver as 'browser2':
21+
* """
22+
* {
23+
* "capabilities": {
24+
* "browserName": "firefox"
25+
* }
26+
* }
27+
* """
2128
*/
2229
When('I launch new driver as {string}:', async function (driverName: string, rawConfig: string) {
2330
const config = await getValue(rawConfig);
@@ -40,7 +47,7 @@ When('I switch to {string} driver', async function (driverName: string) {
4047
* Close driver
4148
* @param {string} driverName - driver name
4249
* @example
43-
* When I close to 'browser2' driver
50+
* When I close 'browser2' driver
4451
*/
4552
When('I close {string} driver', async function (driverName: string) {
4653
await browserManager.closeDriver(driverName);
@@ -72,7 +79,7 @@ When('I switch to {string} browser context', async function (browserContextName:
7279
* Close browser context
7380
* @param {string} browserContextName - browser context name
7481
* @example
75-
* When I close to 'browser2' browser context
82+
* When I close 'browser2' browser context
7683
*/
7784
When('I close {string} browser context', async function (browserContextName: string) {
7885
await browserManager.closeContext(browserContextName);

src/utils/tracingManager.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { saveTrace, traceArchive } from './utils';
2+
import { readFile } from 'node:fs/promises';
3+
4+
class TracingManager {
5+
6+
isTracingStarted = false;
7+
async start(driverConfig: any) {
8+
if (driverConfig.trace) {
9+
if (!driverConfig.reuseSession || (driverConfig.reuseSession && !this.isTracingStarted)) {
10+
this.isTracingStarted = true;
11+
await context.tracing.start({
12+
screenshots: true,
13+
snapshots: true
14+
});
15+
}
16+
await context.tracing.startChunk();
17+
}
18+
}
19+
20+
async stop(driverConfig: any, world: any, scenario: any) {
21+
if (saveTrace(config.driverConfig, scenario)) {
22+
const path = traceArchive(config.driverConfig, scenario);
23+
await context.tracing.stopChunk({ path });
24+
if (driverConfig?.trace.attach) {
25+
const zipBuffer: Buffer = await readFile(path);
26+
world.attach(zipBuffer.toString('base64'), 'base64:application/zip');
27+
}
28+
}
29+
}
30+
}
31+
32+
export default new TracingManager();

0 commit comments

Comments
 (0)