playwright-clipboard-testing 0.3.0 → 0.4.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.
package/README.md CHANGED
@@ -25,9 +25,9 @@ Testing the Clipboard API in Playwright usually requires boilerplate code to man
25
25
  - [Direct Usage](#direct-usage)
26
26
  - [Extended Usage](#extended-usage)
27
27
  - [API](#api)
28
- - [Clipboard Fixture](#clipboard-fixture)
29
- - [toHaveText Matcher](#tohavetext-matcher)
30
- - [toHaveJSON Matcher](#tohavejson-matcher)
28
+ - [Clipboard Fixtures](#clipboard-fixtures)
29
+ - [toHaveTextContent Matcher](#tohavetextcontent-matcher)
30
+ - [toHaveJSONContent Matcher](#tohavejsoncontent-matcher)
31
31
  - [toHaveData Matcher](#tohavedata-matcher)
32
32
  - [Author](#author)
33
33
  - [License](#license)
@@ -84,68 +84,69 @@ test('should copy text to clipboard', async ({ page, clipboard }) => {
84
84
  await page.goto('https://example.com');
85
85
  await page.locator('#copy-button').click();
86
86
 
87
- await expect(clipboard).toHaveData('Hello, World!');
87
+ await expect(clipboard).toHaveTextContent('Hello, World!');
88
88
  });
89
89
  ```
90
90
 
91
91
  ### Extended Usage
92
92
 
93
- If you already have a custom test fixture file, extend Playwright's `test` and `expect` with `clipboardFixture` and `clipboardMatchers`:
93
+ If you already have a custom test fixture file, extend Playwright's `test` and `expect` with `clipboardFixtures` and `clipboardMatchers`:
94
94
  ```ts
95
95
  import { expect as baseExpect, test as baseTest } from '@playwright/test';
96
96
  import {
97
97
  type ClipboardHandler,
98
- clipboardFixture,
98
+ clipboardFixtures,
99
99
  clipboardMatchers,
100
100
  } from 'playwright-clipboard-testing';
101
101
 
102
- export const test = baseTest.extend<{ clipboard: ClipboardHandler }>({
103
- clipboard: clipboardFixture,
104
- });
102
+ export const test = baseTest.extend<{ clipboard: ClipboardHandler }>(clipboardFixtures);
105
103
 
106
104
  export const expect = baseExpect.extend(clipboardMatchers);
107
-
108
105
  ```
109
106
 
110
107
  ## API
111
- ### Clipboard Fixture
112
- The `clipboard` fixture provides direct access to the browser clipboard during tests:
113
- - `clipboard.read(): Promise<string>` - reads the current plain text content from the clipboard.
114
- - `clipboard.readJSON<T>(): Promise<T>` - reads the current clipboard content and parses it as a JSON object of type `T`. Throws an error if the content is not valid JSON.
108
+ ### Clipboard Fixtures
109
+ The package exports `clipboardFixtures` (containing `context` and `clipboard` fixtures) as well as individual fixtures `clipboardFixture` and `contextFixture`:
110
+
111
+ - `clipboardFixtures` — Object containing both `context` and `clipboard` fixtures for simple fixture extension.
112
+ - `contextFixture` (`context`) — Automatically grants `clipboard-read` and `clipboard-write` permissions to Chromium browser contexts.
113
+ - `clipboardFixture` (`clipboard`) — Provides direct access to the `ClipboardHandler` instance during tests:
114
+ - `clipboard.read(): Promise<string>` — reads the current plain text content from the clipboard.
115
+ - `clipboard.readJSON<T>(): Promise<T>` — reads the current clipboard content and parses it as a JSON object of type `T`. Throws an error if the content is not valid JSON.
115
116
 
116
117
  ![NOTE](https://img.shields.io/badge/NOTE-For%20your%20tests%20we%20recommend%20using%20existing%20matchers%20to%20assert%20clipboard%20content-yellow)
117
118
 
118
- ### toHaveText Matcher
119
- `expect(clipboard).toHaveText(expected, options?)`
119
+ ### toHaveTextContent Matcher
120
+ `expect(clipboard).toHaveTextContent(expected, options?)`
120
121
 
121
122
  Asserts that the clipboard content matches the expected string. Uses Playwright's smart polling mechanism to wait for the clipboard to update.
122
123
  - `expected: string` — Expected text to compare against.
123
124
  - `options.timeout: number (optional, default: 10000ms)` — Time in milliseconds to wait for the clipboard content to match.
124
125
  ```ts
125
126
  // assert that the clipboard contains the expected text
126
- await expect(clipboard).toHaveText('Hello, World!');
127
+ await expect(clipboard).toHaveTextContent('Hello, World!');
127
128
  ```
128
129
  ```ts
129
130
  // Custom timeout
130
- await expect(clipboard).toHaveText('Async copied value', { timeout: 5000 });
131
+ await expect(clipboard).toHaveTextContent('Async copied value', { timeout: 5000 });
131
132
  ```
132
133
 
133
- ### toHaveJSON Matcher
134
- `expect(clipboard).toHaveJSON(expected, options?)`
134
+ ### toHaveJSONContent Matcher
135
+ `expect(clipboard).toHaveJSONContent(expected, options?)`
135
136
  Asserts that the clipboard content matches the expected JSON value. Uses Playwright's smart polling mechanism to wait for the clipboard to update.
136
137
  - `expected: unknown` — Expected JSON value to compare against.
137
138
  - `options.timeout: number (optional, default: 10000ms)` — Time in milliseconds to wait for the clipboard content to match.
138
139
  ```ts
139
140
  // assert that the clipboard contains the expected JSON data
140
- await expect(clipboard).toHaveJSON({ message: 'Hello, World!' });
141
+ await expect(clipboard).toHaveJSONContent({ message: 'Hello, World!' });
141
142
  ```
142
143
  ```ts
143
144
  // Custom timeout
144
- await expect(clipboard).toHaveJSON({ message: 'Async copied value' }, { timeout: 5000 });
145
+ await expect(clipboard).toHaveJSONContent({ message: 'Async copied value' }, { timeout: 5000 });
145
146
  ```
146
147
 
147
148
  ### toHaveData Matcher
148
- ![NOTE](https://img.shields.io/badge/NOTE-Matcher%20is%20deprecated%20in%20favor%20of%20toHaveText%20and%20toHaveJSON-yellow)
149
+ ![NOTE](https://img.shields.io/badge/NOTE-Matcher%20is%20deprecated%20in%20favor%20of%20toHaveTextContent%20and%20toHaveJSONContent-yellow)
149
150
 
150
151
  `expect(clipboard).toHaveData(expected, options?)`
151
152
 
package/dist/index.cjs CHANGED
@@ -22,7 +22,9 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  ClipboardHandler: () => ClipboardHandler,
24
24
  clipboardFixture: () => clipboardFixture,
25
+ clipboardFixtures: () => clipboardFixtures,
25
26
  clipboardMatchers: () => clipboardMatchers,
27
+ contextFixture: () => contextFixture,
26
28
  expect: () => expect3,
27
29
  firefoxClipboardPrefs: () => firefoxClipboardPrefs,
28
30
  test: () => test
@@ -40,28 +42,10 @@ var firefoxClipboardPrefs = {
40
42
 
41
43
  // src/utils/clipboardHandler.ts
42
44
  var ClipboardHandler = class {
43
- constructor(page, context, browserName = "chromium") {
45
+ constructor(page) {
44
46
  this.page = page;
45
- this.context = context;
46
- this.browserName = browserName;
47
- this.isPermissionGranted = false;
48
47
  }
49
48
  page;
50
- context;
51
- browserName;
52
- isPermissionGranted;
53
- /**
54
- * Grants clipboard permissions to the Chromium browser context if not already granted.
55
- * @private
56
- */
57
- async grantPermissions() {
58
- if (this.browserName === "chromium") {
59
- if (!this.isPermissionGranted) {
60
- await this.context.grantPermissions(["clipboard-read", "clipboard-write"]);
61
- this.isPermissionGranted = true;
62
- }
63
- }
64
- }
65
49
  /**
66
50
  * Reads the current text content from the browser clipboard.
67
51
  * If the content is a JSON-encoded string (e.g., has extra quotes),
@@ -70,7 +54,6 @@ var ClipboardHandler = class {
70
54
  * @returns A promise that resolves to the clipboard string content.
71
55
  */
72
56
  async read() {
73
- await this.grantPermissions();
74
57
  return await this.page.evaluate(() => navigator.clipboard.readText());
75
58
  }
76
59
  /**
@@ -92,21 +75,35 @@ var ClipboardHandler = class {
92
75
  };
93
76
 
94
77
  // src/fixtures/clipboardFixture.ts
95
- var clipboardFixture = async ({ page, context, browserName }, use) => {
78
+ var clipboardFixture = async ({ page, browserName }, use) => {
96
79
  if (browserName === "webkit") {
97
80
  throw new Error(
98
81
  `[playwright-clipboard] Browser '${browserName}' is not supported. Clipboard API testing is currently supported only in Chromium-based and Firefox browsers.
99
82
  Add test.skip(browserName === 'webkit', 'Clipboard API is only supported in Chromium and Firefox'); to your test body.`
100
83
  );
101
84
  }
102
- const handler = new ClipboardHandler(page, context, browserName);
85
+ const handler = new ClipboardHandler(page);
103
86
  await use(handler);
104
87
  };
105
88
 
89
+ // src/fixtures/contextFixture.ts
90
+ var contextFixture = async ({ context, browserName }, use) => {
91
+ if (browserName === "chromium") {
92
+ await context.grantPermissions(["clipboard-read", "clipboard-write"]);
93
+ }
94
+ await use(context);
95
+ };
96
+
97
+ // src/fixtures/index.ts
98
+ var clipboardFixtures = {
99
+ context: contextFixture,
100
+ clipboard: clipboardFixture
101
+ };
102
+
106
103
  // src/fixtures.ts
107
104
  var import_test3 = require("@playwright/test");
108
105
 
109
- // src/matchers/toHaveJSON.ts
106
+ // src/matchers/toHaveJSONContent.ts
110
107
  var import_test = require("@playwright/test");
111
108
 
112
109
  // src/utils/matcherUtils.ts
@@ -125,9 +122,9 @@ ${error.message}`;
125
122
  Received: ${this.utils.printReceived(actual)}`;
126
123
  }
127
124
 
128
- // src/matchers/toHaveJSON.ts
129
- async function toHaveJSON(clipboard, expected, options = {}) {
130
- const name = "toHaveJSON";
125
+ // src/matchers/toHaveJSONContent.ts
126
+ async function toHaveJSONContent(clipboard, expected, options = {}) {
127
+ const name = "toHaveJSONContent";
131
128
  let pass;
132
129
  let actual;
133
130
  let errorReason = null;
@@ -168,10 +165,10 @@ async function toHaveJSON(clipboard, expected, options = {}) {
168
165
  return matcherReturn;
169
166
  }
170
167
 
171
- // src/matchers/toHaveText.ts
168
+ // src/matchers/toHaveTextContent.ts
172
169
  var import_test2 = require("@playwright/test");
173
- async function toHaveText(clipboard, expected, options = {}) {
174
- const name = "toHaveText";
170
+ async function toHaveTextContent(clipboard, expected, options = {}) {
171
+ const name = "toHaveTextContent";
175
172
  let pass;
176
173
  let actual;
177
174
  let errorReason = null;
@@ -213,9 +210,9 @@ async function toHaveData(clipboard, expected, options = {}) {
213
210
  const name = "toHaveData";
214
211
  let matcherReturn = null;
215
212
  if (typeof expected === "string") {
216
- matcherReturn = await toHaveText.call(this, clipboard, expected, options);
213
+ matcherReturn = await toHaveTextContent.call(this, clipboard, expected, options);
217
214
  } else {
218
- matcherReturn = await toHaveJSON.call(this, clipboard, expected, options);
215
+ matcherReturn = await toHaveJSONContent.call(this, clipboard, expected, options);
219
216
  }
220
217
  return {
221
218
  ...matcherReturn,
@@ -229,25 +226,21 @@ async function toHaveData(clipboard, expected, options = {}) {
229
226
 
230
227
  // src/matchers/clipboardMatchers.ts
231
228
  var clipboardMatchers = {
232
- toHaveText,
233
- toHaveJSON,
229
+ toHaveTextContent,
230
+ toHaveJSONContent,
234
231
  toHaveData
235
232
  };
236
233
 
237
234
  // src/fixtures.ts
238
- var test = import_test3.test.extend({
239
- /**
240
- * A fixture that provides an instance of the Clipboard utility for interacting with the system clipboard.
241
- * It allows reading from the clipboard during tests.
242
- */
243
- clipboard: clipboardFixture
244
- });
235
+ var test = import_test3.test.extend(clipboardFixtures);
245
236
  var expect3 = import_test3.expect.extend({ ...clipboardMatchers });
246
237
  // Annotate the CommonJS export names for ESM import in node:
247
238
  0 && (module.exports = {
248
239
  ClipboardHandler,
249
240
  clipboardFixture,
241
+ clipboardFixtures,
250
242
  clipboardMatchers,
243
+ contextFixture,
251
244
  expect,
252
245
  firefoxClipboardPrefs,
253
246
  test
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/utils/clipboardHandler.ts","../src/fixtures/clipboardFixture.ts","../src/fixtures.ts","../src/matchers/toHaveJSON.ts","../src/utils/matcherUtils.ts","../src/matchers/toHaveText.ts","../src/matchers/toHaveData.ts","../src/matchers/clipboardMatchers.ts"],"sourcesContent":["export { firefoxClipboardPrefs } from './constants.js';\nexport { clipboardFixture } from './fixtures/clipboardFixture.js';\nexport { expect, test } from './fixtures.js';\nexport { clipboardMatchers } from './matchers/clipboardMatchers.js';\nexport { ClipboardHandler } from './utils/clipboardHandler.js';\n","export const firefoxClipboardPrefs = {\n 'dom.events.testing.asyncClipboard': true,\n 'dom.events.asyncClipboard.readText': true,\n 'dom.events.asyncClipboard.writeText': true,\n 'permissions.default.clipboard-read': 1,\n 'permissions.default.clipboard-write': 1,\n};\n","/**\n * Playwright-compatible Clipboard utilities.\n *\n * Core functions for interacting with the browser clipboard within Playwright tests.\n * Provides wrappers for reading plain text and JSON.\n *\n * @remarks\n * These utilities require 'clipboard-read' and 'clipboard-write' permissions\n * to be granted in the browser context.\n */\n\nimport type { BrowserContext, Page } from '@playwright/test';\nimport type { BrowserName } from '../types.js';\n\nexport class ClipboardHandler {\n private readonly browserName: BrowserName;\n private isPermissionGranted: boolean;\n\n constructor(\n private readonly page: Page,\n private readonly context: BrowserContext,\n browserName: BrowserName = 'chromium',\n ) {\n this.browserName = browserName;\n this.isPermissionGranted = false;\n }\n\n /**\n * Grants clipboard permissions to the Chromium browser context if not already granted.\n * @private\n */\n private async grantPermissions() {\n if (this.browserName === 'chromium') {\n if (!this.isPermissionGranted) {\n await this.context.grantPermissions(['clipboard-read', 'clipboard-write']);\n this.isPermissionGranted = true;\n }\n }\n }\n\n /**\n * Reads the current text content from the browser clipboard.\n * If the content is a JSON-encoded string (e.g., has extra quotes),\n * it will be returned as is. Use readJSON for automatic parsing.\n *\n * @returns A promise that resolves to the clipboard string content.\n */\n async read(): Promise<string> {\n await this.grantPermissions();\n return await this.page.evaluate(() => navigator.clipboard.readText());\n }\n\n /**\n * Reads the clipboard content and parses it as JSON.\n * If the content is a string literal (e.g., '\"value\"'), it returns the unwrapped string ('value').\n *\n * @template T - The expected type of the parsed JSON object.\n * @returns A promise that resolves to the parsed JSON object of type T.\n * @throws {Error} If the clipboard content is not a valid JSON string.\n */\n async readJSON<T = unknown>(): Promise<T> {\n const text = await this.read();\n try {\n return JSON.parse(text);\n } catch {\n throw new Error(`Clipboard content is not a valid JSON: ${JSON.stringify(text)}`);\n }\n }\n}\n","import type { BrowserContext, Page, TestFixture } from '@playwright/test';\nimport type { BrowserName } from '../types.js';\nimport { ClipboardHandler } from '../utils/clipboardHandler.js';\n\n/**\n * A fixture that provides an instance of the Clipboard utility for interacting with the system clipboard.\n * It allows reading from the clipboard during tests.\n */\nexport const clipboardFixture: TestFixture<\n ClipboardHandler,\n { page: Page; context: BrowserContext; browserName: BrowserName }\n> = async ({ page, context, browserName }, use) => {\n if (browserName === 'webkit') {\n throw new Error(\n `[playwright-clipboard] Browser '${browserName}' is not supported. ` +\n 'Clipboard API testing is currently supported only in Chromium-based and Firefox browsers.\\n' +\n `Add test.skip(browserName === 'webkit', 'Clipboard API is only supported in Chromium and Firefox'); to your test body.`,\n );\n }\n\n const handler = new ClipboardHandler(page, context, browserName);\n await use(handler);\n};\n","import { expect as baseExpect, test as baseTest } from '@playwright/test';\nimport { clipboardFixture } from './fixtures/clipboardFixture.js';\nimport { clipboardMatchers } from './matchers/clipboardMatchers.js';\nimport type { ClipboardHandler } from './utils/clipboardHandler.js';\n\nexport const test = baseTest.extend<{\n clipboard: ClipboardHandler;\n}>({\n /**\n * A fixture that provides an instance of the Clipboard utility for interacting with the system clipboard.\n * It allows reading from the clipboard during tests.\n */\n clipboard: clipboardFixture,\n});\n\nexport const expect = baseExpect.extend({ ...clipboardMatchers });\n","import type { ExpectMatcherState, MatcherReturnType } from '@playwright/test';\nimport { expect } from '@playwright/test';\nimport type { ClipboardHandler } from '../utils/clipboardHandler.js';\nimport { getErrorMessage } from '../utils/matcherUtils.js';\nimport type { MatcherOptions } from './types.js';\n\n/**\n * Asserts that the clipboard content matches the expected JSON value.\n *\n * @this ExpectMatcherState\n * @param clipboard The Clipboard utility instance.\n * @param expected The expected JSON value.\n * @param options Matcher options.\n * @returns A Promise that resolves to a MatcherReturnType object.\n */\nexport async function toHaveJSON(\n this: ExpectMatcherState,\n clipboard: ClipboardHandler,\n expected: unknown,\n options: MatcherOptions = {},\n) {\n const name = 'toHaveJSON';\n let pass: boolean;\n let actual: unknown;\n let errorReason: Error | null = null;\n\n const { timeout = 10_000 } = options;\n\n const poll = expect.poll(\n async () => {\n try {\n actual = await clipboard.readJSON();\n errorReason = null;\n return actual;\n } catch (error) {\n errorReason = error instanceof Error ? error : new Error(String(error));\n\n try {\n actual = await clipboard.read();\n } catch {\n actual = undefined;\n }\n\n throw errorReason;\n }\n },\n { timeout },\n );\n\n try {\n const expectation = this.isNot ? poll.not : poll;\n await expectation.toEqual(expected);\n pass = true;\n } catch {\n pass = false;\n }\n\n if (this.isNot) pass = !pass;\n\n const matcherReturn: MatcherReturnType = {\n message: getErrorMessage.call(this, name, expected, actual, errorReason),\n pass,\n name,\n expected,\n actual,\n };\n\n return matcherReturn;\n}\n","import type { ExpectMatcherState } from '@playwright/test';\n\n/**\n * Generates an error message for a custom matcher.\n *\n * @this ExpectMatcherState\n * @param name The name of the matcher.\n * @param expected The expected value.\n * @param actual The actual value.\n * @param error An optional error object.\n * @param errorMessage An optional error message string.\n * @returns A function that returns the error message string.\n */\nexport function getErrorMessage(\n this: ExpectMatcherState,\n name: string,\n expected: unknown,\n actual: unknown,\n error?: Error | null,\n errorMessage?: string | undefined | null,\n): () => string {\n const message = `${this.utils.matcherHint(name, undefined, undefined, { isNot: this.isNot })}\\n\\n`;\n\n if (error) {\n return () => `${message}An unexpected error occurred:\\n${error.message}`;\n }\n\n if (errorMessage) {\n return () => `${message}${errorMessage}`;\n }\n\n return () =>\n message +\n `Expected: ${this.isNot ? 'not ' : ''}${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(actual)}`;\n}\n","import { type ExpectMatcherState, expect, type MatcherReturnType } from '@playwright/test';\nimport type { ClipboardHandler } from '../utils/clipboardHandler.js';\nimport { getErrorMessage } from '../utils/matcherUtils.js';\nimport type { MatcherOptions } from './types.js';\n\n/**\n * Asserts that the clipboard content matches the expected text value.\n *\n * @this ExpectMatcherState\n * @param clipboard The Clipboard utility instance.\n * @param expected The expected text value.\n * @param options Matcher options.\n * @returns A Promise that resolves to a MatcherReturnType object.\n */\nexport async function toHaveText(\n this: ExpectMatcherState,\n clipboard: ClipboardHandler,\n expected: string,\n options: MatcherOptions = {},\n) {\n const name = 'toHaveText';\n let pass: boolean;\n let actual: unknown;\n let errorReason: Error | null = null;\n\n const { timeout = 10_000 } = options;\n\n const poll = expect.poll(\n async () => {\n try {\n actual = await clipboard.read();\n errorReason = null;\n return actual;\n } catch (error) {\n errorReason = error instanceof Error ? error : new Error(String(error));\n actual = undefined;\n\n throw errorReason;\n }\n },\n { timeout },\n );\n\n try {\n const expectation = this.isNot ? poll.not : poll;\n await expectation.toEqual(expected);\n pass = true;\n } catch {\n pass = false;\n }\n\n if (this.isNot) pass = !pass;\n\n const matcherReturn: MatcherReturnType = {\n message: getErrorMessage.call(this, name, expected, actual, errorReason),\n pass,\n name,\n expected,\n actual,\n };\n\n return matcherReturn;\n}\n","import type { ExpectMatcherState, MatcherReturnType } from '@playwright/test';\nimport type { ClipboardHandler } from '../utils/clipboardHandler.js';\nimport { toHaveJSON } from './toHaveJSON.js';\nimport { toHaveText } from './toHaveText.js';\nimport type { MatcherOptions } from './types.js';\n\n/**\n * Asserts that the clipboard content matches the expected value.\n * Uses smart polling to wait for the clipboard to be updated.\n * If the `expected` value is an object, it attempts to parse the clipboard\n * content as JSON before comparing.\n *\n * @this ExpectMatcherState\n * @param clipboard The Clipboard utility instance.\n * @param expected The string or object to compare against the clipboard content.\n * @param options Optional settings for the matcher, such as timeout.\n * @returns A Promise that resolves to a MatcherReturnType object.\n */\nexport async function toHaveData(\n this: ExpectMatcherState,\n clipboard: ClipboardHandler,\n expected: unknown,\n options: MatcherOptions = {},\n) {\n const name = 'toHaveData';\n let matcherReturn: MatcherReturnType | null = null;\n\n if (typeof expected === 'string') {\n matcherReturn = await toHaveText.call(this, clipboard, expected, options);\n } else {\n matcherReturn = await toHaveJSON.call(this, clipboard, expected, options);\n }\n\n return {\n ...matcherReturn,\n name,\n message: () => {\n const originalMessage = matcherReturn.message();\n return originalMessage.replace('toHaveText', name).replace('toHaveJSON', name);\n },\n };\n}\n","import { toHaveData } from './toHaveData.js';\nimport { toHaveJSON } from './toHaveJSON.js';\nimport { toHaveText } from './toHaveText.js';\n\n/**\n * Export an object containing all the custom clipboard matchers for Playwright.\n */\nexport const clipboardMatchers = {\n toHaveText,\n toHaveJSON,\n toHaveData,\n};\n"],"mappings":"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","names":["expect","import_test","import_test","baseTest","expect","baseExpect"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/utils/clipboardHandler.ts","../src/fixtures/clipboardFixture.ts","../src/fixtures/contextFixture.ts","../src/fixtures/index.ts","../src/fixtures.ts","../src/matchers/toHaveJSONContent.ts","../src/utils/matcherUtils.ts","../src/matchers/toHaveTextContent.ts","../src/matchers/toHaveData.ts","../src/matchers/clipboardMatchers.ts"],"sourcesContent":["export { firefoxClipboardPrefs } from './constants.js';\nexport { clipboardFixture, clipboardFixtures, contextFixture } from './fixtures/index.js';\nexport { expect, test } from './fixtures.js';\nexport { clipboardMatchers } from './matchers/index.js';\nexport { ClipboardHandler } from './utils/index.js';\n","export const firefoxClipboardPrefs = {\n 'dom.events.testing.asyncClipboard': true,\n 'dom.events.asyncClipboard.readText': true,\n 'dom.events.asyncClipboard.writeText': true,\n 'permissions.default.clipboard-read': 1,\n 'permissions.default.clipboard-write': 1,\n};\n","/**\n * Playwright-compatible Clipboard utilities.\n *\n * Core functions for interacting with the browser clipboard within Playwright tests.\n * Provides wrappers for reading plain text and JSON.\n *\n * @remarks\n * These utilities require 'clipboard-read' and 'clipboard-write' permissions\n * to be granted in the browser context.\n */\n\nimport type { Page } from '@playwright/test';\n\nexport class ClipboardHandler {\n constructor(private readonly page: Page) {}\n\n /**\n * Reads the current text content from the browser clipboard.\n * If the content is a JSON-encoded string (e.g., has extra quotes),\n * it will be returned as is. Use readJSON for automatic parsing.\n *\n * @returns A promise that resolves to the clipboard string content.\n */\n async read(): Promise<string> {\n return await this.page.evaluate(() => navigator.clipboard.readText());\n }\n\n /**\n * Reads the clipboard content and parses it as JSON.\n * If the content is a string literal (e.g., '\"value\"'), it returns the unwrapped string ('value').\n *\n * @template T - The expected type of the parsed JSON object.\n * @returns A promise that resolves to the parsed JSON object of type T.\n * @throws {Error} If the clipboard content is not a valid JSON string.\n */\n async readJSON<T = unknown>(): Promise<T> {\n const text = await this.read();\n try {\n return JSON.parse(text);\n } catch {\n throw new Error(`Clipboard content is not a valid JSON: ${JSON.stringify(text)}`);\n }\n }\n}\n","import type { Page, TestFixture } from '@playwright/test';\nimport type { BrowserName } from '../types.js';\nimport { ClipboardHandler } from '../utils/index.js';\n\n/**\n * A fixture that provides an instance of the Clipboard utility for interacting with the system clipboard.\n * It allows reading from the clipboard during tests.\n */\nexport const clipboardFixture: TestFixture<\n ClipboardHandler,\n { page: Page; browserName: BrowserName }\n> = async ({ page, browserName }, use) => {\n if (browserName === 'webkit') {\n throw new Error(\n `[playwright-clipboard] Browser '${browserName}' is not supported. ` +\n 'Clipboard API testing is currently supported only in Chromium-based and Firefox browsers.\\n' +\n `Add test.skip(browserName === 'webkit', 'Clipboard API is only supported in Chromium and Firefox'); to your test body.`,\n );\n }\n\n const handler = new ClipboardHandler(page);\n await use(handler);\n};\n","import type { BrowserContext, TestFixture } from '@playwright/test';\nimport type { BrowserName } from '../types.js';\n\n/**\n * A fixture that provides a BrowserContext with clipboard permissions granted for Chromium browsers.\n */\nexport const contextFixture: TestFixture<\n BrowserContext,\n { context: BrowserContext; browserName: BrowserName }\n> = async ({ context, browserName }, use) => {\n if (browserName === 'chromium') {\n await context.grantPermissions(['clipboard-read', 'clipboard-write']);\n }\n\n await use(context);\n};\n","import { clipboardFixture } from './clipboardFixture.js';\nimport { contextFixture } from './contextFixture.js';\n\n/**\n * A collection of fixtures related to clipboard testing, including the clipboard fixture and context fixture.\n * These fixtures can be used in Playwright tests to facilitate clipboard interactions and context management.\n */\nexport const clipboardFixtures = {\n context: contextFixture,\n clipboard: clipboardFixture,\n};\n\nexport { clipboardFixture, contextFixture };\n","import { expect as baseExpect, test as baseTest } from '@playwright/test';\nimport { clipboardFixtures } from './fixtures/index.js';\nimport { clipboardMatchers } from './matchers/index.js';\nimport type { ClipboardHandler } from './utils/index.js';\n\nexport const test = baseTest.extend<{\n clipboard: ClipboardHandler;\n}>(clipboardFixtures);\n\nexport const expect = baseExpect.extend({ ...clipboardMatchers });\n","import type { ExpectMatcherState, MatcherReturnType } from '@playwright/test';\nimport { expect } from '@playwright/test';\nimport type { ClipboardHandler } from '../utils/clipboardHandler.js';\nimport { getErrorMessage } from '../utils/matcherUtils.js';\nimport type { MatcherOptions } from './types.js';\n\n/**\n * Asserts that the clipboard content matches the expected JSON value.\n *\n * @this ExpectMatcherState\n * @param clipboard The Clipboard utility instance.\n * @param expected The expected JSON value.\n * @param options Matcher options.\n * @returns A Promise that resolves to a MatcherReturnType object.\n */\nexport async function toHaveJSONContent(\n this: ExpectMatcherState,\n clipboard: ClipboardHandler,\n expected: unknown,\n options: MatcherOptions = {},\n) {\n const name = 'toHaveJSONContent';\n let pass: boolean;\n let actual: unknown;\n let errorReason: Error | null = null;\n\n const { timeout = 10_000 } = options;\n\n const poll = expect.poll(\n async () => {\n try {\n actual = await clipboard.readJSON();\n errorReason = null;\n return actual;\n } catch (error) {\n errorReason = error instanceof Error ? error : new Error(String(error));\n\n try {\n actual = await clipboard.read();\n } catch {\n actual = undefined;\n }\n\n throw errorReason;\n }\n },\n { timeout },\n );\n\n try {\n const expectation = this.isNot ? poll.not : poll;\n await expectation.toEqual(expected);\n pass = true;\n } catch {\n pass = false;\n }\n\n if (this.isNot) pass = !pass;\n\n const matcherReturn: MatcherReturnType = {\n message: getErrorMessage.call(this, name, expected, actual, errorReason),\n pass,\n name,\n expected,\n actual,\n };\n\n return matcherReturn;\n}\n","import type { ExpectMatcherState } from '@playwright/test';\n\n/**\n * Generates an error message for a custom matcher.\n *\n * @this ExpectMatcherState\n * @param name The name of the matcher.\n * @param expected The expected value.\n * @param actual The actual value.\n * @param error An optional error object.\n * @param errorMessage An optional error message string.\n * @returns A function that returns the error message string.\n */\nexport function getErrorMessage(\n this: ExpectMatcherState,\n name: string,\n expected: unknown,\n actual: unknown,\n error?: Error | null,\n errorMessage?: string | undefined | null,\n): () => string {\n const message = `${this.utils.matcherHint(name, undefined, undefined, { isNot: this.isNot })}\\n\\n`;\n\n if (error) {\n return () => `${message}An unexpected error occurred:\\n${error.message}`;\n }\n\n if (errorMessage) {\n return () => `${message}${errorMessage}`;\n }\n\n return () =>\n message +\n `Expected: ${this.isNot ? 'not ' : ''}${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(actual)}`;\n}\n","import { type ExpectMatcherState, expect, type MatcherReturnType } from '@playwright/test';\nimport type { ClipboardHandler } from '../utils/clipboardHandler.js';\nimport { getErrorMessage } from '../utils/matcherUtils.js';\nimport type { MatcherOptions } from './types.js';\n\n/**\n * Asserts that the clipboard content matches the expected text value.\n *\n * @this ExpectMatcherState\n * @param clipboard The Clipboard utility instance.\n * @param expected The expected text value.\n * @param options Matcher options.\n * @returns A Promise that resolves to a MatcherReturnType object.\n */\nexport async function toHaveTextContent(\n this: ExpectMatcherState,\n clipboard: ClipboardHandler,\n expected: string,\n options: MatcherOptions = {},\n) {\n const name = 'toHaveTextContent';\n let pass: boolean;\n let actual: unknown;\n let errorReason: Error | null = null;\n\n const { timeout = 10_000 } = options;\n\n const poll = expect.poll(\n async () => {\n try {\n actual = await clipboard.read();\n errorReason = null;\n return actual;\n } catch (error) {\n errorReason = error instanceof Error ? error : new Error(String(error));\n actual = undefined;\n\n throw errorReason;\n }\n },\n { timeout },\n );\n\n try {\n const expectation = this.isNot ? poll.not : poll;\n await expectation.toEqual(expected);\n pass = true;\n } catch {\n pass = false;\n }\n\n if (this.isNot) pass = !pass;\n\n const matcherReturn: MatcherReturnType = {\n message: getErrorMessage.call(this, name, expected, actual, errorReason),\n pass,\n name,\n expected,\n actual,\n };\n\n return matcherReturn;\n}\n","import type { ExpectMatcherState, MatcherReturnType } from '@playwright/test';\nimport type { ClipboardHandler } from '../utils/clipboardHandler.js';\nimport { toHaveJSONContent } from './toHaveJSONContent.js';\nimport { toHaveTextContent } from './toHaveTextContent.js';\nimport type { MatcherOptions } from './types.js';\n\n/**\n * Asserts that the clipboard content matches the expected value.\n * Uses smart polling to wait for the clipboard to be updated.\n * If the `expected` value is an object, it attempts to parse the clipboard\n * content as JSON before comparing.\n *\n * @this ExpectMatcherState\n * @param clipboard The Clipboard utility instance.\n * @param expected The string or object to compare against the clipboard content.\n * @param options Optional settings for the matcher, such as timeout.\n * @returns A Promise that resolves to a MatcherReturnType object.\n */\nexport async function toHaveData(\n this: ExpectMatcherState,\n clipboard: ClipboardHandler,\n expected: unknown,\n options: MatcherOptions = {},\n) {\n const name = 'toHaveData';\n let matcherReturn: MatcherReturnType | null = null;\n\n if (typeof expected === 'string') {\n matcherReturn = await toHaveTextContent.call(this, clipboard, expected, options);\n } else {\n matcherReturn = await toHaveJSONContent.call(this, clipboard, expected, options);\n }\n\n return {\n ...matcherReturn,\n name,\n message: () => {\n const originalMessage = matcherReturn.message();\n return originalMessage.replace('toHaveText', name).replace('toHaveJSON', name);\n },\n };\n}\n","import { toHaveData } from './toHaveData.js';\nimport { toHaveJSONContent } from './toHaveJSONContent.js';\nimport { toHaveTextContent } from './toHaveTextContent.js';\n\n/**\n * Export an object containing all the custom clipboard matchers for Playwright.\n */\nexport const clipboardMatchers = {\n toHaveTextContent,\n toHaveJSONContent,\n toHaveData,\n};\n"],"mappings":"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","names":["expect","import_test","import_test","baseTest","expect","baseExpect"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,7 @@
1
+ import * as playwright_test from 'playwright/test';
2
+ import * as playwright_core from 'playwright-core';
1
3
  import * as _playwright_test from '@playwright/test';
2
- import { Page, BrowserContext, TestFixture, ExpectMatcherState, MatcherReturnType } from '@playwright/test';
4
+ import { Page, TestFixture, BrowserContext, ExpectMatcherState, MatcherReturnType } from '@playwright/test';
3
5
 
4
6
  declare const firefoxClipboardPrefs: {
5
7
  'dom.events.testing.asyncClipboard': boolean;
@@ -24,15 +26,7 @@ type BrowserName = 'chromium' | 'firefox' | 'webkit';
24
26
 
25
27
  declare class ClipboardHandler {
26
28
  private readonly page;
27
- private readonly context;
28
- private readonly browserName;
29
- private isPermissionGranted;
30
- constructor(page: Page, context: BrowserContext, browserName?: BrowserName);
31
- /**
32
- * Grants clipboard permissions to the Chromium browser context if not already granted.
33
- * @private
34
- */
35
- private grantPermissions;
29
+ constructor(page: Page);
36
30
  /**
37
31
  * Reads the current text content from the browser clipboard.
38
32
  * If the content is a JSON-encoded string (e.g., has extra quotes),
@@ -58,10 +52,32 @@ declare class ClipboardHandler {
58
52
  */
59
53
  declare const clipboardFixture: TestFixture<ClipboardHandler, {
60
54
  page: Page;
55
+ browserName: BrowserName;
56
+ }>;
57
+
58
+ /**
59
+ * A fixture that provides a BrowserContext with clipboard permissions granted for Chromium browsers.
60
+ */
61
+ declare const contextFixture: TestFixture<BrowserContext, {
61
62
  context: BrowserContext;
62
63
  browserName: BrowserName;
63
64
  }>;
64
65
 
66
+ /**
67
+ * A collection of fixtures related to clipboard testing, including the clipboard fixture and context fixture.
68
+ * These fixtures can be used in Playwright tests to facilitate clipboard interactions and context management.
69
+ */
70
+ declare const clipboardFixtures: {
71
+ context: playwright_test.TestFixture<playwright_core.BrowserContext, {
72
+ context: playwright_core.BrowserContext;
73
+ browserName: BrowserName;
74
+ }>;
75
+ clipboard: playwright_test.TestFixture<ClipboardHandler, {
76
+ page: playwright_core.Page;
77
+ browserName: BrowserName;
78
+ }>;
79
+ };
80
+
65
81
  type MatcherOptions = {
66
82
  timeout?: number;
67
83
  };
@@ -79,7 +95,7 @@ declare global {
79
95
  * @example
80
96
  * await expect(clipboard).toHaveText('Copied value');
81
97
  */
82
- toHaveText(expected: string, options?: MatcherOptions): Promise<R>;
98
+ toHaveTextContent(expected: string, options?: MatcherOptions): Promise<R>;
83
99
  /**
84
100
  * Asserts that the clipboard content matches the expected JSON value.
85
101
  * Uses smart polling to wait for the clipboard to be updated.
@@ -91,7 +107,7 @@ declare global {
91
107
  * @example
92
108
  * await expect(clipboard).toHaveJSON({ id: 123, status: 'success' });
93
109
  */
94
- toHaveJSON(expected: unknown, options?: MatcherOptions): Promise<R>;
110
+ toHaveJSONContent(expected: unknown, options?: MatcherOptions): Promise<R>;
95
111
  /**
96
112
  * Asserts that the clipboard content matches the expected value.
97
113
  * Uses smart polling to wait for the clipboard to be updated.
@@ -144,7 +160,7 @@ declare function toHaveData(this: ExpectMatcherState, clipboard: ClipboardHandle
144
160
  * @param options Matcher options.
145
161
  * @returns A Promise that resolves to a MatcherReturnType object.
146
162
  */
147
- declare function toHaveJSON(this: ExpectMatcherState, clipboard: ClipboardHandler, expected: unknown, options?: MatcherOptions): Promise<MatcherReturnType>;
163
+ declare function toHaveJSONContent(this: ExpectMatcherState, clipboard: ClipboardHandler, expected: unknown, options?: MatcherOptions): Promise<MatcherReturnType>;
148
164
 
149
165
  /**
150
166
  * Asserts that the clipboard content matches the expected text value.
@@ -155,14 +171,14 @@ declare function toHaveJSON(this: ExpectMatcherState, clipboard: ClipboardHandle
155
171
  * @param options Matcher options.
156
172
  * @returns A Promise that resolves to a MatcherReturnType object.
157
173
  */
158
- declare function toHaveText(this: ExpectMatcherState, clipboard: ClipboardHandler, expected: string, options?: MatcherOptions): Promise<MatcherReturnType>;
174
+ declare function toHaveTextContent(this: ExpectMatcherState, clipboard: ClipboardHandler, expected: string, options?: MatcherOptions): Promise<MatcherReturnType>;
159
175
 
160
176
  declare const test: _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & {
161
177
  clipboard: ClipboardHandler;
162
178
  }, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
163
179
  declare const expect: _playwright_test.Expect<{
164
- toHaveText: typeof toHaveText;
165
- toHaveJSON: typeof toHaveJSON;
180
+ toHaveTextContent: typeof toHaveTextContent;
181
+ toHaveJSONContent: typeof toHaveJSONContent;
166
182
  toHaveData: typeof toHaveData;
167
183
  }>;
168
184
 
@@ -170,9 +186,9 @@ declare const expect: _playwright_test.Expect<{
170
186
  * Export an object containing all the custom clipboard matchers for Playwright.
171
187
  */
172
188
  declare const clipboardMatchers: {
173
- toHaveText: typeof toHaveText;
174
- toHaveJSON: typeof toHaveJSON;
189
+ toHaveTextContent: typeof toHaveTextContent;
190
+ toHaveJSONContent: typeof toHaveJSONContent;
175
191
  toHaveData: typeof toHaveData;
176
192
  };
177
193
 
178
- export { ClipboardHandler, clipboardFixture, clipboardMatchers, expect, firefoxClipboardPrefs, test };
194
+ export { ClipboardHandler, clipboardFixture, clipboardFixtures, clipboardMatchers, contextFixture, expect, firefoxClipboardPrefs, test };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
+ import * as playwright_test from 'playwright/test';
2
+ import * as playwright_core from 'playwright-core';
1
3
  import * as _playwright_test from '@playwright/test';
2
- import { Page, BrowserContext, TestFixture, ExpectMatcherState, MatcherReturnType } from '@playwright/test';
4
+ import { Page, TestFixture, BrowserContext, ExpectMatcherState, MatcherReturnType } from '@playwright/test';
3
5
 
4
6
  declare const firefoxClipboardPrefs: {
5
7
  'dom.events.testing.asyncClipboard': boolean;
@@ -24,15 +26,7 @@ type BrowserName = 'chromium' | 'firefox' | 'webkit';
24
26
 
25
27
  declare class ClipboardHandler {
26
28
  private readonly page;
27
- private readonly context;
28
- private readonly browserName;
29
- private isPermissionGranted;
30
- constructor(page: Page, context: BrowserContext, browserName?: BrowserName);
31
- /**
32
- * Grants clipboard permissions to the Chromium browser context if not already granted.
33
- * @private
34
- */
35
- private grantPermissions;
29
+ constructor(page: Page);
36
30
  /**
37
31
  * Reads the current text content from the browser clipboard.
38
32
  * If the content is a JSON-encoded string (e.g., has extra quotes),
@@ -58,10 +52,32 @@ declare class ClipboardHandler {
58
52
  */
59
53
  declare const clipboardFixture: TestFixture<ClipboardHandler, {
60
54
  page: Page;
55
+ browserName: BrowserName;
56
+ }>;
57
+
58
+ /**
59
+ * A fixture that provides a BrowserContext with clipboard permissions granted for Chromium browsers.
60
+ */
61
+ declare const contextFixture: TestFixture<BrowserContext, {
61
62
  context: BrowserContext;
62
63
  browserName: BrowserName;
63
64
  }>;
64
65
 
66
+ /**
67
+ * A collection of fixtures related to clipboard testing, including the clipboard fixture and context fixture.
68
+ * These fixtures can be used in Playwright tests to facilitate clipboard interactions and context management.
69
+ */
70
+ declare const clipboardFixtures: {
71
+ context: playwright_test.TestFixture<playwright_core.BrowserContext, {
72
+ context: playwright_core.BrowserContext;
73
+ browserName: BrowserName;
74
+ }>;
75
+ clipboard: playwright_test.TestFixture<ClipboardHandler, {
76
+ page: playwright_core.Page;
77
+ browserName: BrowserName;
78
+ }>;
79
+ };
80
+
65
81
  type MatcherOptions = {
66
82
  timeout?: number;
67
83
  };
@@ -79,7 +95,7 @@ declare global {
79
95
  * @example
80
96
  * await expect(clipboard).toHaveText('Copied value');
81
97
  */
82
- toHaveText(expected: string, options?: MatcherOptions): Promise<R>;
98
+ toHaveTextContent(expected: string, options?: MatcherOptions): Promise<R>;
83
99
  /**
84
100
  * Asserts that the clipboard content matches the expected JSON value.
85
101
  * Uses smart polling to wait for the clipboard to be updated.
@@ -91,7 +107,7 @@ declare global {
91
107
  * @example
92
108
  * await expect(clipboard).toHaveJSON({ id: 123, status: 'success' });
93
109
  */
94
- toHaveJSON(expected: unknown, options?: MatcherOptions): Promise<R>;
110
+ toHaveJSONContent(expected: unknown, options?: MatcherOptions): Promise<R>;
95
111
  /**
96
112
  * Asserts that the clipboard content matches the expected value.
97
113
  * Uses smart polling to wait for the clipboard to be updated.
@@ -144,7 +160,7 @@ declare function toHaveData(this: ExpectMatcherState, clipboard: ClipboardHandle
144
160
  * @param options Matcher options.
145
161
  * @returns A Promise that resolves to a MatcherReturnType object.
146
162
  */
147
- declare function toHaveJSON(this: ExpectMatcherState, clipboard: ClipboardHandler, expected: unknown, options?: MatcherOptions): Promise<MatcherReturnType>;
163
+ declare function toHaveJSONContent(this: ExpectMatcherState, clipboard: ClipboardHandler, expected: unknown, options?: MatcherOptions): Promise<MatcherReturnType>;
148
164
 
149
165
  /**
150
166
  * Asserts that the clipboard content matches the expected text value.
@@ -155,14 +171,14 @@ declare function toHaveJSON(this: ExpectMatcherState, clipboard: ClipboardHandle
155
171
  * @param options Matcher options.
156
172
  * @returns A Promise that resolves to a MatcherReturnType object.
157
173
  */
158
- declare function toHaveText(this: ExpectMatcherState, clipboard: ClipboardHandler, expected: string, options?: MatcherOptions): Promise<MatcherReturnType>;
174
+ declare function toHaveTextContent(this: ExpectMatcherState, clipboard: ClipboardHandler, expected: string, options?: MatcherOptions): Promise<MatcherReturnType>;
159
175
 
160
176
  declare const test: _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & {
161
177
  clipboard: ClipboardHandler;
162
178
  }, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
163
179
  declare const expect: _playwright_test.Expect<{
164
- toHaveText: typeof toHaveText;
165
- toHaveJSON: typeof toHaveJSON;
180
+ toHaveTextContent: typeof toHaveTextContent;
181
+ toHaveJSONContent: typeof toHaveJSONContent;
166
182
  toHaveData: typeof toHaveData;
167
183
  }>;
168
184
 
@@ -170,9 +186,9 @@ declare const expect: _playwright_test.Expect<{
170
186
  * Export an object containing all the custom clipboard matchers for Playwright.
171
187
  */
172
188
  declare const clipboardMatchers: {
173
- toHaveText: typeof toHaveText;
174
- toHaveJSON: typeof toHaveJSON;
189
+ toHaveTextContent: typeof toHaveTextContent;
190
+ toHaveJSONContent: typeof toHaveJSONContent;
175
191
  toHaveData: typeof toHaveData;
176
192
  };
177
193
 
178
- export { ClipboardHandler, clipboardFixture, clipboardMatchers, expect, firefoxClipboardPrefs, test };
194
+ export { ClipboardHandler, clipboardFixture, clipboardFixtures, clipboardMatchers, contextFixture, expect, firefoxClipboardPrefs, test };
package/dist/index.js CHANGED
@@ -9,28 +9,10 @@ var firefoxClipboardPrefs = {
9
9
 
10
10
  // src/utils/clipboardHandler.ts
11
11
  var ClipboardHandler = class {
12
- constructor(page, context, browserName = "chromium") {
12
+ constructor(page) {
13
13
  this.page = page;
14
- this.context = context;
15
- this.browserName = browserName;
16
- this.isPermissionGranted = false;
17
14
  }
18
15
  page;
19
- context;
20
- browserName;
21
- isPermissionGranted;
22
- /**
23
- * Grants clipboard permissions to the Chromium browser context if not already granted.
24
- * @private
25
- */
26
- async grantPermissions() {
27
- if (this.browserName === "chromium") {
28
- if (!this.isPermissionGranted) {
29
- await this.context.grantPermissions(["clipboard-read", "clipboard-write"]);
30
- this.isPermissionGranted = true;
31
- }
32
- }
33
- }
34
16
  /**
35
17
  * Reads the current text content from the browser clipboard.
36
18
  * If the content is a JSON-encoded string (e.g., has extra quotes),
@@ -39,7 +21,6 @@ var ClipboardHandler = class {
39
21
  * @returns A promise that resolves to the clipboard string content.
40
22
  */
41
23
  async read() {
42
- await this.grantPermissions();
43
24
  return await this.page.evaluate(() => navigator.clipboard.readText());
44
25
  }
45
26
  /**
@@ -61,21 +42,35 @@ var ClipboardHandler = class {
61
42
  };
62
43
 
63
44
  // src/fixtures/clipboardFixture.ts
64
- var clipboardFixture = async ({ page, context, browserName }, use) => {
45
+ var clipboardFixture = async ({ page, browserName }, use) => {
65
46
  if (browserName === "webkit") {
66
47
  throw new Error(
67
48
  `[playwright-clipboard] Browser '${browserName}' is not supported. Clipboard API testing is currently supported only in Chromium-based and Firefox browsers.
68
49
  Add test.skip(browserName === 'webkit', 'Clipboard API is only supported in Chromium and Firefox'); to your test body.`
69
50
  );
70
51
  }
71
- const handler = new ClipboardHandler(page, context, browserName);
52
+ const handler = new ClipboardHandler(page);
72
53
  await use(handler);
73
54
  };
74
55
 
56
+ // src/fixtures/contextFixture.ts
57
+ var contextFixture = async ({ context, browserName }, use) => {
58
+ if (browserName === "chromium") {
59
+ await context.grantPermissions(["clipboard-read", "clipboard-write"]);
60
+ }
61
+ await use(context);
62
+ };
63
+
64
+ // src/fixtures/index.ts
65
+ var clipboardFixtures = {
66
+ context: contextFixture,
67
+ clipboard: clipboardFixture
68
+ };
69
+
75
70
  // src/fixtures.ts
76
71
  import { expect as baseExpect, test as baseTest } from "@playwright/test";
77
72
 
78
- // src/matchers/toHaveJSON.ts
73
+ // src/matchers/toHaveJSONContent.ts
79
74
  import { expect } from "@playwright/test";
80
75
 
81
76
  // src/utils/matcherUtils.ts
@@ -94,9 +89,9 @@ ${error.message}`;
94
89
  Received: ${this.utils.printReceived(actual)}`;
95
90
  }
96
91
 
97
- // src/matchers/toHaveJSON.ts
98
- async function toHaveJSON(clipboard, expected, options = {}) {
99
- const name = "toHaveJSON";
92
+ // src/matchers/toHaveJSONContent.ts
93
+ async function toHaveJSONContent(clipboard, expected, options = {}) {
94
+ const name = "toHaveJSONContent";
100
95
  let pass;
101
96
  let actual;
102
97
  let errorReason = null;
@@ -137,10 +132,10 @@ async function toHaveJSON(clipboard, expected, options = {}) {
137
132
  return matcherReturn;
138
133
  }
139
134
 
140
- // src/matchers/toHaveText.ts
135
+ // src/matchers/toHaveTextContent.ts
141
136
  import { expect as expect2 } from "@playwright/test";
142
- async function toHaveText(clipboard, expected, options = {}) {
143
- const name = "toHaveText";
137
+ async function toHaveTextContent(clipboard, expected, options = {}) {
138
+ const name = "toHaveTextContent";
144
139
  let pass;
145
140
  let actual;
146
141
  let errorReason = null;
@@ -182,9 +177,9 @@ async function toHaveData(clipboard, expected, options = {}) {
182
177
  const name = "toHaveData";
183
178
  let matcherReturn = null;
184
179
  if (typeof expected === "string") {
185
- matcherReturn = await toHaveText.call(this, clipboard, expected, options);
180
+ matcherReturn = await toHaveTextContent.call(this, clipboard, expected, options);
186
181
  } else {
187
- matcherReturn = await toHaveJSON.call(this, clipboard, expected, options);
182
+ matcherReturn = await toHaveJSONContent.call(this, clipboard, expected, options);
188
183
  }
189
184
  return {
190
185
  ...matcherReturn,
@@ -198,24 +193,20 @@ async function toHaveData(clipboard, expected, options = {}) {
198
193
 
199
194
  // src/matchers/clipboardMatchers.ts
200
195
  var clipboardMatchers = {
201
- toHaveText,
202
- toHaveJSON,
196
+ toHaveTextContent,
197
+ toHaveJSONContent,
203
198
  toHaveData
204
199
  };
205
200
 
206
201
  // src/fixtures.ts
207
- var test = baseTest.extend({
208
- /**
209
- * A fixture that provides an instance of the Clipboard utility for interacting with the system clipboard.
210
- * It allows reading from the clipboard during tests.
211
- */
212
- clipboard: clipboardFixture
213
- });
202
+ var test = baseTest.extend(clipboardFixtures);
214
203
  var expect3 = baseExpect.extend({ ...clipboardMatchers });
215
204
  export {
216
205
  ClipboardHandler,
217
206
  clipboardFixture,
207
+ clipboardFixtures,
218
208
  clipboardMatchers,
209
+ contextFixture,
219
210
  expect3 as expect,
220
211
  firefoxClipboardPrefs,
221
212
  test
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/utils/clipboardHandler.ts","../src/fixtures/clipboardFixture.ts","../src/fixtures.ts","../src/matchers/toHaveJSON.ts","../src/utils/matcherUtils.ts","../src/matchers/toHaveText.ts","../src/matchers/toHaveData.ts","../src/matchers/clipboardMatchers.ts"],"sourcesContent":["export const firefoxClipboardPrefs = {\n 'dom.events.testing.asyncClipboard': true,\n 'dom.events.asyncClipboard.readText': true,\n 'dom.events.asyncClipboard.writeText': true,\n 'permissions.default.clipboard-read': 1,\n 'permissions.default.clipboard-write': 1,\n};\n","/**\n * Playwright-compatible Clipboard utilities.\n *\n * Core functions for interacting with the browser clipboard within Playwright tests.\n * Provides wrappers for reading plain text and JSON.\n *\n * @remarks\n * These utilities require 'clipboard-read' and 'clipboard-write' permissions\n * to be granted in the browser context.\n */\n\nimport type { BrowserContext, Page } from '@playwright/test';\nimport type { BrowserName } from '../types.js';\n\nexport class ClipboardHandler {\n private readonly browserName: BrowserName;\n private isPermissionGranted: boolean;\n\n constructor(\n private readonly page: Page,\n private readonly context: BrowserContext,\n browserName: BrowserName = 'chromium',\n ) {\n this.browserName = browserName;\n this.isPermissionGranted = false;\n }\n\n /**\n * Grants clipboard permissions to the Chromium browser context if not already granted.\n * @private\n */\n private async grantPermissions() {\n if (this.browserName === 'chromium') {\n if (!this.isPermissionGranted) {\n await this.context.grantPermissions(['clipboard-read', 'clipboard-write']);\n this.isPermissionGranted = true;\n }\n }\n }\n\n /**\n * Reads the current text content from the browser clipboard.\n * If the content is a JSON-encoded string (e.g., has extra quotes),\n * it will be returned as is. Use readJSON for automatic parsing.\n *\n * @returns A promise that resolves to the clipboard string content.\n */\n async read(): Promise<string> {\n await this.grantPermissions();\n return await this.page.evaluate(() => navigator.clipboard.readText());\n }\n\n /**\n * Reads the clipboard content and parses it as JSON.\n * If the content is a string literal (e.g., '\"value\"'), it returns the unwrapped string ('value').\n *\n * @template T - The expected type of the parsed JSON object.\n * @returns A promise that resolves to the parsed JSON object of type T.\n * @throws {Error} If the clipboard content is not a valid JSON string.\n */\n async readJSON<T = unknown>(): Promise<T> {\n const text = await this.read();\n try {\n return JSON.parse(text);\n } catch {\n throw new Error(`Clipboard content is not a valid JSON: ${JSON.stringify(text)}`);\n }\n }\n}\n","import type { BrowserContext, Page, TestFixture } from '@playwright/test';\nimport type { BrowserName } from '../types.js';\nimport { ClipboardHandler } from '../utils/clipboardHandler.js';\n\n/**\n * A fixture that provides an instance of the Clipboard utility for interacting with the system clipboard.\n * It allows reading from the clipboard during tests.\n */\nexport const clipboardFixture: TestFixture<\n ClipboardHandler,\n { page: Page; context: BrowserContext; browserName: BrowserName }\n> = async ({ page, context, browserName }, use) => {\n if (browserName === 'webkit') {\n throw new Error(\n `[playwright-clipboard] Browser '${browserName}' is not supported. ` +\n 'Clipboard API testing is currently supported only in Chromium-based and Firefox browsers.\\n' +\n `Add test.skip(browserName === 'webkit', 'Clipboard API is only supported in Chromium and Firefox'); to your test body.`,\n );\n }\n\n const handler = new ClipboardHandler(page, context, browserName);\n await use(handler);\n};\n","import { expect as baseExpect, test as baseTest } from '@playwright/test';\nimport { clipboardFixture } from './fixtures/clipboardFixture.js';\nimport { clipboardMatchers } from './matchers/clipboardMatchers.js';\nimport type { ClipboardHandler } from './utils/clipboardHandler.js';\n\nexport const test = baseTest.extend<{\n clipboard: ClipboardHandler;\n}>({\n /**\n * A fixture that provides an instance of the Clipboard utility for interacting with the system clipboard.\n * It allows reading from the clipboard during tests.\n */\n clipboard: clipboardFixture,\n});\n\nexport const expect = baseExpect.extend({ ...clipboardMatchers });\n","import type { ExpectMatcherState, MatcherReturnType } from '@playwright/test';\nimport { expect } from '@playwright/test';\nimport type { ClipboardHandler } from '../utils/clipboardHandler.js';\nimport { getErrorMessage } from '../utils/matcherUtils.js';\nimport type { MatcherOptions } from './types.js';\n\n/**\n * Asserts that the clipboard content matches the expected JSON value.\n *\n * @this ExpectMatcherState\n * @param clipboard The Clipboard utility instance.\n * @param expected The expected JSON value.\n * @param options Matcher options.\n * @returns A Promise that resolves to a MatcherReturnType object.\n */\nexport async function toHaveJSON(\n this: ExpectMatcherState,\n clipboard: ClipboardHandler,\n expected: unknown,\n options: MatcherOptions = {},\n) {\n const name = 'toHaveJSON';\n let pass: boolean;\n let actual: unknown;\n let errorReason: Error | null = null;\n\n const { timeout = 10_000 } = options;\n\n const poll = expect.poll(\n async () => {\n try {\n actual = await clipboard.readJSON();\n errorReason = null;\n return actual;\n } catch (error) {\n errorReason = error instanceof Error ? error : new Error(String(error));\n\n try {\n actual = await clipboard.read();\n } catch {\n actual = undefined;\n }\n\n throw errorReason;\n }\n },\n { timeout },\n );\n\n try {\n const expectation = this.isNot ? poll.not : poll;\n await expectation.toEqual(expected);\n pass = true;\n } catch {\n pass = false;\n }\n\n if (this.isNot) pass = !pass;\n\n const matcherReturn: MatcherReturnType = {\n message: getErrorMessage.call(this, name, expected, actual, errorReason),\n pass,\n name,\n expected,\n actual,\n };\n\n return matcherReturn;\n}\n","import type { ExpectMatcherState } from '@playwright/test';\n\n/**\n * Generates an error message for a custom matcher.\n *\n * @this ExpectMatcherState\n * @param name The name of the matcher.\n * @param expected The expected value.\n * @param actual The actual value.\n * @param error An optional error object.\n * @param errorMessage An optional error message string.\n * @returns A function that returns the error message string.\n */\nexport function getErrorMessage(\n this: ExpectMatcherState,\n name: string,\n expected: unknown,\n actual: unknown,\n error?: Error | null,\n errorMessage?: string | undefined | null,\n): () => string {\n const message = `${this.utils.matcherHint(name, undefined, undefined, { isNot: this.isNot })}\\n\\n`;\n\n if (error) {\n return () => `${message}An unexpected error occurred:\\n${error.message}`;\n }\n\n if (errorMessage) {\n return () => `${message}${errorMessage}`;\n }\n\n return () =>\n message +\n `Expected: ${this.isNot ? 'not ' : ''}${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(actual)}`;\n}\n","import { type ExpectMatcherState, expect, type MatcherReturnType } from '@playwright/test';\nimport type { ClipboardHandler } from '../utils/clipboardHandler.js';\nimport { getErrorMessage } from '../utils/matcherUtils.js';\nimport type { MatcherOptions } from './types.js';\n\n/**\n * Asserts that the clipboard content matches the expected text value.\n *\n * @this ExpectMatcherState\n * @param clipboard The Clipboard utility instance.\n * @param expected The expected text value.\n * @param options Matcher options.\n * @returns A Promise that resolves to a MatcherReturnType object.\n */\nexport async function toHaveText(\n this: ExpectMatcherState,\n clipboard: ClipboardHandler,\n expected: string,\n options: MatcherOptions = {},\n) {\n const name = 'toHaveText';\n let pass: boolean;\n let actual: unknown;\n let errorReason: Error | null = null;\n\n const { timeout = 10_000 } = options;\n\n const poll = expect.poll(\n async () => {\n try {\n actual = await clipboard.read();\n errorReason = null;\n return actual;\n } catch (error) {\n errorReason = error instanceof Error ? error : new Error(String(error));\n actual = undefined;\n\n throw errorReason;\n }\n },\n { timeout },\n );\n\n try {\n const expectation = this.isNot ? poll.not : poll;\n await expectation.toEqual(expected);\n pass = true;\n } catch {\n pass = false;\n }\n\n if (this.isNot) pass = !pass;\n\n const matcherReturn: MatcherReturnType = {\n message: getErrorMessage.call(this, name, expected, actual, errorReason),\n pass,\n name,\n expected,\n actual,\n };\n\n return matcherReturn;\n}\n","import type { ExpectMatcherState, MatcherReturnType } from '@playwright/test';\nimport type { ClipboardHandler } from '../utils/clipboardHandler.js';\nimport { toHaveJSON } from './toHaveJSON.js';\nimport { toHaveText } from './toHaveText.js';\nimport type { MatcherOptions } from './types.js';\n\n/**\n * Asserts that the clipboard content matches the expected value.\n * Uses smart polling to wait for the clipboard to be updated.\n * If the `expected` value is an object, it attempts to parse the clipboard\n * content as JSON before comparing.\n *\n * @this ExpectMatcherState\n * @param clipboard The Clipboard utility instance.\n * @param expected The string or object to compare against the clipboard content.\n * @param options Optional settings for the matcher, such as timeout.\n * @returns A Promise that resolves to a MatcherReturnType object.\n */\nexport async function toHaveData(\n this: ExpectMatcherState,\n clipboard: ClipboardHandler,\n expected: unknown,\n options: MatcherOptions = {},\n) {\n const name = 'toHaveData';\n let matcherReturn: MatcherReturnType | null = null;\n\n if (typeof expected === 'string') {\n matcherReturn = await toHaveText.call(this, clipboard, expected, options);\n } else {\n matcherReturn = await toHaveJSON.call(this, clipboard, expected, options);\n }\n\n return {\n ...matcherReturn,\n name,\n message: () => {\n const originalMessage = matcherReturn.message();\n return originalMessage.replace('toHaveText', name).replace('toHaveJSON', name);\n },\n };\n}\n","import { toHaveData } from './toHaveData.js';\nimport { toHaveJSON } from './toHaveJSON.js';\nimport { toHaveText } from './toHaveText.js';\n\n/**\n * Export an object containing all the custom clipboard matchers for Playwright.\n */\nexport const clipboardMatchers = {\n toHaveText,\n toHaveJSON,\n toHaveData,\n};\n"],"mappings":";AAAO,IAAM,wBAAwB;AAAA,EACnC,qCAAqC;AAAA,EACrC,sCAAsC;AAAA,EACtC,uCAAuC;AAAA,EACvC,sCAAsC;AAAA,EACtC,uCAAuC;AACzC;;;ACQO,IAAM,mBAAN,MAAuB;AAAA,EAI5B,YACmB,MACA,SACjB,cAA2B,YAC3B;AAHiB;AACA;AAGjB,SAAK,cAAc;AACnB,SAAK,sBAAsB;AAAA,EAC7B;AAAA,EANmB;AAAA,EACA;AAAA,EALF;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAeR,MAAc,mBAAmB;AAC/B,QAAI,KAAK,gBAAgB,YAAY;AACnC,UAAI,CAAC,KAAK,qBAAqB;AAC7B,cAAM,KAAK,QAAQ,iBAAiB,CAAC,kBAAkB,iBAAiB,CAAC;AACzE,aAAK,sBAAsB;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAwB;AAC5B,UAAM,KAAK,iBAAiB;AAC5B,WAAO,MAAM,KAAK,KAAK,SAAS,MAAM,UAAU,UAAU,SAAS,CAAC;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,WAAoC;AACxC,UAAM,OAAO,MAAM,KAAK,KAAK;AAC7B,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AACN,YAAM,IAAI,MAAM,0CAA0C,KAAK,UAAU,IAAI,CAAC,EAAE;AAAA,IAClF;AAAA,EACF;AACF;;;AC5DO,IAAM,mBAGT,OAAO,EAAE,MAAM,SAAS,YAAY,GAAG,QAAQ;AACjD,MAAI,gBAAgB,UAAU;AAC5B,UAAM,IAAI;AAAA,MACR,mCAAmC,WAAW;AAAA;AAAA,IAGhD;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,iBAAiB,MAAM,SAAS,WAAW;AAC/D,QAAM,IAAI,OAAO;AACnB;;;ACtBA,SAAS,UAAU,YAAY,QAAQ,gBAAgB;;;ACCvD,SAAS,cAAc;;;ACYhB,SAAS,gBAEd,MACA,UACA,QACA,OACA,cACc;AACd,QAAM,UAAU,GAAG,KAAK,MAAM,YAAY,MAAM,QAAW,QAAW,EAAE,OAAO,KAAK,MAAM,CAAC,CAAC;AAAA;AAAA;AAE5F,MAAI,OAAO;AACT,WAAO,MAAM,GAAG,OAAO;AAAA,EAAkC,MAAM,OAAO;AAAA,EACxE;AAEA,MAAI,cAAc;AAChB,WAAO,MAAM,GAAG,OAAO,GAAG,YAAY;AAAA,EACxC;AAEA,SAAO,MACL,UACA,aAAa,KAAK,QAAQ,SAAS,EAAE,GAAG,KAAK,MAAM,cAAc,QAAQ,CAAC;AAAA,YAC7D,KAAK,MAAM,cAAc,MAAM,CAAC;AACjD;;;ADpBA,eAAsB,WAEpB,WACA,UACA,UAA0B,CAAC,GAC3B;AACA,QAAM,OAAO;AACb,MAAI;AACJ,MAAI;AACJ,MAAI,cAA4B;AAEhC,QAAM,EAAE,UAAU,IAAO,IAAI;AAE7B,QAAM,OAAO,OAAO;AAAA,IAClB,YAAY;AACV,UAAI;AACF,iBAAS,MAAM,UAAU,SAAS;AAClC,sBAAc;AACd,eAAO;AAAA,MACT,SAAS,OAAO;AACd,sBAAc,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAEtE,YAAI;AACF,mBAAS,MAAM,UAAU,KAAK;AAAA,QAChC,QAAQ;AACN,mBAAS;AAAA,QACX;AAEA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,EAAE,QAAQ;AAAA,EACZ;AAEA,MAAI;AACF,UAAM,cAAc,KAAK,QAAQ,KAAK,MAAM;AAC5C,UAAM,YAAY,QAAQ,QAAQ;AAClC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,MAAI,KAAK,MAAO,QAAO,CAAC;AAExB,QAAM,gBAAmC;AAAA,IACvC,SAAS,gBAAgB,KAAK,MAAM,MAAM,UAAU,QAAQ,WAAW;AAAA,IACvE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;;;AEpEA,SAAkC,UAAAA,eAAsC;AAcxE,eAAsB,WAEpB,WACA,UACA,UAA0B,CAAC,GAC3B;AACA,QAAM,OAAO;AACb,MAAI;AACJ,MAAI;AACJ,MAAI,cAA4B;AAEhC,QAAM,EAAE,UAAU,IAAO,IAAI;AAE7B,QAAM,OAAOC,QAAO;AAAA,IAClB,YAAY;AACV,UAAI;AACF,iBAAS,MAAM,UAAU,KAAK;AAC9B,sBAAc;AACd,eAAO;AAAA,MACT,SAAS,OAAO;AACd,sBAAc,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AACtE,iBAAS;AAET,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,EAAE,QAAQ;AAAA,EACZ;AAEA,MAAI;AACF,UAAM,cAAc,KAAK,QAAQ,KAAK,MAAM;AAC5C,UAAM,YAAY,QAAQ,QAAQ;AAClC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,MAAI,KAAK,MAAO,QAAO,CAAC;AAExB,QAAM,gBAAmC;AAAA,IACvC,SAAS,gBAAgB,KAAK,MAAM,MAAM,UAAU,QAAQ,WAAW;AAAA,IACvE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;;;AC5CA,eAAsB,WAEpB,WACA,UACA,UAA0B,CAAC,GAC3B;AACA,QAAM,OAAO;AACb,MAAI,gBAA0C;AAE9C,MAAI,OAAO,aAAa,UAAU;AAChC,oBAAgB,MAAM,WAAW,KAAK,MAAM,WAAW,UAAU,OAAO;AAAA,EAC1E,OAAO;AACL,oBAAgB,MAAM,WAAW,KAAK,MAAM,WAAW,UAAU,OAAO;AAAA,EAC1E;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA,SAAS,MAAM;AACb,YAAM,kBAAkB,cAAc,QAAQ;AAC9C,aAAO,gBAAgB,QAAQ,cAAc,IAAI,EAAE,QAAQ,cAAc,IAAI;AAAA,IAC/E;AAAA,EACF;AACF;;;AClCO,IAAM,oBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AACF;;;ALNO,IAAM,OAAO,SAAS,OAE1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAKD,WAAW;AACb,CAAC;AAEM,IAAMC,UAAS,WAAW,OAAO,EAAE,GAAG,kBAAkB,CAAC;","names":["expect","expect","expect"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/utils/clipboardHandler.ts","../src/fixtures/clipboardFixture.ts","../src/fixtures/contextFixture.ts","../src/fixtures/index.ts","../src/fixtures.ts","../src/matchers/toHaveJSONContent.ts","../src/utils/matcherUtils.ts","../src/matchers/toHaveTextContent.ts","../src/matchers/toHaveData.ts","../src/matchers/clipboardMatchers.ts"],"sourcesContent":["export const firefoxClipboardPrefs = {\n 'dom.events.testing.asyncClipboard': true,\n 'dom.events.asyncClipboard.readText': true,\n 'dom.events.asyncClipboard.writeText': true,\n 'permissions.default.clipboard-read': 1,\n 'permissions.default.clipboard-write': 1,\n};\n","/**\n * Playwright-compatible Clipboard utilities.\n *\n * Core functions for interacting with the browser clipboard within Playwright tests.\n * Provides wrappers for reading plain text and JSON.\n *\n * @remarks\n * These utilities require 'clipboard-read' and 'clipboard-write' permissions\n * to be granted in the browser context.\n */\n\nimport type { Page } from '@playwright/test';\n\nexport class ClipboardHandler {\n constructor(private readonly page: Page) {}\n\n /**\n * Reads the current text content from the browser clipboard.\n * If the content is a JSON-encoded string (e.g., has extra quotes),\n * it will be returned as is. Use readJSON for automatic parsing.\n *\n * @returns A promise that resolves to the clipboard string content.\n */\n async read(): Promise<string> {\n return await this.page.evaluate(() => navigator.clipboard.readText());\n }\n\n /**\n * Reads the clipboard content and parses it as JSON.\n * If the content is a string literal (e.g., '\"value\"'), it returns the unwrapped string ('value').\n *\n * @template T - The expected type of the parsed JSON object.\n * @returns A promise that resolves to the parsed JSON object of type T.\n * @throws {Error} If the clipboard content is not a valid JSON string.\n */\n async readJSON<T = unknown>(): Promise<T> {\n const text = await this.read();\n try {\n return JSON.parse(text);\n } catch {\n throw new Error(`Clipboard content is not a valid JSON: ${JSON.stringify(text)}`);\n }\n }\n}\n","import type { Page, TestFixture } from '@playwright/test';\nimport type { BrowserName } from '../types.js';\nimport { ClipboardHandler } from '../utils/index.js';\n\n/**\n * A fixture that provides an instance of the Clipboard utility for interacting with the system clipboard.\n * It allows reading from the clipboard during tests.\n */\nexport const clipboardFixture: TestFixture<\n ClipboardHandler,\n { page: Page; browserName: BrowserName }\n> = async ({ page, browserName }, use) => {\n if (browserName === 'webkit') {\n throw new Error(\n `[playwright-clipboard] Browser '${browserName}' is not supported. ` +\n 'Clipboard API testing is currently supported only in Chromium-based and Firefox browsers.\\n' +\n `Add test.skip(browserName === 'webkit', 'Clipboard API is only supported in Chromium and Firefox'); to your test body.`,\n );\n }\n\n const handler = new ClipboardHandler(page);\n await use(handler);\n};\n","import type { BrowserContext, TestFixture } from '@playwright/test';\nimport type { BrowserName } from '../types.js';\n\n/**\n * A fixture that provides a BrowserContext with clipboard permissions granted for Chromium browsers.\n */\nexport const contextFixture: TestFixture<\n BrowserContext,\n { context: BrowserContext; browserName: BrowserName }\n> = async ({ context, browserName }, use) => {\n if (browserName === 'chromium') {\n await context.grantPermissions(['clipboard-read', 'clipboard-write']);\n }\n\n await use(context);\n};\n","import { clipboardFixture } from './clipboardFixture.js';\nimport { contextFixture } from './contextFixture.js';\n\n/**\n * A collection of fixtures related to clipboard testing, including the clipboard fixture and context fixture.\n * These fixtures can be used in Playwright tests to facilitate clipboard interactions and context management.\n */\nexport const clipboardFixtures = {\n context: contextFixture,\n clipboard: clipboardFixture,\n};\n\nexport { clipboardFixture, contextFixture };\n","import { expect as baseExpect, test as baseTest } from '@playwright/test';\nimport { clipboardFixtures } from './fixtures/index.js';\nimport { clipboardMatchers } from './matchers/index.js';\nimport type { ClipboardHandler } from './utils/index.js';\n\nexport const test = baseTest.extend<{\n clipboard: ClipboardHandler;\n}>(clipboardFixtures);\n\nexport const expect = baseExpect.extend({ ...clipboardMatchers });\n","import type { ExpectMatcherState, MatcherReturnType } from '@playwright/test';\nimport { expect } from '@playwright/test';\nimport type { ClipboardHandler } from '../utils/clipboardHandler.js';\nimport { getErrorMessage } from '../utils/matcherUtils.js';\nimport type { MatcherOptions } from './types.js';\n\n/**\n * Asserts that the clipboard content matches the expected JSON value.\n *\n * @this ExpectMatcherState\n * @param clipboard The Clipboard utility instance.\n * @param expected The expected JSON value.\n * @param options Matcher options.\n * @returns A Promise that resolves to a MatcherReturnType object.\n */\nexport async function toHaveJSONContent(\n this: ExpectMatcherState,\n clipboard: ClipboardHandler,\n expected: unknown,\n options: MatcherOptions = {},\n) {\n const name = 'toHaveJSONContent';\n let pass: boolean;\n let actual: unknown;\n let errorReason: Error | null = null;\n\n const { timeout = 10_000 } = options;\n\n const poll = expect.poll(\n async () => {\n try {\n actual = await clipboard.readJSON();\n errorReason = null;\n return actual;\n } catch (error) {\n errorReason = error instanceof Error ? error : new Error(String(error));\n\n try {\n actual = await clipboard.read();\n } catch {\n actual = undefined;\n }\n\n throw errorReason;\n }\n },\n { timeout },\n );\n\n try {\n const expectation = this.isNot ? poll.not : poll;\n await expectation.toEqual(expected);\n pass = true;\n } catch {\n pass = false;\n }\n\n if (this.isNot) pass = !pass;\n\n const matcherReturn: MatcherReturnType = {\n message: getErrorMessage.call(this, name, expected, actual, errorReason),\n pass,\n name,\n expected,\n actual,\n };\n\n return matcherReturn;\n}\n","import type { ExpectMatcherState } from '@playwright/test';\n\n/**\n * Generates an error message for a custom matcher.\n *\n * @this ExpectMatcherState\n * @param name The name of the matcher.\n * @param expected The expected value.\n * @param actual The actual value.\n * @param error An optional error object.\n * @param errorMessage An optional error message string.\n * @returns A function that returns the error message string.\n */\nexport function getErrorMessage(\n this: ExpectMatcherState,\n name: string,\n expected: unknown,\n actual: unknown,\n error?: Error | null,\n errorMessage?: string | undefined | null,\n): () => string {\n const message = `${this.utils.matcherHint(name, undefined, undefined, { isNot: this.isNot })}\\n\\n`;\n\n if (error) {\n return () => `${message}An unexpected error occurred:\\n${error.message}`;\n }\n\n if (errorMessage) {\n return () => `${message}${errorMessage}`;\n }\n\n return () =>\n message +\n `Expected: ${this.isNot ? 'not ' : ''}${this.utils.printExpected(expected)}\\n` +\n `Received: ${this.utils.printReceived(actual)}`;\n}\n","import { type ExpectMatcherState, expect, type MatcherReturnType } from '@playwright/test';\nimport type { ClipboardHandler } from '../utils/clipboardHandler.js';\nimport { getErrorMessage } from '../utils/matcherUtils.js';\nimport type { MatcherOptions } from './types.js';\n\n/**\n * Asserts that the clipboard content matches the expected text value.\n *\n * @this ExpectMatcherState\n * @param clipboard The Clipboard utility instance.\n * @param expected The expected text value.\n * @param options Matcher options.\n * @returns A Promise that resolves to a MatcherReturnType object.\n */\nexport async function toHaveTextContent(\n this: ExpectMatcherState,\n clipboard: ClipboardHandler,\n expected: string,\n options: MatcherOptions = {},\n) {\n const name = 'toHaveTextContent';\n let pass: boolean;\n let actual: unknown;\n let errorReason: Error | null = null;\n\n const { timeout = 10_000 } = options;\n\n const poll = expect.poll(\n async () => {\n try {\n actual = await clipboard.read();\n errorReason = null;\n return actual;\n } catch (error) {\n errorReason = error instanceof Error ? error : new Error(String(error));\n actual = undefined;\n\n throw errorReason;\n }\n },\n { timeout },\n );\n\n try {\n const expectation = this.isNot ? poll.not : poll;\n await expectation.toEqual(expected);\n pass = true;\n } catch {\n pass = false;\n }\n\n if (this.isNot) pass = !pass;\n\n const matcherReturn: MatcherReturnType = {\n message: getErrorMessage.call(this, name, expected, actual, errorReason),\n pass,\n name,\n expected,\n actual,\n };\n\n return matcherReturn;\n}\n","import type { ExpectMatcherState, MatcherReturnType } from '@playwright/test';\nimport type { ClipboardHandler } from '../utils/clipboardHandler.js';\nimport { toHaveJSONContent } from './toHaveJSONContent.js';\nimport { toHaveTextContent } from './toHaveTextContent.js';\nimport type { MatcherOptions } from './types.js';\n\n/**\n * Asserts that the clipboard content matches the expected value.\n * Uses smart polling to wait for the clipboard to be updated.\n * If the `expected` value is an object, it attempts to parse the clipboard\n * content as JSON before comparing.\n *\n * @this ExpectMatcherState\n * @param clipboard The Clipboard utility instance.\n * @param expected The string or object to compare against the clipboard content.\n * @param options Optional settings for the matcher, such as timeout.\n * @returns A Promise that resolves to a MatcherReturnType object.\n */\nexport async function toHaveData(\n this: ExpectMatcherState,\n clipboard: ClipboardHandler,\n expected: unknown,\n options: MatcherOptions = {},\n) {\n const name = 'toHaveData';\n let matcherReturn: MatcherReturnType | null = null;\n\n if (typeof expected === 'string') {\n matcherReturn = await toHaveTextContent.call(this, clipboard, expected, options);\n } else {\n matcherReturn = await toHaveJSONContent.call(this, clipboard, expected, options);\n }\n\n return {\n ...matcherReturn,\n name,\n message: () => {\n const originalMessage = matcherReturn.message();\n return originalMessage.replace('toHaveText', name).replace('toHaveJSON', name);\n },\n };\n}\n","import { toHaveData } from './toHaveData.js';\nimport { toHaveJSONContent } from './toHaveJSONContent.js';\nimport { toHaveTextContent } from './toHaveTextContent.js';\n\n/**\n * Export an object containing all the custom clipboard matchers for Playwright.\n */\nexport const clipboardMatchers = {\n toHaveTextContent,\n toHaveJSONContent,\n toHaveData,\n};\n"],"mappings":"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","names":["expect","expect","expect"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playwright-clipboard-testing",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Playwright fixture and custom matchers for clipboard testing and assertions.",
5
5
  "author": "Sergii Oleksenko <serg.oleksenko@gmail.com>",
6
6
  "license": "MIT",
@@ -50,12 +50,16 @@
50
50
  "lint:fix": "biome check --write .",
51
51
  "typecheck": "tsc --noEmit",
52
52
  "format": "biome format --write .",
53
- "test": "vitest run",
53
+ "test:unit": "vitest run",
54
+ "test:e2e": "playwright test",
55
+ "test:e2e:ui": "playwright test --ui",
56
+ "test": "npm run test:unit && npm run test:e2e",
54
57
  "test:watch": "vitest"
55
58
  },
56
59
  "devDependencies": {
57
60
  "@biomejs/biome": "2.5.10",
58
- "@playwright/test": "1.62.1",
61
+ "@playwright/test": "^1.63.0",
62
+ "@types/node": "^26.4.1",
59
63
  "tsup": "^8.5.1",
60
64
  "typescript": "5.8.3",
61
65
  "vitest": "^4.1.11"