@serenity-js/playwright 3.42.1 → 3.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/esm/screenplay/abilities/BrowseTheWebWithPlaywright.d.ts +60 -2
  3. package/esm/screenplay/abilities/BrowseTheWebWithPlaywright.d.ts.map +1 -1
  4. package/esm/screenplay/abilities/BrowseTheWebWithPlaywright.js +74 -2
  5. package/esm/screenplay/abilities/BrowseTheWebWithPlaywright.js.map +1 -1
  6. package/esm/screenplay/models/ElectronLaunchOptions.d.ts +55 -0
  7. package/esm/screenplay/models/ElectronLaunchOptions.d.ts.map +1 -0
  8. package/esm/screenplay/models/ElectronLaunchOptions.js +2 -0
  9. package/esm/screenplay/models/ElectronLaunchOptions.js.map +1 -0
  10. package/esm/screenplay/models/PlaywrightBrowsingSessionWithBrowser.d.ts +3 -2
  11. package/esm/screenplay/models/PlaywrightBrowsingSessionWithBrowser.d.ts.map +1 -1
  12. package/esm/screenplay/models/PlaywrightBrowsingSessionWithBrowser.js +6 -5
  13. package/esm/screenplay/models/PlaywrightBrowsingSessionWithBrowser.js.map +1 -1
  14. package/esm/screenplay/models/PlaywrightBrowsingSessionWithElectron.d.ts +52 -0
  15. package/esm/screenplay/models/PlaywrightBrowsingSessionWithElectron.d.ts.map +1 -0
  16. package/esm/screenplay/models/PlaywrightBrowsingSessionWithElectron.js +103 -0
  17. package/esm/screenplay/models/PlaywrightBrowsingSessionWithElectron.js.map +1 -0
  18. package/esm/screenplay/models/PlaywrightBrowsingSessionWithPage.d.ts +1 -0
  19. package/esm/screenplay/models/PlaywrightBrowsingSessionWithPage.d.ts.map +1 -1
  20. package/esm/screenplay/models/PlaywrightBrowsingSessionWithPage.js +3 -0
  21. package/esm/screenplay/models/PlaywrightBrowsingSessionWithPage.js.map +1 -1
  22. package/esm/screenplay/models/SelfLaunchingPlaywrightBrowsingSessionWithElectron.d.ts +52 -0
  23. package/esm/screenplay/models/SelfLaunchingPlaywrightBrowsingSessionWithElectron.d.ts.map +1 -0
  24. package/esm/screenplay/models/SelfLaunchingPlaywrightBrowsingSessionWithElectron.js +70 -0
  25. package/esm/screenplay/models/SelfLaunchingPlaywrightBrowsingSessionWithElectron.js.map +1 -0
  26. package/esm/screenplay/models/index.d.ts +3 -0
  27. package/esm/screenplay/models/index.d.ts.map +1 -1
  28. package/esm/screenplay/models/index.js +3 -0
  29. package/esm/screenplay/models/index.js.map +1 -1
  30. package/lib/screenplay/abilities/BrowseTheWebWithPlaywright.d.ts +60 -2
  31. package/lib/screenplay/abilities/BrowseTheWebWithPlaywright.d.ts.map +1 -1
  32. package/lib/screenplay/abilities/BrowseTheWebWithPlaywright.js +73 -1
  33. package/lib/screenplay/abilities/BrowseTheWebWithPlaywright.js.map +1 -1
  34. package/lib/screenplay/models/ElectronLaunchOptions.d.ts +55 -0
  35. package/lib/screenplay/models/ElectronLaunchOptions.d.ts.map +1 -0
  36. package/lib/screenplay/models/ElectronLaunchOptions.js +3 -0
  37. package/lib/screenplay/models/ElectronLaunchOptions.js.map +1 -0
  38. package/lib/screenplay/models/PlaywrightBrowsingSessionWithBrowser.d.ts +3 -2
  39. package/lib/screenplay/models/PlaywrightBrowsingSessionWithBrowser.d.ts.map +1 -1
  40. package/lib/screenplay/models/PlaywrightBrowsingSessionWithBrowser.js +6 -5
  41. package/lib/screenplay/models/PlaywrightBrowsingSessionWithBrowser.js.map +1 -1
  42. package/lib/screenplay/models/PlaywrightBrowsingSessionWithElectron.d.ts +52 -0
  43. package/lib/screenplay/models/PlaywrightBrowsingSessionWithElectron.d.ts.map +1 -0
  44. package/lib/screenplay/models/PlaywrightBrowsingSessionWithElectron.js +107 -0
  45. package/lib/screenplay/models/PlaywrightBrowsingSessionWithElectron.js.map +1 -0
  46. package/lib/screenplay/models/PlaywrightBrowsingSessionWithPage.d.ts +1 -0
  47. package/lib/screenplay/models/PlaywrightBrowsingSessionWithPage.d.ts.map +1 -1
  48. package/lib/screenplay/models/PlaywrightBrowsingSessionWithPage.js +3 -0
  49. package/lib/screenplay/models/PlaywrightBrowsingSessionWithPage.js.map +1 -1
  50. package/lib/screenplay/models/SelfLaunchingPlaywrightBrowsingSessionWithElectron.d.ts +52 -0
  51. package/lib/screenplay/models/SelfLaunchingPlaywrightBrowsingSessionWithElectron.d.ts.map +1 -0
  52. package/lib/screenplay/models/SelfLaunchingPlaywrightBrowsingSessionWithElectron.js +107 -0
  53. package/lib/screenplay/models/SelfLaunchingPlaywrightBrowsingSessionWithElectron.js.map +1 -0
  54. package/lib/screenplay/models/index.d.ts +3 -0
  55. package/lib/screenplay/models/index.d.ts.map +1 -1
  56. package/lib/screenplay/models/index.js +3 -0
  57. package/lib/screenplay/models/index.js.map +1 -1
  58. package/package.json +21 -9
  59. package/src/screenplay/abilities/BrowseTheWebWithPlaywright.ts +112 -7
  60. package/src/screenplay/models/ElectronLaunchOptions.ts +55 -0
  61. package/src/screenplay/models/PlaywrightBrowsingSessionWithBrowser.ts +13 -8
  62. package/src/screenplay/models/PlaywrightBrowsingSessionWithElectron.ts +129 -0
  63. package/src/screenplay/models/PlaywrightBrowsingSessionWithPage.ts +4 -0
  64. package/src/screenplay/models/SelfLaunchingPlaywrightBrowsingSessionWithElectron.ts +85 -0
  65. package/src/screenplay/models/index.ts +3 -0
@@ -0,0 +1,129 @@
1
+ import { CorrelationId } from '@serenity-js/core/model';
2
+ import type { BrowserCapabilities } from '@serenity-js/web';
3
+ import type * as playwright from 'playwright-core';
4
+
5
+ import type { ExtraBrowserContextOptions } from '../../ExtraBrowserContextOptions.js';
6
+ import { PlaywrightBrowsingSession } from './PlaywrightBrowsingSession.js';
7
+ import { PlaywrightPage } from './PlaywrightPage.js';
8
+
9
+ /**
10
+ * Playwright-specific implementation of [`BrowsingSession`](https://serenity-js.org/api/web/class/BrowsingSession/)
11
+ * for Electron applications.
12
+ *
13
+ * Use this class when you have an already-launched `ElectronApplication` instance,
14
+ * typically in Playwright Test scenarios where the app is managed per-worker.
15
+ *
16
+ * ## Example
17
+ *
18
+ * ```ts
19
+ * import { _electron as electron } from 'playwright';
20
+ * import { actorCalled } from '@serenity-js/core';
21
+ * import { BrowseTheWebWithPlaywright } from '@serenity-js/playwright';
22
+ *
23
+ * const electronApp = await electron.launch({ args: ['main.js'] });
24
+ *
25
+ * const actor = actorCalled('Tester').whoCan(
26
+ * BrowseTheWebWithPlaywright.usingElectronApp(electronApp)
27
+ * );
28
+ *
29
+ * // After tests, close the app manually
30
+ * await electronApp.close();
31
+ * ```
32
+ *
33
+ * @group Models
34
+ */
35
+ export class PlaywrightBrowsingSessionWithElectron extends PlaywrightBrowsingSession {
36
+
37
+ constructor(
38
+ protected electronApp: playwright.ElectronApplication,
39
+ extraBrowserContextOptions: Partial<ExtraBrowserContextOptions>,
40
+ selectors: playwright.Selectors,
41
+ ) {
42
+ super(extraBrowserContextOptions, selectors);
43
+ }
44
+
45
+ protected override async createBrowserContext(): Promise<playwright.BrowserContext> {
46
+ return this.electronApp.context();
47
+ }
48
+
49
+ protected override async registerCurrentPage(): Promise<PlaywrightPage> {
50
+ // Ensure browser context is initialized before accessing windows
51
+ await this.browserContext();
52
+ const windows = this.electronApp.windows();
53
+
54
+ let targetPage: playwright.Page;
55
+
56
+ if (windows.length === 0) {
57
+ // Wait for the first window to open
58
+ targetPage = await this.electronApp.firstWindow();
59
+ }
60
+ else {
61
+ // Use the last opened window
62
+ targetPage = windows.at(-1)!;
63
+ }
64
+
65
+ // Check if this window is already registered
66
+ const allPages = await this.allPages();
67
+ for (const page of allPages) {
68
+ const nativePage = await page.nativePage();
69
+ if (nativePage === targetPage) {
70
+ return page;
71
+ }
72
+ }
73
+
74
+ // Create and register a new PlaywrightPage
75
+ const playwrightPage = new PlaywrightPage(
76
+ this,
77
+ targetPage,
78
+ this.extraBrowserContextOptions,
79
+ CorrelationId.create()
80
+ );
81
+
82
+ this.register(playwrightPage);
83
+
84
+ // Set up close handler for automatic deregistration
85
+ targetPage.on('close', () => {
86
+ this.deregister(playwrightPage.id);
87
+ });
88
+
89
+ return playwrightPage;
90
+ }
91
+
92
+ /**
93
+ * Closes all Electron windows but does NOT close the Electron application itself.
94
+ * The application lifecycle is managed externally.
95
+ */
96
+ override async closeAllPages(): Promise<void> {
97
+ const pages = await this.allPages();
98
+ for (const page of pages) {
99
+ await page.close();
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Returns [basic meta-data](https://serenity-js.org/api/web/interface/BrowserCapabilities/) about the Electron application.
105
+ *
106
+ * **Please note** that since Playwright does not expose information about the operating system
107
+ * the tests are running on, **Serenity/JS assumes that the tests are running locally**
108
+ * and therefore returns the value of Node.js `process.platform` for `platformName`.
109
+ */
110
+ override async browserCapabilities(): Promise<BrowserCapabilities> {
111
+ return {
112
+ browserName: 'electron',
113
+ platformName: process.platform,
114
+ browserVersion: await this.getElectronVersion(),
115
+ };
116
+ }
117
+
118
+ private async getElectronVersion(): Promise<string> {
119
+ try {
120
+ const version = await this.electronApp.evaluate(
121
+ () => process.versions.electron
122
+ );
123
+ return version || 'unknown';
124
+ }
125
+ catch {
126
+ return 'unknown';
127
+ }
128
+ }
129
+ }
@@ -56,4 +56,8 @@ export class PlaywrightBrowsingSessionWithPage extends PlaywrightBrowsingSession
56
56
  browserVersion: browser.version()
57
57
  }
58
58
  }
59
+
60
+ async discard(): Promise<void> {
61
+ await this.closeAllPages();
62
+ }
59
63
  }
@@ -0,0 +1,85 @@
1
+ import type { Discardable, Initialisable } from '@serenity-js/core';
2
+ import * as playwright from 'playwright-core';
3
+
4
+ import type { ExtraBrowserContextOptions } from '../../ExtraBrowserContextOptions.js';
5
+ import type { ElectronLaunchOptions } from './ElectronLaunchOptions.js';
6
+ import { PlaywrightBrowsingSessionWithElectron } from './PlaywrightBrowsingSessionWithElectron.js';
7
+
8
+ /**
9
+ * Self-launching implementation of [`PlaywrightBrowsingSession`](https://serenity-js.org/api/playwright/class/PlaywrightBrowsingSession/)
10
+ * for Electron applications.
11
+ *
12
+ * This class launches the Electron application on first use and closes it when discarded.
13
+ * Use this for test runners like Mocha or Jasmine that don't manage Electron lifecycle.
14
+ *
15
+ * ## Example
16
+ *
17
+ * ```typescript
18
+ * import { actorCalled } from '@serenity-js/core';
19
+ * import { BrowseTheWebWithPlaywright } from '@serenity-js/playwright';
20
+ *
21
+ * const actor = actorCalled('Tester').whoCan(
22
+ * BrowseTheWebWithPlaywright.launchingElectronApp({
23
+ * args: ['path/to/main.js'],
24
+ * cwd: 'path/to/app',
25
+ * })
26
+ * );
27
+ *
28
+ * // The app is automatically closed when the actor is dismissed
29
+ * ```
30
+ *
31
+ * @group Models
32
+ */
33
+ export class SelfLaunchingPlaywrightBrowsingSessionWithElectron
34
+ extends PlaywrightBrowsingSessionWithElectron
35
+ implements Initialisable, Discardable
36
+ {
37
+ constructor(
38
+ private readonly launchOptions: ElectronLaunchOptions,
39
+ extraBrowserContextOptions: Partial<ExtraBrowserContextOptions>,
40
+ selectors: playwright.Selectors,
41
+ ) {
42
+ // setting electronApp to undefined since it's lazily initialised
43
+ super(undefined, extraBrowserContextOptions, selectors);
44
+ }
45
+
46
+ /**
47
+ * Launches the Electron application using the configured launch options.
48
+ *
49
+ * This method is idempotent - calling it multiple times will only launch
50
+ * the application once.
51
+ */
52
+ async initialise(): Promise<void> {
53
+ if (this.electronApp) {
54
+ return;
55
+ }
56
+
57
+ this.electronApp = await playwright._electron.launch(this.launchOptions);
58
+ this.currentBrowserPage = await this.registerCurrentPage();
59
+ }
60
+
61
+ /**
62
+ * Returns `true` if the Electron application has been launched.
63
+ */
64
+ isInitialised(): boolean {
65
+ return this.electronApp !== undefined;
66
+ }
67
+
68
+ /**
69
+ * Closes the Electron application that was launched by this session.
70
+ * Called when the ability is discarded.
71
+ */
72
+ async closeElectronApp(): Promise<void> {
73
+ if (this.electronApp) {
74
+ await this.electronApp.close();
75
+ this.electronApp = undefined;
76
+ }
77
+ }
78
+
79
+ async discard(): Promise<void> {
80
+ await this.closeElectronApp();
81
+
82
+ this.pages.clear();
83
+ this.currentBrowserPage = undefined;
84
+ }
85
+ }
@@ -1,7 +1,10 @@
1
+ export * from './ElectronLaunchOptions.js';
1
2
  export * from './locators/index.js';
2
3
  export * from './PlaywrightBrowsingSession.js';
3
4
  export * from './PlaywrightBrowsingSessionWithBrowser.js';
5
+ export * from './PlaywrightBrowsingSessionWithElectron.js';
4
6
  export * from './PlaywrightBrowsingSessionWithPage.js';
5
7
  export * from './PlaywrightCookie.js';
6
8
  export * from './PlaywrightPage.js';
7
9
  export * from './PlaywrightPageElement.js';
10
+ export * from './SelfLaunchingPlaywrightBrowsingSessionWithElectron.js';