@stablyai/playwright-test 2.1.9 → 2.1.10

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/dist/index.mjs CHANGED
@@ -5,7 +5,7 @@ export * from '@playwright/test';
5
5
  import { requireApiKey, augmentPage, augmentBrowserContext, augmentBrowser, stablyPlaywrightMatchers } from '@stablyai/playwright-base';
6
6
  export { Agent, setApiKey } from '@stablyai/playwright-base';
7
7
  import { c as createClient, p as postInternalV1TestAccountGoogleAuthState } from './index-DnDradnc.mjs';
8
- export { v as stablyReporter } from './index-CzSSL_f7.mjs';
8
+ export { U as stablyReporter } from './index-B5Tfm-dD.mjs';
9
9
  import 'node:buffer';
10
10
  import 'node:path';
11
11
  import 'node:child_process';
@@ -32,7 +32,7 @@ import 'zlib';
32
32
  import 'buffer';
33
33
 
34
34
  const getApiUrl = () => process.env.STABLY_API_URL ?? "https://api.stably.ai";
35
- const sdkVersion = "2.1.9" ;
35
+ const sdkVersion = "2.1.10" ;
36
36
  const assertNonEmptyString = (value, fieldName) => {
37
37
  if (!value.trim()) {
38
38
  throw new Error(`Missing required field: ${fieldName}`);
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/auth-with-google.ts","../src/index.ts"],"sourcesContent":["import type { BrowserContext } from \"@playwright/test\";\n\nimport {\n createClient,\n postInternalV1TestAccountGoogleAuthState,\n} from \"@stablyai-internal/api-client\";\nimport { requireApiKey } from \"@stablyai/playwright-base\";\n\ndeclare const __PACKAGE_VERSION__: string;\n\ntype PlaywrightCookie = Parameters<BrowserContext[\"addCookies\"]>[0][number];\n\ntype LocalStorageEntry = {\n name: string;\n value: string;\n};\n\ntype StorageOrigin = {\n localStorage: LocalStorageEntry[];\n origin: string;\n};\n\n/**\n * Playwright-compatible storage state.\n */\nexport type GoogleStorageState = {\n cookies: PlaywrightCookie[];\n origins: StorageOrigin[];\n};\n\n/**\n * Input for {@link authWithGoogle}.\n */\nexport type AuthWithGoogleOptions = {\n /**\n * Browser context where auth state should be applied.\n */\n context: BrowserContext;\n /**\n * Google account email.\n */\n email: string;\n /**\n * Google account password.\n */\n password: string;\n /**\n * TOTP seed/secret used to generate the Google 2FA code.\n */\n otpSecret: string;\n /**\n * Force a cache refresh server-side. Defaults to `false`.\n */\n forceRefresh?: boolean;\n /**\n * Optional API key override. Defaults to the configured Stably API key.\n */\n apiKey?: string;\n};\n\nconst getApiUrl = (): string =>\n process.env.STABLY_API_URL ?? \"https://api.stably.ai\";\n\nconst sdkVersion =\n typeof __PACKAGE_VERSION__ !== \"undefined\"\n ? __PACKAGE_VERSION__\n : (process.env.npm_package_version ?? \"local\");\n\nconst assertNonEmptyString = (value: string, fieldName: string): void => {\n if (!value.trim()) {\n throw new Error(`Missing required field: ${fieldName}`);\n }\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nconst parseCookie = (value: unknown): PlaywrightCookie => {\n if (!isRecord(value)) {\n throw new Error(\"Invalid Google storage state: cookie must be an object\");\n }\n\n const { domain } = value;\n const { name } = value;\n const { path } = value;\n const { sameSite } = value;\n const valueText = value.value;\n\n if (\n typeof domain !== \"string\" ||\n typeof name !== \"string\" ||\n typeof path !== \"string\" ||\n typeof valueText !== \"string\"\n ) {\n throw new Error(\n \"Invalid Google storage state: cookie is missing required fields\",\n );\n }\n\n return {\n ...(typeof value.expires === \"number\" ? { expires: value.expires } : {}),\n ...(typeof value.httpOnly === \"boolean\"\n ? { httpOnly: value.httpOnly }\n : {}),\n ...(typeof value.partitionKey === \"string\"\n ? { partitionKey: value.partitionKey }\n : {}),\n ...(typeof value.secure === \"boolean\" ? { secure: value.secure } : {}),\n ...(sameSite === \"Lax\" || sameSite === \"None\" || sameSite === \"Strict\"\n ? { sameSite }\n : {}),\n domain,\n name,\n path,\n value: valueText,\n };\n};\n\nconst parseLocalStorageEntry = (value: unknown): LocalStorageEntry => {\n if (!isRecord(value)) {\n throw new Error(\n \"Invalid Google storage state: localStorage entry must be an object\",\n );\n }\n\n const { name } = value;\n const storedValue = value.value;\n\n if (typeof name !== \"string\" || typeof storedValue !== \"string\") {\n throw new Error(\n \"Invalid Google storage state: localStorage entry must contain string name and value\",\n );\n }\n\n return { name, value: storedValue };\n};\n\nconst parseOrigin = (value: unknown): StorageOrigin => {\n if (!isRecord(value)) {\n throw new Error(\"Invalid Google storage state: origin must be an object\");\n }\n\n const { origin } = value;\n const rawLocalStorage = value.localStorage;\n\n if (typeof origin !== \"string\") {\n throw new Error(\"Invalid Google storage state: origin must be a string\");\n }\n\n if (!Array.isArray(rawLocalStorage)) {\n return { localStorage: [], origin };\n }\n\n return {\n localStorage: rawLocalStorage.map(parseLocalStorageEntry),\n origin,\n };\n};\n\nconst parseStorageState = (value: {\n cookies?: unknown[];\n origins?: unknown[];\n}): GoogleStorageState => ({\n cookies: Array.isArray(value.cookies) ? value.cookies.map(parseCookie) : [],\n origins: Array.isArray(value.origins) ? value.origins.map(parseOrigin) : [],\n});\n\nconst applyStorageStateToContext = async (\n context: BrowserContext,\n storageState: GoogleStorageState,\n): Promise<void> => {\n if (storageState.cookies.length > 0) {\n await context.addCookies(storageState.cookies);\n }\n\n for (const originState of storageState.origins) {\n if (originState.localStorage.length === 0) {\n continue;\n }\n\n const page = await context.newPage();\n try {\n await page.goto(originState.origin, { waitUntil: \"domcontentloaded\" });\n await page.evaluate((entries: LocalStorageEntry[]) => {\n for (const entry of entries) {\n window.localStorage.setItem(entry.name, entry.value);\n }\n }, originState.localStorage);\n } finally {\n await page.close();\n }\n }\n};\n\n/**\n * Signs in a Google test account and applies the authenticated session to a Playwright context.\n *\n * Use this when your test needs to start in an already-authenticated state without\n * manually driving the login UI. After this resolves, cookies and localStorage are\n * applied to the provided context and subsequent pages in that context can continue\n * as an authenticated user.\n *\n * @param options - Google credentials and target Playwright context.\n * @param options.context - Browser context to receive the authenticated session.\n * @param options.email - Google account email.\n * @param options.password - Google account password.\n * @param options.otpSecret - TOTP secret for 2FA. See https://docs.stably.ai/stably2/auth/google-otp-secret-helper.\n * @param options.forceRefresh - Optional flag to force regeneration of session state.\n * @param options.apiKey - Optional Stably API key override.\n *\n * @returns Resolves when auth state has been successfully applied to the context.\n *\n * @example\n * ```ts\n * import { test } from \"@stablyai/playwright-test\";\n *\n * test(\"opens Google settings as authenticated user\", async ({ context, page }) => {\n * await context.authWithGoogle({\n * email: \"qa@example.com\",\n * password: process.env.GOOGLE_TEST_PASSWORD!,\n * otpSecret: process.env.GOOGLE_TEST_OTP_SECRET!,\n * });\n *\n * await page.goto(\"https://myaccount.google.com\");\n * });\n * ```\n */\nexport async function authWithGoogle(\n options: AuthWithGoogleOptions,\n): Promise<void> {\n const apiKey = options.apiKey ?? requireApiKey();\n\n assertNonEmptyString(options.email, \"email\");\n assertNonEmptyString(options.password, \"password\");\n assertNonEmptyString(options.otpSecret, \"otpSecret\");\n\n const client = createClient({\n baseUrl: getApiUrl(),\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"X-Client-Name\": \"stably-playwright-test\",\n \"X-Client-Version\": sdkVersion,\n \"X-Stably-SDK-Version\": sdkVersion,\n },\n });\n\n const response = await postInternalV1TestAccountGoogleAuthState({\n body: {\n email: options.email,\n forceRefresh: options.forceRefresh,\n otpSecret: options.otpSecret,\n password: options.password,\n },\n client,\n });\n\n if (response.error) {\n const errorMessage =\n \"error\" in response.error ? response.error.error : \"Unknown error\";\n throw new Error(`Failed to authenticate with Google: ${errorMessage}`);\n }\n\n const storageState = parseStorageState(response.data.storageState);\n await applyStorageStateToContext(options.context, storageState);\n}\n","import { dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\n\nimport type { BrowserContext } from \"@playwright/test\";\nimport {\n defineConfig as playwrightDefineConfig,\n expect as playwrightExpect,\n test as playwrightTest,\n} from \"@playwright/test\";\nimport \"@stablyai/playwright-base\";\n\nimport type { Agent } from \"@stablyai/playwright-base\";\nimport {\n augmentBrowser,\n augmentBrowserContext,\n augmentPage,\n stablyPlaywrightMatchers,\n} from \"@stablyai/playwright-base\";\n\nimport type { StablyNotificationConfig } from \"@stablyai/playwright-reporter\";\nimport {\n authWithGoogle,\n type AuthWithGoogleOptions,\n type GoogleStorageState,\n} from \"./auth-with-google\";\n\nexport { stablyReporter } from \"@stablyai/playwright-reporter\";\nexport type {\n StablyReporterOptions,\n ProjectNotificationConfig,\n NotificationResultPolicy,\n StablyEmailNotificationConfig,\n StablySlackNotificationConfig,\n StablyNotificationConfig,\n} from \"@stablyai/playwright-reporter\";\nexport { Agent, setApiKey } from \"@stablyai/playwright-base\";\nexport { authWithGoogle, type AuthWithGoogleOptions, type GoogleStorageState };\nexport type {\n AIModel,\n GetLocatorsByAIOptions,\n GetLocatorsByAIResult,\n ScreenshotPromptOptions,\n} from \"@stablyai/playwright-base\";\n\n/**\n * Get the directory name from an import.meta.url.\n * This is the ESM equivalent of __dirname.\n *\n * @example\n * ```ts\n * import { getDirname } from '@stablyai/playwright-test';\n * const __dirname = getDirname(import.meta.url);\n *\n * // Use in tests for file paths\n * await page.setInputFiles('input', path.join(__dirname, 'fixtures', 'file.pdf'));\n * ```\n */\nexport function getDirname(importMetaUrl: string): string {\n return dirname(fileURLToPath(importMetaUrl));\n}\n\n/**\n * Get the filename from an import.meta.url.\n * This is the ESM equivalent of __filename.\n *\n * @example\n * ```ts\n * import { getFilename } from '@stablyai/playwright-test';\n * const __filename = getFilename(import.meta.url);\n * ```\n */\nexport function getFilename(importMetaUrl: string): string {\n return fileURLToPath(importMetaUrl);\n}\n\nexport const test: typeof playwrightTest = playwrightTest.extend<{\n agent: Agent;\n}>({\n agent: async (\n { context }: { context: BrowserContext },\n use: (agent: Agent) => Promise<void>,\n ) => {\n // Create a default agent from the default context\n const agent = context.newAgent();\n await use(agent);\n },\n browser: async ({ browser }, use) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await use(augmentBrowser(browser as any) as any);\n },\n context: async ({ context }, use) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion -- context augmentation requires type widening\n const augmentedContext = augmentBrowserContext(context as any) as any;\n if (!(\"authWithGoogle\" in augmentedContext)) {\n augmentedContext.authWithGoogle = (\n options: Omit<AuthWithGoogleOptions, \"context\">,\n ) => authWithGoogle({ context: augmentedContext, ...options });\n }\n\n await use(augmentedContext);\n },\n page: async ({ page }, use) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await use(augmentPage(page as any) as any);\n },\n});\n\nexport const expect = playwrightExpect.extend(stablyPlaywrightMatchers);\n\nexport * from \"@playwright/test\";\n\nexport type StablyProjectConfig = {\n notifications?: StablyNotificationConfig;\n};\n\n/**\n * Stably-enhanced defineConfig with typed support for stably notification configuration in projects.\n * The `stably` property on projects is available via module augmentation of `@playwright/test`.\n *\n * @example\n * ```ts\n * import { defineConfig, stablyReporter } from \"@stablyai/playwright-test\";\n *\n * export default defineConfig({\n * reporter: [stablyReporter({ apiKey: \"...\" })],\n * projects: [\n * {\n * name: \"smoke\",\n * stably: {\n * notifications: {\n * slack: { channelName: \"#alerts\", notifyOnResult: \"failures-only\" },\n * },\n * },\n * },\n * ],\n * });\n * ```\n */\nexport const defineConfig = playwrightDefineConfig;\n\ndeclare module \"@playwright/test\" {\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface LocatorAssertions {\n /**\n * Asserts that the locator satisfies a natural language condition using AI vision.\n *\n * Takes a screenshot of the locator and uses AI to verify whether the specified condition is met.\n *\n * @param condition - A natural language description of what should be true about the locator\n * @param options - Optional screenshot options (e.g., timeout)\n *\n * @example\n * ```typescript\n * await expect(page.locator('.button')).aiAssert('The button is disabled and grayed out');\n * ```\n */\n aiAssert(\n condition: string,\n // eslint-disable-next-line @typescript-eslint/consistent-type-imports\n options?: import(\"@stablyai/playwright-base\").ScreenshotPromptOptions,\n ): Promise<void>;\n\n /**\n * @deprecated Use `aiAssert` instead. This method will be removed in a future version.\n */\n toMatchScreenshotPrompt(\n condition: string,\n // eslint-disable-next-line @typescript-eslint/consistent-type-imports\n options?: import(\"@stablyai/playwright-base\").ScreenshotPromptOptions,\n ): Promise<void>;\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface PageAssertions {\n /**\n * Asserts that the page satisfies a natural language condition using AI vision.\n *\n * Takes a screenshot of the page and uses AI to verify whether the specified condition is met.\n *\n * @param condition - A natural language description of what should be true about the page\n * @param options - Optional screenshot options (e.g., fullPage, timeout)\n *\n * @example\n * ```typescript\n * await expect(page).aiAssert('The page shows a success message after form submission');\n * ```\n */\n aiAssert(\n condition: string,\n // eslint-disable-next-line @typescript-eslint/consistent-type-imports\n options?: import(\"@stablyai/playwright-base\").ScreenshotPromptOptions,\n ): Promise<void>;\n\n /**\n * @deprecated Use `aiAssert` instead. This method will be removed in a future version.\n */\n toMatchScreenshotPrompt(\n condition: string,\n // eslint-disable-next-line @typescript-eslint/consistent-type-imports\n options?: import(\"@stablyai/playwright-base\").ScreenshotPromptOptions,\n ): Promise<void>;\n }\n\n // Add agent fixture to test args\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface PlaywrightTestArgs {\n agent: Agent;\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface BrowserContext {\n /**\n * Generates and applies Google auth state to this context.\n *\n * Calls Stably's Google auth-state endpoint and proactively sets cookies and\n * localStorage values on this context.\n */\n authWithGoogle(\n options: Omit<AuthWithGoogleOptions, \"context\">,\n ): Promise<void>;\n }\n\n // Add stably config to project configuration\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface Project {\n stably?: StablyProjectConfig;\n }\n}\n"],"names":["playwrightTest","playwrightExpect","playwrightDefineConfig"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/auth-with-google.ts","../src/index.ts"],"sourcesContent":["import type { BrowserContext } from \"@playwright/test\";\n\nimport {\n createClient,\n postInternalV1TestAccountGoogleAuthState,\n} from \"@stablyai-internal/api-client\";\nimport { requireApiKey } from \"@stablyai/playwright-base\";\n\ndeclare const __PACKAGE_VERSION__: string;\n\ntype PlaywrightCookie = Parameters<BrowserContext[\"addCookies\"]>[0][number];\n\ntype LocalStorageEntry = {\n name: string;\n value: string;\n};\n\ntype StorageOrigin = {\n localStorage: LocalStorageEntry[];\n origin: string;\n};\n\n/**\n * Playwright-compatible storage state.\n */\nexport type GoogleStorageState = {\n cookies: PlaywrightCookie[];\n origins: StorageOrigin[];\n};\n\n/**\n * Input for {@link authWithGoogle}.\n */\nexport type AuthWithGoogleOptions = {\n /**\n * Browser context where auth state should be applied.\n */\n context: BrowserContext;\n /**\n * Google account email.\n */\n email: string;\n /**\n * Google account password.\n */\n password: string;\n /**\n * TOTP seed/secret used to generate the Google 2FA code.\n */\n otpSecret: string;\n /**\n * Force a cache refresh server-side. Defaults to `false`.\n */\n forceRefresh?: boolean;\n /**\n * Optional API key override. Defaults to the configured Stably API key.\n */\n apiKey?: string;\n};\n\nconst getApiUrl = (): string =>\n process.env.STABLY_API_URL ?? \"https://api.stably.ai\";\n\nconst sdkVersion =\n typeof __PACKAGE_VERSION__ !== \"undefined\"\n ? __PACKAGE_VERSION__\n : (process.env.npm_package_version ?? \"local\");\n\nconst assertNonEmptyString = (value: string, fieldName: string): void => {\n if (!value.trim()) {\n throw new Error(`Missing required field: ${fieldName}`);\n }\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nconst parseCookie = (value: unknown): PlaywrightCookie => {\n if (!isRecord(value)) {\n throw new Error(\"Invalid Google storage state: cookie must be an object\");\n }\n\n const { domain } = value;\n const { name } = value;\n const { path } = value;\n const { sameSite } = value;\n const valueText = value.value;\n\n if (\n typeof domain !== \"string\" ||\n typeof name !== \"string\" ||\n typeof path !== \"string\" ||\n typeof valueText !== \"string\"\n ) {\n throw new Error(\n \"Invalid Google storage state: cookie is missing required fields\",\n );\n }\n\n return {\n ...(typeof value.expires === \"number\" ? { expires: value.expires } : {}),\n ...(typeof value.httpOnly === \"boolean\"\n ? { httpOnly: value.httpOnly }\n : {}),\n ...(typeof value.partitionKey === \"string\"\n ? { partitionKey: value.partitionKey }\n : {}),\n ...(typeof value.secure === \"boolean\" ? { secure: value.secure } : {}),\n ...(sameSite === \"Lax\" || sameSite === \"None\" || sameSite === \"Strict\"\n ? { sameSite }\n : {}),\n domain,\n name,\n path,\n value: valueText,\n };\n};\n\nconst parseLocalStorageEntry = (value: unknown): LocalStorageEntry => {\n if (!isRecord(value)) {\n throw new Error(\n \"Invalid Google storage state: localStorage entry must be an object\",\n );\n }\n\n const { name } = value;\n const storedValue = value.value;\n\n if (typeof name !== \"string\" || typeof storedValue !== \"string\") {\n throw new Error(\n \"Invalid Google storage state: localStorage entry must contain string name and value\",\n );\n }\n\n return { name, value: storedValue };\n};\n\nconst parseOrigin = (value: unknown): StorageOrigin => {\n if (!isRecord(value)) {\n throw new Error(\"Invalid Google storage state: origin must be an object\");\n }\n\n const { origin } = value;\n const rawLocalStorage = value.localStorage;\n\n if (typeof origin !== \"string\") {\n throw new Error(\"Invalid Google storage state: origin must be a string\");\n }\n\n if (!Array.isArray(rawLocalStorage)) {\n return { localStorage: [], origin };\n }\n\n return {\n localStorage: rawLocalStorage.map(parseLocalStorageEntry),\n origin,\n };\n};\n\nconst parseStorageState = (value: {\n cookies?: unknown[];\n origins?: unknown[];\n}): GoogleStorageState => ({\n cookies: Array.isArray(value.cookies) ? value.cookies.map(parseCookie) : [],\n origins: Array.isArray(value.origins) ? value.origins.map(parseOrigin) : [],\n});\n\nconst applyStorageStateToContext = async (\n context: BrowserContext,\n storageState: GoogleStorageState,\n): Promise<void> => {\n if (storageState.cookies.length > 0) {\n await context.addCookies(storageState.cookies);\n }\n\n for (const originState of storageState.origins) {\n if (originState.localStorage.length === 0) {\n continue;\n }\n\n const page = await context.newPage();\n try {\n await page.goto(originState.origin, { waitUntil: \"domcontentloaded\" });\n await page.evaluate((entries: LocalStorageEntry[]) => {\n for (const entry of entries) {\n window.localStorage.setItem(entry.name, entry.value);\n }\n }, originState.localStorage);\n } finally {\n await page.close();\n }\n }\n};\n\n/**\n * Signs in a Google test account and applies the authenticated session to a Playwright context.\n *\n * Use this when your test needs to start in an already-authenticated state without\n * manually driving the login UI. After this resolves, cookies and localStorage are\n * applied to the provided context and subsequent pages in that context can continue\n * as an authenticated user.\n *\n * @param options - Google credentials and target Playwright context.\n * @param options.context - Browser context to receive the authenticated session.\n * @param options.email - Google account email.\n * @param options.password - Google account password.\n * @param options.otpSecret - TOTP secret for 2FA. See https://docs.stably.ai/stably2/auth/google-otp-secret-helper.\n * @param options.forceRefresh - Optional flag to force regeneration of session state.\n * @param options.apiKey - Optional Stably API key override.\n *\n * @returns Resolves when auth state has been successfully applied to the context.\n *\n * @example\n * ```ts\n * import { test } from \"@stablyai/playwright-test\";\n *\n * test(\"opens Google settings as authenticated user\", async ({ context, page }) => {\n * await context.authWithGoogle({\n * email: \"qa@example.com\",\n * password: process.env.GOOGLE_TEST_PASSWORD!,\n * otpSecret: process.env.GOOGLE_TEST_OTP_SECRET!,\n * });\n *\n * await page.goto(\"https://myaccount.google.com\");\n * });\n * ```\n */\nexport async function authWithGoogle(\n options: AuthWithGoogleOptions,\n): Promise<void> {\n const apiKey = options.apiKey ?? requireApiKey();\n\n assertNonEmptyString(options.email, \"email\");\n assertNonEmptyString(options.password, \"password\");\n assertNonEmptyString(options.otpSecret, \"otpSecret\");\n\n const client = createClient({\n baseUrl: getApiUrl(),\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"X-Client-Name\": \"stably-playwright-test\",\n \"X-Client-Version\": sdkVersion,\n \"X-Stably-SDK-Version\": sdkVersion,\n },\n });\n\n const response = await postInternalV1TestAccountGoogleAuthState({\n body: {\n email: options.email,\n forceRefresh: options.forceRefresh,\n otpSecret: options.otpSecret,\n password: options.password,\n },\n client,\n });\n\n if (response.error) {\n const errorMessage =\n \"error\" in response.error ? response.error.error : \"Unknown error\";\n throw new Error(`Failed to authenticate with Google: ${errorMessage}`);\n }\n\n const storageState = parseStorageState(response.data.storageState);\n await applyStorageStateToContext(options.context, storageState);\n}\n","import { dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\n\nimport type { BrowserContext } from \"@playwright/test\";\nimport {\n defineConfig as playwrightDefineConfig,\n expect as playwrightExpect,\n test as playwrightTest,\n} from \"@playwright/test\";\nimport \"@stablyai/playwright-base\";\n\nimport type { Agent } from \"@stablyai/playwright-base\";\nimport {\n augmentBrowser,\n augmentBrowserContext,\n augmentPage,\n stablyPlaywrightMatchers,\n} from \"@stablyai/playwright-base\";\n\nimport type { StablyNotificationConfig } from \"@stablyai/playwright-reporter\";\nimport {\n authWithGoogle,\n type AuthWithGoogleOptions,\n type GoogleStorageState,\n} from \"./auth-with-google\";\n\nexport { stablyReporter } from \"@stablyai/playwright-reporter\";\nexport type {\n StablyReporterOptions,\n ProjectNotificationConfig,\n NotificationResultPolicy,\n StablyEmailNotificationConfig,\n StablySlackNotificationConfig,\n StablyNotificationConfig,\n} from \"@stablyai/playwright-reporter\";\nexport { Agent, setApiKey } from \"@stablyai/playwright-base\";\nexport { authWithGoogle, type AuthWithGoogleOptions, type GoogleStorageState };\nexport type {\n AIModel,\n GetLocatorsByAIOptions,\n GetLocatorsByAIResult,\n ScreenshotPromptOptions,\n} from \"@stablyai/playwright-base\";\n\n/**\n * Get the directory name from an import.meta.url.\n * This is the ESM equivalent of __dirname.\n *\n * @example\n * ```ts\n * import { getDirname } from '@stablyai/playwright-test';\n * const __dirname = getDirname(import.meta.url);\n *\n * // Use in tests for file paths\n * await page.setInputFiles('input', path.join(__dirname, 'fixtures', 'file.pdf'));\n * ```\n */\nexport function getDirname(importMetaUrl: string): string {\n return dirname(fileURLToPath(importMetaUrl));\n}\n\n/**\n * Get the filename from an import.meta.url.\n * This is the ESM equivalent of __filename.\n *\n * @example\n * ```ts\n * import { getFilename } from '@stablyai/playwright-test';\n * const __filename = getFilename(import.meta.url);\n * ```\n */\nexport function getFilename(importMetaUrl: string): string {\n return fileURLToPath(importMetaUrl);\n}\n\nexport const test: typeof playwrightTest = playwrightTest.extend<{\n agent: Agent;\n}>({\n agent: async (\n { context }: { context: BrowserContext },\n use: (agent: Agent) => Promise<void>,\n ) => {\n // Create a default agent from the default context\n const agent = context.newAgent();\n await use(agent);\n },\n browser: async ({ browser }, use) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await use(augmentBrowser(browser as any) as any);\n },\n context: async ({ context }, use) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion -- context augmentation requires type widening\n const augmentedContext = augmentBrowserContext(context as any) as any;\n if (!(\"authWithGoogle\" in augmentedContext)) {\n augmentedContext.authWithGoogle = (\n options: Omit<AuthWithGoogleOptions, \"context\">,\n ) => authWithGoogle({ context: augmentedContext, ...options });\n }\n\n await use(augmentedContext);\n },\n page: async ({ page }, use) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await use(augmentPage(page as any) as any);\n },\n});\n\nexport const expect = playwrightExpect.extend(stablyPlaywrightMatchers);\n\nexport * from \"@playwright/test\";\n\nexport type StablyProjectConfig = {\n notifications?: StablyNotificationConfig;\n};\n\n/**\n * Stably-enhanced defineConfig with typed support for stably notification configuration in projects.\n * The `stably` property on projects is available via module augmentation of `@playwright/test`.\n *\n * @example\n * ```ts\n * import { defineConfig, stablyReporter } from \"@stablyai/playwright-test\";\n *\n * export default defineConfig({\n * reporter: [stablyReporter({ apiKey: \"...\" })],\n * projects: [\n * {\n * name: \"smoke\",\n * stably: {\n * notifications: {\n * slack: { channelName: \"#alerts\", notifyOnResult: \"failures-only\" },\n * },\n * },\n * },\n * ],\n * });\n * ```\n */\nexport const defineConfig = playwrightDefineConfig;\n\ndeclare module \"@playwright/test\" {\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface LocatorAssertions {\n /**\n * Asserts that the locator satisfies a natural language condition using AI vision.\n *\n * Takes a screenshot of the locator and uses AI to verify whether the specified condition is met.\n *\n * @param condition - A natural language description of what should be true about the locator\n * @param options - Optional screenshot options (e.g., timeout)\n *\n * @example\n * ```typescript\n * await expect(page.locator('.button')).aiAssert('The button is disabled and grayed out');\n * ```\n */\n aiAssert(\n condition: string,\n // eslint-disable-next-line @typescript-eslint/consistent-type-imports\n options?: import(\"@stablyai/playwright-base\").ScreenshotPromptOptions,\n ): Promise<void>;\n\n /**\n * @deprecated Use `aiAssert` instead. This method will be removed in a future version.\n */\n toMatchScreenshotPrompt(\n condition: string,\n // eslint-disable-next-line @typescript-eslint/consistent-type-imports\n options?: import(\"@stablyai/playwright-base\").ScreenshotPromptOptions,\n ): Promise<void>;\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface PageAssertions {\n /**\n * Asserts that the page satisfies a natural language condition using AI vision.\n *\n * Takes a screenshot of the page and uses AI to verify whether the specified condition is met.\n *\n * @param condition - A natural language description of what should be true about the page\n * @param options - Optional screenshot options (e.g., fullPage, timeout)\n *\n * @example\n * ```typescript\n * await expect(page).aiAssert('The page shows a success message after form submission');\n * ```\n */\n aiAssert(\n condition: string,\n // eslint-disable-next-line @typescript-eslint/consistent-type-imports\n options?: import(\"@stablyai/playwright-base\").ScreenshotPromptOptions,\n ): Promise<void>;\n\n /**\n * @deprecated Use `aiAssert` instead. This method will be removed in a future version.\n */\n toMatchScreenshotPrompt(\n condition: string,\n // eslint-disable-next-line @typescript-eslint/consistent-type-imports\n options?: import(\"@stablyai/playwright-base\").ScreenshotPromptOptions,\n ): Promise<void>;\n }\n\n // Add agent fixture to test args\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface PlaywrightTestArgs {\n agent: Agent;\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface BrowserContext {\n /**\n * Generates and applies Google auth state to this context.\n *\n * Calls Stably's Google auth-state endpoint and proactively sets cookies and\n * localStorage values on this context.\n */\n authWithGoogle(\n options: Omit<AuthWithGoogleOptions, \"context\">,\n ): Promise<void>;\n }\n\n // Add stably config to project configuration\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface Project {\n stably?: StablyProjectConfig;\n }\n}\n"],"names":["playwrightTest","playwrightExpect","playwrightDefineConfig"],"mappings":"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"}
package/dist/reporter.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-D7GNnxbC.cjs');
3
+ var index = require('./index-Li4YhdtX.cjs');
4
4
  require('node:buffer');
5
5
  require('node:path');
6
6
  require('node:child_process');
@@ -30,5 +30,5 @@ require('buffer');
30
30
 
31
31
 
32
32
 
33
- module.exports = index.Cn;
33
+ module.exports = index.vn;
34
34
  //# sourceMappingURL=reporter.cjs.map
package/dist/reporter.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { C as Cn } from './index-CzSSL_f7.mjs';
1
+ import { v as vn } from './index-B5Tfm-dD.mjs';
2
2
  import 'node:buffer';
3
3
  import 'node:path';
4
4
  import 'node:child_process';
@@ -28,5 +28,5 @@ import 'buffer';
28
28
 
29
29
 
30
30
 
31
- export { Cn as default };
31
+ export { vn as default };
32
32
  //# sourceMappingURL=reporter.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stablyai/playwright-test",
3
- "version": "2.1.9",
3
+ "version": "2.1.10",
4
4
  "description": "Playwright Test wrapper with Stably AI matchers",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -31,8 +31,8 @@
31
31
  "dist"
32
32
  ],
33
33
  "dependencies": {
34
- "@stablyai/playwright": "2.1.9",
35
- "@stablyai/playwright-base": "2.1.9"
34
+ "@stablyai/playwright": "2.1.10",
35
+ "@stablyai/playwright-base": "2.1.10"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@stablyai-internal/api-client": "^0.1.7",