diff --git a/docs/API.md b/docs/API.md index eb8b036a9..879841e0c 100644 --- a/docs/API.md +++ b/docs/API.md @@ -907,60 +907,56 @@ await expect(elem).toHaveElementClass(/Container/i) In addition to the WebdriverIO matchers, `expect-webdriverio` also provides basic matchers from Jest's [expect](https://jestjs.io/docs/expect) library. ```ts - describe('Expect matchers', () => { - test('Basic matchers', async () => { - // Equality - expect(2 + 2).toBe(4); - expect({a: 1}).toEqual({a: 1}); - expect([1, 2, 3]).toStrictEqual([1, 2, 3]); - expect(2 + 2).not.toBe(5); - - // Truthiness - expect(null).toBeNull(); - expect(undefined).toBeUndefined(); - expect(0).toBeFalsy(); - expect(1).toBeTruthy(); - expect(NaN).toBeNaN(); - - // Numbers - expect(4).toBeGreaterThan(3); - expect(4).toBeGreaterThanOrEqual(4); - expect(4).toBeLessThan(5); - expect(4).toBeLessThanOrEqual(4); - expect(0.2 + 0.1).toBeCloseTo(0.3, 5); - - // Strings - expect('team').toMatch(/team/); - expect('Christoph').toContain('stop'); - - // Arrays and iterables - expect([1, 2, 3]).toContain(2); - expect([{a: 1}, {b: 2}]).toContainEqual({a: 1}); - expect([1, 2, 3]).toHaveLength(3); - - // Objects - expect({a: 1, b: 2}).toHaveProperty('a'); - expect({a: {b: 2}}).toHaveProperty('a.b', 2); - - // Errors - expect(() => { throw new Error('error!') }).toThrow('error!'); - expect(() => { throw new TypeError('wrong type') }).toThrow(TypeError); - - // Asymmetric matchers - expect({foo: 'bar', baz: 1}).toEqual(expect.objectContaining({foo: expect.any(String)})); - expect([1, 2, 3]).toEqual(expect.arrayContaining([2])); - expect('abc').toEqual(expect.stringContaining('b')); - expect('abc').toEqual(expect.stringMatching(/b/)); - expect(123).toEqual(expect.any(Number)); - - // Others - expect(new Set([1, 2, 3])).toContain(2); - - // .resolves / .rejects (async) - await expect(Promise.resolve(42)).resolves.toBe(42); - await expect(Promise.reject(new Error('fail'))).rejects.toThrow('fail'); - }); - }); +// Equality +expect(2 + 2).toBe(4); +expect({a: 1}).toEqual({a: 1}); +expect([1, 2, 3]).toStrictEqual([1, 2, 3]); +expect(2 + 2).not.toBe(5); + +// Truthiness +expect(null).toBeNull(); +expect(undefined).toBeUndefined(); +expect(0).toBeFalsy(); +expect(1).toBeTruthy(); +expect(NaN).toBeNaN(); + +// Numbers +expect(4).toBeGreaterThan(3); +expect(4).toBeGreaterThanOrEqual(4); +expect(4).toBeLessThan(5); +expect(4).toBeLessThanOrEqual(4); +expect(0.2 + 0.1).toBeCloseTo(0.3, 5); + +// Strings +expect('team').toMatch(/team/); +expect('Christoph').toContain('stop'); + +// Arrays and iterables +expect([1, 2, 3]).toContain(2); +expect([{a: 1}, {b: 2}]).toContainEqual({a: 1}); +expect([1, 2, 3]).toHaveLength(3); + +// Objects +expect({a: 1, b: 2}).toHaveProperty('a'); +expect({a: {b: 2}}).toHaveProperty('a.b', 2); + +// Errors +expect(() => { throw new Error('error!') }).toThrow('error!'); +expect(() => { throw new TypeError('wrong type') }).toThrow(TypeError); + +// Asymmetric matchers +expect({foo: 'bar', baz: 1}).toEqual(expect.objectContaining({foo: expect.any(String)})); +expect([1, 2, 3]).toEqual(expect.arrayContaining([2])); +expect('abc').toEqual(expect.stringContaining('b')); +expect('abc').toEqual(expect.stringMatching(/b/)); +expect(123).toEqual(expect.any(Number)); + +// Others +expect(new Set([1, 2, 3])).toContain(2); + +// .resolves / .rejects (async) +await expect(Promise.resolve(42)).resolves.toBe(42); +await expect(Promise.reject(new Error('fail'))).rejects.toThrow('fail'); ``` ### Jasmine @@ -1010,18 +1006,12 @@ await expect(browser).toHaveTitle(expect.not.stringContaining('some title')) ### Jasmine -Even under `@wdio/jasmine-framework`, Jasmine asymmetric matchers do not work with WebdriverIO matchers. +Under `@wdio/jasmine-framework`, some Jasmine asymmetric matchers now work with WebdriverIO matchers and the global import. ```ts -// DOES NOT work +// Jasmine's stringContaining works just like the one from expect await expect(browser).toHaveTitle(jasmine.stringContaining('some title')) - -// Use expect await expect(browser).toHaveTitle(expect.stringContaining('some title')) ``` -However, when using Jasmine original matchers, both works. -```ts -await expect(url).toEqual(jasmine.stringMatching(/^https:\/\//)) -await expect(url).toEqual(expect.stringMatching(/^https:\/\//)) -``` +**Note:** Known limitations still exist with `jasmine.arrayContaining` and `jasmine.objectContaining` with basic matchers. diff --git a/docs/CustomMatchers.md b/docs/CustomMatchers.md index 8fa9b00ef..0846e50b9 100644 --- a/docs/CustomMatchers.md +++ b/docs/CustomMatchers.md @@ -1,6 +1,16 @@ +# Custom Matchers + +`expect-webdriverio` registers WebdriverIO custom matchers out of the box for a seamless experience. + +To use WebdriverIO custom matchers (except asymmetric matchers) directly in: +- **Jest**: Register matchers manually with `expect.extend`. +- **Jasmine**: Using `@wdio/jasmine-framework` provides an out-of-the-box experience. + - Else, register matchers manually with `jasmine.addAsyncMatchers`, then they will be available on `expectAsync`. +- **Types**: Type augmentation for custom matchers is provided. See [Types.md](Types.md) for details. + ## Adding your own matchers -Similar to how `expect-webdriverio` extends Jasmine/Jest matchers it's possible to add custom matchers. +Similar to how `expect-webdriverio` provide custom matchers it's possible to add your own custom matchers. - [Jasmine](https://jasmine.github.io/) see [custom matchers](https://jasmine.github.io/tutorials/custom_matchers) doc - Everyone else see [Jest's expect.extend](https://jestjs.io/docs/expect#expectextendmatchers) diff --git a/docs/Framework.md b/docs/Framework.md index 1ca5804ba..7c53b7cf2 100644 --- a/docs/Framework.md +++ b/docs/Framework.md @@ -60,10 +60,10 @@ Option 2: Reconfigure Jest's expect with the custom matchers and the soft assert ```ts // Configure the custom matchers: import { expect } from "@jest/globals"; -import { matchers } from "expect-webdriverio"; +import { wdioCustomMatchers } from "expect-webdriverio"; beforeAll(async () => { - expect.extend(matchers as Record); + expect.extend(wdioCustomMatchers); }); ``` diff --git a/jasmine-wdio-expect-async.d.ts b/jasmine-wdio-expect-async.d.ts index 9c7c93cb1..6c42e9d4b 100644 --- a/jasmine-wdio-expect-async.d.ts +++ b/jasmine-wdio-expect-async.d.ts @@ -1,5 +1,14 @@ /// +/** + * Augment the Jasmine namespace to match the behavior of `@wdio/jasmine-framework`. + * Only custom WDIO matchers are available under `expectAsync`, as well as Jasmine's built-in matchers. + * `expectAsync` is forced into the `expect` global ambient, making all Jasmine sync-matchers asynchronous. + * + * When using `@wdio/jasmine-framework`, specify `expect-webdriverio/jasmine-wdio-expect-async` in the tsconfig.json's types. + * TODO move into `@wdio/jasmine-framework` and deprecated it from `expect-webdriverio`. + */ + declare namespace jasmine { /** @@ -10,28 +19,36 @@ declare namespace jasmine { * * We force Matchers to return a `Promise` since Jasmine's `expectAsync` expects a promise in all cases (different from Jest) */ + + // eslint-disable-next-line @typescript-eslint/no-unused-vars -- U is required to properly override Jasmine's AsyncMatchers + interface AsyncMatchers extends ExpectWebdriverIO.Matchers, T> {} + + // Needed to reference it below for the withContext method // eslint-disable-next-line @typescript-eslint/no-unused-vars - interface AsyncMatchers extends Omit, T>, 'toMatchSnapshot' | 'toMatchInlineSnapshot'> { - /** - * snapshot matcher - * @param label optional snapshot label - */ - toMatchSnapshot(label?: string): Promise; - /** - * inline snapshot matcher - * @param snapshot snapshot string (autogenerated if not specified) - * @param label optional snapshot label - */ - toMatchInlineSnapshot(snapshot?: string, label?: string): Promise; - } + interface Matchers {} } -/** - * Overrides the default WDIO expect specifically for Jasmine, since `expectAsync` is forced into `expect`, making all matchers fully asynchronous. This is not the case under Jest or Mocha. - * Using `jasmine.AsyncMatchers` pull on WdioMatchers above but also allow to using Jasmine's built-in matchers and also `withContext` matcher. - */ declare namespace ExpectWebdriverIO { - interface Expect { + + // Should be the same as https://github.com/webdriverio/webdriverio/blob/ea0e3e00288abced4c739ff9e46c46977b7cdbd2/packages/wdio-jasmine-framework/src/index.ts#L21-L29 + interface JasmineAsymmetricMatchers extends Pick {} + + // Hack to convert all sync matchers to return Promise since `wdio/jasmine-framework` forces `expect` to be async + type JasmineSyncMatchers = { + [K in keyof jasmine.Matchers]: K extends 'not' + ? JasmineSyncMatchers + // eslint-disable-next-line @typescript-eslint/no-explicit-any + : jasmine.Matchers[K] extends (...args: any) => any + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ? (...args: any[]) => Promise + : jasmine.Matchers[K] + } + + /** + * Overrides the default WDIO expect specifically for Jasmine, since `expectAsync` is forced into `expect`, making all matchers fully asynchronous. This is not the case under Jest or Mocha. + * Using `jasmine.AsyncMatchers` includes the WdioMatchers from above, but also allows using Jasmine's built-in matchers and the `withContext` matcher. + */ + interface JasmineExpect extends ExpectWebdriverIO.JasmineAsymmetricMatchers, ExpectLibInverse { /** * The `expect` function is used every time you want to test a value. * You will rarely call `expect` by itself. @@ -40,10 +57,22 @@ declare namespace ExpectWebdriverIO { * - T: the type of the actual value, e.g. any type, not just WebdriverIO.Browser or WebdriverIO.Element * - R: the type of the return value, e.g. Promise or void * - * Note: The function must stay here in the namespace to overwrite correctly the expect function from the expect library. - * * @param actual The value to apply matchers against. */ - (actual: T): jasmine.AsyncMatchers + (actual: T): { + withContext(message: string): jasmine.AsyncMatchers> & JasmineSyncMatchers; + } & jasmine.AsyncMatchers> & JasmineSyncMatchers + } +} + +/** + * Under `@wdio/jasmine-framework`, the global `expect` is overridden to use Jasmine's `expectAsync`. + * It contains custom WebdriverIO matchers as well as Jasmine's built-in async & sync matchers but not the basic Jest's expect library matchers. + */ +// @ts-expect-error: IDE might flag this, but ignore it. This way the `tsc:root-types` can pass! +declare const expect: ExpectWebdriverIO.JasmineExpect +declare namespace NodeJS { + interface Global { + expect: ExpectWebdriverIO.JasmineExpect } } diff --git a/jasmine.d.ts b/jasmine.d.ts index d13a1f2f2..2937f8bf3 100644 --- a/jasmine.d.ts +++ b/jasmine.d.ts @@ -1,27 +1,20 @@ /// +/** + * Augment the Jasmine namespace to include the WDIO custom async matchers only. + * When using the vanilla Jasmine Library, use `jasmine.addAsyncMatchers(wdioCustomMatchers)` and specify `expect-webdriverio/jasmine` in the tsconfig.json's types. + */ + declare namespace jasmine { /** - * Async matchers for Jasmine to allow the typing of `expectAsync` with WebDriverIO matchers. + * Async matchers for Jasmine to allow the typing of `expectAsync` with WebDriverIO custom matchers. * T is the type of the actual value * U is the type of the expected value * Both T,U must stay named as they are to override the default `AsyncMatchers` type from Jasmine. * - * We force Matchers to return a `Promise` since Jasmine's `expectAsync` expects a promise in all cases (different from Jest) + * We force Matchers to return a `Promise` since under Jasmine's `expectAsync` everything is a promise. */ // eslint-disable-next-line @typescript-eslint/no-unused-vars - interface AsyncMatchers extends Omit, T>, 'toMatchSnapshot' | 'toMatchInlineSnapshot'> { - /** - * snapshot matcher - * @param label optional snapshot label - */ - toMatchSnapshot(label?: string): Promise; - /** - * inline snapshot matcher - * @param snapshot snapshot string (autogenerated if not specified) - * @param label optional snapshot label - */ - toMatchInlineSnapshot(snapshot?: string, label?: string): Promise; - } -} \ No newline at end of file + interface AsyncMatchers extends ExpectWebdriverIO.Matchers, T> {} +} diff --git a/jest.d.ts b/jest.d.ts index cf96fe737..b7282c01d 100644 --- a/jest.d.ts +++ b/jest.d.ts @@ -1,8 +1,8 @@ /// /** - * Augment the Jest namespace to include the matchers from expect-webdriverio. - * When Jest Library is used, it specifies `expect-webdriverio/jest` for this file in the tsconfig.json's types. + * Augment the Jest namespace to include the WebDriverIO custom matchers only. + * When Jest Library is used, specify `expect-webdriverio/jest` for this file in the tsconfig.json's types. */ declare namespace jest { @@ -13,7 +13,7 @@ declare namespace jest { * Below are overloaded Jest's matchers not part of `expect` but of `jest-snapshot`. * @see https://github.com/jestjs/jest/blob/73dbef5d2d3195a1e55fb254c54cce70d3036252/packages/jest-snapshot/src/types.ts#L37 * - * Note: We need to define them below so that they are correctly typed overloaded. + * Note: We need to define them below so that they are correctly overloaded. * Else even when extending `WdioJestOverloadedMatchers` we have typing errors. */ @@ -21,17 +21,17 @@ declare namespace jest { * snapshot matcher * @param label optional snapshot label */ - toMatchSnapshot(label?: string): T extends WdioPromiseLike ? Promise : void; + toMatchSnapshot(label?: string): T extends WdioElementOrPromiseLike ? Promise : R; /** * inline snapshot matcher * @param snapshot snapshot string (autogenerated if not specified) * @param label optional snapshot label */ - toMatchInlineSnapshot(snapshot?: string, label?: string): T extends WdioPromiseLike ? Promise : void; + toMatchInlineSnapshot(snapshot?: string, label?: string): T extends WdioElementOrPromiseLike ? Promise : R; } interface Expect extends ExpectWebdriverIO.Expect {} interface InverseAsymmetricMatchers extends ExpectWebdriverIO.AsymmetricMatchers {} -} \ No newline at end of file +} diff --git a/package-lock.json b/package-lock.json index 0a89129f0..7a274a9d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,24 +15,24 @@ "jest-matcher-utils": "^30.2.0" }, "devDependencies": { - "@jest/globals": "^30.2.0", + "@jest/globals": "^30.3.0", "@types/debug": "^4.1.12", - "@types/jasmine": "^5.1.8", + "@types/jasmine": "^5.1.15", "@types/jest": "^30.0.0", "@types/mocha": "^10.0.10", - "@types/node": "^24.10.1", - "@vitest/coverage-v8": "^4.0.16", - "@wdio/eslint": "^0.1.2", - "@wdio/types": "^9.20.0", - "eslint": "^9.39.2", + "@types/node": "^24.12.0", + "@vitest/coverage-v8": "^4.1.0", + "@wdio/eslint": "^0.1.3", + "@wdio/types": "^9.25.0", + "eslint": "^9.39.4", "husky": "^9.1.7", "npm-run-all2": "^8.0.4", - "release-it": "^19.1.0", - "rimraf": "^6.1.2", + "release-it": "^19.2.4", + "rimraf": "^6.1.3", "shelljs": "^0.10.0", "typescript": "^5.9.3", - "vitest": "^4.0.16", - "webdriverio": "^9.21.0" + "vitest": "^4.1.0", + "webdriverio": "^9.25.0" }, "engines": { "node": ">=20" @@ -55,12 +55,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -75,9 +75,9 @@ "license": "MIT" }, "node_modules/@babel/compat-data": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", - "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", "dev": true, "license": "MIT", "engines": { @@ -85,21 +85,21 @@ } }, "node_modules/@babel/core": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", - "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -126,14 +126,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", - "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -143,13 +143,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", + "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", @@ -190,29 +190,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -222,9 +222,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "dev": true, "license": "MIT", "engines": { @@ -260,27 +260,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", - "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.5" + "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -345,13 +345,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -387,13 +387,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -513,13 +513,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -529,503 +529,95 @@ } }, "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", - "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/types": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", - "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", - "cpu": [ - "x64" - ], + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", - "cpu": [ - "arm64" - ], + "node_modules/@emnapi/core": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.0.tgz", + "integrity": "sha512-0DQ98G9ZQZOxfUcQn1waV2yS8aWdZ6kJMbYCJB3oUBecjWYO1fqJ+a1DRfPF3O5JEkwqwP1A9QEN/9mYm2Yd0w==", "dev": true, "license": "MIT", "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@emnapi/wasi-threads": "1.2.0", + "tslib": "^2.4.0" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", - "cpu": [ - "ia32" - ], + "node_modules/@emnapi/runtime": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.0.tgz", + "integrity": "sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw==", "dev": true, "license": "MIT", "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", - "cpu": [ - "x64" - ], + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz", + "integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==", "dev": true, "license": "MIT", "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" + "dependencies": { + "tslib": "^2.4.0" } }, "node_modules/@eslint-community/eslint-utils": { @@ -1071,15 +663,15 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", - "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", - "minimatch": "^3.1.2" + "minimatch": "^3.1.5" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1136,20 +728,20 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", - "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", + "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", - "minimatch": "^3.1.2", + "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" }, "engines": { @@ -1197,9 +789,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", - "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", "dev": true, "license": "MIT", "engines": { @@ -1799,13 +1391,6 @@ "node": ">=8" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", @@ -1817,48 +1402,48 @@ } }, "node_modules/@jest/diff-sequences": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", - "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.3.0.tgz", + "integrity": "sha512-cG51MVnLq1ecVUaQ3fr6YuuAOitHK1S4WUJHnsPFE/quQr33ADUx1FfrTCpMCRxvy0Yr9BThKpDjSlcTi91tMA==", "license": "MIT", "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/environment": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz", - "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.3.0.tgz", + "integrity": "sha512-SlLSF4Be735yQXyh2+mctBOzNDx5s5uLv88/j8Qn1wH679PDcwy67+YdADn8NJnGjzlXtN62asGH/T4vWOkfaw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", + "@jest/fake-timers": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", - "jest-mock": "30.2.0" + "jest-mock": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.3.0.tgz", + "integrity": "sha512-76Nlh4xJxk2D/9URCn3wFi98d2hb19uWE1idLsTt2ywhvdOldbw3S570hBgn25P4ICUZ/cBjybrBex2g17IDbg==", "dev": true, "license": "MIT", "dependencies": { - "expect": "30.2.0", - "jest-snapshot": "30.2.0" + "expect": "30.3.0", + "jest-snapshot": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", - "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.3.0.tgz", + "integrity": "sha512-j0+W5iQQ8hBh7tHZkTQv3q2Fh/M7Je72cIsYqC4OaktgtO7v1So9UTjp6uPBHIaB6beoF/RRsCgMJKvti0wADA==", "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0" @@ -1868,18 +1453,18 @@ } }, "node_modules/@jest/fake-timers": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz", - "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.3.0.tgz", + "integrity": "sha512-WUQDs8SOP9URStX1DzhD425CqbN/HxUYCTwVrT8sTVBfMvFqYt/s61EK5T05qnHu0po6RitXIvP9otZxYDzTGQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "@sinonjs/fake-timers": "^13.0.0", + "@jest/types": "30.3.0", + "@sinonjs/fake-timers": "^15.0.0", "@types/node": "*", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", + "jest-util": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -1895,16 +1480,16 @@ } }, "node_modules/@jest/globals": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz", - "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.3.0.tgz", + "integrity": "sha512-+owLCBBdfpgL3HU+BD5etr1SvbXpSitJK0is1kiYjJxAAJggYMRQz5hSdd5pq1sSggfxPbw2ld71pt4x5wwViA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/expect": "30.2.0", - "@jest/types": "30.2.0", - "jest-mock": "30.2.0" + "@jest/environment": "30.3.0", + "@jest/expect": "30.3.0", + "@jest/types": "30.3.0", + "jest-mock": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -1935,13 +1520,13 @@ } }, "node_modules/@jest/snapshot-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz", - "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.3.0.tgz", + "integrity": "sha512-ORbRN9sf5PP82v3FXNSwmO1OTDR2vzR2YTaR+E3VkSBZ8zadQE6IqYdYEeFH1NIkeB2HIGdF02dapb6K0Mj05g==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "natural-compare": "^1.4.0" @@ -1984,24 +1569,23 @@ } }, "node_modules/@jest/transform": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", - "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.3.0.tgz", + "integrity": "sha512-TLKY33fSLVd/lKB2YI1pH69ijyUblO/BQvCj566YvnwuzoTNr648iE0j22vRvVNk2HsPwByPxATg3MleS3gf5A==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.27.4", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@jridgewell/trace-mapping": "^0.3.25", "babel-plugin-istanbul": "^7.0.1", "chalk": "^4.1.2", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", + "jest-haste-map": "30.3.0", "jest-regex-util": "30.0.1", - "jest-util": "30.2.0", - "micromatch": "^4.0.8", + "jest-util": "30.3.0", "pirates": "^4.0.7", "slash": "^3.0.0", "write-file-atomic": "^5.0.1" @@ -2044,9 +1628,9 @@ } }, "node_modules/@jest/types": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", - "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.3.0.tgz", + "integrity": "sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==", "license": "MIT", "dependencies": { "@jest/pattern": "30.0.1", @@ -2065,6 +1649,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -2079,6 +1664,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2139,6 +1725,23 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz", + "integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2353,6 +1956,26 @@ "@octokit/openapi-types": "^27.0.0" } }, + "node_modules/@oxc-project/runtime": { + "version": "0.115.0", + "resolved": "https://registry.npmjs.org/@oxc-project/runtime/-/runtime-0.115.0.tgz", + "integrity": "sha512-Rg8Wlt5dCbXhQnsXPrkOjL1DTSvXLgb2R/KYfnf1/K+R0k6UMLEmbQXPM+kwrWqSmWA2t0B1EtHy2/3zikQpvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.115.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.115.0.tgz", + "integrity": "sha512-4n91DKnebUS4yjUHl2g3/b2T+IUdCfmoZGhmwsovZCDaJSs+QkVAM+0AqqTxHSsHfeiMuueT75cZaZcT/m0pSw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, "node_modules/@phun-ky/typeof": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@phun-ky/typeof/-/typeof-2.0.3.tgz", @@ -2410,16 +2033,16 @@ } }, "node_modules/@puppeteer/browsers": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.11.1.tgz", - "integrity": "sha512-YmhAxs7XPuxN0j7LJloHpfD1ylhDuFmmwMvfy/+6nBSrETT2ycL53LrhgPtR+f+GcPSybQVuQ5inWWu5MrWCpA==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.13.0.tgz", + "integrity": "sha512-46BZJYJjc/WwmKjsvDFykHtXrtomsCIrwYQPOP7VfMJoZY2bsDF9oROBABR3paDjDcmkUye1Pb1BqdcdiipaWA==", "license": "Apache-2.0", "dependencies": { "debug": "^4.4.3", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.5.0", - "semver": "^7.7.3", + "semver": "^7.7.4", "tar-fs": "^3.1.1", "yargs": "^17.7.2" }, @@ -2430,24 +2053,22 @@ "node": ">=18" } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", - "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] + "node_modules/@puppeteer/browsers/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", - "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.9.tgz", + "integrity": "sha512-lcJL0bN5hpgJfSIz/8PIf02irmyL43P+j1pTCfbD1DbLkmGRuFIA4DD3B3ZOvGqG0XiVvRznbKtN0COQVaKUTg==", "cpu": [ "arm64" ], @@ -2456,12 +2077,15 @@ "optional": true, "os": [ "android" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", - "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.9.tgz", + "integrity": "sha512-J7Zk3kLYFsLtuH6U+F4pS2sYVzac0qkjcO5QxHS7OS7yZu2LRs+IXo+uvJ/mvpyUljDJ3LROZPoQfgBIpCMhdQ==", "cpu": [ "arm64" ], @@ -2470,12 +2094,15 @@ "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", - "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.9.tgz", + "integrity": "sha512-iwtmmghy8nhfRGeNAIltcNXzD0QMNaaA5U/NyZc1Ia4bxrzFByNMDoppoC+hl7cDiUq5/1CnFthpT9n+UtfFyg==", "cpu": [ "x64" ], @@ -2484,26 +2111,15 @@ "optional": true, "os": [ "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", - "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", - "cpu": [ - "arm64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", - "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.9.tgz", + "integrity": "sha512-DLFYI78SCiZr5VvdEplsVC2Vx53lnA4/Ga5C65iyldMVaErr86aiqCoNBLl92PXPfDtUYjUh+xFFor40ueNs4Q==", "cpu": [ "x64" ], @@ -2512,26 +2128,15 @@ "optional": true, "os": [ "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", - "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", - "cpu": [ - "arm" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", - "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.9.tgz", + "integrity": "sha512-CsjTmTwd0Hri6iTw/DRMK7kOZ7FwAkrO4h8YWKoX/kcj833e4coqo2wzIFywtch/8Eb5enQ/lwLM7w6JX1W5RQ==", "cpu": [ "arm" ], @@ -2540,26 +2145,15 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", - "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", - "cpu": [ - "arm64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", - "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-2x9O2JbSPxpxMDhP9Z74mahAStibTlrBMW0520+epJH5sac7/LwZW5Bmg/E6CXuEF53JJFW509uP+lSedaUNxg==", "cpu": [ "arm64" ], @@ -2568,54 +2162,32 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", - "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", - "cpu": [ - "loong64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", - "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.9.tgz", + "integrity": "sha512-JA1QRW31ogheAIRhIg9tjMfsYbglXXYGNPLdPEYrwFxdbkQCAzvpSCSHCDWNl4hTtrol8WeboCSEpjdZK8qrCg==", "cpu": [ - "loong64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", - "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", - "cpu": [ - "ppc64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", - "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-aOKU9dJheda8Kj8Y3w9gnt9QFOO+qKPAl8SWd7JPHP+Cu0EuDAE5wokQubLzIDQWg2myXq2XhTpOVS07qqvT+w==", "cpu": [ "ppc64" ], @@ -2624,40 +2196,15 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", - "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", - "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", - "cpu": [ - "riscv64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", - "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-OalO94fqj7IWRn3VdXWty75jC5dk4C197AWEuMhIpvVv2lw9fiPhud0+bW2ctCxb3YoBZor71QHbY+9/WToadA==", "cpu": [ "s390x" ], @@ -2666,12 +2213,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", - "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-cVEl1vZtBsBZna3YMjGXNvnYYrOJ7RzuWvZU0ffvJUexWkukMaDuGhUXn0rjnV0ptzGVkvc+vW9Yqy6h8YX4pg==", "cpu": [ "x64" ], @@ -2680,12 +2230,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", - "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.9.tgz", + "integrity": "sha512-UzYnKCIIc4heAKgI4PZ3dfBGUZefGCJ1TPDuLHoCzgrMYPb5Rv6TLFuYtyM4rWyHM7hymNdsg5ik2C+UD9VDbA==", "cpu": [ "x64" ], @@ -2694,26 +2247,15 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", - "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", - "cpu": [ - "x64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", - "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.9.tgz", + "integrity": "sha512-+6zoiF+RRyf5cdlFQP7nm58mq7+/2PFaY2DNQeD4B87N36JzfF/l9mdBkkmTvSYcYPE8tMh/o3cRlsx1ldLfog==", "cpu": [ "arm64" ], @@ -2722,40 +2264,49 @@ "optional": true, "os": [ "openharmony" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", - "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.9.tgz", + "integrity": "sha512-rgFN6sA/dyebil3YTlL2evvi/M+ivhfnyxec7AccTpRPccno/rPoNlqybEZQBkcbZu8Hy+eqNJCqfBR8P7Pg8g==", "cpu": [ - "arm64" + "wasm32" ], "dev": true, "license": "MIT", "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@napi-rs/wasm-runtime": "^1.1.1" + }, + "engines": { + "node": ">=14.0.0" + } }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", - "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.9.tgz", + "integrity": "sha512-lHVNUG/8nlF1IQk1C0Ci574qKYyty2goMiPlRqkC5R+3LkXDkL5Dhx8ytbxq35m+pkHVIvIxviD+TWLdfeuadA==", "cpu": [ - "ia32" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", - "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.9.tgz", + "integrity": "sha512-G0oA4+w1iY5AGi5HcDTxWsoxF509hrFIPB2rduV5aDqS9FtDg1CAfa7V34qImbjfhIcA8C+RekocJZA96EarwQ==", "cpu": [ "x64" ], @@ -2764,21 +2315,17 @@ "optional": true, "os": [ "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", - "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", - "cpu": [ - "x64" ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.9.tgz", + "integrity": "sha512-w6oiRWgEBl04QkFZgmW+jnU1EC9b57Oihi2ot3HNWIQRqgHp5PnYDia5iZ5FF7rpa4EQdiqMDXjlqKGXBhsoXw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "license": "MIT" }, "node_modules/@sinclair/typebox": { "version": "0.34.41", @@ -2797,9 +2344,9 @@ } }, "node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.1.1.tgz", + "integrity": "sha512-cO5W33JgAPbOh07tvZjUOJ7oWhtaqGHiZw+11DPbyqh2kHTBc3eF/CjJDeQ4205RLQsX6rxCuYOroFQwl7JDRw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -2840,6 +2387,17 @@ "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", "license": "MIT" }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/chai": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", @@ -2939,9 +2497,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.10.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.4.tgz", - "integrity": "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==", + "version": "24.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz", + "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==", "license": "MIT", "dependencies": { "undici-types": "~7.16.0" @@ -3244,29 +2802,29 @@ "license": "ISC" }, "node_modules/@vitest/coverage-v8": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.0.18.tgz", - "integrity": "sha512-7i+N2i0+ME+2JFZhfuz7Tg/FqKtilHjGyGvoHYQ6iLV0zahbsJ9sljC9OcFcPDbhYKCet+sG8SsVqlyGvPflZg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.0.tgz", + "integrity": "sha512-nDWulKeik2bL2Va/Wl4x7DLuTKAXa906iRFooIRPR+huHkcvp9QDkPQ2RJdmjOFrqOqvNfoSQLF68deE3xC3CQ==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^1.0.2", - "@vitest/utils": "4.0.18", - "ast-v8-to-istanbul": "^0.3.10", + "@vitest/utils": "4.1.0", + "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-reports": "^3.2.0", - "magicast": "^0.5.1", + "magicast": "^0.5.2", "obug": "^2.1.1", - "std-env": "^3.10.0", + "std-env": "^4.0.0-rc.1", "tinyrainbow": "^3.0.3" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "4.0.18", - "vitest": "4.0.18" + "@vitest/browser": "4.1.0", + "vitest": "4.1.0" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -3275,17 +2833,17 @@ } }, "node_modules/@vitest/expect": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", - "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.0.tgz", + "integrity": "sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA==", "dev": true, "license": "MIT", "dependencies": { - "@standard-schema/spec": "^1.0.0", + "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "chai": "^6.2.1", + "@vitest/spy": "4.1.0", + "@vitest/utils": "4.1.0", + "chai": "^6.2.2", "tinyrainbow": "^3.0.3" }, "funding": { @@ -3293,13 +2851,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", - "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.0.tgz", + "integrity": "sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.0.18", + "@vitest/spy": "4.1.0", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -3308,7 +2866,7 @@ }, "peerDependencies": { "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0-0" + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" }, "peerDependenciesMeta": { "msw": { @@ -3320,9 +2878,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", - "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.0.tgz", + "integrity": "sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A==", "license": "MIT", "dependencies": { "tinyrainbow": "^3.0.3" @@ -3332,13 +2890,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", - "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.0.tgz", + "integrity": "sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.0.18", + "@vitest/utils": "4.1.0", "pathe": "^2.0.3" }, "funding": { @@ -3346,12 +2904,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", - "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.0.tgz", + "integrity": "sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg==", "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.18", + "@vitest/pretty-format": "4.1.0", + "@vitest/utils": "4.1.0", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -3360,9 +2919,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", - "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.0.tgz", + "integrity": "sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw==", "dev": true, "license": "MIT", "funding": { @@ -3370,13 +2929,13 @@ } }, "node_modules/@vitest/utils": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", - "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", - "dev": true, + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.0.tgz", + "integrity": "sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==", "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.18", + "@vitest/pretty-format": "4.1.0", + "convert-source-map": "^2.0.0", "tinyrainbow": "^3.0.3" }, "funding": { @@ -3384,17 +2943,18 @@ } }, "node_modules/@wdio/config": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-9.23.2.tgz", - "integrity": "sha512-19Z+AIQ1NUpr6ncTumjSthm6A7c3DbaGTp+VCdcyN+vHYOK4WsWIomSk+uSbFosYFQVGRjCaHaeGSnC8GNPGYQ==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-9.25.0.tgz", + "integrity": "sha512-EWa7l1rrbSNthCRDpdBw7ESAa1/jAjSsWCGkaVAO0HMOGlQjzvYI6gNi4KUeymnurDZ2IPr0jr+f9We6AWi6QA==", "license": "MIT", "dependencies": { "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "deepmerge-ts": "^7.0.3", "glob": "^10.2.2", - "import-meta-resolve": "^4.0.0" + "import-meta-resolve": "^4.0.0", + "jiti": "^2.6.1" }, "engines": { "node": ">=18.20.0" @@ -3404,6 +2964,7 @@ "version": "10.5.0", "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -3498,9 +3059,9 @@ } }, "node_modules/@wdio/protocols": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-9.23.2.tgz", - "integrity": "sha512-pmCYOYI2N89QCC8IaiHwaWyP0mR8T1iKkEGpoTq2XVihp7VK/lfPvieyeZT5/e28MadYLJsDQ603pbu5J1NRDg==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-9.25.0.tgz", + "integrity": "sha512-PErbZqdpFmE69bRuku3OR34Ro2xuZNNLXYFOcJnjXJVzf5+ApDyGHYrMlvhtrrSy9/55LUybk851ppjS+3RoDA==", "license": "MIT" }, "node_modules/@wdio/repl": { @@ -3531,9 +3092,9 @@ "license": "MIT" }, "node_modules/@wdio/types": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.23.2.tgz", - "integrity": "sha512-ryfrERGsNp+aCcrTE1rFU6cbmDj8GHZ04R9k52KNt2u1a6bv3Eh5A/cUA0hXuMdEUfsc8ePLYdwQyOLFydZ0ig==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.25.0.tgz", + "integrity": "sha512-ovSEcUBLz6gVDIsBZYKQXz8EGU37jS8sqbmlOe5+jB4XbsTBCyTLjQK/rO7LWQAKJcs0vBq+Pd+VrlsFtA7tTQ==", "license": "MIT", "dependencies": { "@types/node": "^20.1.0" @@ -3558,14 +3119,14 @@ "license": "MIT" }, "node_modules/@wdio/utils": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-9.23.2.tgz", - "integrity": "sha512-+QfgXUWeA940AXT5l5UlrBKoHBk9GLSQE3BA+7ra1zWuFvv6SHG6M2mwplcPlOlymJMqXy8e7ZgLEoLkXuvC1Q==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-9.25.0.tgz", + "integrity": "sha512-w/ej8gZkc2tZr8L91ATyA1AWrbPDYDOvblQ7r+zt1uPRobuA4H98GME7Zm7i3FIP695BvV4G35Gcs5NssZW1pw==", "license": "MIT", "dependencies": { "@puppeteer/browsers": "^2.2.0", "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", + "@wdio/types": "9.25.0", "decamelize": "^6.0.0", "deepmerge-ts": "^7.0.3", "edgedriver": "^6.1.2", @@ -3583,9 +3144,9 @@ } }, "node_modules/@zip.js/zip.js": { - "version": "2.8.15", - "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.8.15.tgz", - "integrity": "sha512-HZKJLFe4eGVgCe9J87PnijY7T1Zn638bEHS+Fm/ygHZozRpefzWcOYfPaP52S8pqk9g4xN3+LzMDl3Lv9dLglA==", + "version": "2.8.23", + "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.8.23.tgz", + "integrity": "sha512-RB+RLnxPJFPrGvQ9rgO+4JOcsob6lD32OcF0QE0yg24oeW9q8KnTTNlugcDaIveEcCbclobJcZP+fLQ++sH0bw==", "license": "BSD-3-Clause", "engines": { "bun": ">=0.7.0", @@ -3638,9 +3199,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -3822,15 +3383,15 @@ } }, "node_modules/ast-v8-to-istanbul": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.10.tgz", - "integrity": "sha512-p4K7vMz2ZSk3wN8l5o3y2bJAoZXT3VuJI5OLTATY/01CYWumWvwkUw0SqDBnNq6IiTO3qDa1eSQDibAV8g7XOQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.0.tgz", + "integrity": "sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.31", "estree-walker": "^3.0.3", - "js-tokens": "^9.0.1" + "js-tokens": "^10.0.0" } }, "node_modules/async": { @@ -3931,9 +3492,9 @@ } }, "node_modules/bare-fs": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.3.tgz", - "integrity": "sha512-9+kwVx8QYvt3hPWnmb19tPnh38c6Nihz8Lx3t0g9+4GoIf3/fTgYwM4Z6NxgI+B9elLQA7mLE9PpqcWtOMRDiQ==", + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.5.tgz", + "integrity": "sha512-XvwYM6VZqKoqDll8BmSww5luA5eflDzY0uEFfBJtFKe4PAAtxBjU3YIxzIBzhyaEQBy1VXEQBto4cpN5RZJw+w==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -3956,9 +3517,9 @@ } }, "node_modules/bare-os": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.2.tgz", - "integrity": "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.8.0.tgz", + "integrity": "sha512-Dc9/SlwfxkXIGYhvMQNUtKaXCaGkZYGcd1vuNUUADVqzu4/vQfvnMkYYOUnt2VwQ2AqKr/8qAVFRtwETljgeFg==", "license": "Apache-2.0", "optional": true, "engines": { @@ -3976,13 +3537,14 @@ } }, "node_modules/bare-stream": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.7.0.tgz", - "integrity": "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.8.1.tgz", + "integrity": "sha512-bSeR8RfvbRwDpD7HWZvn8M3uYNDrk7m9DQjYOFkENZlXW8Ju/MPaqUPQq5LqJ3kyjEm07siTaAQ7wBKCU59oHg==", "license": "Apache-2.0", "optional": true, "dependencies": { - "streamx": "^2.21.0" + "streamx": "^2.21.0", + "teex": "^1.0.1" }, "peerDependencies": { "bare-buffer": "*", @@ -4072,6 +3634,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -4598,7 +4161,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, "license": "MIT" }, "node_modules/core-js-compat": { @@ -4833,6 +4395,16 @@ "dev": true, "license": "MIT" }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -4947,21 +4519,21 @@ } }, "node_modules/edgedriver/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "license": "ISC", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=16" + "node": ">=20" } }, "node_modules/edgedriver/node_modules/which": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz", - "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", "license": "ISC", "dependencies": { - "isexe": "^3.1.1" + "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" @@ -5030,54 +4602,12 @@ } }, "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "dev": true, "license": "MIT" }, - "node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.2", - "@esbuild/android-arm": "0.27.2", - "@esbuild/android-arm64": "0.27.2", - "@esbuild/android-x64": "0.27.2", - "@esbuild/darwin-arm64": "0.27.2", - "@esbuild/darwin-x64": "0.27.2", - "@esbuild/freebsd-arm64": "0.27.2", - "@esbuild/freebsd-x64": "0.27.2", - "@esbuild/linux-arm": "0.27.2", - "@esbuild/linux-arm64": "0.27.2", - "@esbuild/linux-ia32": "0.27.2", - "@esbuild/linux-loong64": "0.27.2", - "@esbuild/linux-mips64el": "0.27.2", - "@esbuild/linux-ppc64": "0.27.2", - "@esbuild/linux-riscv64": "0.27.2", - "@esbuild/linux-s390x": "0.27.2", - "@esbuild/linux-x64": "0.27.2", - "@esbuild/netbsd-arm64": "0.27.2", - "@esbuild/netbsd-x64": "0.27.2", - "@esbuild/openbsd-arm64": "0.27.2", - "@esbuild/openbsd-x64": "0.27.2", - "@esbuild/openharmony-arm64": "0.27.2", - "@esbuild/sunos-x64": "0.27.2", - "@esbuild/win32-arm64": "0.27.2", - "@esbuild/win32-ia32": "0.27.2", - "@esbuild/win32-x64": "0.27.2" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -5122,25 +4652,25 @@ } }, "node_modules/eslint": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", - "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.1", + "@eslint/config-array": "^0.21.2", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.2", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "ajv": "^6.12.4", + "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", @@ -5159,7 +4689,7 @@ "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", + "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, @@ -5503,17 +5033,17 @@ "license": "ISC" }, "node_modules/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.3.0.tgz", + "integrity": "sha512-1zQrciTiQfRdo7qJM1uG4navm8DayFa2TgCSRlzUyNkhcJ6XUZF3hjnpkyr3VhAqPH7i/9GkG7Tv5abz6fqz0Q==", "license": "MIT", "dependencies": { - "@jest/expect-utils": "30.2.0", + "@jest/expect-utils": "30.3.0", "@jest/get-type": "30.1.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", + "jest-util": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -5678,21 +5208,24 @@ "license": "MIT" }, "node_modules/fast-xml-builder": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.0.0.tgz", - "integrity": "sha512-fpZuDogrAgnyt9oDDz+5DBz0zgPdPZz6D4IR7iESxRXElrlGTRkHJ9eEt+SACRJwT0FNFrt71DFQIUFBJfX/uQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.3.tgz", + "integrity": "sha512-1o60KoFw2+LWKQu3IdcfcFlGTW4dpqEWmjhYec6H82AYZU2TVBXep6tMl8Z1Y+wM+ZrzCwe3BZ9Vyd9N2rIvmg==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" } ], - "license": "MIT" + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.1.3" + } }, "node_modules/fast-xml-parser": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.4.2.tgz", - "integrity": "sha512-pw/6pIl4k0CSpElPEJhDppLzaixDEuWui2CUQQBH/ECDf7+y6YwA4Gf7Tyb0Rfe4DIMuZipYj4AEL0nACKglvQ==", + "version": "5.5.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.5.5.tgz", + "integrity": "sha512-NLY+V5NNbdmiEszx9n14mZBseJTC50bRq1VHsaxOmR72JDuZt+5J1Co+dC/4JPnyq+WrIHNM69r0sqf7BMb3Mg==", "funding": [ { "type": "github", @@ -5701,7 +5234,8 @@ ], "license": "MIT", "dependencies": { - "fast-xml-builder": "^1.0.0", + "fast-xml-builder": "^1.1.3", + "path-expression-matcher": "^1.1.3", "strnum": "^2.1.2" }, "bin": { @@ -5772,6 +5306,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -6011,18 +5546,18 @@ } }, "node_modules/glob": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", - "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "minimatch": "^10.1.1", - "minipass": "^7.1.2", - "path-scurry": "^2.0.0" + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -6467,6 +6002,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -6636,15 +6172,15 @@ } }, "node_modules/jest-diff": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", - "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.3.0.tgz", + "integrity": "sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==", "license": "MIT", "dependencies": { - "@jest/diff-sequences": "30.0.1", + "@jest/diff-sequences": "30.3.0", "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "pretty-format": "30.2.0" + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -6682,21 +6218,21 @@ } }, "node_modules/jest-haste-map": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", - "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.3.0.tgz", + "integrity": "sha512-mMi2oqG4KRU0R9QEtscl87JzMXfUhbKaFqOxmjb2CKcbHcUGFrJCBWHmnTiUqi6JcnzoBlO4rWfpdl2k/RfLCA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "anymatch": "^3.1.3", "fb-watchman": "^2.0.2", "graceful-fs": "^4.2.11", "jest-regex-util": "30.0.1", - "jest-util": "30.2.0", - "jest-worker": "30.2.0", - "micromatch": "^4.0.8", + "jest-util": "30.3.0", + "jest-worker": "30.3.0", + "picomatch": "^4.0.3", "walker": "^1.0.8" }, "engines": { @@ -6707,15 +6243,15 @@ } }, "node_modules/jest-matcher-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", - "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.3.0.tgz", + "integrity": "sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==", "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "jest-diff": "30.2.0", - "pretty-format": "30.2.0" + "jest-diff": "30.3.0", + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -6753,18 +6289,18 @@ } }, "node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -6776,6 +6312,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -6790,6 +6327,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -6802,14 +6340,14 @@ } }, "node_modules/jest-mock": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", - "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.3.0.tgz", + "integrity": "sha512-OTzICK8CpE+t4ndhKrwlIdbM6Pn8j00lvmSmq5ejiO+KxukbLjgOflKWMn3KE34EZdQm5RqTuKj+5RIEniYhog==", "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", - "jest-util": "30.2.0" + "jest-util": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -6824,9 +6362,9 @@ } }, "node_modules/jest-snapshot": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz", - "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.3.0.tgz", + "integrity": "sha512-f14c7atpb4O2DeNhwcvS810Y63wEn8O1HqK/luJ4F6M4NjvxmAKQwBUWjbExUtMxWJQ0wVgmCKymeJK6NZMnfQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6835,20 +6373,20 @@ "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/types": "^7.27.3", - "@jest/expect-utils": "30.2.0", + "@jest/expect-utils": "30.3.0", "@jest/get-type": "30.1.0", - "@jest/snapshot-utils": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/snapshot-utils": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "babel-preset-current-node-syntax": "^1.2.0", "chalk": "^4.1.2", - "expect": "30.2.0", + "expect": "30.3.0", "graceful-fs": "^4.2.11", - "jest-diff": "30.2.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", - "pretty-format": "30.2.0", + "jest-diff": "30.3.0", + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-util": "30.3.0", + "pretty-format": "30.3.0", "semver": "^7.7.2", "synckit": "^0.11.8" }, @@ -6890,17 +6428,17 @@ } }, "node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -6910,6 +6448,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -6924,6 +6463,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -6936,15 +6476,15 @@ } }, "node_modules/jest-worker": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz", - "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.3.0.tgz", + "integrity": "sha512-DrCKkaQwHexjRUFTmPzs7sHQe0TSj9nvDALKGdwmK5mW9v7j90BudWirKAJHt3QQ9Dhrg1F7DogPzhChppkJpQ==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", "@ungap/structured-clone": "^1.3.0", - "jest-util": "30.2.0", + "jest-util": "30.3.0", "merge-stream": "^2.0.0", "supports-color": "^8.1.1" }, @@ -6972,16 +6512,15 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "dev": true, "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" } }, "node_modules/js-tokens": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", - "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", "dev": true, "license": "MIT" }, @@ -7172,6 +6711,267 @@ "immediate": "~3.0.5" } }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/locate-app": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/locate-app/-/locate-app-2.5.0.tgz", @@ -7349,14 +7149,14 @@ } }, "node_modules/magicast": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.1.tgz", - "integrity": "sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz", + "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", "source-map-js": "^1.2.1" } }, @@ -7416,6 +7216,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -7429,6 +7230,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -7503,10 +7305,10 @@ } }, "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", "engines": { "node": ">=16 || 14 >=14.17" } @@ -7518,9 +7320,9 @@ "license": "MIT" }, "node_modules/modern-tar": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/modern-tar/-/modern-tar-0.7.3.tgz", - "integrity": "sha512-4W79zekKGyYU4JXVmB78DOscMFaJth2gGhgfTl2alWE4rNe3nf4N2pqenQ0rEtIewrnD79M687Ouba3YGTLOvg==", + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/modern-tar/-/modern-tar-0.7.5.tgz", + "integrity": "sha512-YTefgdpKKFgoTDbEUqXqgUJct2OG6/4hs4XWLsxcHkDLj/x/V8WmKIRppPnXP5feQ7d1vuYWSp3qKkxfwaFaxA==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -8034,6 +7836,21 @@ "node": ">=8" } }, + "node_modules/path-expression-matcher": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.1.3.tgz", + "integrity": "sha512-qdVgY8KXmVdJZRSS1JdEPOKPdTiEK/pi0RkcT2sw1RhXxohdujUlJFPuS1TSkevZ9vzd3ZlL7ULl1MHGTApKzQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -8054,9 +7871,9 @@ } }, "node_modules/path-scurry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", - "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -8064,16 +7881,16 @@ "minipass": "^7.1.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.2.4", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", - "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -8163,9 +7980,9 @@ } }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", "dev": true, "funding": [ { @@ -8202,9 +8019,9 @@ } }, "node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "license": "MIT", "dependencies": { "@jest/schemas": "30.0.5", @@ -8284,9 +8101,9 @@ "license": "MIT" }, "node_modules/pump": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -8571,13 +8388,13 @@ "license": "MIT" }, "node_modules/rimraf": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", - "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "glob": "^13.0.0", + "glob": "^13.0.3", "package-json-from-dist": "^1.0.1" }, "bin": { @@ -8590,49 +8407,38 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rollup": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", - "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "node_modules/rolldown": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.9.tgz", + "integrity": "sha512-9EbgWge7ZH+yqb4d2EnELAntgPTWbfL8ajiTW+SyhJEC4qhBbkCKbqFV4Ge4zmu5ziQuVbWxb/XwLZ+RIO7E8Q==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" + "@oxc-project/types": "=0.115.0", + "@rolldown/pluginutils": "1.0.0-rc.9" }, "bin": { - "rollup": "dist/bin/rollup" + "rolldown": "bin/cli.mjs" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" + "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.59.0", - "@rollup/rollup-android-arm64": "4.59.0", - "@rollup/rollup-darwin-arm64": "4.59.0", - "@rollup/rollup-darwin-x64": "4.59.0", - "@rollup/rollup-freebsd-arm64": "4.59.0", - "@rollup/rollup-freebsd-x64": "4.59.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", - "@rollup/rollup-linux-arm-musleabihf": "4.59.0", - "@rollup/rollup-linux-arm64-gnu": "4.59.0", - "@rollup/rollup-linux-arm64-musl": "4.59.0", - "@rollup/rollup-linux-loong64-gnu": "4.59.0", - "@rollup/rollup-linux-loong64-musl": "4.59.0", - "@rollup/rollup-linux-ppc64-gnu": "4.59.0", - "@rollup/rollup-linux-ppc64-musl": "4.59.0", - "@rollup/rollup-linux-riscv64-gnu": "4.59.0", - "@rollup/rollup-linux-riscv64-musl": "4.59.0", - "@rollup/rollup-linux-s390x-gnu": "4.59.0", - "@rollup/rollup-linux-x64-gnu": "4.59.0", - "@rollup/rollup-linux-x64-musl": "4.59.0", - "@rollup/rollup-openbsd-x64": "4.59.0", - "@rollup/rollup-openharmony-arm64": "4.59.0", - "@rollup/rollup-win32-arm64-msvc": "4.59.0", - "@rollup/rollup-win32-ia32-msvc": "4.59.0", - "@rollup/rollup-win32-x64-gnu": "4.59.0", - "@rollup/rollup-win32-x64-msvc": "4.59.0", - "fsevents": "~2.3.2" + "@rolldown/binding-android-arm64": "1.0.0-rc.9", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.9", + "@rolldown/binding-darwin-x64": "1.0.0-rc.9", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.9", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.9", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.9", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.9", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.9", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.9", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.9", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.9" } }, "node_modules/run-applescript": { @@ -8750,6 +8556,7 @@ "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -8950,6 +8757,13 @@ "node": ">= 10.x" } }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -8979,9 +8793,9 @@ "license": "MIT" }, "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", + "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", "dev": true, "license": "MIT" }, @@ -9145,9 +8959,9 @@ } }, "node_modules/strnum": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.2.tgz", - "integrity": "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.0.tgz", + "integrity": "sha512-Y7Bj8XyJxnPAORMZj/xltsfo55uOiyHcU2tnAVzHUnSJR/KsEX+9RoDeXEnsXtl/CX4fAcrt64gZ13aGaWPeBg==", "funding": [ { "type": "github", @@ -9169,9 +8983,9 @@ } }, "node_modules/synckit": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", - "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", + "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9185,9 +8999,9 @@ } }, "node_modules/tar-fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", - "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.2.tgz", + "integrity": "sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw==", "license": "MIT", "dependencies": { "pump": "^3.0.0", @@ -9209,6 +9023,16 @@ "streamx": "^2.15.0" } }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "license": "MIT", + "optional": true, + "dependencies": { + "streamx": "^2.12.5" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -9239,7 +9063,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -9333,6 +9157,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -9529,17 +9354,17 @@ "license": "MIT" }, "node_modules/vite": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.0.tgz", + "integrity": "sha512-fPGaRNj9Zytaf8LEiBhY7Z6ijnFKdzU/+mL8EFBaKr7Vw1/FWcTBAMW0wLPJAGMPX38ZPVCVgLceWiEqeoqL2Q==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.27.0", - "fdir": "^6.5.0", + "@oxc-project/runtime": "0.115.0", + "lightningcss": "^1.32.0", "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", + "postcss": "^8.5.8", + "rolldown": "1.0.0-rc.9", "tinyglobby": "^0.2.15" }, "bin": { @@ -9556,9 +9381,10 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.0.0-alpha.31", + "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", - "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", @@ -9571,13 +9397,16 @@ "@types/node": { "optional": true }, - "jiti": { + "@vitejs/devtools": { "optional": true }, - "less": { + "esbuild": { "optional": true }, - "lightningcss": { + "jiti": { + "optional": true + }, + "less": { "optional": true }, "sass": { @@ -9604,31 +9433,31 @@ } }, "node_modules/vitest": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", - "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.0.tgz", + "integrity": "sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.0.18", - "@vitest/mocker": "4.0.18", - "@vitest/pretty-format": "4.0.18", - "@vitest/runner": "4.0.18", - "@vitest/snapshot": "4.0.18", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "es-module-lexer": "^1.7.0", - "expect-type": "^1.2.2", + "@vitest/expect": "4.1.0", + "@vitest/mocker": "4.1.0", + "@vitest/pretty-format": "4.1.0", + "@vitest/runner": "4.1.0", + "@vitest/snapshot": "4.1.0", + "@vitest/spy": "4.1.0", + "@vitest/utils": "4.1.0", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", - "std-env": "^3.10.0", + "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", - "vite": "^6.0.0 || ^7.0.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0", "why-is-node-running": "^2.3.0" }, "bin": { @@ -9644,12 +9473,13 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.0.18", - "@vitest/browser-preview": "4.0.18", - "@vitest/browser-webdriverio": "4.0.18", - "@vitest/ui": "4.0.18", + "@vitest/browser-playwright": "4.1.0", + "@vitest/browser-preview": "4.1.0", + "@vitest/browser-webdriverio": "4.1.0", + "@vitest/ui": "4.1.0", "happy-dom": "*", - "jsdom": "*" + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" }, "peerDependenciesMeta": { "@edge-runtime/vm": { @@ -9678,6 +9508,9 @@ }, "jsdom": { "optional": true + }, + "vite": { + "optional": false } } }, @@ -9740,18 +9573,18 @@ } }, "node_modules/webdriver": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-9.23.2.tgz", - "integrity": "sha512-HZy3eydZbmex0pbyLwHaDsAyZ+S+V4XQTdGK/nAOi4uPa74U6yT9vXqtb+3B+5/LDM7L8kTD6Z3b1y4gB4pmTw==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-9.25.0.tgz", + "integrity": "sha512-XnABKdrp83zX3xVltmX0OcFzn8zOzWGtZQxIUKY0+INB0g9Nnnfu7G75W0G+0y4nyb3zH8mavGzDBiXctdEd3Q==", "license": "MIT", "dependencies": { "@types/node": "^20.1.0", "@types/ws": "^8.5.3", - "@wdio/config": "9.23.2", + "@wdio/config": "9.25.0", "@wdio/logger": "9.18.0", - "@wdio/protocols": "9.23.2", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/protocols": "9.25.0", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "deepmerge-ts": "^7.0.3", "https-proxy-agent": "^7.0.6", "undici": "^6.21.3", @@ -9762,9 +9595,9 @@ } }, "node_modules/webdriver/node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -9777,19 +9610,19 @@ "license": "MIT" }, "node_modules/webdriverio": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-9.23.2.tgz", - "integrity": "sha512-VjfTw1bRJdBrzjoCu7BGThxn1JK2V7mAGvxibaBrCNIayPPQjLhVDNJPOVEiR7txM6zmOUWxhkCDxHjhMYirfQ==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-9.25.0.tgz", + "integrity": "sha512-ualC/LtWGjL5rwGAbUUzURKqKoHJG2/qecEppcS9k4n1IX3MlbzGXuL/qpXiRbs/h4981HpRbZAKBxRYqwUe3g==", "license": "MIT", "dependencies": { "@types/node": "^20.11.30", "@types/sinonjs__fake-timers": "^8.1.5", - "@wdio/config": "9.23.2", + "@wdio/config": "9.25.0", "@wdio/logger": "9.18.0", - "@wdio/protocols": "9.23.2", + "@wdio/protocols": "9.25.0", "@wdio/repl": "9.16.2", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "archiver": "^7.0.1", "aria-query": "^5.3.0", "cheerio": "^1.0.0-rc.12", @@ -9806,7 +9639,7 @@ "rgb2hex": "0.2.5", "serialize-error": "^12.0.0", "urlpattern-polyfill": "^10.0.0", - "webdriver": "9.23.2" + "webdriver": "9.25.0" }, "engines": { "node": ">=18.20.0" diff --git a/package.json b/package.json index 96f1ac5ac..4f09342d5 100644 --- a/package.json +++ b/package.json @@ -63,11 +63,10 @@ "test:unit": "vitest --run", "test:types": "npm run ts && npm run tsc:root-types", "ts": "run-s ts:* ts:*:*", - "ts:jest:@jest/global": "cd test-types/jest-@jest_global && tsc --project ./tsconfig.json", "ts:jest:@types-jest": "cd test-types/jest-@types_jest && tsc --project ./tsconfig.json", "ts:mocha": "cd test-types/mocha && tsc --project ./tsconfig.json", "ts:jasmine": "cd test-types/jasmine && tsc --project ./tsconfig.json", - "ts:jasmine-async": "cd test-types/jasmine-async && tsc --project ./tsconfig.json", + "ts:jasmine-global-expect": "cd test-types/jasmine-global-expect-async && tsc --project ./tsconfig.json", "checks:all": "npm run build && npm run compile && npm run tsc:root-types && npm run test && npm run ts", "watch": "npm run compile -- --watch", "prepare": "husky install", @@ -82,24 +81,24 @@ "jest-matcher-utils": "^30.2.0" }, "devDependencies": { + "@jest/globals": "^30.3.0", "@types/debug": "^4.1.12", - "@types/jasmine": "^5.1.8", + "@types/jasmine": "^5.1.15", "@types/jest": "^30.0.0", - "@types/node": "^24.10.1", "@types/mocha": "^10.0.10", - "@jest/globals": "^30.2.0", - "@vitest/coverage-v8": "^4.0.16", - "@wdio/eslint": "^0.1.2", - "@wdio/types": "^9.20.0", - "eslint": "^9.39.2", + "@types/node": "^24.12.0", + "@vitest/coverage-v8": "^4.1.0", + "@wdio/eslint": "^0.1.3", + "@wdio/types": "^9.25.0", + "eslint": "^9.39.4", "husky": "^9.1.7", "npm-run-all2": "^8.0.4", - "release-it": "^19.1.0", - "rimraf": "^6.1.2", + "release-it": "^19.2.4", + "rimraf": "^6.1.3", "shelljs": "^0.10.0", "typescript": "^5.9.3", - "vitest": "^4.0.16", - "webdriverio": "^9.21.0" + "vitest": "^4.1.0", + "webdriverio": "^9.25.0" }, "peerDependencies": { "@wdio/globals": "^9.0.0", diff --git a/playgrounds/jasmine/README.md b/playgrounds/jasmine/README.md new file mode 100644 index 000000000..6ae131632 --- /dev/null +++ b/playgrounds/jasmine/README.md @@ -0,0 +1,16 @@ +# Jasmine Playground + +This is a playground for E2E testing with the `@wdio/jasmine-framework` to ensure compatibility with `expect-webdriverio`. + +## Features and Limitations + +* **Soft Assertions**: `SoftAssertionService` is not supported, as Jasmine provides similar behavior natively. +* **Snapshots**: Basic snapshot testing currently does not work well. +* **Visual Snapshots**: The `@wdio/visual-service` does not work properly due to a lack of compatible hooks in Jasmine. +* **Options Configuration**: Global configurations (like `setOptions({ wait: 500 })`) are fully supported. +* **Asymmetric Matchers**: Native Jasmine asymmetric matchers (like `jasmine.any()`) are properly supported. + +## Test Structure + +* `test/specs/expect-wdioImport/`: Tests using the direct import of `expect-webdriverio` (Jest-based). +* `test/specs/globalImport/`: Tests using the global import, which pulls the Jasmine `expect` by default. diff --git a/playgrounds/jasmine/eslint.config.mjs b/playgrounds/jasmine/eslint.config.mjs index 97baff722..41afa4b75 100644 --- a/playgrounds/jasmine/eslint.config.mjs +++ b/playgrounds/jasmine/eslint.config.mjs @@ -1,5 +1,6 @@ import tsEslintPlugin from '@typescript-eslint/eslint-plugin'; import tsParser from '@typescript-eslint/parser'; +import jasminePlugin from 'eslint-plugin-jasmine'; export default { files: ['**/*.ts', '**/*.js'], @@ -20,9 +21,11 @@ export default { }, plugins: { '@typescript-eslint': tsEslintPlugin, + 'jasmine': jasminePlugin, }, rules: { ...tsEslintPlugin.configs['recommended'].rules, '@typescript-eslint/no-floating-promises': 'error', + 'jasmine/no-focused-tests': 'error', }, }; diff --git a/playgrounds/jasmine/package-lock.json b/playgrounds/jasmine/package-lock.json index d0672a0e8..2687a4e05 100644 --- a/playgrounds/jasmine/package-lock.json +++ b/playgrounds/jasmine/package-lock.json @@ -9,22 +9,23 @@ "version": "1.0.0", "hasInstallScript": true, "devDependencies": { - "@types/jasmine": "^5.1.4", - "@types/node": "^22.10.5", - "@wdio/cli": "^9.4.0", - "@wdio/globals": "^9.4.0", - "@wdio/jasmine-framework": "^9.4.0", - "@wdio/local-runner": "^9.4.0", - "@wdio/spec-reporter": "^9.4.0", - "@wdio/visual-service": "^9.1.2", - "eslint": "^9.39.2", + "@types/jasmine": "^5.1.15", + "@types/node": "^24.12.0", + "@wdio/cli": "^9.25.0", + "@wdio/globals": "^9.23.0", + "@wdio/jasmine-framework": "^9.25.0", + "@wdio/local-runner": "^9.25.0", + "@wdio/spec-reporter": "^9.25.0", + "@wdio/visual-service": "^9.1.6", + "eslint": "^9.39.4", + "eslint-plugin-jasmine": "^4.2.2", "expect-webdriverio": "file:../..", "ts-node": "^10.9.2", "typescript": "^5.9.3" } }, "../..": { - "version": "5.6.4", + "version": "5.6.5", "dev": true, "license": "MIT", "dependencies": { @@ -34,24 +35,24 @@ "jest-matcher-utils": "^30.2.0" }, "devDependencies": { - "@jest/globals": "^30.2.0", + "@jest/globals": "^30.3.0", "@types/debug": "^4.1.12", - "@types/jasmine": "^5.1.8", + "@types/jasmine": "^5.1.15", "@types/jest": "^30.0.0", "@types/mocha": "^10.0.10", - "@types/node": "^24.10.1", - "@vitest/coverage-v8": "^4.0.16", - "@wdio/eslint": "^0.1.2", - "@wdio/types": "^9.20.0", - "eslint": "^9.39.2", + "@types/node": "^24.12.0", + "@vitest/coverage-v8": "^4.1.0", + "@wdio/eslint": "^0.1.3", + "@wdio/types": "^9.25.0", + "eslint": "^9.39.4", "husky": "^9.1.7", "npm-run-all2": "^8.0.4", - "release-it": "^19.1.0", - "rimraf": "^6.1.2", + "release-it": "^19.2.4", + "rimraf": "^6.1.3", "shelljs": "^0.10.0", "typescript": "^5.9.3", - "vitest": "^4.0.16", - "webdriverio": "^9.21.0" + "vitest": "^4.1.0", + "webdriverio": "^9.25.0" }, "engines": { "node": ">=20" @@ -74,9 +75,9 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", - "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, "license": "MIT", "dependencies": { @@ -596,15 +597,15 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", - "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", - "minimatch": "^3.1.2" + "minimatch": "^3.1.5" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -661,20 +662,20 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", - "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", + "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", - "minimatch": "^3.1.2", + "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" }, "engines": { @@ -709,9 +710,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", - "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", "dev": true, "license": "MIT", "engines": { @@ -1801,15 +1802,22 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.19.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.7.tgz", - "integrity": "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==", + "version": "24.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz", + "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.16.0" } }, + "node_modules/@types/node/node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/normalize-package-data": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", @@ -1881,23 +1889,23 @@ } }, "node_modules/@wdio/cli": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-9.23.2.tgz", - "integrity": "sha512-D6KZGomfNmjFhSWYdfR7Ojik5qWEpPoR4g5LQPzbFwiii/RkTudLcMFcCO6s7HTMLDQDWryOStV2KK6KqrIF8A==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-9.25.0.tgz", + "integrity": "sha512-7m6Au8U0Fz+/n6vlchxHd5ogYESjz2XEYVnmcqnDapCAUo570Ilb86Muz69AFrBiZ6D+xkesQTwlWOdNRjIY1w==", "dev": true, "license": "MIT", "dependencies": { "@vitest/snapshot": "^2.1.1", - "@wdio/config": "9.23.2", + "@wdio/config": "9.25.0", "@wdio/globals": "9.23.0", "@wdio/logger": "9.18.0", - "@wdio/protocols": "9.23.2", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/protocols": "9.25.0", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "async-exit-hook": "^2.0.1", "chalk": "^5.4.1", "chokidar": "^4.0.0", - "create-wdio": "9.21.0", + "create-wdio": "9.25.0", "dotenv": "^17.2.0", "import-meta-resolve": "^4.0.0", "lodash.flattendeep": "^4.4.0", @@ -1905,7 +1913,7 @@ "lodash.union": "^4.6.0", "read-pkg-up": "^10.0.0", "tsx": "^4.7.2", - "webdriverio": "9.23.2", + "webdriverio": "9.25.0", "yargs": "^17.7.2" }, "bin": { @@ -1916,32 +1924,33 @@ } }, "node_modules/@wdio/config": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-9.23.2.tgz", - "integrity": "sha512-19Z+AIQ1NUpr6ncTumjSthm6A7c3DbaGTp+VCdcyN+vHYOK4WsWIomSk+uSbFosYFQVGRjCaHaeGSnC8GNPGYQ==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-9.25.0.tgz", + "integrity": "sha512-EWa7l1rrbSNthCRDpdBw7ESAa1/jAjSsWCGkaVAO0HMOGlQjzvYI6gNi4KUeymnurDZ2IPr0jr+f9We6AWi6QA==", "dev": true, "license": "MIT", "dependencies": { "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "deepmerge-ts": "^7.0.3", "glob": "^10.2.2", - "import-meta-resolve": "^4.0.0" + "import-meta-resolve": "^4.0.0", + "jiti": "^2.6.1" }, "engines": { "node": ">=18.20.0" } }, "node_modules/@wdio/dot-reporter": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/dot-reporter/-/dot-reporter-9.23.2.tgz", - "integrity": "sha512-3+5y7P4GS7UTIgr6zPhxKHMmDSwiNjgdwnWIUYXr2eQLcpnPGhc9GL1IEDgQEAcziXG9BfaKzZQHi+vH89PR5w==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/dot-reporter/-/dot-reporter-9.25.0.tgz", + "integrity": "sha512-yFlyHfCJOERWIgiFzbyliCr6YxEYZDM3rykCHmpIlbAOwATxjIh26fvkKI8/23LDqMybym8Pn/Yjj/W78/KgIg==", "dev": true, "license": "MIT", "dependencies": { - "@wdio/reporter": "9.23.2", - "@wdio/types": "9.23.2", + "@wdio/reporter": "9.25.0", + "@wdio/types": "9.25.0", "chalk": "^5.0.1" }, "engines": { @@ -1971,9 +1980,9 @@ } }, "node_modules/@wdio/image-comparison-core": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@wdio/image-comparison-core/-/image-comparison-core-1.1.2.tgz", - "integrity": "sha512-Wvm4iGwONoWlcw7xMGl4UxNYj6aqqrQJXMAJlNik4bpubiGKIVa0NRG05kRVqn8UvOwS1CHfd/9xdXw5a+1DAA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@wdio/image-comparison-core/-/image-comparison-core-1.1.4.tgz", + "integrity": "sha512-WUT+YmzPj4nWSuWACuuKqJXDYAZd4Od3Up+6hRAI1ZA5yV+KEcT8yb7taWY1hjWHqlbCjbuJUaQD80u/7ToqDA==", "dev": true, "license": "MIT", "dependencies": { @@ -1983,9 +1992,9 @@ } }, "node_modules/@wdio/jasmine-framework": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/jasmine-framework/-/jasmine-framework-9.23.2.tgz", - "integrity": "sha512-yrGVkx4mXkgIwRbabWu39HteZQn0ic5HcYtU7eq85hqdZOqxzhFOnQVN27rKB4+IpMtnlPD1TiDrPDF+8Xk5pg==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/jasmine-framework/-/jasmine-framework-9.25.0.tgz", + "integrity": "sha512-J3jNEHZHUuqlbDg68gMMjB3PiN4uQUSzbG87nbLcQCuacaPeqqvcwttmCfEQz6ETh4+MNhIwImsl5D3BP+nPsA==", "dev": true, "license": "MIT", "dependencies": { @@ -1993,8 +2002,8 @@ "@types/node": "^20.1.0", "@wdio/globals": "9.23.0", "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "jasmine": "^5.0.0" }, "engines": { @@ -2024,18 +2033,18 @@ } }, "node_modules/@wdio/local-runner": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-9.23.2.tgz", - "integrity": "sha512-tS8l2iaQc5aQav2LYYXx296F9KpdrU4/dmw5t9n9baXgdu8CKyGEd9orhTFQ7fYR55wFJ/85toQNOvIQHtIZrA==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-9.25.0.tgz", + "integrity": "sha512-E6pEeQouVLle19Gk55Y/JxPGMzT2jhmHS80yjT3g481Q1EML9y8m3T6UMemAUnz70FGneP0aCcuFKJdmkF9dKw==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "^20.1.0", "@wdio/logger": "9.18.0", "@wdio/repl": "9.16.2", - "@wdio/runner": "9.23.2", - "@wdio/types": "9.23.2", - "@wdio/xvfb": "9.23.2", + "@wdio/runner": "9.25.0", + "@wdio/types": "9.25.0", + "@wdio/xvfb": "9.25.0", "exit-hook": "^4.0.0", "expect-webdriverio": "^5.3.4", "split2": "^4.1.0", @@ -2073,9 +2082,9 @@ } }, "node_modules/@wdio/protocols": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-9.23.2.tgz", - "integrity": "sha512-pmCYOYI2N89QCC8IaiHwaWyP0mR8T1iKkEGpoTq2XVihp7VK/lfPvieyeZT5/e28MadYLJsDQ603pbu5J1NRDg==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-9.25.0.tgz", + "integrity": "sha512-PErbZqdpFmE69bRuku3OR34Ro2xuZNNLXYFOcJnjXJVzf5+ApDyGHYrMlvhtrrSy9/55LUybk851ppjS+3RoDA==", "dev": true, "license": "MIT" }, @@ -2103,15 +2112,15 @@ } }, "node_modules/@wdio/reporter": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-9.23.2.tgz", - "integrity": "sha512-+L1knNyQl+Xs+/VkM5JOX/HINe+g3ZVWt0Scsb9DcOCll8xG8jisxArutZLo+UuV6Bm1BzqfJJb/+ae04EuRAQ==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-9.25.0.tgz", + "integrity": "sha512-zmyjr7/EoGwlmrICNzhRL3k0dlJoqdQShzHd5l8V1axYsaC3UHGy2oNDXwKD/OjhEThJsGHxwjyUDkKYhbZdCw==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "^20.1.0", "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", + "@wdio/types": "9.25.0", "diff": "^8.0.2", "object-inspect": "^1.12.0" }, @@ -2120,9 +2129,9 @@ } }, "node_modules/@wdio/reporter/node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", "dev": true, "license": "MIT", "dependencies": { @@ -2130,22 +2139,22 @@ } }, "node_modules/@wdio/runner": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-9.23.2.tgz", - "integrity": "sha512-joFHYO4jnDixsBRM6tJ/nVeH15UNIthIAp2Yky+yPsh1HkM+x9gZG5ZT0TnSXw/E2tQRb2yO3d+jsEHedsE0jw==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-9.25.0.tgz", + "integrity": "sha512-Oe7NnFWJICF5g+LGLVWi3x41aL2ZRto3bOQZlBjNnGFRkx+BPz7qHdENueflfh7VCX9o3qRns6cQ3CEuurLaNg==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "^20.11.28", - "@wdio/config": "9.23.2", - "@wdio/dot-reporter": "9.23.2", + "@wdio/config": "9.25.0", + "@wdio/dot-reporter": "9.25.0", "@wdio/globals": "9.23.0", "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "deepmerge-ts": "^7.0.3", - "webdriver": "9.23.2", - "webdriverio": "9.23.2" + "webdriver": "9.25.0", + "webdriverio": "9.25.0" }, "engines": { "node": ">=18.20.0" @@ -2174,14 +2183,14 @@ } }, "node_modules/@wdio/spec-reporter": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-9.23.2.tgz", - "integrity": "sha512-9uwbrOFgPuF5NqixiU9db46HNJERN04beefNh4f4usJSP41Mbru0isps64qKkWSpFJhYl1LZrSGELezxH9bZ6A==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-9.25.0.tgz", + "integrity": "sha512-15+YnhnXDW7dAJ4PP+qZ2imAbVcMMSwewtjVrKRWK0OsMASXRXka/zV3jViRp1Rf+WCGp76HMxhv7YOygfE68A==", "dev": true, "license": "MIT", "dependencies": { - "@wdio/reporter": "9.23.2", - "@wdio/types": "9.23.2", + "@wdio/reporter": "9.25.0", + "@wdio/types": "9.25.0", "chalk": "^5.1.2", "easy-table": "^1.2.0", "pretty-ms": "^9.0.0" @@ -2191,9 +2200,9 @@ } }, "node_modules/@wdio/types": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.23.2.tgz", - "integrity": "sha512-ryfrERGsNp+aCcrTE1rFU6cbmDj8GHZ04R9k52KNt2u1a6bv3Eh5A/cUA0hXuMdEUfsc8ePLYdwQyOLFydZ0ig==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.25.0.tgz", + "integrity": "sha512-ovSEcUBLz6gVDIsBZYKQXz8EGU37jS8sqbmlOe5+jB4XbsTBCyTLjQK/rO7LWQAKJcs0vBq+Pd+VrlsFtA7tTQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2214,15 +2223,15 @@ } }, "node_modules/@wdio/utils": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-9.23.2.tgz", - "integrity": "sha512-+QfgXUWeA940AXT5l5UlrBKoHBk9GLSQE3BA+7ra1zWuFvv6SHG6M2mwplcPlOlymJMqXy8e7ZgLEoLkXuvC1Q==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-9.25.0.tgz", + "integrity": "sha512-w/ej8gZkc2tZr8L91ATyA1AWrbPDYDOvblQ7r+zt1uPRobuA4H98GME7Zm7i3FIP695BvV4G35Gcs5NssZW1pw==", "dev": true, "license": "MIT", "dependencies": { "@puppeteer/browsers": "^2.2.0", "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", + "@wdio/types": "9.25.0", "decamelize": "^6.0.0", "deepmerge-ts": "^7.0.3", "edgedriver": "^6.1.2", @@ -2240,23 +2249,23 @@ } }, "node_modules/@wdio/visual-service": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@wdio/visual-service/-/visual-service-9.1.2.tgz", - "integrity": "sha512-FYyv4kXWqm4LmX62VwC/uR0khRFlSmvUVDyyKWLiIMdzQGiXLYOotxGs5E/wQcHHZPPv+/1wWFJLoE3w1rWt+w==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/@wdio/visual-service/-/visual-service-9.1.6.tgz", + "integrity": "sha512-oQIzo0I6kX/IV7rferoLllf8vnTtDOHpbdBMeio8+fsJqC39eKOpWp1+fiGyByrO9zF0GMJELM/r76ZiEeV+qA==", "dev": true, "license": "MIT", "dependencies": { "@wdio/globals": "^9.23.0", - "@wdio/image-comparison-core": "1.1.2", + "@wdio/image-comparison-core": "1.1.4", "@wdio/logger": "^9.18.0", "@wdio/types": "^9.20.0", "expect-webdriverio": "^5.6.1" } }, "node_modules/@wdio/xvfb": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/xvfb/-/xvfb-9.23.2.tgz", - "integrity": "sha512-48KiET6Phmu7SIQgpTXSn7eRJK6MJdTKib2MLT5WTKIJ+t0OyGKl/ESXi6tzFrGFPzLkvogSIRy8O2sKM0PcbA==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/xvfb/-/xvfb-9.25.0.tgz", + "integrity": "sha512-qbsdWm1sP5CGikz3n3dwoVGqbRyBsERGzckDMsQeQ9QVTG6OsNOm4KiVejdiwdPXqDjLUnBv8xGtfuFrftFwcA==", "dev": true, "license": "MIT", "dependencies": { @@ -2338,9 +2347,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -2928,9 +2937,9 @@ "license": "MIT" }, "node_modules/commander": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", - "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", "dev": true, "license": "MIT", "engines": { @@ -3016,9 +3025,9 @@ "license": "MIT" }, "node_modules/create-wdio": { - "version": "9.21.0", - "resolved": "https://registry.npmjs.org/create-wdio/-/create-wdio-9.21.0.tgz", - "integrity": "sha512-L6gsQLArY3AH5uTGpf3VfUezIsmZKufkF3ixSWqCuA/m458YVKeGghu1bBOWBdDIzqa6GX4e29dv0uVam0CTpw==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/create-wdio/-/create-wdio-9.25.0.tgz", + "integrity": "sha512-ZnkJVDx3HB7UNH2t1kxK1VoNWQAQhLYyTjSEdpcFTHoj/QUrzS7K9nW99Q6WT0mgsedbtl86VMq4IXfy6f8Jrw==", "dev": true, "license": "MIT", "dependencies": { @@ -3528,25 +3537,25 @@ } }, "node_modules/eslint": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", - "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.1", + "@eslint/config-array": "^0.21.2", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.2", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "ajv": "^6.12.4", + "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", @@ -3565,7 +3574,7 @@ "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", + "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, @@ -3587,6 +3596,17 @@ } } }, + "node_modules/eslint-plugin-jasmine": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jasmine/-/eslint-plugin-jasmine-4.2.2.tgz", + "integrity": "sha512-nALbewRk63uz28UGNhUTJyd6GofXxVNFpWFNAwr9ySc6kpSRIoO4suwZqIYz3cfJmCacilmjp7+1Ocjr7zRagA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8", + "npm": ">=6" + } + }, "node_modules/eslint-scope": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", @@ -4067,9 +4087,9 @@ } }, "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4763,6 +4783,16 @@ "node": ">=18" } }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/jpeg-js": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", @@ -6057,9 +6087,9 @@ "license": "MIT" }, "node_modules/sax": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", - "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.5.0.tgz", + "integrity": "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -6247,9 +6277,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.22", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", - "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", "dev": true, "license": "CC0-1.0" }, @@ -6804,19 +6834,19 @@ } }, "node_modules/webdriver": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-9.23.2.tgz", - "integrity": "sha512-HZy3eydZbmex0pbyLwHaDsAyZ+S+V4XQTdGK/nAOi4uPa74U6yT9vXqtb+3B+5/LDM7L8kTD6Z3b1y4gB4pmTw==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-9.25.0.tgz", + "integrity": "sha512-XnABKdrp83zX3xVltmX0OcFzn8zOzWGtZQxIUKY0+INB0g9Nnnfu7G75W0G+0y4nyb3zH8mavGzDBiXctdEd3Q==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "^20.1.0", "@types/ws": "^8.5.3", - "@wdio/config": "9.23.2", + "@wdio/config": "9.25.0", "@wdio/logger": "9.18.0", - "@wdio/protocols": "9.23.2", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/protocols": "9.25.0", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "deepmerge-ts": "^7.0.3", "https-proxy-agent": "^7.0.6", "undici": "^6.21.3", @@ -6827,9 +6857,9 @@ } }, "node_modules/webdriver/node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", "dev": true, "license": "MIT", "dependencies": { @@ -6837,20 +6867,20 @@ } }, "node_modules/webdriverio": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-9.23.2.tgz", - "integrity": "sha512-VjfTw1bRJdBrzjoCu7BGThxn1JK2V7mAGvxibaBrCNIayPPQjLhVDNJPOVEiR7txM6zmOUWxhkCDxHjhMYirfQ==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-9.25.0.tgz", + "integrity": "sha512-ualC/LtWGjL5rwGAbUUzURKqKoHJG2/qecEppcS9k4n1IX3MlbzGXuL/qpXiRbs/h4981HpRbZAKBxRYqwUe3g==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "^20.11.30", "@types/sinonjs__fake-timers": "^8.1.5", - "@wdio/config": "9.23.2", + "@wdio/config": "9.25.0", "@wdio/logger": "9.18.0", - "@wdio/protocols": "9.23.2", + "@wdio/protocols": "9.25.0", "@wdio/repl": "9.16.2", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "archiver": "^7.0.1", "aria-query": "^5.3.0", "cheerio": "^1.0.0-rc.12", @@ -6867,7 +6897,7 @@ "rgb2hex": "0.2.5", "serialize-error": "^12.0.0", "urlpattern-polyfill": "^10.0.0", - "webdriver": "9.23.2" + "webdriver": "9.25.0" }, "engines": { "node": ">=18.20.0" diff --git a/playgrounds/jasmine/package.json b/playgrounds/jasmine/package.json index c0fd161a2..30e6d9cbc 100644 --- a/playgrounds/jasmine/package.json +++ b/playgrounds/jasmine/package.json @@ -11,15 +11,16 @@ "checks:all": "npm run typecheck && npm run lint && npm test" }, "devDependencies": { - "@types/jasmine": "^5.1.4", - "@types/node": "^22.10.5", - "@wdio/cli": "^9.4.0", - "@wdio/globals": "^9.4.0", - "@wdio/jasmine-framework": "^9.4.0", - "@wdio/local-runner": "^9.4.0", - "@wdio/spec-reporter": "^9.4.0", - "@wdio/visual-service": "^9.1.2", - "eslint": "^9.39.2", + "@types/jasmine": "^5.1.15", + "@types/node": "^24.12.0", + "@wdio/cli": "^9.25.0", + "@wdio/globals": "^9.23.0", + "@wdio/jasmine-framework": "^9.25.0", + "@wdio/local-runner": "^9.25.0", + "@wdio/spec-reporter": "^9.25.0", + "@wdio/visual-service": "^9.1.6", + "eslint": "^9.39.4", + "eslint-plugin-jasmine": "^4.2.2", "expect-webdriverio": "file:../..", "ts-node": "^10.9.2", "typescript": "^5.9.3" diff --git a/playgrounds/jasmine/test/specs/basic-matchers.test.ts b/playgrounds/jasmine/test/specs/basic-matchers.test.ts deleted file mode 100644 index bee35cd6f..000000000 --- a/playgrounds/jasmine/test/specs/basic-matchers.test.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { browser, $, $$ } from '@wdio/globals' - -describe('Basic Expect Matchers', () => { - beforeEach(async () => { - await browser.url('https://webdriver.io') - }) - - describe('Boolean matchers', () => { - it('should verify truthy values', async () => { - const element = await $('.navbar') - const isDisplayed = await element.isDisplayed() - - await expect(isDisplayed).toBe(true) - await expect(isDisplayed).toBeTruthy() - }) - - it('should verify falsy values', async () => { - const element = await $('.non-existent-element') - const exists = await element.isExisting() - - await expect(exists).toBe(false) - await expect(exists).toBeFalsy() - }) - }) - - describe('String matchers', () => { - it('should match exact text', async () => { - const title = await browser.getTitle() - await expect(title).toContain('WebdriverIO') - }) - - it('should match with regex', async () => { - const url = await browser.getUrl() - await expect(url).toMatch(/^https:\/\/webdriver\.io/) - }) - }) - - describe('Number matchers', () => { - it('should compare numbers', async () => { - const navLinks = await $$('nav a') - const count = navLinks.length - - await expect(count).toBeGreaterThan(5) - await expect(count).toBeGreaterThanOrEqual(6) - await expect(count).toBeLessThan(100) - await expect(count).toBeLessThanOrEqual(50) - }) - }) - - describe('Array matchers', () => { - it('should verify array contents', async () => { - const navLinks = await $$('nav a') - const hrefs: string[] = [] - for (const link of navLinks) { - hrefs.push(await link.getAttribute('href')) - } - - await expect(hrefs).toBeInstanceOf(Array) - await expect(hrefs.length).toBeGreaterThan(0) - await expect(hrefs).toEqual(expect.arrayContaining(['/docs/gettingstarted'])) - }) - }) - - // TODO failing with TypeError: await expect(...).toHaveProperty is not a function - xdescribe('Object matchers', () => { - it('should match object properties', async () => { - const capabilities = await browser.capabilities - - await expect(capabilities).toHaveProperty('browserName') - await expect(capabilities).toMatchObject({ - browserName: 'chrome' - }) - }) - }) - - describe('Negation', () => { - it('should work with not', async () => { - const title = await browser.getTitle() - - await expect(title).not.toBe('') - await expect(title).not.toContain('Firefox') - }) - }) - - xdescribe('Async/Promise matchers', () => { - it('should handle promises', async () => { - const titlePromise = browser.getTitle() - - // @ts-expect-error -- resolves should not exists on expect - await expect(titlePromise).resolves.toContain('WebdriverIO') - }) - - it('should not reject', async () => { - const urlPromise = browser.getUrl() - - // @ts-expect-error -- rejects should not exists on expect - await expect(urlPromise).resolves.toBeDefined() - }) - }) -}) diff --git a/playgrounds/jasmine/test/specs/expect-wdioImport/basic-matchers.test.ts b/playgrounds/jasmine/test/specs/expect-wdioImport/basic-matchers.test.ts new file mode 100644 index 000000000..4e3a7a384 --- /dev/null +++ b/playgrounds/jasmine/test/specs/expect-wdioImport/basic-matchers.test.ts @@ -0,0 +1,172 @@ +import { browser, $, $$ } from '@wdio/globals' +import { expect } from 'expect-webdriverio' + +describe('Basic Expect Matchers available when pulling expect from expect-webdriverio directly', () => { + beforeEach(async () => { + await browser.url('https://webdriver.io') + }) + + describe('Boolean matchers', () => { + it('should verify truthy values', async () => { + const element = await $('.navbar') + const isDisplayed = await element.isDisplayed() + + await expect(isDisplayed).toBe(true) + await expect(isDisplayed).toBeTruthy() + }) + + it('should verify falsy values', async () => { + const element = await $('.non-existent-element') + const exists = await element.isExisting() + + await expect(exists).toBe(false) + await expect(exists).toBeFalsy() + }) + }) + + describe('String matchers', () => { + it('should match exact text', async () => { + const title = await browser.getTitle() + await expect(title).toContain('WebdriverIO') + }) + + it('should match with regex', async () => { + const url = await browser.getUrl() + await expect(url).toMatch(/^https:\/\/webdriver\.io/) + }) + }) + + describe('Number matchers', () => { + it('should compare numbers', async () => { + const navLinks = await $$('nav a') + const count = navLinks.length + + await expect(count).toBeGreaterThan(5) + await expect(count).toBeGreaterThanOrEqual(6) + await expect(count).toBeLessThan(100) + await expect(count).toBeLessThanOrEqual(50) + }) + }) + + describe('Negation', () => { + it('should work with not', async () => { + const title = await browser.getTitle() + + await expect(title).not.toBe('') + await expect(title).not.toContain('Firefox') + }) + }) + + + describe('Array matchers', () => { + it('should verify array contents', async () => { + const navLinks = await $$('nav a') + const hrefs: string[] = [] + for (const link of navLinks) { + const href = await link.getAttribute('href') + if (href) hrefs.push(href) + } + + await expect(hrefs).toBeInstanceOf(Array) + await expect(hrefs.length).toBeGreaterThan(0) + await expect(hrefs).toEqual(expect.arrayContaining(['/docs/gettingstarted'])) + }) + }) + + describe('Object matchers', () => { + it('should match object properties', async () => { + const capabilities = await browser.capabilities + + await expect(capabilities).toHaveProperty('browserName') + await expect(capabilities).toMatchObject({ + browserName: 'chrome' + }) + }) + }) + + describe('Async/Promise matchers', () => { + it('should handle promises', async () => { + const titlePromise = browser.getTitle() + + await expect(titlePromise).resolves.toContain('WebdriverIO') + }) + + it('should not reject', async () => { + const urlPromise = browser.getUrl() + + await expect(urlPromise).resolves.toBeDefined() + }) + }) + + describe('Basis matcher with Jasmine asymmetric matchers', () => { + it('should have toEqual work with jasmine.stringContaining', async () => { + expect('title').toEqual(jasmine.stringContaining('title')) + }) + + it('should have toEqual work with jasmine.any', async () => { + expect('title').toEqual(jasmine.any(String)) + expect(123).toEqual(jasmine.any(Number)) + }) + + // TODO to support one day? + xit('should have toEqual work with jasmine.objectContaining', async () => { + expect({ a: 1, b: 2 }).toEqual(jasmine.objectContaining({ a: 1 })) + }) + + // TODO to support one day? + xit('should have toEqual work with jasmine.arrayContaining', async () => { + expect([1, 2, 3]).toEqual(jasmine.arrayContaining([2])) + }) + + it('should have toEqual work with jasmine.stringMatching', async () => { + expect('title').toEqual(jasmine.stringMatching(/itl/)) + }) + + it('should have toEqual work with jasmine.anything', async () => { + expect({ foo: 'bar' }).toEqual({ foo: jasmine.anything() }) + }) + + it('should have toBe not work with stringContaining', async () => { + expect(() => { + expect('title').toBe(jasmine.stringContaining('title')) + }).toThrow() + }) + }) + + describe('Basis matcher with asymmetric matchers', () => { + it('should have toEqual work with expect.stringContaining', async () => { + expect('title').toEqual(expect.stringContaining('title')) + }) + + it('should have toEqual work with expect.any', async () => { + expect('title').toEqual(expect.any(String)) + expect(123).toEqual(expect.any(Number)) + }) + + it('should have toEqual work with expect.objectContaining', async () => { + expect({ a: 1, b: 2 }).toEqual(expect.objectContaining({ a: 1 })) + }) + + it('should have toEqual work with expect.arrayContaining', async () => { + expect([1, 2, 3]).toEqual(expect.arrayContaining([2])) + }) + + it('should have toEqual work with expect.stringMatching', async () => { + expect('title').toEqual(expect.stringMatching(/itl/)) + }) + + it('should have toEqual work with expect.anything', async () => { + expect({ foo: 'bar' }).toEqual({ foo: expect.anything() }) + }) + + it('should have toEqual work with expect.closeTo', async () => { + expect({ num: 1.1 }).toEqual({ num: expect.closeTo(1.101, 2) }) + }) + + it('should have toBe not work with stringContaining', async () => { + expect(() => { + expect('title').toBe(expect.stringContaining('title')) + }).toThrow() + }) + }) +}) diff --git a/playgrounds/jasmine/test/specs/expect-wdioImport/wdio-matchers.test.ts b/playgrounds/jasmine/test/specs/expect-wdioImport/wdio-matchers.test.ts new file mode 100644 index 000000000..b7e075971 --- /dev/null +++ b/playgrounds/jasmine/test/specs/expect-wdioImport/wdio-matchers.test.ts @@ -0,0 +1,180 @@ +import { browser, $, $$ } from '@wdio/globals' +import { expect } from 'expect-webdriverio' + +describe('WebdriverIO Custom Matchers', () => { + beforeEach(async () => { + await browser.url('https://webdriver.io') + }) + + describe('Browser matchers', () => { + it('should verify browser title', async () => { + await expect(browser).toHaveTitle('WebdriverIO · Next-gen browser and mobile automation test framework for Node.js | WebdriverIO') + }) + + it('should verify browser title contains text', async () => { + await expect(browser).toHaveTitle(expect.stringContaining('WebdriverIO')) + }) + + it('should verify browser URL', async () => { + await expect(browser).toHaveUrl('https://webdriver.io/') + }) + + it('should verify URL contains path', async () => { + await expect(browser).toHaveUrl(expect.stringContaining('webdriver.io')) + }) + }) + + describe('Element existence matchers', () => { + it('should verify element exists', async () => { + const searchButton = await $('.DocSearch-Button') + await expect(searchButton).toExist() + await expect(searchButton).toBeExisting() + }) + + it('should verify element does not exist', async () => { + const nonExistent = await $('.non-existent-element') + await expect(nonExistent).not.toExist() + }) + }) + + describe('Element visibility matchers', () => { + it('should verify element is displayed', async () => { + const nav = await $('nav') + await expect(nav).toBeDisplayed() + }) + + it('should verify element is displayed in viewport', async () => { + const searchButton = await $('.DocSearch-Button') + await expect(searchButton).toBeDisplayedInViewport() + }) + }) + + describe('Element state matchers', () => { + it('should verify element is clickable', async () => { + const searchButton = await $('.DocSearch-Button') + await expect(searchButton).toBeClickable() + }) + + it('should verify element is enabled', async () => { + const searchButton = await $('.DocSearch-Button') + await expect(searchButton).toBeEnabled() + }) + + it('should verify button is not disabled', async () => { + const searchButton = await $('.DocSearch-Button') + await expect(searchButton).not.toBeDisabled() + }) + }) + + describe('Element text matchers', () => { + it('should verify element text', async () => { + const docsLink = await $('=Docs') + await expect(docsLink).toBeDisplayed() + await expect(docsLink).toHaveText('Docs') + }) + + it('should verify element contains text', async () => { + const heading = await $$('h1')[1] // Second h1 has text + await expect(heading).toHaveText(expect.stringContaining('Open Source')) + }) + + it('should verify text with options', async () => { + const heading = await $$('h1')[1] // Second h1 has text + await expect(heading).toHaveText('OPEN SOURCE', { ignoreCase: true, containing: true }) + }) + }) + + describe('Element attribute matchers', () => { + it('should verify element has attribute', async () => { + const docsLink = await $('a[href="/docs/gettingstarted"]') + await expect(docsLink).toHaveAttribute('href', '/docs/gettingstarted') + }) + + it('should verify attribute contains value', async () => { + const docsLink = await $('a[href="/docs/gettingstarted"]') + await expect(docsLink).toHaveAttribute('href', expect.stringContaining('docs')) + }) + + it('should verify element has class', async () => { + const searchButton = await $('.DocSearch-Button') + await expect(searchButton).toHaveElementClass('DocSearch-Button') + }) + + it('should verify element has multiple classes', async () => { + const searchButton = await $('.DocSearch-Button') + await expect(searchButton).toHaveElementClass(expect.stringContaining('DocSearch')) + }) + }) + + describe('Element property matchers', () => { + it('should verify element property', async () => { + const searchButton = await $('.DocSearch-Button') + await expect(searchButton).toHaveElementProperty('type', 'button') + }) + }) + + describe('Element value matchers', () => { + it('should verify input value', async () => { + // Navigate to a page with inputs + await browser.url('https://the-internet.herokuapp.com/login') + const username = await $('#username') + await username.setValue('testuser') + await expect(username).toHaveValue('testuser') + }) + + it('should verify value contains text', async () => { + await browser.url('https://the-internet.herokuapp.com/login') + const username = await $('#username') + await username.setValue('testuser123') + await expect(username).toHaveValue(expect.stringContaining('testuser')) + }) + }) + + describe('Elements array matchers', () => { + it('should verify elements array size', async () => { + const navLinks = await $$('nav a') + await expect(navLinks).toBeElementsArrayOfSize(49) + }) + + it('should verify elements array size with comparison', async () => { + const navLinks = await $$('nav a') + await expect(navLinks).toBeElementsArrayOfSize({ gte: 40 }) + await expect(navLinks).toBeElementsArrayOfSize({ lte: 50 }) + }) + }) + + describe('Focus matchers', () => { + it('should verify element is focused', async () => { + const searchButton = await $('.DocSearch-Button') + await searchButton.click() + + // The search modal input should be focused after clicking + + await browser.pause(500) // Wait for modal to open + const searchInput = await $('.DocSearch-Input') + if (await searchInput.isExisting()) { + await expect(searchInput).toBeFocused() + } + }) + }) + + describe('With wait options', () => { + it('should wait for condition to be met', async () => { + const heading = await $('h1') + await expect(heading).toBeDisplayed({ wait: 5000 }) + }) + + it('should use custom interval', async () => { + const nav = await $('nav') + await expect(nav).toExist({ wait: 3000, interval: 100 }) + }) + }) + + describe('Negated matchers', () => { + it('should work with not', async () => { + const nonExistent = await $('.non-existent-element-xyz') + await expect(nonExistent).not.toBeDisplayed() + await expect(nonExistent).not.toExist() + }) + }) +}) diff --git a/playgrounds/jasmine/test/specs/globalImport/basic-matchers-jasmine.test.ts b/playgrounds/jasmine/test/specs/globalImport/basic-matchers-jasmine.test.ts new file mode 100644 index 000000000..0e306c602 --- /dev/null +++ b/playgrounds/jasmine/test/specs/globalImport/basic-matchers-jasmine.test.ts @@ -0,0 +1,111 @@ +import { browser, $, $$ } from '@wdio/globals' + +describe('Basic Matchers', () => { + beforeEach(async () => { + await browser.url('https://webdriver.io') + }) + + describe('Basic Matchers available in Jasmine', () => { + describe('Boolean matchers', () => { + it('should verify truthy values', async () => { + const element = await $('.navbar') + const isDisplayed = await element.isDisplayed() + + await expect(isDisplayed).toBe(true) + await expect(isDisplayed).toBeTruthy() + }) + + it('should verify falsy values', async () => { + const element = await $('.non-existent-element') + const exists = await element.isExisting() + + await expect(exists).toBe(false) + await expect(exists).toBeFalsy() + }) + }) + + describe('String matchers', () => { + it('should match exact text', async () => { + const title = await browser.getTitle() + await expect(title).toContain('WebdriverIO') + }) + + it('should match with regex', async () => { + const url = await browser.getUrl() + await expect(url).toMatch(/^https:\/\/webdriver\.io/) + }) + }) + + describe('Number matchers', () => { + it('should compare numbers', async () => { + const navLinks = await $$('nav a') + const count = navLinks.length + + await expect(count).toBeGreaterThan(5) + await expect(count).toBeGreaterThanOrEqual(6) + await expect(count).toBeLessThan(100) + await expect(count).toBeLessThanOrEqual(50) + }) + }) + + describe('Negation', () => { + it('should work with not', async () => { + const title = await browser.getTitle() + + await expect(title).not.toBe('') + await expect(title).not.toContain('Firefox') + }) + }) + describe('Array matchers', () => { + it('should verify array contents', async () => { + const navLinks = await $$('nav a') + const hrefs: string[] = [] + for (const link of navLinks) { + const href = await link.getAttribute('href') + if (href) hrefs.push(href) + } + + await expect(hrefs).toBeInstanceOf(Array) + await expect(hrefs.length).toBeGreaterThan(0) + await expect(hrefs).toEqual(expect.arrayContaining(['/docs/gettingstarted'])) + }) + }) + }) + + // Simply showing not available matchers in Jasmine + xdescribe('Excluded tests showing unavailable matchers in Jasmine', () => { + describe('Object matchers', () => { + it('should match object properties', async () => { + const capabilities = await browser.capabilities + + // @ts-expect-error -- toMatchObject is not available in Jasmine even at runtime + await expect(capabilities).toMatchObject({ + browserName: 'chrome' + }) + + // @ts-expect-error -- toHaveProperty is not available in Jasmine even at runtime + await expect(capabilities).toHaveProperty('browserName') + // @ts-expect-error -- toMatchObject is not available in Jasmine even at runtime + await expect(capabilities).toMatchObject({ + browserName: 'chrome' + }) + }) + }) + + describe('Async/Promise matchers', () => { + it('should handle promises', async () => { + const titlePromise = browser.getTitle() + + // @ts-expect-error -- resolves should not exists on expect + await expect(titlePromise).resolves.toContain('WebdriverIO') + }) + + it('should not reject', async () => { + const urlPromise = browser.getUrl() + + // @ts-expect-error -- rejects should not exists on expect + await expect(urlPromise).resolves.toBeDefined() + }) + }) + }) +}) diff --git a/playgrounds/jasmine/test/specs/jasmine-specific.test.ts b/playgrounds/jasmine/test/specs/globalImport/jasmine-specific.test.ts similarity index 86% rename from playgrounds/jasmine/test/specs/jasmine-specific.test.ts rename to playgrounds/jasmine/test/specs/globalImport/jasmine-specific.test.ts index 57441a075..833e2e02b 100644 --- a/playgrounds/jasmine/test/specs/jasmine-specific.test.ts +++ b/playgrounds/jasmine/test/specs/globalImport/jasmine-specific.test.ts @@ -38,7 +38,8 @@ describe('Jasmine-Specific Features', () => { const navLinks = await $$('nav a') const hrefs: string[] = [] for (const link of navLinks) { - hrefs.push(await link.getAttribute('href')) + const href = await link.getAttribute('href') + if (href) hrefs.push(href) } await expect(hrefs).toEqual(jasmine.arrayContaining(['/docs/gettingstarted'])) }) @@ -64,14 +65,12 @@ describe('Jasmine-Specific Features', () => { await expect(searchButton).withContext('Search button should exist on the homepage').toExist() }) - // TODO failing on jasmine.stringContaining not working properly with wdio matchers - xit('should use asymmetric matchers in toHaveAttribute', async () => { + it('should use asymmetric matchers in toHaveAttribute', async () => { const docsLink = await $('a[href="/docs/gettingstarted"]') await expect(docsLink).toHaveAttribute('href', jasmine.stringContaining('docs')) }) - // TODO failing on jasmine.stringContaining not working properly with wdio matchers - xit('should use asymmetric matchers in toHaveText', async () => { + it('should use asymmetric matchers in toHaveText', async () => { const heading = await $$('h1')[1] await expect(heading).toHaveText(jasmine.stringContaining('Open')) }) @@ -91,8 +90,7 @@ describe('Jasmine-Specific Features', () => { }) describe('Array and collection validation', () => { - // TODO asymmetric matchers are not working properly in this test - xit('should validate collections with jasmine matchers', async () => { + it('should validate collections with jasmine matchers', async () => { const navLinks = await $$('nav a') const count = navLinks.length @@ -117,9 +115,8 @@ describe('Jasmine-Specific Features', () => { }) }) - // failing on jasmine.stringContaining not working properly with wdio matchers describe('Browser state validation', () => { - xit('should validate browser properties with asymmetric matchers', async () => { + it('should validate browser properties with asymmetric matchers', async () => { const title = await browser.getTitle() const url = await browser.getUrl() @@ -129,6 +126,8 @@ describe('Jasmine-Specific Features', () => { // Combined with WebdriverIO matchers await expect(browser).toHaveUrl(jasmine.stringContaining('webdriver.io')) await expect(browser).toHaveTitle(jasmine.stringContaining('WebdriverIO')) + await expect(browser).toHaveUrl(jasmine.stringContaining('WEBDRIVER.io'),{ignoreCase: true}) + await expect(browser).toHaveTitle(jasmine.stringContaining('WEBDRIVERIO'), {ignoreCase: true}) }) }) @@ -146,8 +145,7 @@ describe('Jasmine-Specific Features', () => { await expect(size.height).toBeGreaterThan(0) }) - // TODO failing with Error: Can't call getText on element with selector ".non-existent-element-xyz" because element wasn't found - xit('should validate element attributes', async () => { + it('should validate element attributes', async () => { const searchButton = await $('.DocSearch-Button') const classList = await searchButton.getAttribute('class') @@ -164,12 +162,17 @@ describe('Jasmine-Specific Features', () => { await expect(title).not.toEqual(jasmine.stringMatching(/selenium/i)) }) - // TODO to keep? Failing since element not found - xit('should combine not with WebdriverIO matchers', async () => { - const nonExistent = await $('.non-existent-element-xyz') + it('should combine not.toBeDisplayed with WebdriverIO matchers', async () => { + const nonExistent = $('.non-existent-element-xyz') await expect(nonExistent).not.toBeDisplayed() - await expect(nonExistent).not.toHaveText(jasmine.any(String)) + }) + + + it('should combine not.toHaveText with WebdriverIO matchers', async () => { + const searchButton = await $('.DocSearch-Button') + + await expect(searchButton).not.toHaveText('test') }) }) @@ -183,6 +186,12 @@ describe('Jasmine-Specific Features', () => { const arr = [1, 2, 3] const obj = { foo: 'bar', num: 42 } + // withContext with various matchers + await expect(title).toMatch(/WebdriverIO/) + await expect(title).withContext('Title should contain WebdriverIO').not.toMatch(/NOT WebdriverIO/) + await expect(arr).withContext('Array should contain 2').toContain(3) + await expect(obj).withContext('Object should have foo').toEqual(jasmine.objectContaining({ foo: 'bar' })) + // Equality await expect(title).toEqual('WebdriverIO · Next-gen browser and mobile automation test framework for Node.js | WebdriverIO') await expect(count).toBeGreaterThan(0) @@ -209,15 +218,8 @@ describe('Jasmine-Specific Features', () => { await expect(Promise.resolve(42)).toBeResolvedTo(42) // @ts-expect-error -- toBeRejectedWith is not recognized properly to fix one day await expect(Promise.reject('fail')).toBeRejectedWith('fail') - // @ts-expect-error -- toThrowError is not recognized properly to fix one day - await expect(() => { throw new Error('fail') }).toThrowError('fail') - // withContext with various matchers - await expect(title).withContext('Title should contain WebdriverIO').toMatch(/WebdriverIO/) - await expect(arr).withContext('Array should contain 2').toContain(2) - await expect(obj).withContext('Object should have foo').toEqual(jasmine.objectContaining({ foo: 'bar' })) + await expect(() => { throw new Error('fail') }).toThrowError('fail') }) - - }) }) diff --git a/playgrounds/jasmine/test/specs/globalImport/network-matchers.test.ts b/playgrounds/jasmine/test/specs/globalImport/network-matchers.test.ts new file mode 100644 index 000000000..b0f3d1290 --- /dev/null +++ b/playgrounds/jasmine/test/specs/globalImport/network-matchers.test.ts @@ -0,0 +1,49 @@ +import { browser } from '@wdio/globals' + +describe('Network Matchers', () => { + let mock: WebdriverIO.Mock + + beforeAll(async () => { + mock = await browser.mock('https://webdriver.io/api/foo', { + method: 'POST' + }) + mock.respond({ success: true }, { + statusCode: 200, + headers: { Authorization: 'bar' } + }) + + await browser.url('https://webdriver.io/') + + await browser.execute(async () => { + await fetch('https://webdriver.io/api/foo', { + method: 'POST', + headers: { Authorization: 'foo' }, + body: JSON.stringify({ title: 'foo', description: 'bar' }) + }) + }) + }) + + it('should assert on network calls', async () => { + await expect(mock).toBeRequested() + await expect(mock).toBeRequestedTimes(1) + + // Detailed check (simplified to match available Bidi fields) + await expect(mock).toBeRequestedWith({ + url: 'https://webdriver.io/api/foo', + method: 'POST' + }) + }) + + it('should support asymmetric matchers', async () => { + await expect(mock).toBeRequestedWith(expect.objectContaining({ + method: 'POST' + })) + }) + + it('should support jasmine asymmetric matchers', async () => { + await expect(mock).toBeRequestedWith(jasmine.objectContaining({ + method: 'POST' + })) + }) +}) + diff --git a/playgrounds/jasmine/test/specs/wdio-matchers.test.ts b/playgrounds/jasmine/test/specs/globalImport/wdio-matchers.test.ts similarity index 100% rename from playgrounds/jasmine/test/specs/wdio-matchers.test.ts rename to playgrounds/jasmine/test/specs/globalImport/wdio-matchers.test.ts diff --git a/playgrounds/jasmine/tsconfig.json b/playgrounds/jasmine/tsconfig.json index 45f9bbcc2..468b40f10 100644 --- a/playgrounds/jasmine/tsconfig.json +++ b/playgrounds/jasmine/tsconfig.json @@ -5,7 +5,6 @@ "moduleResolution": "bundler", "types": [ "node", - "expect-webdriverio/expect-global", "expect-webdriverio/jasmine-wdio-expect-async", "@types/jasmine", "@wdio/globals/types", // Need to be last to so the above from the projects have priority diff --git a/playgrounds/jasmine/wdio.conf.ts b/playgrounds/jasmine/wdio.conf.ts index 0ab2ad596..d68488433 100644 --- a/playgrounds/jasmine/wdio.conf.ts +++ b/playgrounds/jasmine/wdio.conf.ts @@ -15,8 +15,11 @@ export const config: WebdriverIO.Config = { // ================== // specs: [ - './test/specs/**/*.test.ts' - // './test/specs/**/jasmine-specific.test.ts', + './test/specs/**/*.test.ts', + //'./test/specs/expect-wdioImport/basic-matchers.test.ts', + // './test/specs/expect-wdioImport/wdio-matchers.test.ts' + // './test/specs/globalImport/jasmine-specific.test.ts', + //'./test/specs/globalImport/snapshot.test.ts', ], // @@ -48,7 +51,7 @@ export const config: WebdriverIO.Config = { connectionRetryCount: 3, services: [ // SoftAssertionService is not supported since anyway Jasmine is designed that way out of the box - // Viusal Snapshot Service is not supported + // visual snapshot service does not work properly with Jasmine due to the lack of proper hooks ], framework: 'jasmine', reporters: ['spec'], diff --git a/playgrounds/jest/.gitignore b/playgrounds/jest/.gitignore deleted file mode 100644 index 9572d27e9..000000000 --- a/playgrounds/jest/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules/ -.temp/ diff --git a/playgrounds/jest/README.md b/playgrounds/jest/README.md new file mode 100644 index 000000000..a85b8ef51 --- /dev/null +++ b/playgrounds/jest/README.md @@ -0,0 +1,15 @@ +# Jest Playground + +This is a playground for E2E testing with Jest, ensuring the compatibility of `expect-webdriverio` and primarily serving to test Jest augmentation. + +## Notes and Limitations + +* **Framework**: There is no official WebdriverIO framework for Jest (e.g., no `@wdio/jest-framework`). +* **Matcher Registration**: WebdriverIO custom matchers need to be manually registered via Jest augmentation to work with Jest's global `expect`. +* **Snapshots**: Basic snapshot testing can work fine, but it may conflict with Jest's native snapshot mechanism. +* **Visual Snapshots**: Visual snapshot testing works successfully. + +## Test Structure + +* `test/`: Tests demonstrating integration with Jest using global matcher augmentation. +* **TODO**: Add a `test/expect-wdioImport` folder showing how to use `expect-webdriverio` by importing it directly as a standalone module without global Jest augmentation. diff --git a/playgrounds/jest/eslint.config.mjs b/playgrounds/jest/eslint.config.mjs index 97baff722..1590c1339 100644 --- a/playgrounds/jest/eslint.config.mjs +++ b/playgrounds/jest/eslint.config.mjs @@ -1,5 +1,6 @@ import tsEslintPlugin from '@typescript-eslint/eslint-plugin'; import tsParser from '@typescript-eslint/parser'; +import jestPlugin from 'eslint-plugin-jest'; export default { files: ['**/*.ts', '**/*.js'], @@ -20,9 +21,11 @@ export default { }, plugins: { '@typescript-eslint': tsEslintPlugin, + 'jest': jestPlugin, }, rules: { ...tsEslintPlugin.configs['recommended'].rules, '@typescript-eslint/no-floating-promises': 'error', + 'jest/no-focused-tests': 'error', }, }; diff --git a/playgrounds/jest/global.d.ts b/playgrounds/jest/global.d.ts new file mode 100644 index 000000000..58a4841c8 --- /dev/null +++ b/playgrounds/jest/global.d.ts @@ -0,0 +1,3 @@ +export declare global { + var standalone: WebdriverIO.Browser; +} diff --git a/playgrounds/jest/jest.config.mjs b/playgrounds/jest/jest.config.mjs new file mode 100644 index 000000000..8e69d8a08 --- /dev/null +++ b/playgrounds/jest/jest.config.mjs @@ -0,0 +1,19 @@ +import { inject } from "vitest"; + +export default { + preset: 'ts-jest/presets/default-esm', + moduleNameMapper: { + '^(\\.{1,2}/.*)\\.[jt]s$': '$1', + }, + testEnvironment: 'node', + maxWorkers: 1, + setupFilesAfterEnv: ['./jest.setup.after-env.ts'], + testPathIgnorePatterns: ['.history', 'node_modules'], + extensionsToTreatAsEsm: ['.ts'], + transform: { + '^.+\\.ts$': ['ts-jest', { + useESM: true, + injectGlobals: true + }] + } +}; diff --git a/playgrounds/jest/jest.setup.after-env.ts b/playgrounds/jest/jest.setup.after-env.ts new file mode 100644 index 000000000..c5d28d6b2 --- /dev/null +++ b/playgrounds/jest/jest.setup.after-env.ts @@ -0,0 +1,17 @@ +import { jest, beforeAll, afterAll, expect } from "@jest/globals"; +import { remote } from "webdriverio"; +import { config } from "./wdio.conf"; +import { wdioCustomMatchers } from "expect-webdriverio"; + +jest.setTimeout(30000); + +beforeAll(async () => { + // Add custom wdio matcher to Jest's expect + expect.extend(wdioCustomMatchers); + + globalThis.standalone = await remote(config); +}); + +afterAll(async () => { + await globalThis.standalone?.deleteSession(); +}); diff --git a/playgrounds/jest/package-lock.json b/playgrounds/jest/package-lock.json index cf9bbf7ad..4878f3928 100644 --- a/playgrounds/jest/package-lock.json +++ b/playgrounds/jest/package-lock.json @@ -10,21 +10,24 @@ "hasInstallScript": true, "devDependencies": { "@types/jest": "^30.0.0", - "@types/node": "^22.10.5", - "@wdio/cli": "^9.4.0", - "@wdio/globals": "^9.4.0", - "@wdio/local-runner": "^9.4.0", + "@types/node": "^24.12.0", + "@wdio/cli": "^9.25.0", + "@wdio/globals": "^9.23.0", + "@wdio/local-runner": "^9.25.0", "@wdio/mocha-framework": "^9.4.0", - "@wdio/spec-reporter": "^9.4.0", - "@wdio/visual-service": "^9.1.2", - "eslint": "^9.39.2", + "@wdio/spec-reporter": "^9.25.0", + "@wdio/visual-service": "^9.1.6", + "eslint": "^9.39.4", + "eslint-plugin-jest": "^29.15.0", "expect-webdriverio": "file:../..", + "jest": "^30.3.0", + "ts-jest": "^29.4.6", "ts-node": "^10.9.2", "typescript": "^5.9.3" } }, "../..": { - "version": "5.6.4", + "version": "5.6.5", "dev": true, "license": "MIT", "dependencies": { @@ -34,24 +37,24 @@ "jest-matcher-utils": "^30.2.0" }, "devDependencies": { - "@jest/globals": "^30.2.0", + "@jest/globals": "^30.3.0", "@types/debug": "^4.1.12", - "@types/jasmine": "^5.1.8", + "@types/jasmine": "^5.1.15", "@types/jest": "^30.0.0", "@types/mocha": "^10.0.10", - "@types/node": "^24.10.1", - "@vitest/coverage-v8": "^4.0.16", - "@wdio/eslint": "^0.1.2", - "@wdio/types": "^9.20.0", - "eslint": "^9.39.2", + "@types/node": "^24.12.0", + "@vitest/coverage-v8": "^4.1.0", + "@wdio/eslint": "^0.1.3", + "@wdio/types": "^9.25.0", + "eslint": "^9.39.4", "husky": "^9.1.7", "npm-run-all2": "^8.0.4", - "release-it": "^19.1.0", - "rimraf": "^6.1.2", + "release-it": "^19.2.4", + "rimraf": "^6.1.3", "shelljs": "^0.10.0", "typescript": "^5.9.3", - "vitest": "^4.0.16", - "webdriverio": "^9.21.0" + "vitest": "^4.1.0", + "webdriverio": "^9.25.0" }, "engines": { "node": ">=20" @@ -74,9 +77,9 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", - "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, "license": "MIT", "dependencies": { @@ -88,322 +91,613 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", - "cpu": [ - "arm" - ], + "node_modules/@babel/generator": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.0.tgz", + "integrity": "sha512-vSH118/wwM/pLR38g/Sgk05sNtro6TlTJKuiMXDaZqPUfjTFcudpCOt00IhOfj+1BFAX+UFAlzCU+6WXr3GLFQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", - "cpu": [ - "x64" - ], + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", - "cpu": [ - "arm" - ], + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", - "cpu": [ - "loong64" - ], + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", - "cpu": [ - "mips64el" - ], + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, "engines": { - "node": ">=18" + "node": ">=6.0.0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", - "cpu": [ - "riscv64" - ], + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-s390x": { + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@emnapi/core": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.0.tgz", + "integrity": "sha512-0DQ98G9ZQZOxfUcQn1waV2yS8aWdZ6kJMbYCJB3oUBecjWYO1fqJ+a1DRfPF3O5JEkwqwP1A9QEN/9mYm2Yd0w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.0.tgz", + "integrity": "sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz", + "integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", "cpu": [ - "s390x" + "ppc64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" + "aix" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/linux-x64": { + "node_modules/@esbuild/android-arm": { "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", "cpu": [ - "x64" + "arm" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" + "android" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/netbsd-arm64": { + "node_modules/@esbuild/android-arm64": { "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", "cpu": [ "arm64" ], @@ -411,16 +705,16 @@ "license": "MIT", "optional": true, "os": [ - "netbsd" + "android" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/netbsd-x64": { + "node_modules/@esbuild/android-x64": { "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", "cpu": [ "x64" ], @@ -428,16 +722,16 @@ "license": "MIT", "optional": true, "os": [ - "netbsd" + "android" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/openbsd-arm64": { + "node_modules/@esbuild/darwin-arm64": { "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", "cpu": [ "arm64" ], @@ -445,16 +739,16 @@ "license": "MIT", "optional": true, "os": [ - "openbsd" + "darwin" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/openbsd-x64": { + "node_modules/@esbuild/darwin-x64": { "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", "cpu": [ "x64" ], @@ -462,16 +756,16 @@ "license": "MIT", "optional": true, "os": [ - "openbsd" + "darwin" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/openharmony-arm64": { + "node_modules/@esbuild/freebsd-arm64": { "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", "cpu": [ "arm64" ], @@ -479,16 +773,16 @@ "license": "MIT", "optional": true, "os": [ - "openharmony" + "freebsd" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/sunos-x64": { + "node_modules/@esbuild/freebsd-x64": { "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", "cpu": [ "x64" ], @@ -496,209 +790,464 @@ "license": "MIT", "optional": true, "os": [ - "sunos" + "freebsd" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/win32-arm64": { + "node_modules/@esbuild/linux-arm": { "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", "cpu": [ - "arm64" + "arm" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/win32-ia32": { + "node_modules/@esbuild/linux-arm64": { "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", "cpu": [ - "ia32" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/win32-x64": { + "node_modules/@esbuild/linux-ia32": { "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", "cpu": [ - "x64" + "ia32" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": ">=18" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", - "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "cpu": [ + "loong64" + ], "dev": true, "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=18" } }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "cpu": [ + "mips64el" + ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@eslint/config-array": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", - "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "cpu": [ + "riscv64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.7", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "cpu": [ + "s390x" + ], "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "node_modules/@esbuild/linux-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "*" + "node": ">=18" } }, - "node_modules/@eslint/config-helpers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.17.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", - "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.1", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -709,9 +1258,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", - "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", "dev": true, "license": "MIT", "engines": { @@ -1196,1764 +1745,4310 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@jest/diff-sequences": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", - "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=8" } }, - "node_modules/@jest/expect-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", - "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/get-type": "30.1.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "sprintf-js": "~1.0.2" } }, - "node_modules/@jest/get-type": { - "version": "30.1.0", - "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", - "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, "license": "MIT", "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=6" } }, - "node_modules/@jest/pattern": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", - "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "jest-regex-util": "30.0.1" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=8" } }, - "node_modules/@jest/schemas": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", - "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, "license": "MIT", "dependencies": { - "@sinclair/typebox": "^0.34.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@jest/types": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", - "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "license": "MIT", "dependencies": { - "@jest/pattern": "30.0.1", - "@jest/schemas": "30.0.5", - "@types/istanbul-lib-coverage": "^2.0.6", - "@types/istanbul-reports": "^3.0.4", - "@types/node": "*", - "@types/yargs": "^17.0.33", - "chalk": "^4.1.2" + "p-locate": "^4.1.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=8" } }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "p-try": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=6" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/types/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "p-limit": "^2.2.0" }, "engines": { "node": ">=8" } }, - "node_modules/@jimp/core": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/core/-/core-1.6.0.tgz", - "integrity": "sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "license": "MIT", - "dependencies": { - "@jimp/file-ops": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "await-to-js": "^3.0.0", - "exif-parser": "^0.1.12", - "file-type": "^16.0.0", - "mime": "3" - }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@jimp/diff": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/diff/-/diff-1.6.0.tgz", - "integrity": "sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, "license": "MIT", - "dependencies": { - "@jimp/plugin-resize": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "pixelmatch": "^5.3.0" - }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@jimp/file-ops": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/file-ops/-/file-ops-1.6.0.tgz", - "integrity": "sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ==", + "node_modules/@jest/console": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.3.0.tgz", + "integrity": "sha512-PAwCvFJ4696XP2qZj+LAn1BWjZaJ6RjG6c7/lkMaUJnkyMS34ucuIsfqYvfskVNvUI27R/u4P1HMYFnlVXG/Ww==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/types": "30.3.0", + "@types/node": "*", + "chalk": "^4.1.2", + "jest-message-util": "30.3.0", + "jest-util": "30.3.0", + "slash": "^3.0.0" + }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jimp/js-bmp": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/js-bmp/-/js-bmp-1.6.0.tgz", - "integrity": "sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw==", + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "bmp-ts": "^1.0.9" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jimp/js-gif": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/js-gif/-/js-gif-1.6.0.tgz", - "integrity": "sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g==", + "node_modules/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "gifwrap": "^0.10.1", - "omggif": "^1.0.10" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@jimp/js-jpeg": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/js-jpeg/-/js-jpeg-1.6.0.tgz", - "integrity": "sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA==", + "node_modules/@jest/core": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.3.0.tgz", + "integrity": "sha512-U5mVPsBxLSO6xYbf+tgkymLx+iAhvZX43/xI1+ej2ZOPnPdkdO1CzDmFKh2mZBn2s4XZixszHeQnzp1gm/DIxw==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "jpeg-js": "^0.4.4" + "@jest/console": "30.3.0", + "@jest/pattern": "30.0.1", + "@jest/reporters": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-changed-files": "30.3.0", + "jest-config": "30.3.0", + "jest-haste-map": "30.3.0", + "jest-message-util": "30.3.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.3.0", + "jest-resolve-dependencies": "30.3.0", + "jest-runner": "30.3.0", + "jest-runtime": "30.3.0", + "jest-snapshot": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", + "jest-watcher": "30.3.0", + "pretty-format": "30.3.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@jimp/js-png": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/js-png/-/js-png-1.6.0.tgz", - "integrity": "sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==", + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "pngjs": "^7.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jimp/js-tiff": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/js-tiff/-/js-tiff-1.6.0.tgz", - "integrity": "sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw==", + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "utif2": "^4.1.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@jimp/plugin-blit": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-1.6.0.tgz", - "integrity": "sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA==", + "node_modules/@jest/diff-sequences": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.3.0.tgz", + "integrity": "sha512-cG51MVnLq1ecVUaQ3fr6YuuAOitHK1S4WUJHnsPFE/quQr33ADUx1FfrTCpMCRxvy0Yr9BThKpDjSlcTi91tMA==", "dev": true, "license": "MIT", - "dependencies": { - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "zod": "^3.23.8" - }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jimp/plugin-blur": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-1.6.0.tgz", - "integrity": "sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw==", + "node_modules/@jest/environment": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.3.0.tgz", + "integrity": "sha512-SlLSF4Be735yQXyh2+mctBOzNDx5s5uLv88/j8Qn1wH679PDcwy67+YdADn8NJnGjzlXtN62asGH/T4vWOkfaw==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/utils": "1.6.0" + "@jest/fake-timers": "30.3.0", + "@jest/types": "30.3.0", + "@types/node": "*", + "jest-mock": "30.3.0" }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jimp/plugin-circle": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-1.6.0.tgz", - "integrity": "sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw==", + "node_modules/@jest/expect": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.3.0.tgz", + "integrity": "sha512-76Nlh4xJxk2D/9URCn3wFi98d2hb19uWE1idLsTt2ywhvdOldbw3S570hBgn25P4ICUZ/cBjybrBex2g17IDbg==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/types": "1.6.0", - "zod": "^3.23.8" + "expect": "30.3.0", + "jest-snapshot": "30.3.0" }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jimp/plugin-color": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-1.6.0.tgz", - "integrity": "sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA==", + "node_modules/@jest/expect-utils": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.3.0.tgz", + "integrity": "sha512-j0+W5iQQ8hBh7tHZkTQv3q2Fh/M7Je72cIsYqC4OaktgtO7v1So9UTjp6uPBHIaB6beoF/RRsCgMJKvti0wADA==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "tinycolor2": "^1.6.0", - "zod": "^3.23.8" + "@jest/get-type": "30.1.0" }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jimp/plugin-contain": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-1.6.0.tgz", - "integrity": "sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ==", + "node_modules/@jest/fake-timers": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.3.0.tgz", + "integrity": "sha512-WUQDs8SOP9URStX1DzhD425CqbN/HxUYCTwVrT8sTVBfMvFqYt/s61EK5T05qnHu0po6RitXIvP9otZxYDzTGQ==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/plugin-blit": "1.6.0", - "@jimp/plugin-resize": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "zod": "^3.23.8" + "@jest/types": "30.3.0", + "@sinonjs/fake-timers": "^15.0.0", + "@types/node": "*", + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", + "jest-util": "30.3.0" }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jimp/plugin-cover": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-1.6.0.tgz", - "integrity": "sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA==", + "node_modules/@jest/get-type": { + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", + "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", "dev": true, "license": "MIT", - "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/plugin-crop": "1.6.0", - "@jimp/plugin-resize": "1.6.0", - "@jimp/types": "1.6.0", - "zod": "^3.23.8" - }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jimp/plugin-crop": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-1.6.0.tgz", - "integrity": "sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang==", + "node_modules/@jest/globals": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.3.0.tgz", + "integrity": "sha512-+owLCBBdfpgL3HU+BD5etr1SvbXpSitJK0is1kiYjJxAAJggYMRQz5hSdd5pq1sSggfxPbw2ld71pt4x5wwViA==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "zod": "^3.23.8" + "@jest/environment": "30.3.0", + "@jest/expect": "30.3.0", + "@jest/types": "30.3.0", + "jest-mock": "30.3.0" }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jimp/plugin-displace": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-1.6.0.tgz", - "integrity": "sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q==", + "node_modules/@jest/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "zod": "^3.23.8" + "@types/node": "*", + "jest-regex-util": "30.0.1" }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jimp/plugin-dither": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-1.6.0.tgz", - "integrity": "sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ==", + "node_modules/@jest/reporters": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.3.0.tgz", + "integrity": "sha512-a09z89S+PkQnL055bVj8+pe2Caed2PBOaczHcXCykW5ngxX9EWx/1uAwncxc/HiU0oZqfwseMjyhxgRjS49qPw==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/types": "1.6.0" + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", + "@jridgewell/trace-mapping": "^0.3.25", + "@types/node": "*", + "chalk": "^4.1.2", + "collect-v8-coverage": "^1.0.2", + "exit-x": "^0.2.2", + "glob": "^10.5.0", + "graceful-fs": "^4.2.11", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^5.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "30.3.0", + "jest-util": "30.3.0", + "jest-worker": "30.3.0", + "slash": "^3.0.0", + "string-length": "^4.0.2", + "v8-to-istanbul": "^9.0.1" }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@jimp/plugin-fisheye": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-1.6.0.tgz", - "integrity": "sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA==", + "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "zod": "^3.23.8" - }, - "engines": { - "node": ">=18" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jimp/plugin-flip": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-1.6.0.tgz", - "integrity": "sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg==", + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/types": "1.6.0", - "zod": "^3.23.8" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jimp/plugin-hash": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-hash/-/plugin-hash-1.6.0.tgz", - "integrity": "sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q==", + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/js-bmp": "1.6.0", - "@jimp/js-jpeg": "1.6.0", - "@jimp/js-png": "1.6.0", - "@jimp/js-tiff": "1.6.0", - "@jimp/plugin-color": "1.6.0", - "@jimp/plugin-resize": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "any-base": "^1.1.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@jimp/plugin-mask": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-1.6.0.tgz", - "integrity": "sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA==", + "node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/types": "1.6.0", - "zod": "^3.23.8" + "@sinclair/typebox": "^0.34.0" }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jimp/plugin-print": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-1.6.0.tgz", - "integrity": "sha512-zarTIJi8fjoGMSI/M3Xh5yY9T65p03XJmPsuNet19K/Q7mwRU6EV2pfj+28++2PV2NJ+htDF5uecAlnGyxFN2A==", + "node_modules/@jest/snapshot-utils": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.3.0.tgz", + "integrity": "sha512-ORbRN9sf5PP82v3FXNSwmO1OTDR2vzR2YTaR+E3VkSBZ8zadQE6IqYdYEeFH1NIkeB2HIGdF02dapb6K0Mj05g==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/js-jpeg": "1.6.0", - "@jimp/js-png": "1.6.0", - "@jimp/plugin-blit": "1.6.0", - "@jimp/types": "1.6.0", - "parse-bmfont-ascii": "^1.0.6", - "parse-bmfont-binary": "^1.0.6", - "parse-bmfont-xml": "^1.1.6", - "simple-xml-to-json": "^1.2.2", - "zod": "^3.23.8" + "@jest/types": "30.3.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jimp/plugin-quantize": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-quantize/-/plugin-quantize-1.6.0.tgz", - "integrity": "sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg==", + "node_modules/@jest/snapshot-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "image-q": "^4.0.0", - "zod": "^3.23.8" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jimp/plugin-resize": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-1.6.0.tgz", - "integrity": "sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA==", + "node_modules/@jest/snapshot-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/types": "1.6.0", - "zod": "^3.23.8" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@jimp/plugin-rotate": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-1.6.0.tgz", - "integrity": "sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw==", + "node_modules/@jest/source-map": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", + "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/plugin-crop": "1.6.0", - "@jimp/plugin-resize": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "zod": "^3.23.8" + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jimp/plugin-threshold": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-1.6.0.tgz", - "integrity": "sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==", + "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/core": "1.6.0", - "@jimp/plugin-color": "1.6.0", - "@jimp/plugin-hash": "1.6.0", - "@jimp/types": "1.6.0", - "@jimp/utils": "1.6.0", - "zod": "^3.23.8" - }, - "engines": { - "node": ">=18" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jimp/types": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/types/-/types-1.6.0.tgz", - "integrity": "sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==", + "node_modules/@jest/test-result": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.3.0.tgz", + "integrity": "sha512-e/52nJGuD74AKTSe0P4y5wFRlaXP0qmrS17rqOMHeSwm278VyNyXE3gFO/4DTGF9w+65ra3lo3VKj0LBrzmgdQ==", "dev": true, "license": "MIT", "dependencies": { - "zod": "^3.23.8" + "@jest/console": "30.3.0", + "@jest/types": "30.3.0", + "@types/istanbul-lib-coverage": "^2.0.6", + "collect-v8-coverage": "^1.0.2" }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jimp/utils": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-1.6.0.tgz", - "integrity": "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==", + "node_modules/@jest/test-sequencer": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.3.0.tgz", + "integrity": "sha512-dgbWy9b8QDlQeRZcv7LNF+/jFiiYHTKho1xirauZ7kVwY7avjFF6uTT0RqlgudB5OuIPagFdVtfFMosjVbk1eA==", "dev": true, "license": "MIT", "dependencies": { - "@jimp/types": "1.6.0", - "tinycolor2": "^1.6.0" + "@jest/test-result": "30.3.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.3.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@jest/transform": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.3.0.tgz", + "integrity": "sha512-TLKY33fSLVd/lKB2YI1pH69ijyUblO/BQvCj566YvnwuzoTNr648iE0j22vRvVNk2HsPwByPxATg3MleS3gf5A==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.3.0", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.1", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.3.0", + "jest-regex-util": "30.0.1", + "jest-util": "30.3.0", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, "engines": { - "node": ">=6.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", - "optional": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=14" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@promptbook/utils": { - "version": "0.69.5", - "resolved": "https://registry.npmjs.org/@promptbook/utils/-/utils-0.69.5.tgz", - "integrity": "sha512-xm5Ti/Hp3o4xHrsK9Yy3MS6KbDxYbq485hDsFvxqaNA7equHLPdo8H8faTitTeb14QCDfLW4iwCxdVYu5sn6YQ==", + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://buymeacoffee.com/hejny" - }, - { - "type": "github", - "url": "https://github.com/webgptorg/promptbook/blob/main/README.md#%EF%B8%8F-contributing" - } - ], - "license": "CC-BY-4.0", + "license": "MIT", "dependencies": { - "spacetrim": "0.11.59" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@puppeteer/browsers": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.11.1.tgz", - "integrity": "sha512-YmhAxs7XPuxN0j7LJloHpfD1ylhDuFmmwMvfy/+6nBSrETT2ycL53LrhgPtR+f+GcPSybQVuQ5inWWu5MrWCpA==", + "node_modules/@jest/types": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.3.0.tgz", + "integrity": "sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "debug": "^4.4.3", - "extract-zip": "^2.0.1", - "progress": "^2.0.3", - "proxy-agent": "^6.5.0", - "semver": "^7.7.3", - "tar-fs": "^3.1.1", - "yargs": "^17.7.2" - }, - "bin": { - "browsers": "lib/cjs/main-cli.js" + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, "engines": { - "node": ">=18" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/@sec-ant/readable-stream": { - "version": "0.4.1", + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jimp/core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-1.6.0.tgz", + "integrity": "sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/file-ops": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "await-to-js": "^3.0.0", + "exif-parser": "^0.1.12", + "file-type": "^16.0.0", + "mime": "3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/diff": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/diff/-/diff-1.6.0.tgz", + "integrity": "sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "pixelmatch": "^5.3.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/file-ops": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/file-ops/-/file-ops-1.6.0.tgz", + "integrity": "sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-bmp": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-bmp/-/js-bmp-1.6.0.tgz", + "integrity": "sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "bmp-ts": "^1.0.9" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-gif": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-gif/-/js-gif-1.6.0.tgz", + "integrity": "sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "gifwrap": "^0.10.1", + "omggif": "^1.0.10" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-jpeg": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-jpeg/-/js-jpeg-1.6.0.tgz", + "integrity": "sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "jpeg-js": "^0.4.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-png": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-png/-/js-png-1.6.0.tgz", + "integrity": "sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "pngjs": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-tiff": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/js-tiff/-/js-tiff-1.6.0.tgz", + "integrity": "sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "utif2": "^4.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-blit": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-1.6.0.tgz", + "integrity": "sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-blur": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-1.6.0.tgz", + "integrity": "sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/utils": "1.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-circle": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-1.6.0.tgz", + "integrity": "sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-color": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-1.6.0.tgz", + "integrity": "sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "tinycolor2": "^1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-contain": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-1.6.0.tgz", + "integrity": "sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/plugin-blit": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-cover": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-1.6.0.tgz", + "integrity": "sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/plugin-crop": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-crop": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-1.6.0.tgz", + "integrity": "sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-displace": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-1.6.0.tgz", + "integrity": "sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-dither": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-1.6.0.tgz", + "integrity": "sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-fisheye": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-1.6.0.tgz", + "integrity": "sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-flip": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-1.6.0.tgz", + "integrity": "sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-hash": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-hash/-/plugin-hash-1.6.0.tgz", + "integrity": "sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/js-bmp": "1.6.0", + "@jimp/js-jpeg": "1.6.0", + "@jimp/js-png": "1.6.0", + "@jimp/js-tiff": "1.6.0", + "@jimp/plugin-color": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "any-base": "^1.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-mask": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-1.6.0.tgz", + "integrity": "sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-print": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-1.6.0.tgz", + "integrity": "sha512-zarTIJi8fjoGMSI/M3Xh5yY9T65p03XJmPsuNet19K/Q7mwRU6EV2pfj+28++2PV2NJ+htDF5uecAlnGyxFN2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/js-jpeg": "1.6.0", + "@jimp/js-png": "1.6.0", + "@jimp/plugin-blit": "1.6.0", + "@jimp/types": "1.6.0", + "parse-bmfont-ascii": "^1.0.6", + "parse-bmfont-binary": "^1.0.6", + "parse-bmfont-xml": "^1.1.6", + "simple-xml-to-json": "^1.2.2", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-quantize": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-quantize/-/plugin-quantize-1.6.0.tgz", + "integrity": "sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "image-q": "^4.0.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-resize": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-1.6.0.tgz", + "integrity": "sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/types": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-rotate": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-1.6.0.tgz", + "integrity": "sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/plugin-crop": "1.6.0", + "@jimp/plugin-resize": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-threshold": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-1.6.0.tgz", + "integrity": "sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.0", + "@jimp/plugin-color": "1.6.0", + "@jimp/plugin-hash": "1.6.0", + "@jimp/types": "1.6.0", + "@jimp/utils": "1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/types": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-1.6.0.tgz", + "integrity": "sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.0", + "tinycolor2": "^1.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@promptbook/utils": { + "version": "0.69.5", + "resolved": "https://registry.npmjs.org/@promptbook/utils/-/utils-0.69.5.tgz", + "integrity": "sha512-xm5Ti/Hp3o4xHrsK9Yy3MS6KbDxYbq485hDsFvxqaNA7equHLPdo8H8faTitTeb14QCDfLW4iwCxdVYu5sn6YQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://buymeacoffee.com/hejny" + }, + { + "type": "github", + "url": "https://github.com/webgptorg/promptbook/blob/main/README.md#%EF%B8%8F-contributing" + } + ], + "license": "CC-BY-4.0", + "dependencies": { + "spacetrim": "0.11.59" + } + }, + "node_modules/@puppeteer/browsers": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.11.1.tgz", + "integrity": "sha512-YmhAxs7XPuxN0j7LJloHpfD1ylhDuFmmwMvfy/+6nBSrETT2ycL53LrhgPtR+f+GcPSybQVuQ5inWWu5MrWCpA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.4.3", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.5.0", + "semver": "^7.7.3", + "tar-fs": "^3.1.1", + "yargs": "^17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", "dev": true, - "license": "MIT" + "license": "MIT" + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.48", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.48.tgz", + "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.1.1.tgz", + "integrity": "sha512-cO5W33JgAPbOh07tvZjUOJ7oWhtaqGHiZw+11DPbyqh2kHTBc3eF/CjJDeQ4205RLQsX6rxCuYOroFQwl7JDRw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", + "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^30.0.0", + "pretty-format": "^30.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mocha": { + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", + "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz", + "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/node/node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/which/-/which-2.0.2.tgz", + "integrity": "sha512-113D3mDkZDjo+EeUEHCFy0qniNc1ZpecGiAU7WSo7YDoSzolZIQKpYFHrPpjkB2nuyahcKfrmLXeQlh7gqJYdw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.57.0.tgz", + "integrity": "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.57.0", + "@typescript-eslint/types": "^8.57.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.57.0.tgz", + "integrity": "sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.57.0.tgz", + "integrity": "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.57.0.tgz", + "integrity": "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.57.0.tgz", + "integrity": "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.57.0", + "@typescript-eslint/tsconfig-utils": "8.57.0", + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.57.0.tgz", + "integrity": "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.57.0", + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/typescript-estree": "8.57.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.57.0.tgz", + "integrity": "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.57.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vitest/pretty-format": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", + "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz", + "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.9", + "magic-string": "^0.30.12", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@wdio/cli": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-9.25.0.tgz", + "integrity": "sha512-7m6Au8U0Fz+/n6vlchxHd5ogYESjz2XEYVnmcqnDapCAUo570Ilb86Muz69AFrBiZ6D+xkesQTwlWOdNRjIY1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/snapshot": "^2.1.1", + "@wdio/config": "9.25.0", + "@wdio/globals": "9.23.0", + "@wdio/logger": "9.18.0", + "@wdio/protocols": "9.25.0", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", + "async-exit-hook": "^2.0.1", + "chalk": "^5.4.1", + "chokidar": "^4.0.0", + "create-wdio": "9.25.0", + "dotenv": "^17.2.0", + "import-meta-resolve": "^4.0.0", + "lodash.flattendeep": "^4.4.0", + "lodash.pickby": "^4.6.0", + "lodash.union": "^4.6.0", + "read-pkg-up": "^10.0.0", + "tsx": "^4.7.2", + "webdriverio": "9.25.0", + "yargs": "^17.7.2" + }, + "bin": { + "wdio": "bin/wdio.js" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/cli/node_modules/@types/node": { + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@wdio/cli/node_modules/@wdio/types": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.25.0.tgz", + "integrity": "sha512-ovSEcUBLz6gVDIsBZYKQXz8EGU37jS8sqbmlOe5+jB4XbsTBCyTLjQK/rO7LWQAKJcs0vBq+Pd+VrlsFtA7tTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^20.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/cli/node_modules/@wdio/utils": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-9.25.0.tgz", + "integrity": "sha512-w/ej8gZkc2tZr8L91ATyA1AWrbPDYDOvblQ7r+zt1uPRobuA4H98GME7Zm7i3FIP695BvV4G35Gcs5NssZW1pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@puppeteer/browsers": "^2.2.0", + "@wdio/logger": "9.18.0", + "@wdio/types": "9.25.0", + "decamelize": "^6.0.0", + "deepmerge-ts": "^7.0.3", + "edgedriver": "^6.1.2", + "geckodriver": "^6.1.0", + "get-port": "^7.0.0", + "import-meta-resolve": "^4.0.0", + "locate-app": "^2.2.24", + "mitt": "^3.0.1", + "safaridriver": "^1.0.0", + "split2": "^4.2.0", + "wait-port": "^1.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/config": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-9.25.0.tgz", + "integrity": "sha512-EWa7l1rrbSNthCRDpdBw7ESAa1/jAjSsWCGkaVAO0HMOGlQjzvYI6gNi4KUeymnurDZ2IPr0jr+f9We6AWi6QA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@wdio/logger": "9.18.0", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", + "deepmerge-ts": "^7.0.3", + "glob": "^10.2.2", + "import-meta-resolve": "^4.0.0", + "jiti": "^2.6.1" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/config/node_modules/@types/node": { + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@wdio/config/node_modules/@wdio/types": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.25.0.tgz", + "integrity": "sha512-ovSEcUBLz6gVDIsBZYKQXz8EGU37jS8sqbmlOe5+jB4XbsTBCyTLjQK/rO7LWQAKJcs0vBq+Pd+VrlsFtA7tTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^20.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/config/node_modules/@wdio/utils": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-9.25.0.tgz", + "integrity": "sha512-w/ej8gZkc2tZr8L91ATyA1AWrbPDYDOvblQ7r+zt1uPRobuA4H98GME7Zm7i3FIP695BvV4G35Gcs5NssZW1pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@puppeteer/browsers": "^2.2.0", + "@wdio/logger": "9.18.0", + "@wdio/types": "9.25.0", + "decamelize": "^6.0.0", + "deepmerge-ts": "^7.0.3", + "edgedriver": "^6.1.2", + "geckodriver": "^6.1.0", + "get-port": "^7.0.0", + "import-meta-resolve": "^4.0.0", + "locate-app": "^2.2.24", + "mitt": "^3.0.1", + "safaridriver": "^1.0.0", + "split2": "^4.2.0", + "wait-port": "^1.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/dot-reporter": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/dot-reporter/-/dot-reporter-9.25.0.tgz", + "integrity": "sha512-yFlyHfCJOERWIgiFzbyliCr6YxEYZDM3rykCHmpIlbAOwATxjIh26fvkKI8/23LDqMybym8Pn/Yjj/W78/KgIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@wdio/reporter": "9.25.0", + "@wdio/types": "9.25.0", + "chalk": "^5.0.1" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/dot-reporter/node_modules/@types/node": { + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@wdio/dot-reporter/node_modules/@wdio/types": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.25.0.tgz", + "integrity": "sha512-ovSEcUBLz6gVDIsBZYKQXz8EGU37jS8sqbmlOe5+jB4XbsTBCyTLjQK/rO7LWQAKJcs0vBq+Pd+VrlsFtA7tTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^20.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/globals": { + "version": "9.23.0", + "resolved": "https://registry.npmjs.org/@wdio/globals/-/globals-9.23.0.tgz", + "integrity": "sha512-OmwPKV8c5ecLqo+EkytN7oUeYfNmRI4uOXGIR1ybP7AK5Zz+l9R0dGfoadEuwi1aZXAL0vwuhtq3p0OL3dfqHQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.20.0" + }, + "peerDependencies": { + "expect-webdriverio": "^5.3.4", + "webdriverio": "^9.0.0" + }, + "peerDependenciesMeta": { + "expect-webdriverio": { + "optional": false + }, + "webdriverio": { + "optional": false + } + } + }, + "node_modules/@wdio/image-comparison-core": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@wdio/image-comparison-core/-/image-comparison-core-1.1.4.tgz", + "integrity": "sha512-WUT+YmzPj4nWSuWACuuKqJXDYAZd4Od3Up+6hRAI1ZA5yV+KEcT8yb7taWY1hjWHqlbCjbuJUaQD80u/7ToqDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@wdio/logger": "^9.18.0", + "@wdio/types": "^9.20.0", + "jimp": "^1.6.0" + } + }, + "node_modules/@wdio/local-runner": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-9.25.0.tgz", + "integrity": "sha512-E6pEeQouVLle19Gk55Y/JxPGMzT2jhmHS80yjT3g481Q1EML9y8m3T6UMemAUnz70FGneP0aCcuFKJdmkF9dKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^20.1.0", + "@wdio/logger": "9.18.0", + "@wdio/repl": "9.16.2", + "@wdio/runner": "9.25.0", + "@wdio/types": "9.25.0", + "@wdio/xvfb": "9.25.0", + "exit-hook": "^4.0.0", + "expect-webdriverio": "^5.3.4", + "split2": "^4.1.0", + "stream-buffers": "^3.0.2" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/local-runner/node_modules/@types/node": { + "version": "20.19.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", + "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@wdio/local-runner/node_modules/@wdio/types": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.25.0.tgz", + "integrity": "sha512-ovSEcUBLz6gVDIsBZYKQXz8EGU37jS8sqbmlOe5+jB4XbsTBCyTLjQK/rO7LWQAKJcs0vBq+Pd+VrlsFtA7tTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^20.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/logger": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-9.18.0.tgz", + "integrity": "sha512-HdzDrRs+ywAqbXGKqe1i/bLtCv47plz4TvsHFH3j729OooT5VH38ctFn5aLXgECmiAKDkmH/A6kOq2Zh5DIxww==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.1.2", + "loglevel": "^1.6.0", + "loglevel-plugin-prefix": "^0.8.4", + "safe-regex2": "^5.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/mocha-framework": { + "version": "9.23.2", + "resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-9.23.2.tgz", + "integrity": "sha512-V1wx8A8vMAExricXlCv0jzQOJTAgvgM/646QFr65U028+lqAGU23EkFp5H1WJj9I9jCHJTfMkxtUrPv0v7y63A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mocha": "^10.0.6", + "@types/node": "^20.11.28", + "@wdio/logger": "9.18.0", + "@wdio/types": "9.23.2", + "@wdio/utils": "9.23.2", + "mocha": "^10.3.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/mocha-framework/node_modules/@types/node": { + "version": "20.19.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", + "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@wdio/protocols": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-9.25.0.tgz", + "integrity": "sha512-PErbZqdpFmE69bRuku3OR34Ro2xuZNNLXYFOcJnjXJVzf5+ApDyGHYrMlvhtrrSy9/55LUybk851ppjS+3RoDA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@wdio/repl": { + "version": "9.16.2", + "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-9.16.2.tgz", + "integrity": "sha512-FLTF0VL6+o5BSTCO7yLSXocm3kUnu31zYwzdsz4n9s5YWt83sCtzGZlZpt7TaTzb3jVUfxuHNQDTb8UMkCu0lQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^20.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/repl/node_modules/@types/node": { + "version": "20.19.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", + "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@wdio/reporter": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-9.25.0.tgz", + "integrity": "sha512-zmyjr7/EoGwlmrICNzhRL3k0dlJoqdQShzHd5l8V1axYsaC3UHGy2oNDXwKD/OjhEThJsGHxwjyUDkKYhbZdCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^20.1.0", + "@wdio/logger": "9.18.0", + "@wdio/types": "9.25.0", + "diff": "^8.0.2", + "object-inspect": "^1.12.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/reporter/node_modules/@types/node": { + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@wdio/reporter/node_modules/@wdio/types": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.25.0.tgz", + "integrity": "sha512-ovSEcUBLz6gVDIsBZYKQXz8EGU37jS8sqbmlOe5+jB4XbsTBCyTLjQK/rO7LWQAKJcs0vBq+Pd+VrlsFtA7tTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^20.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/runner": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-9.25.0.tgz", + "integrity": "sha512-Oe7NnFWJICF5g+LGLVWi3x41aL2ZRto3bOQZlBjNnGFRkx+BPz7qHdENueflfh7VCX9o3qRns6cQ3CEuurLaNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^20.11.28", + "@wdio/config": "9.25.0", + "@wdio/dot-reporter": "9.25.0", + "@wdio/globals": "9.23.0", + "@wdio/logger": "9.18.0", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", + "deepmerge-ts": "^7.0.3", + "webdriver": "9.25.0", + "webdriverio": "9.25.0" + }, + "engines": { + "node": ">=18.20.0" + }, + "peerDependencies": { + "expect-webdriverio": "^5.3.4", + "webdriverio": "^9.0.0" + }, + "peerDependenciesMeta": { + "expect-webdriverio": { + "optional": false + }, + "webdriverio": { + "optional": false + } + } + }, + "node_modules/@wdio/runner/node_modules/@types/node": { + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@wdio/runner/node_modules/@wdio/types": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.25.0.tgz", + "integrity": "sha512-ovSEcUBLz6gVDIsBZYKQXz8EGU37jS8sqbmlOe5+jB4XbsTBCyTLjQK/rO7LWQAKJcs0vBq+Pd+VrlsFtA7tTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^20.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/runner/node_modules/@wdio/utils": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-9.25.0.tgz", + "integrity": "sha512-w/ej8gZkc2tZr8L91ATyA1AWrbPDYDOvblQ7r+zt1uPRobuA4H98GME7Zm7i3FIP695BvV4G35Gcs5NssZW1pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@puppeteer/browsers": "^2.2.0", + "@wdio/logger": "9.18.0", + "@wdio/types": "9.25.0", + "decamelize": "^6.0.0", + "deepmerge-ts": "^7.0.3", + "edgedriver": "^6.1.2", + "geckodriver": "^6.1.0", + "get-port": "^7.0.0", + "import-meta-resolve": "^4.0.0", + "locate-app": "^2.2.24", + "mitt": "^3.0.1", + "safaridriver": "^1.0.0", + "split2": "^4.2.0", + "wait-port": "^1.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/spec-reporter": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-9.25.0.tgz", + "integrity": "sha512-15+YnhnXDW7dAJ4PP+qZ2imAbVcMMSwewtjVrKRWK0OsMASXRXka/zV3jViRp1Rf+WCGp76HMxhv7YOygfE68A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@wdio/reporter": "9.25.0", + "@wdio/types": "9.25.0", + "chalk": "^5.1.2", + "easy-table": "^1.2.0", + "pretty-ms": "^9.0.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/spec-reporter/node_modules/@types/node": { + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@wdio/spec-reporter/node_modules/@wdio/types": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.25.0.tgz", + "integrity": "sha512-ovSEcUBLz6gVDIsBZYKQXz8EGU37jS8sqbmlOe5+jB4XbsTBCyTLjQK/rO7LWQAKJcs0vBq+Pd+VrlsFtA7tTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^20.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/types": { + "version": "9.23.2", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.23.2.tgz", + "integrity": "sha512-ryfrERGsNp+aCcrTE1rFU6cbmDj8GHZ04R9k52KNt2u1a6bv3Eh5A/cUA0hXuMdEUfsc8ePLYdwQyOLFydZ0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^20.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/types/node_modules/@types/node": { + "version": "20.19.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", + "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@wdio/utils": { + "version": "9.23.2", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-9.23.2.tgz", + "integrity": "sha512-+QfgXUWeA940AXT5l5UlrBKoHBk9GLSQE3BA+7ra1zWuFvv6SHG6M2mwplcPlOlymJMqXy8e7ZgLEoLkXuvC1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@puppeteer/browsers": "^2.2.0", + "@wdio/logger": "9.18.0", + "@wdio/types": "9.23.2", + "decamelize": "^6.0.0", + "deepmerge-ts": "^7.0.3", + "edgedriver": "^6.1.2", + "geckodriver": "^6.1.0", + "get-port": "^7.0.0", + "import-meta-resolve": "^4.0.0", + "locate-app": "^2.2.24", + "mitt": "^3.0.1", + "safaridriver": "^1.0.0", + "split2": "^4.2.0", + "wait-port": "^1.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/visual-service": { + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/@wdio/visual-service/-/visual-service-9.1.6.tgz", + "integrity": "sha512-oQIzo0I6kX/IV7rferoLllf8vnTtDOHpbdBMeio8+fsJqC39eKOpWp1+fiGyByrO9zF0GMJELM/r76ZiEeV+qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@wdio/globals": "^9.23.0", + "@wdio/image-comparison-core": "1.1.4", + "@wdio/logger": "^9.18.0", + "@wdio/types": "^9.20.0", + "expect-webdriverio": "^5.6.1" + } + }, + "node_modules/@wdio/xvfb": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/xvfb/-/xvfb-9.25.0.tgz", + "integrity": "sha512-qbsdWm1sP5CGikz3n3dwoVGqbRyBsERGzckDMsQeQ9QVTG6OsNOm4KiVejdiwdPXqDjLUnBv8xGtfuFrftFwcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@wdio/logger": "9.18.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@zip.js/zip.js": { + "version": "2.8.15", + "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.8.15.tgz", + "integrity": "sha512-HZKJLFe4eGVgCe9J87PnijY7T1Zn638bEHS+Fm/ygHZozRpefzWcOYfPaP52S8pqk9g4xN3+LzMDl3Lv9dLglA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "bun": ">=0.7.0", + "deno": ">=1.0.0", + "node": ">=18.0.0" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv/node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } }, - "node_modules/@sinclair/typebox": { - "version": "0.34.48", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.48.tgz", - "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==", + "node_modules/any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==", "dev": true, "license": "MIT" }, - "node_modules/@sindresorhus/merge-streams": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", - "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/archiver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", + "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", "dev": true, "license": "MIT", + "dependencies": { + "archiver-utils": "^5.0.2", + "async": "^3.2.4", + "buffer-crc32": "^1.0.0", + "readable-stream": "^4.0.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^3.0.0", + "zip-stream": "^6.0.1" + }, "engines": { - "node": ">=18" + "node": ">= 14" + } + }, + "node_modules/archiver-utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", + "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^10.0.0", + "graceful-fs": "^4.2.0", + "is-stream": "^2.0.1", + "lazystream": "^1.0.0", + "lodash": "^4.17.15", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/archiver-utils/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true, "license": "MIT" }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, - "license": "MIT" + "license": "Python-2.0" }, - "node_modules/@tsconfig/node10": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", - "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "dev": true, "license": "MIT" }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "node_modules/await-to-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-3.0.0.tgz", + "integrity": "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "node_modules/b4a": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", + "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "node_modules/babel-jest": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.3.0.tgz", + "integrity": "sha512-gRpauEU2KRrCox5Z296aeVHR4jQ98BCnu0IO332D/xpHNOsIH/bgSRk9k6GbKIbBw8vFeN6ctuu6tV8WOyVfYQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/istanbul-lib-coverage": "*" + "@jest/transform": "30.3.0", + "@types/babel__core": "^7.20.5", + "babel-plugin-istanbul": "^7.0.1", + "babel-preset-jest": "30.3.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0 || ^8.0.0-0" } }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "@types/istanbul-lib-report": "*" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@types/jest": { - "version": "30.0.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", - "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz", + "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==", + "dev": true, + "license": "BSD-3-Clause", + "workspaces": [ + "test/babel-8" + ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.3.0.tgz", + "integrity": "sha512-+TRkByhsws6sfPjVaitzadk1I0F5sPvOVUH5tyTSzhePpsGIVrdeunHSw/C36QeocS95OOk8lunc4rlu5Anwsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/babel__core": "^7.20.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.3.0.tgz", + "integrity": "sha512-6ZcUbWHC+dMz2vfzdNwi87Z1gQsLNK2uLuK1Q89R11xdvejcivlYYwDlEv0FHX3VwEXpbBQ9uufB/MUNpZGfhQ==", "dev": true, "license": "MIT", "dependencies": { - "expect": "^30.0.0", - "pretty-format": "^30.0.0" + "babel-plugin-jest-hoist": "30.3.0", + "babel-preset-current-node-syntax": "^1.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0 || ^8.0.0-beta.1" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, "license": "MIT" }, - "node_modules/@types/mocha": { - "version": "10.0.10", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", - "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", + "node_modules/bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } }, - "node_modules/@types/node": { - "version": "22.19.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.7.tgz", - "integrity": "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==", + "node_modules/bare-fs": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.3.tgz", + "integrity": "sha512-9+kwVx8QYvt3hPWnmb19tPnh38c6Nihz8Lx3t0g9+4GoIf3/fTgYwM4Z6NxgI+B9elLQA7mLE9PpqcWtOMRDiQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "undici-types": "~6.21.0" + "bare-events": "^2.5.4", + "bare-path": "^3.0.0", + "bare-stream": "^2.6.4", + "bare-url": "^2.2.2", + "fast-fifo": "^1.3.2" + }, + "engines": { + "bare": ">=1.16.0" + }, + "peerDependencies": { + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + } } }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "node_modules/bare-os": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.2.tgz", + "integrity": "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "optional": true, + "engines": { + "bare": ">=1.14.0" + } }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", - "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", + "node_modules/bare-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", + "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-os": "^3.0.1" + } }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "node_modules/bare-stream": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.7.0.tgz", + "integrity": "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "streamx": "^2.21.0" + }, + "peerDependencies": { + "bare-buffer": "*", + "bare-events": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + }, + "bare-events": { + "optional": true + } + } }, - "node_modules/@types/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/which/-/which-2.0.2.tgz", - "integrity": "sha512-113D3mDkZDjo+EeUEHCFy0qniNc1ZpecGiAU7WSo7YDoSzolZIQKpYFHrPpjkB2nuyahcKfrmLXeQlh7gqJYdw==", + "node_modules/bare-url": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.3.2.tgz", + "integrity": "sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-path": "^3.0.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT" }, - "node_modules/@types/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "node_modules/baseline-browser-mapping": { + "version": "2.9.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", + "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/basic-ftp": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.0.tgz", + "integrity": "sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==", "dev": true, "license": "MIT", - "dependencies": { - "@types/node": "*" + "engines": { + "node": ">=10.0.0" } }, - "node_modules/@types/yargs": { - "version": "17.0.35", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", - "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "node_modules/bmp-ts": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bmp-ts/-/bmp-ts-1.0.9.tgz", + "integrity": "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==", "dev": true, "license": "MIT" }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } + "license": "ISC" }, - "node_modules/@vitest/pretty-format": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", - "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "balanced-match": "^1.0.0" } }, - "node_modules/@vitest/snapshot": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz", - "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.9", - "magic-string": "^0.30.12", - "pathe": "^1.1.2" + "fill-range": "^7.1.1" }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": ">=8" } }, - "node_modules/@wdio/cli": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-9.23.2.tgz", - "integrity": "sha512-D6KZGomfNmjFhSWYdfR7Ojik5qWEpPoR4g5LQPzbFwiii/RkTudLcMFcCO6s7HTMLDQDWryOStV2KK6KqrIF8A==", + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/snapshot": "^2.1.1", - "@wdio/config": "9.23.2", - "@wdio/globals": "9.23.0", - "@wdio/logger": "9.18.0", - "@wdio/protocols": "9.23.2", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", - "async-exit-hook": "^2.0.1", - "chalk": "^5.4.1", - "chokidar": "^4.0.0", - "create-wdio": "9.21.0", - "dotenv": "^17.2.0", - "import-meta-resolve": "^4.0.0", - "lodash.flattendeep": "^4.4.0", - "lodash.pickby": "^4.6.0", - "lodash.union": "^4.6.0", - "read-pkg-up": "^10.0.0", - "tsx": "^4.7.2", - "webdriverio": "9.23.2", - "yargs": "^17.7.2" + "license": "ISC" + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" }, "bin": { - "wdio": "bin/wdio.js" + "browserslist": "cli.js" }, "engines": { - "node": ">=18.20.0" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/@wdio/config": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-9.23.2.tgz", - "integrity": "sha512-19Z+AIQ1NUpr6ncTumjSthm6A7c3DbaGTp+VCdcyN+vHYOK4WsWIomSk+uSbFosYFQVGRjCaHaeGSnC8GNPGYQ==", + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", "dev": true, "license": "MIT", "dependencies": { - "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", - "deepmerge-ts": "^7.0.3", - "glob": "^10.2.2", - "import-meta-resolve": "^4.0.0" + "fast-json-stable-stringify": "2.x" }, "engines": { - "node": ">=18.20.0" + "node": ">= 6" } }, - "node_modules/@wdio/dot-reporter": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/dot-reporter/-/dot-reporter-9.23.2.tgz", - "integrity": "sha512-3+5y7P4GS7UTIgr6zPhxKHMmDSwiNjgdwnWIUYXr2eQLcpnPGhc9GL1IEDgQEAcziXG9BfaKzZQHi+vH89PR5w==", + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT", "dependencies": { - "@wdio/reporter": "9.23.2", - "@wdio/types": "9.23.2", - "chalk": "^5.0.1" - }, + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=18.20.0" + "node": ">=8.0.0" } }, - "node_modules/@wdio/globals": { - "version": "9.23.0", - "resolved": "https://registry.npmjs.org/@wdio/globals/-/globals-9.23.0.tgz", - "integrity": "sha512-OmwPKV8c5ecLqo+EkytN7oUeYfNmRI4uOXGIR1ybP7AK5Zz+l9R0dGfoadEuwi1aZXAL0vwuhtq3p0OL3dfqHQ==", + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=18.20.0" - }, - "peerDependencies": { - "expect-webdriverio": "^5.3.4", - "webdriverio": "^9.0.0" + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" }, - "peerDependenciesMeta": { - "expect-webdriverio": { - "optional": false + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001767", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001767.tgz", + "integrity": "sha512-34+zUAMhSH+r+9eKmYG+k2Rpt8XttfE4yXAjoZvkAPs15xcYQhyBYdalJ65BzivAvGRMViEjy6oKr/S91loekQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" }, - "webdriverio": { - "optional": false + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@wdio/image-comparison-core": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@wdio/image-comparison-core/-/image-comparison-core-1.1.2.tgz", - "integrity": "sha512-Wvm4iGwONoWlcw7xMGl4UxNYj6aqqrQJXMAJlNik4bpubiGKIVa0NRG05kRVqn8UvOwS1CHfd/9xdXw5a+1DAA==", + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true, "license": "MIT", - "dependencies": { - "@wdio/logger": "^9.18.0", - "@wdio/types": "^9.20.0", - "jimp": "^1.6.0" + "engines": { + "node": ">=10" } }, - "node_modules/@wdio/local-runner": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-9.23.2.tgz", - "integrity": "sha512-tS8l2iaQc5aQav2LYYXx296F9KpdrU4/dmw5t9n9baXgdu8CKyGEd9orhTFQ7fYR55wFJ/85toQNOvIQHtIZrA==", + "node_modules/chardet": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", + "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cheerio": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz", + "integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "^20.1.0", - "@wdio/logger": "9.18.0", - "@wdio/repl": "9.16.2", - "@wdio/runner": "9.23.2", - "@wdio/types": "9.23.2", - "@wdio/xvfb": "9.23.2", - "exit-hook": "^4.0.0", - "expect-webdriverio": "^5.3.4", - "split2": "^4.1.0", - "stream-buffers": "^3.0.2" + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.1", + "htmlparser2": "^10.1.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.19.0", + "whatwg-mimetype": "^4.0.0" }, "engines": { - "node": ">=18.20.0" + "node": ">=20.18.1" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" } }, - "node_modules/@wdio/local-runner/node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "undici-types": "~6.21.0" + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/@wdio/logger": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-9.18.0.tgz", - "integrity": "sha512-HdzDrRs+ywAqbXGKqe1i/bLtCv47plz4TvsHFH3j729OooT5VH38ctFn5aLXgECmiAKDkmH/A6kOq2Zh5DIxww==", + "node_modules/cheerio/node_modules/undici": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.19.1.tgz", + "integrity": "sha512-Gpq0iNm5M6cQWlyHQv9MV+uOj1jWk7LpkoE5vSp/7zjb4zMdAcUD+VL5y0nH4p9EbUklq00eVIIX/XcDHzu5xg==", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^5.1.2", - "loglevel": "^1.6.0", - "loglevel-plugin-prefix": "^0.8.4", - "safe-regex2": "^5.0.0", - "strip-ansi": "^7.1.0" - }, "engines": { - "node": ">=18.20.0" + "node": ">=20.18.1" } }, - "node_modules/@wdio/mocha-framework": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-9.23.2.tgz", - "integrity": "sha512-V1wx8A8vMAExricXlCv0jzQOJTAgvgM/646QFr65U028+lqAGU23EkFp5H1WJj9I9jCHJTfMkxtUrPv0v7y63A==", + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", "dependencies": { - "@types/mocha": "^10.0.6", - "@types/node": "^20.11.28", - "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", - "mocha": "^10.3.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">=18.20.0" + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@wdio/mocha-framework/node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "node_modules/ci-info": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" + "engines": { + "node": ">=8" } }, - "node_modules/@wdio/protocols": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-9.23.2.tgz", - "integrity": "sha512-pmCYOYI2N89QCC8IaiHwaWyP0mR8T1iKkEGpoTq2XVihp7VK/lfPvieyeZT5/e28MadYLJsDQ603pbu5J1NRDg==", + "node_modules/cjs-module-lexer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", "dev": true, "license": "MIT" }, - "node_modules/@wdio/repl": { - "version": "9.16.2", - "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-9.16.2.tgz", - "integrity": "sha512-FLTF0VL6+o5BSTCO7yLSXocm3kUnu31zYwzdsz4n9s5YWt83sCtzGZlZpt7TaTzb3jVUfxuHNQDTb8UMkCu0lQ==", + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@types/node": "^20.1.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=18.20.0" + "node": ">=12" } }, - "node_modules/@wdio/repl/node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } + "license": "MIT" }, - "node_modules/@wdio/reporter": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-9.23.2.tgz", - "integrity": "sha512-+L1knNyQl+Xs+/VkM5JOX/HINe+g3ZVWt0Scsb9DcOCll8xG8jisxArutZLo+UuV6Bm1BzqfJJb/+ae04EuRAQ==", + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "^20.1.0", - "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", - "diff": "^8.0.2", - "object-inspect": "^1.12.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=18.20.0" + "node": ">=8" } }, - "node_modules/@wdio/reporter/node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@wdio/runner": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-9.23.2.tgz", - "integrity": "sha512-joFHYO4jnDixsBRM6tJ/nVeH15UNIthIAp2Yky+yPsh1HkM+x9gZG5ZT0TnSXw/E2tQRb2yO3d+jsEHedsE0jw==", + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "^20.11.28", - "@wdio/config": "9.23.2", - "@wdio/dot-reporter": "9.23.2", - "@wdio/globals": "9.23.0", - "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", - "deepmerge-ts": "^7.0.3", - "webdriver": "9.23.2", - "webdriverio": "9.23.2" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=18.20.0" - }, - "peerDependencies": { - "expect-webdriverio": "^5.3.4", - "webdriverio": "^9.0.0" + "node": ">=10" }, - "peerDependenciesMeta": { - "expect-webdriverio": { - "optional": false - }, - "webdriverio": { - "optional": false - } + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@wdio/runner/node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" + "optional": true, + "engines": { + "node": ">=0.8" } }, - "node_modules/@wdio/spec-reporter": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-9.23.2.tgz", - "integrity": "sha512-9uwbrOFgPuF5NqixiU9db46HNJERN04beefNh4f4usJSP41Mbru0isps64qKkWSpFJhYl1LZrSGELezxH9bZ6A==", + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, "license": "MIT", - "dependencies": { - "@wdio/reporter": "9.23.2", - "@wdio/types": "9.23.2", - "chalk": "^5.1.2", - "easy-table": "^1.2.0", - "pretty-ms": "^9.0.0" - }, "engines": { - "node": ">=18.20.0" + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" } }, - "node_modules/@wdio/types": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.23.2.tgz", - "integrity": "sha512-ryfrERGsNp+aCcrTE1rFU6cbmDj8GHZ04R9k52KNt2u1a6bv3Eh5A/cUA0hXuMdEUfsc8ePLYdwQyOLFydZ0ig==", + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "^20.1.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=18.20.0" + "node": ">=7.0.0" } }, - "node_modules/@wdio/types/node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } + "license": "MIT" }, - "node_modules/@wdio/utils": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-9.23.2.tgz", - "integrity": "sha512-+QfgXUWeA940AXT5l5UlrBKoHBk9GLSQE3BA+7ra1zWuFvv6SHG6M2mwplcPlOlymJMqXy8e7ZgLEoLkXuvC1Q==", + "node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", "dev": true, "license": "MIT", - "dependencies": { - "@puppeteer/browsers": "^2.2.0", - "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", - "decamelize": "^6.0.0", - "deepmerge-ts": "^7.0.3", - "edgedriver": "^6.1.2", - "geckodriver": "^6.1.0", - "get-port": "^7.0.0", - "import-meta-resolve": "^4.0.0", - "locate-app": "^2.2.24", - "mitt": "^3.0.1", - "safaridriver": "^1.0.0", - "split2": "^4.2.0", - "wait-port": "^1.1.0" - }, "engines": { - "node": ">=18.20.0" + "node": ">=20" } }, - "node_modules/@wdio/visual-service": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@wdio/visual-service/-/visual-service-9.1.2.tgz", - "integrity": "sha512-FYyv4kXWqm4LmX62VwC/uR0khRFlSmvUVDyyKWLiIMdzQGiXLYOotxGs5E/wQcHHZPPv+/1wWFJLoE3w1rWt+w==", + "node_modules/compress-commons": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", + "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", "dev": true, "license": "MIT", "dependencies": { - "@wdio/globals": "^9.23.0", - "@wdio/image-comparison-core": "1.1.2", - "@wdio/logger": "^9.18.0", - "@wdio/types": "^9.20.0", - "expect-webdriverio": "^5.6.1" + "crc-32": "^1.2.0", + "crc32-stream": "^6.0.0", + "is-stream": "^2.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" } }, - "node_modules/@wdio/xvfb": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/xvfb/-/xvfb-9.23.2.tgz", - "integrity": "sha512-48KiET6Phmu7SIQgpTXSn7eRJK6MJdTKib2MLT5WTKIJ+t0OyGKl/ESXi6tzFrGFPzLkvogSIRy8O2sKM0PcbA==", + "node_modules/compress-commons/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, "license": "MIT", - "dependencies": { - "@wdio/logger": "9.18.0" - }, "engines": { - "node": ">=18" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@zip.js/zip.js": { - "version": "2.8.15", - "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.8.15.tgz", - "integrity": "sha512-HZKJLFe4eGVgCe9J87PnijY7T1Zn638bEHS+Fm/ygHZozRpefzWcOYfPaP52S8pqk9g4xN3+LzMDl3Lv9dLglA==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "bun": ">=0.7.0", - "deno": ">=1.0.0", - "node": ">=18.0.0" - } + "license": "MIT" }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } + "license": "MIT" }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "license": "Apache-2.0", "bin": { - "acorn": "bin/acorn" + "crc32": "bin/crc32.njs" }, "engines": { - "node": ">=0.4.0" + "node": ">=0.8" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/crc32-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", + "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", "dev": true, "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" } }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-wdio": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/create-wdio/-/create-wdio-9.25.0.tgz", + "integrity": "sha512-ZnkJVDx3HB7UNH2t1kxK1VoNWQAQhLYyTjSEdpcFTHoj/QUrzS7K9nW99Q6WT0mgsedbtl86VMq4IXfy6f8Jrw==", "dev": true, "license": "MIT", "dependencies": { - "acorn": "^8.11.0" + "chalk": "^5.3.0", + "commander": "^14.0.0", + "cross-spawn": "^7.0.3", + "ejs": "^3.1.10", + "execa": "^9.6.0", + "import-meta-resolve": "^4.1.0", + "inquirer": "^12.7.0", + "normalize-package-data": "^7.0.0", + "read-pkg-up": "^10.1.0", + "recursive-readdir": "^2.2.3", + "semver": "^7.6.3", + "type-fest": "^4.41.0", + "yargs": "^17.7.2" + }, + "bin": { + "create-wdio": "bin/wdio.js" }, "engines": { - "node": ">=0.4.0" + "node": ">=12.0.0" } }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, "engines": { - "node": ">= 14" + "node": ">= 8" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/ajv/node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "node_modules/css-shorthand-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/css-shorthand-properties/-/css-shorthand-properties-1.1.2.tgz", + "integrity": "sha512-C2AugXIpRGQTxaCW0N7n5jD/p5irUmCrwl03TrnMFBHDbdq44CFWR2zO7rK9xPN4Eo3pUxC4vQzQgbIpzrD1PQ==", "dev": true, "license": "MIT" }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "node_modules/css-value": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", + "integrity": "sha512-FUV3xaJ63buRLgHrLQVlVgQnQdR4yqdLGaDu7g8CQcWjInDfM9plBTPI9FRfpahju1UBSaMckeb2/46ApS/V1Q==", + "dev": true + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "engines": { - "node": ">=6" + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 14" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "ms": "^2.1.3" }, "engines": { - "node": ">=8" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.1.tgz", + "integrity": "sha512-G7Cqgaelq68XHJNGlZ7lrNQyhZGsFqpwtGFexqUv4IQdjKoSYF7ipZ9UuTJZUSQXFj/XaoBLuEVIVqr8EJngEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/any-base": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", - "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==", + "node_modules/dedent": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, "license": "MIT" }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, + "license": "MIT", "engines": { - "node": ">= 8" + "node": ">=0.10.0" } }, - "node_modules/archiver": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", - "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "archiver-utils": "^5.0.2", - "async": "^3.2.4", - "buffer-crc32": "^1.0.0", - "readable-stream": "^4.0.0", - "readdir-glob": "^1.1.2", - "tar-stream": "^3.0.0", - "zip-stream": "^6.0.1" + "clone": "^1.0.2" }, - "engines": { - "node": ">= 14" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/archiver-utils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", - "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", "dev": true, "license": "MIT", "dependencies": { - "glob": "^10.0.0", - "graceful-fs": "^4.2.0", - "is-stream": "^2.0.1", - "lazystream": "^1.0.0", - "lodash": "^4.17.15", - "normalize-path": "^3.0.0", - "readable-stream": "^4.0.0" + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" }, "engines": { "node": ">= 14" } }, - "node_modules/archiver-utils/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, "license": "MIT", "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "node_modules/diff": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz", + "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", "dev": true, - "license": "Apache-2.0", + "license": "BSD-3-Clause", "engines": { - "node": ">= 0.4" + "node": ">=0.3.1" } }, - "node_modules/ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.0.1" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "dev": true, - "license": "MIT" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" }, - "node_modules/async-exit-hook": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", - "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, "engines": { - "node": ">=0.12.0" + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/await-to-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-3.0.0.tgz", - "integrity": "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==", + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/b4a": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", - "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", + "node_modules/dotenv": { + "version": "17.2.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", + "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", "dev": true, - "license": "Apache-2.0", - "peerDependencies": { - "react-native-b4a": "*" + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" }, - "peerDependenciesMeta": { - "react-native-b4a": { - "optional": true - } + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true, "license": "MIT" }, - "node_modules/bare-events": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", - "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "node_modules/easy-table": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.2.0.tgz", + "integrity": "sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww==", "dev": true, - "license": "Apache-2.0", - "peerDependencies": { - "bare-abort-controller": "*" + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" }, - "peerDependenciesMeta": { - "bare-abort-controller": { - "optional": true - } + "optionalDependencies": { + "wcwidth": "^1.0.1" } }, - "node_modules/bare-fs": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.3.tgz", - "integrity": "sha512-9+kwVx8QYvt3hPWnmb19tPnh38c6Nihz8Lx3t0g9+4GoIf3/fTgYwM4Z6NxgI+B9elLQA7mLE9PpqcWtOMRDiQ==", + "node_modules/edge-paths": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/edge-paths/-/edge-paths-3.0.5.tgz", + "integrity": "sha512-sB7vSrDnFa4ezWQk9nZ/n0FdpdUuC6R1EOrlU3DL+bovcNFK28rqu2emmAUjujYEJTWIgQGqgVVWUZXMnc8iWg==", "dev": true, - "license": "Apache-2.0", - "optional": true, + "license": "MIT", "dependencies": { - "bare-events": "^2.5.4", - "bare-path": "^3.0.0", - "bare-stream": "^2.6.4", - "bare-url": "^2.2.2", - "fast-fifo": "^1.3.2" + "@types/which": "^2.0.1", + "which": "^2.0.2" }, "engines": { - "bare": ">=1.16.0" - }, - "peerDependencies": { - "bare-buffer": "*" + "node": ">=14.0.0" }, - "peerDependenciesMeta": { - "bare-buffer": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/shirshak55" } }, - "node_modules/bare-os": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.2.tgz", - "integrity": "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==", + "node_modules/edgedriver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/edgedriver/-/edgedriver-6.3.0.tgz", + "integrity": "sha512-ggEQL+oEyIcM4nP2QC3AtCQ04o4kDNefRM3hja0odvlPSnsaxiruMxEZ93v3gDCKWYW6BXUr51PPradb+3nffw==", "dev": true, - "license": "Apache-2.0", - "optional": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@wdio/logger": "^9.18.0", + "@zip.js/zip.js": "^2.8.11", + "decamelize": "^6.0.1", + "edge-paths": "^3.0.5", + "fast-xml-parser": "^5.3.3", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "which": "^6.0.0" + }, + "bin": { + "edgedriver": "bin/edgedriver.js" + }, "engines": { - "bare": ">=1.14.0" + "node": ">=20.0.0" } }, - "node_modules/bare-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", - "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", + "node_modules/edgedriver/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-os": "^3.0.1" + "license": "ISC", + "engines": { + "node": ">=16" } }, - "node_modules/bare-stream": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.7.0.tgz", - "integrity": "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==", + "node_modules/edgedriver/node_modules/which": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz", + "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==", "dev": true, - "license": "Apache-2.0", - "optional": true, + "license": "ISC", "dependencies": { - "streamx": "^2.21.0" + "isexe": "^3.1.1" }, - "peerDependencies": { - "bare-buffer": "*", - "bare-events": "*" + "bin": { + "node-which": "bin/which.js" }, - "peerDependenciesMeta": { - "bare-buffer": { - "optional": true - }, - "bare-events": { - "optional": true - } + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/bare-url": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.3.2.tgz", - "integrity": "sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==", + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, "license": "Apache-2.0", - "optional": true, "dependencies": { - "bare-path": "^3.0.0" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/basic-ftp": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.0.tgz", - "integrity": "sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==", - "dev": true, - "license": "MIT", + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, "engines": { - "node": ">=10.0.0" + "node": ">=0.10.0" } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "node_modules/electron-to-chromium": { + "version": "1.5.286", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", + "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/bmp-ts": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/bmp-ts/-/bmp-ts-1.0.9.tgz", - "integrity": "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==", + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, "license": "MIT" }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true, - "license": "ISC" - }, - "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/encoding-sniffer/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", "dependencies": { - "fill-range": "^7.1.1" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "is-arrayish": "^0.2.1" } }, - "node_modules/buffer-crc32": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", - "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "node_modules/esbuild": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", "dev": true, + "hasInstallScript": true, "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, "engines": { - "node": ">=8.0.0" + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", "engines": { @@ -2963,605 +6058,686 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "optionalDependencies": { + "source-map": "~0.6.1" } }, - "node_modules/chardet": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", - "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cheerio": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz", - "integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==", + "node_modules/eslint": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.2.2", - "encoding-sniffer": "^0.2.1", - "htmlparser2": "^10.1.0", - "parse5": "^7.3.0", - "parse5-htmlparser2-tree-adapter": "^7.1.0", - "parse5-parser-stream": "^7.1.2", - "undici": "^7.19.0", - "whatwg-mimetype": "^4.0.0" + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" }, - "engines": { - "node": ">=20.18.1" + "bin": { + "eslint": "bin/eslint.js" }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, - "node_modules/cheerio/node_modules/undici": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.19.1.tgz", - "integrity": "sha512-Gpq0iNm5M6cQWlyHQv9MV+uOj1jWk7LpkoE5vSp/7zjb4zMdAcUD+VL5y0nH4p9EbUklq00eVIIX/XcDHzu5xg==", + "node_modules/eslint-plugin-jest": { + "version": "29.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.15.0.tgz", + "integrity": "sha512-ZCGr7vTH2WSo2hrK5oM2RULFmMruQ7W3cX7YfwoTiPfzTGTFBMmrVIz45jZHd++cGKj/kWf02li/RhTGcANJSA==", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.0.0" + }, "engines": { - "node": ">=20.18.1" + "node": "^20.12.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "jest": "*", + "typescript": ">=4.8.4 <6.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + }, + "typescript": { + "optional": true + } } }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "readdirp": "^4.0.1" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 14.16.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://opencollective.com/eslint" } }, - "node_modules/ci-info": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", - "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "license": "ISC", - "engines": { - "node": ">= 12" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "node_modules/eslint/node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, "license": "MIT" }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=8" + "node": ">=10.13.0" } }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "ansi-regex": "^5.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" + "has-flag": "^4.0.0" }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "license": "MIT", - "optional": true, "engines": { - "node": ">=0.8" + "node": ">=8" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "color-name": "~1.1.4" + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": ">=7.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/commander": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", - "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, "engines": { - "node": ">=20" + "node": ">=4" } }, - "node_modules/compress-commons": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", - "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "crc-32": "^1.2.0", - "crc32-stream": "^6.0.0", - "is-stream": "^2.0.1", - "normalize-path": "^3.0.0", - "readable-stream": "^4.0.0" + "estraverse": "^5.1.0" }, "engines": { - "node": ">= 14" - } - }, - "node_modules/compress-commons/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "Apache-2.0", - "bin": { - "crc32": "bin/crc32.njs" + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" }, "engines": { - "node": ">=0.8" + "node": ">=4.0" } }, - "node_modules/crc32-stream": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", - "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "MIT", - "dependencies": { - "crc-32": "^1.2.0", - "readable-stream": "^4.0.0" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">= 14" + "node": ">=4.0" } }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "license": "MIT" + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/create-wdio": { - "version": "9.21.0", - "resolved": "https://registry.npmjs.org/create-wdio/-/create-wdio-9.21.0.tgz", - "integrity": "sha512-L6gsQLArY3AH5uTGpf3VfUezIsmZKufkF3ixSWqCuA/m458YVKeGghu1bBOWBdDIzqa6GX4e29dv0uVam0CTpw==", + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "commander": "^14.0.0", - "cross-spawn": "^7.0.3", - "ejs": "^3.1.10", - "execa": "^9.6.0", - "import-meta-resolve": "^4.1.0", - "inquirer": "^12.7.0", - "normalize-package-data": "^7.0.0", - "read-pkg-up": "^10.1.0", - "recursive-readdir": "^2.2.3", - "semver": "^7.6.3", - "type-fest": "^4.41.0", - "yargs": "^17.7.2" - }, - "bin": { - "create-wdio": "bin/wdio.js" - }, "engines": { - "node": ">=12.0.0" + "node": ">=6" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, "engines": { - "node": ">= 8" + "node": ">=0.8.x" } }, - "node_modules/css-select": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", - "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", "dev": true, - "license": "BSD-2-Clause", + "license": "Apache-2.0", "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "bare-events": "^2.7.0" } }, - "node_modules/css-shorthand-properties": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/css-shorthand-properties/-/css-shorthand-properties-1.1.2.tgz", - "integrity": "sha512-C2AugXIpRGQTxaCW0N7n5jD/p5irUmCrwl03TrnMFBHDbdq44CFWR2zO7rK9xPN4Eo3pUxC4vQzQgbIpzrD1PQ==", + "node_modules/execa": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", + "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.6", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.1", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.2.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": "^18.19.0 || >=20.5.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } }, - "node_modules/css-value": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/css-value/-/css-value-0.0.1.tgz", - "integrity": "sha512-FUV3xaJ63buRLgHrLQVlVgQnQdR4yqdLGaDu7g8CQcWjInDfM9plBTPI9FRfpahju1UBSaMckeb2/46ApS/V1Q==", + "node_modules/exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==", "dev": true }, - "node_modules/css-what": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", - "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "node_modules/exit-hook": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-4.0.0.tgz", + "integrity": "sha512-Fqs7ChZm72y40wKjOFXBKg7nJZvQJmewP5/7LtePDdnah/+FH9Hp5sgMujSCMPXlxOAW2//1jrW9pnsY7o20vQ==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "engines": { - "node": ">= 6" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/data-uri-to-buffer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", - "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "node_modules/exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 14" + "node": ">= 0.8.0" } }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/expect": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.3.0.tgz", + "integrity": "sha512-1zQrciTiQfRdo7qJM1uG4navm8DayFa2TgCSRlzUyNkhcJ6XUZF3hjnpkyr3VhAqPH7i/9GkG7Tv5abz6fqz0Q==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "@jest/expect-utils": "30.3.0", + "@jest/get-type": "30.1.0", + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", + "jest-util": "30.3.0" }, "engines": { - "node": ">=6.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/expect-webdriverio": { + "resolved": "../..", + "link": true + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" } }, - "node_modules/decamelize": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.1.tgz", - "integrity": "sha512-G7Cqgaelq68XHJNGlZ7lrNQyhZGsFqpwtGFexqUv4IQdjKoSYF7ipZ9UuTJZUSQXFj/XaoBLuEVIVqr8EJngEQ==", + "node_modules/extract-zip/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "node_modules/fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", "dev": true, "license": "MIT" }, - "node_modules/deepmerge-ts": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", - "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-xml-parser": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.3.3.tgz", + "integrity": "sha512-2O3dkPAAC6JavuMm8+4+pgTk+5hoAs+CjZ+sWcQLkX9+/tHRuTkQh/Oaifr8qDmZ8iEHb771Ea6G8CdwkrgvYA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^2.1.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=16.0.0" + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" } }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "pend": "~1.2.0" } }, - "node_modules/degenerator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", - "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", "dev": true, "license": "MIT", "dependencies": { - "ast-types": "^0.13.4", - "escodegen": "^2.1.0", - "esprima": "^4.0.1" + "is-unicode-supported": "^2.0.0" }, "engines": { - "node": ">= 14" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/diff": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz", - "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, "engines": { - "node": ">=0.3.1" + "node": ">=16.0.0" } }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "node_modules/file-type": { + "version": "16.5.4", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", + "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", "dev": true, "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.2.4", + "token-types": "^4.1.1" + }, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "url": "https://github.com/sindresorhus/file-type?sponsor=1" } }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "node_modules/filelist": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, - "license": "BSD-2-Clause", + "license": "ISC", "dependencies": { - "domelementtype": "^2.3.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "node": ">=10" } }, - "node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" + "to-regex-range": "^5.0.1" }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "engines": { + "node": ">=8" } }, - "node_modules/dotenv": { - "version": "17.2.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", - "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://dotenvx.com" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } }, - "node_modules/easy-table": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.2.0.tgz", - "integrity": "sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww==", + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, - "optionalDependencies": { - "wcwidth": "^1.0.1" + "engines": { + "node": ">=16" } }, - "node_modules/edge-paths": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/edge-paths/-/edge-paths-3.0.5.tgz", - "integrity": "sha512-sB7vSrDnFa4ezWQk9nZ/n0FdpdUuC6R1EOrlU3DL+bovcNFK28rqu2emmAUjujYEJTWIgQGqgVVWUZXMnc8iWg==", + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true, - "license": "MIT", + "license": "ISC" + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", "dependencies": { - "@types/which": "^2.0.1", - "which": "^2.0.2" + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/shirshak55" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/edgedriver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/edgedriver/-/edgedriver-6.3.0.tgz", - "integrity": "sha512-ggEQL+oEyIcM4nP2QC3AtCQ04o4kDNefRM3hja0odvlPSnsaxiruMxEZ93v3gDCKWYW6BXUr51PPradb+3nffw==", + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/geckodriver": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-6.1.0.tgz", + "integrity": "sha512-ZRXLa4ZaYTTgUO4Eefw+RsQCleugU2QLb1ME7qTYxxuRj51yAhfnXaItXNs5/vUzfIaDHuZ+YnSF005hfp07nQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -3569,658 +6745,608 @@ "@wdio/logger": "^9.18.0", "@zip.js/zip.js": "^2.8.11", "decamelize": "^6.0.1", - "edge-paths": "^3.0.5", - "fast-xml-parser": "^5.3.3", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.6", - "which": "^6.0.0" - }, - "bin": { - "edgedriver": "bin/edgedriver.js" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/edgedriver/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16" - } - }, - "node_modules/edgedriver/node_modules/which": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz", - "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" + "modern-tar": "^0.7.2" }, "bin": { - "node-which": "bin/which.js" + "geckodriver": "bin/geckodriver.js" }, "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=20.0.0" } }, - "node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, - "license": "MIT" + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } }, - "node_modules/encoding-sniffer": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", - "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, "license": "MIT", - "dependencies": { - "iconv-lite": "^0.6.3", - "whatwg-encoding": "^3.1.1" - }, - "funding": { - "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + "engines": { + "node": ">=8.0.0" } }, - "node_modules/encoding-sniffer/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "node_modules/get-port": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.1.0.tgz", + "integrity": "sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==", "dev": true, "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", "dev": true, "license": "MIT", "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, "engines": { - "node": ">=0.12" + "node": ">=18" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", "dev": true, "license": "MIT", "dependencies": { - "is-arrayish": "^0.2.1" + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "node_modules/get-uri": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", + "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", "dev": true, - "hasInstallScript": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4" }, "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.2", - "@esbuild/android-arm": "0.27.2", - "@esbuild/android-arm64": "0.27.2", - "@esbuild/android-x64": "0.27.2", - "@esbuild/darwin-arm64": "0.27.2", - "@esbuild/darwin-x64": "0.27.2", - "@esbuild/freebsd-arm64": "0.27.2", - "@esbuild/freebsd-x64": "0.27.2", - "@esbuild/linux-arm": "0.27.2", - "@esbuild/linux-arm64": "0.27.2", - "@esbuild/linux-ia32": "0.27.2", - "@esbuild/linux-loong64": "0.27.2", - "@esbuild/linux-mips64el": "0.27.2", - "@esbuild/linux-ppc64": "0.27.2", - "@esbuild/linux-riscv64": "0.27.2", - "@esbuild/linux-s390x": "0.27.2", - "@esbuild/linux-x64": "0.27.2", - "@esbuild/netbsd-arm64": "0.27.2", - "@esbuild/netbsd-x64": "0.27.2", - "@esbuild/openbsd-arm64": "0.27.2", - "@esbuild/openbsd-x64": "0.27.2", - "@esbuild/openharmony-arm64": "0.27.2", - "@esbuild/sunos-x64": "0.27.2", - "@esbuild/win32-arm64": "0.27.2", - "@esbuild/win32-ia32": "0.27.2", - "@esbuild/win32-x64": "0.27.2" + "node": ">= 14" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/gifwrap": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz", + "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "image-q": "^4.0.0", + "omggif": "^1.0.10" } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "BSD-2-Clause", + "license": "ISC", "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" + "node": ">= 6" } }, - "node_modules/eslint": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", - "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.1", - "@eslint/config-helpers": "^0.4.2", - "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.2", - "@eslint/plugin-kit": "^0.4.1", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" }, "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT" + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=0.4.7" }, - "funding": { - "url": "https://opencollective.com/eslint" + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=8" } }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "bin": { + "he": "bin/he" } }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/hosted-git-info": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.1.0.tgz", + "integrity": "sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "lru-cache": "^10.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/eslint/node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true, "license": "MIT" }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/htmlfy": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/htmlfy/-/htmlfy-0.8.1.tgz", + "integrity": "sha512-xWROBw9+MEGwxpotll0h672KCaLrKKiCYzsyN8ZgL9cQbVumFnyvsk2JqiB9ELAV1GLj1GG/jxZUjV9OZZi/yQ==", "dev": true, - "license": "ISC", + "license": "MIT" + }, + "node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", "dependencies": { - "is-glob": "^4.0.3" - }, + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=10.13.0" + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": "*" + "node": ">= 14" } }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "agent-base": "^7.1.2", + "debug": "4" }, "engines": { - "node": ">=8" + "node": ">= 14" } }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "node_modules/human-signals": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", + "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", "dev": true, - "license": "BSD-2-Clause", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "dev": true, + "license": "MIT", "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=0.10.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" }, - "node_modules/esquery": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, + "license": "MIT", "engines": { - "node": ">=0.10" + "node": ">= 4" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/image-q": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz", + "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" + "@types/node": "16.9.1" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/image-q/node_modules/@types/node": { + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", + "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==", + "dev": true, + "license": "MIT" + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, "engines": { - "node": ">=4.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.8.x" + "node": ">=0.8.19" } }, - "node_modules/events-universal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", - "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, - "license": "Apache-2.0", + "license": "ISC", "dependencies": { - "bare-events": "^2.7.0" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/execa": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", - "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/inquirer": { + "version": "12.11.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.11.1.tgz", + "integrity": "sha512-9VF7mrY+3OmsAfjH3yKz/pLbJ5z22E23hENKw3/LNSaA/sAt3v49bDRY+Ygct1xwuKT+U+cBfTzjCPySna69Qw==", "dev": true, "license": "MIT", "dependencies": { - "@sindresorhus/merge-streams": "^4.0.0", - "cross-spawn": "^7.0.6", - "figures": "^6.1.0", - "get-stream": "^9.0.0", - "human-signals": "^8.0.1", - "is-plain-obj": "^4.1.0", - "is-stream": "^4.0.1", - "npm-run-path": "^6.0.0", - "pretty-ms": "^9.2.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^4.0.0", - "yoctocolors": "^2.1.1" + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/prompts": "^7.10.1", + "@inquirer/type": "^3.0.10", + "mute-stream": "^2.0.0", + "run-async": "^4.0.6", + "rxjs": "^7.8.2" }, "engines": { - "node": "^18.19.0 || >=20.5.0" + "node": ">=18" }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/exif-parser": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", - "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==", - "dev": true - }, - "node_modules/exit-hook": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-4.0.0.tgz", - "integrity": "sha512-Fqs7ChZm72y40wKjOFXBKg7nJZvQJmewP5/7LtePDdnah/+FH9Hp5sgMujSCMPXlxOAW2//1jrW9pnsY7o20vQ==", + "node_modules/ip-address": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 12" } }, - "node_modules/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "30.2.0", - "@jest/get-type": "30.1.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" + "binary-extensions": "^2.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=8" } }, - "node_modules/expect-webdriverio": { - "resolved": "../..", - "link": true - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, + "license": "MIT", "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" + "node": ">=0.10.0" } }, - "node_modules/extract-zip/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } }, - "node_modules/fast-xml-parser": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.3.3.tgz", - "integrity": "sha512-2O3dkPAAC6JavuMm8+4+pgTk+5hoAs+CjZ+sWcQLkX9+/tHRuTkQh/Oaifr8qDmZ8iEHb771Ea6G8CdwkrgvYA==", + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], "license": "MIT", - "dependencies": { - "strnum": "^2.1.0" + "engines": { + "node": ">=12" }, - "bin": { - "fxparser": "src/cli/cli.js" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", "dev": true, "license": "MIT", - "dependencies": { - "pend": "~1.2.0" + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/figures": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", - "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", "dev": true, "license": "MIT", - "dependencies": { - "is-unicode-supported": "^2.0.0" - }, "engines": { "node": ">=18" }, @@ -4228,766 +7354,1013 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "flat-cache": "^4.0.0" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, "engines": { - "node": ">=16.0.0" + "node": ">=10" } }, - "node_modules/file-type": { - "version": "16.5.4", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", - "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "readable-web-to-node-stream": "^3.0.0", - "strtok3": "^6.2.4", - "token-types": "^4.1.1" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" } }, - "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "minimatch": "^5.0.1" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", "dev": true, - "license": "ISC", + "license": "BSD-3-Clause", "dependencies": { - "brace-expansion": "^2.0.1" + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" }, "engines": { "node": ">=10" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/istanbul-lib-source-maps/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" + "@isaacs/cliui": "^8.0.2" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", "dev": true, - "license": "BSD-3-Clause", + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, "bin": { - "flat": "cli.js" + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "node_modules/jest": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.3.0.tgz", + "integrity": "sha512-AkXIIFcaazymvey2i/+F94XRnM6TsVLZDhBMLsd1Sf/W0wzsvvpjeyUrCZD6HGG4SDYPgDJDBKeiJTBb10WzMg==", "dev": true, "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" + "@jest/core": "30.3.0", + "@jest/types": "30.3.0", + "import-local": "^3.2.0", + "jest-cli": "30.3.0" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">=16" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "node_modules/jest-changed-files": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.3.0.tgz", + "integrity": "sha512-B/7Cny6cV5At6M25EWDgf9S617lHivamL8vl6KEpJqkStauzcG4e+WPfDgMMF+H4FVH4A2PLRyvgDJan4441QA==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "execa": "^5.1.1", + "jest-util": "30.3.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "node_modules/jest-changed-files/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">=14" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "node_modules/jest-changed-files/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, - "license": "ISC" + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/jest-changed-files/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/jest-changed-files/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, - "hasInstallScript": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/geckodriver": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-6.1.0.tgz", - "integrity": "sha512-ZRXLa4ZaYTTgUO4Eefw+RsQCleugU2QLb1ME7qTYxxuRj51yAhfnXaItXNs5/vUzfIaDHuZ+YnSF005hfp07nQ==", + "node_modules/jest-changed-files/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, - "hasInstallScript": true, "license": "MIT", "dependencies": { - "@wdio/logger": "^9.18.0", - "@zip.js/zip.js": "^2.8.11", - "decamelize": "^6.0.1", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.6", - "modern-tar": "^0.7.2" - }, - "bin": { - "geckodriver": "bin/geckodriver.js" + "path-key": "^3.0.0" }, "engines": { - "node": ">=20.0.0" + "node": ">=8" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/jest-changed-files/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, - "license": "ISC", + "license": "ISC" + }, + "node_modules/jest-changed-files/node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=6" } }, - "node_modules/get-port": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.1.0.tgz", - "integrity": "sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==", + "node_modules/jest-circus": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.3.0.tgz", + "integrity": "sha512-PyXq5szeSfR/4f1lYqCmmQjh0vqDkURUYi9N6whnHjlRz4IUQfMcXkGLeEoiJtxtyPqgUaUUfyQlApXWBSN1RA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=16" + "dependencies": { + "@jest/environment": "30.3.0", + "@jest/expect": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/types": "30.3.0", + "@types/node": "*", + "chalk": "^4.1.2", + "co": "^4.6.0", + "dedent": "^1.6.0", + "is-generator-fn": "^2.1.0", + "jest-each": "30.3.0", + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-runtime": "30.3.0", + "jest-snapshot": "30.3.0", + "jest-util": "30.3.0", + "p-limit": "^3.1.0", + "pretty-format": "30.3.0", + "pure-rand": "^7.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/get-stream": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", - "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "@sec-ant/readable-stream": "^0.4.1", - "is-stream": "^4.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/get-tsconfig": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", - "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "node_modules/jest-circus/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { - "resolve-pkg-maps": "^1.0.0" + "has-flag": "^4.0.0" }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "engines": { + "node": ">=8" } }, - "node_modules/get-uri": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", - "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", + "node_modules/jest-cli": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.3.0.tgz", + "integrity": "sha512-l6Tqx+j1fDXJEW5bqYykDQQ7mQg+9mhWXtnj+tQZrTWYHyHoi6Be8HPumDSA+UiX2/2buEgjA58iJzdj146uCw==", "dev": true, "license": "MIT", "dependencies": { - "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^6.0.2", - "debug": "^4.3.4" + "@jest/core": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/types": "30.3.0", + "chalk": "^4.1.2", + "exit-x": "^0.2.2", + "import-local": "^3.2.0", + "jest-config": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", + "yargs": "^17.7.2" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">= 14" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/gifwrap": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz", - "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==", + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "image-q": "^4.0.0", - "omggif": "^1.0.10" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "has-flag": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=8" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/jest-config": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.3.0.tgz", + "integrity": "sha512-WPMAkMAtNDY9P/oKObtsRG/6KTrhtgPJoBTmk20uDn4Uy6/3EJnnaZJre/FMT1KVRx8cve1r7/FlMIOfRVWL4w==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "@babel/core": "^7.27.4", + "@jest/get-type": "30.1.0", + "@jest/pattern": "30.0.1", + "@jest/test-sequencer": "30.3.0", + "@jest/types": "30.3.0", + "babel-jest": "30.3.0", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "deepmerge": "^4.3.1", + "glob": "^10.5.0", + "graceful-fs": "^4.2.11", + "jest-circus": "30.3.0", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.3.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.3.0", + "jest-runner": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", + "parse-json": "^5.2.0", + "pretty-format": "30.3.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">= 6" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "esbuild-register": ">=3.4.0", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "esbuild-register": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "node_modules/jest-config/node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "node_modules/jest-config/node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true, "license": "MIT" }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/jest-config/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "node_modules/jest-config/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", - "bin": { - "he": "bin/he" + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/hosted-git-info": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.1.0.tgz", - "integrity": "sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==", + "node_modules/jest-diff": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.3.0.tgz", + "integrity": "sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "lru-cache": "^10.0.1" + "@jest/diff-sequences": "30.3.0", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.3.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/htmlfy": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/htmlfy/-/htmlfy-0.8.1.tgz", - "integrity": "sha512-xWROBw9+MEGwxpotll0h672KCaLrKKiCYzsyN8ZgL9cQbVumFnyvsk2JqiB9ELAV1GLj1GG/jxZUjV9OZZi/yQ==", + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } }, - "node_modules/htmlparser2": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", - "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.2.2", - "entities": "^7.0.1" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", - "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "node_modules/jest-docblock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz", + "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", + "dependencies": { + "detect-newline": "^3.1.0" + }, "engines": { - "node": ">=0.12" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-each": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.3.0.tgz", + "integrity": "sha512-V8eMndg/aZ+3LnCJgSm13IxS5XSBM22QSZc9BtPK8Dek6pm+hfUNfwBdvsB3d342bo1q7wnSkC38zjX259qZNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "@jest/types": "30.3.0", + "chalk": "^4.1.2", + "jest-util": "30.3.0", + "pretty-format": "30.3.0" }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 14" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "node_modules/jest-each/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 14" + "node": ">=8" } }, - "node_modules/human-signals": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", - "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", + "node_modules/jest-environment-node": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.3.0.tgz", + "integrity": "sha512-4i6HItw/JSiJVsC5q0hnKIe/hbYfZLVG9YJ/0pU9Hz2n/9qZe3Rhn5s5CUZA5ORZlcdT/vmAXRMyONXJwPrmYQ==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "@jest/environment": "30.3.0", + "@jest/fake-timers": "30.3.0", + "@jest/types": "30.3.0", + "@types/node": "*", + "jest-mock": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0" + }, "engines": { - "node": ">=18.18.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "node_modules/jest-haste-map": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.3.0.tgz", + "integrity": "sha512-mMi2oqG4KRU0R9QEtscl87JzMXfUhbKaFqOxmjb2CKcbHcUGFrJCBWHmnTiUqi6JcnzoBlO4rWfpdl2k/RfLCA==", "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "@jest/types": "30.3.0", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.3.0", + "jest-worker": "30.3.0", + "picomatch": "^4.0.3", + "walker": "^1.0.8" }, "engines": { - "node": ">=0.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "optionalDependencies": { + "fsevents": "^2.3.3" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "node_modules/jest-haste-map/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { - "node": ">= 4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/image-q": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz", - "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==", + "node_modules/jest-leak-detector": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.3.0.tgz", + "integrity": "sha512-cuKmUUGIjfXZAiGJ7TbEMx0bcqNdPPI6P1V+7aF+m/FUJqFDxkFR4JqkTu8ZOiU5AaX/x0hZ20KaaIPXQzbMGQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "16.9.1" + "@jest/get-type": "30.1.0", + "pretty-format": "30.3.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/image-q/node_modules/@types/node": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", - "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==", - "dev": true, - "license": "MIT" - }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "node_modules/jest-matcher-utils": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.3.0.tgz", + "integrity": "sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==", "dev": true, "license": "MIT", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.3.0", + "pretty-format": "30.3.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/import-meta-resolve": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", - "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=0.8.19" + "node": ">=8" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "node_modules/jest-message-util": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.3.0", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/inquirer": { - "version": "12.11.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.11.1.tgz", - "integrity": "sha512-9VF7mrY+3OmsAfjH3yKz/pLbJ5z22E23hENKw3/LNSaA/sAt3v49bDRY+Ygct1xwuKT+U+cBfTzjCPySna69Qw==", + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/prompts": "^7.10.1", - "@inquirer/type": "^3.0.10", - "mute-stream": "^2.0.0", - "run-async": "^4.0.6", - "rxjs": "^7.8.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": ">=10" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "node_modules/jest-message-util/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { - "node": ">= 12" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/jest-mock": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.3.0.tgz", + "integrity": "sha512-OTzICK8CpE+t4ndhKrwlIdbM6Pn8j00lvmSmq5ejiO+KxukbLjgOflKWMn3KE34EZdQm5RqTuKj+5RIEniYhog==", "dev": true, "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "@jest/types": "30.3.0", + "@types/node": "*", + "jest-util": "30.3.0" }, "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/jest-resolve": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.3.0.tgz", + "integrity": "sha512-NRtTAHQlpd15F9rUR36jqwelbrDV/dY4vzNte3S2kxCKUJRYNd5/6nTSbYiak1VX5g8IoFF23Uj5TURkUW8O5g==", "dev": true, "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.3.0", + "jest-pnp-resolver": "^1.2.3", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", + "slash": "^3.0.0", + "unrs-resolver": "^1.7.11" }, "engines": { - "node": ">=0.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/jest-resolve-dependencies": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.3.0.tgz", + "integrity": "sha512-9ev8s3YN6Hsyz9LV75XUwkCVFlwPbaFn6Wp75qnI0wzAINYWY8Fb3+6y59Rwd3QaS3kKXffHXsZMziMavfz/nw==", "dev": true, "license": "MIT", + "dependencies": { + "jest-regex-util": "30.0.1", + "jest-snapshot": "30.3.0" + }, "engines": { - "node": ">=0.12.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "has-flag": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8" } }, - "node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "node_modules/jest-runner": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.3.0.tgz", + "integrity": "sha512-gDv6C9LGKWDPLia9TSzZwf4h3kMQCqyTpq+95PODnTRDO0g9os48XIYYkS6D236vjpBir2fF63YmJFtqkS5Duw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "@jest/console": "30.3.0", + "@jest/environment": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", + "@types/node": "*", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.3.0", + "jest-haste-map": "30.3.0", + "jest-leak-detector": "30.3.0", + "jest-message-util": "30.3.0", + "jest-resolve": "30.3.0", + "jest-runtime": "30.3.0", + "jest-util": "30.3.0", + "jest-watcher": "30.3.0", + "jest-worker": "30.3.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=10" }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jake": { - "version": "10.9.4", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", - "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "node_modules/jest-runner/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "async": "^3.2.6", - "filelist": "^1.0.4", - "picocolors": "^1.1.1" - }, - "bin": { - "jake": "bin/cli.js" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/jest-diff": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", - "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "node_modules/jest-runtime": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.3.0.tgz", + "integrity": "sha512-CgC+hIBJbuh78HEffkhNKcbXAytQViplcl8xupqeIWyKQF50kCQA8J7GeJCkjisC6hpnC9Muf8jV5RdtdFbGng==", "dev": true, "license": "MIT", "dependencies": { - "@jest/diff-sequences": "30.0.1", - "@jest/get-type": "30.1.0", + "@jest/environment": "30.3.0", + "@jest/fake-timers": "30.3.0", + "@jest/globals": "30.3.0", + "@jest/source-map": "30.0.1", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", + "@types/node": "*", "chalk": "^4.1.2", - "pretty-format": "30.2.0" + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.5.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.3.0", + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.3.0", + "jest-snapshot": "30.3.0", + "jest-util": "30.3.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-diff/node_modules/chalk": { + "node_modules/jest-runtime/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -5004,7 +8377,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-diff/node_modules/supports-color": { + "node_modules/jest-runtime/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -5017,23 +8390,40 @@ "node": ">=8" } }, - "node_modules/jest-matcher-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", - "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "node_modules/jest-snapshot": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.3.0.tgz", + "integrity": "sha512-f14c7atpb4O2DeNhwcvS810Y63wEn8O1HqK/luJ4F6M4NjvxmAKQwBUWjbExUtMxWJQ0wVgmCKymeJK6NZMnfQ==", "dev": true, "license": "MIT", "dependencies": { + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.3.0", "@jest/get-type": "30.1.0", + "@jest/snapshot-utils": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", + "babel-preset-current-node-syntax": "^1.2.0", "chalk": "^4.1.2", - "jest-diff": "30.2.0", - "pretty-format": "30.2.0" + "expect": "30.3.0", + "graceful-fs": "^4.2.11", + "jest-diff": "30.3.0", + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-util": "30.3.0", + "pretty-format": "30.3.0", + "semver": "^7.7.2", + "synckit": "^0.11.8" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-matcher-utils/node_modules/chalk": { + "node_modules/jest-snapshot/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -5050,7 +8440,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-matcher-utils/node_modules/supports-color": { + "node_modules/jest-snapshot/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -5063,28 +8453,25 @@ "node": ">=8" } }, - "node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "node_modules/jest-util": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", - "@types/stack-utils": "^2.0.3", + "@jest/types": "30.3.0", + "@types/node": "*", "chalk": "^4.1.2", + "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-message-util/node_modules/chalk": { + "node_modules/jest-util/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -5101,7 +8488,20 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-message-util/node_modules/supports-color": { + "node_modules/jest-util/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-util/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -5114,50 +8514,75 @@ "node": ">=8" } }, - "node_modules/jest-mock": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", - "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "node_modules/jest-validate": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.3.0.tgz", + "integrity": "sha512-I/xzC8h5G+SHCb2P2gWkJYrNiTbeL47KvKeW5EzplkyxzBRBw1ssSHlI/jXec0ukH2q7x2zAWQm7015iusg62Q==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "jest-util": "30.2.0" + "@jest/get-type": "30.1.0", + "@jest/types": "30.3.0", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-regex-util": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", - "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "node_modules/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.3.0.tgz", + "integrity": "sha512-PJ1d9ThtTR8aMiBWUdcownq9mDdLXsQzJayTk4kmaBRHKvwNQn+ANveuhEBUyNI2hR1TVhvQ8D5kHubbzBHR/w==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/test-result": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", + "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "emittery": "^0.13.1", + "jest-util": "30.3.0", + "string-length": "^4.0.2" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-util/node_modules/chalk": { + "node_modules/jest-watcher/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -5174,20 +8599,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-util/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/jest-util/node_modules/supports-color": { + "node_modules/jest-watcher/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -5200,6 +8612,23 @@ "node": ">=8" } }, + "node_modules/jest-worker": { + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.3.0.tgz", + "integrity": "sha512-DrCKkaQwHexjRUFTmPzs7sHQe0TSj9nvDALKGdwmK5mW9v7j90BudWirKAJHt3QQ9Dhrg1F7DogPzhChppkJpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.3.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, "node_modules/jimp": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/jimp/-/jimp-1.6.0.tgz", @@ -5239,6 +8668,16 @@ "node": ">=18" } }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/jpeg-js": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", @@ -5266,6 +8705,19 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -5297,6 +8749,19 @@ "dev": true, "license": "MIT" }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/jszip": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", @@ -5399,6 +8864,16 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -5505,6 +8980,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -5628,7 +9110,23 @@ "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/make-error": { @@ -5638,20 +9136,23 @@ "dev": true, "license": "ISC" }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" + "tmpl": "1.0.5" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, "node_modules/mime": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", @@ -5665,6 +9166,16 @@ "node": ">=10.0.0" } }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/minimatch": { "version": "9.0.9", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", @@ -5681,6 +9192,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", @@ -5927,6 +9448,22 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5934,6 +9471,13 @@ "dev": true, "license": "MIT" }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, "node_modules/netmask": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", @@ -5944,6 +9488,20 @@ "node": ">= 0.4.0" } }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, "node_modules/normalize-package-data": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-7.0.1.tgz", @@ -6042,6 +9600,22 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -6092,6 +9666,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/pac-proxy-agent": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", @@ -6287,6 +9871,16 @@ "node": ">=8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -6362,6 +9956,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/pixelmatch": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.3.0.tgz", @@ -6385,6 +9989,75 @@ "node": ">=12.13.0" } }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/pngjs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", @@ -6406,9 +10079,9 @@ } }, "node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6534,6 +10207,23 @@ "node": ">=6" } }, + "node_modules/pure-rand": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, "node_modules/query-selector-shadow-dom": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.1.tgz", @@ -6829,6 +10519,29 @@ "node": ">=0.10.0" } }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -6955,9 +10668,9 @@ "license": "MIT" }, "node_modules/sax": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", - "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.5.0.tgz", + "integrity": "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -7113,11 +10826,21 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", - "optional": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/spacetrim": { "version": "0.11.59", "resolved": "https://registry.npmjs.org/spacetrim/-/spacetrim-0.11.59.tgz", @@ -7165,9 +10888,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.22", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", - "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", "dev": true, "license": "CC0-1.0" }, @@ -7181,6 +10904,13 @@ "node": ">= 10.x" } }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -7236,6 +10966,33 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-length/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -7333,6 +11090,16 @@ "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/strip-final-newline": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", @@ -7406,6 +11173,22 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/synckit": { + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", + "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, "node_modules/tar-fs": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", @@ -7416,21 +11199,82 @@ "pump": "^3.0.0", "tar-stream": "^3.1.5" }, - "optionalDependencies": { - "bare-fs": "^4.0.1", - "bare-path": "^3.0.0" + "optionalDependencies": { + "bare-fs": "^4.0.1", + "bare-path": "^3.0.0" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, "node_modules/text-decoder": { @@ -7450,6 +11294,54 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tinyrainbow": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", @@ -7460,6 +11352,13 @@ "node": ">=14.0.0" } }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -7491,6 +11390,82 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/ts-api-utils": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-jest": { + "version": "29.4.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz", + "integrity": "sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.3", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -7585,6 +11560,16 @@ "node": ">= 0.8.0" } }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/type-fest": { "version": "4.41.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", @@ -7612,6 +11597,20 @@ "node": ">=14.17" } }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/undici": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz", @@ -7642,6 +11641,72 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -7693,6 +11758,32 @@ "dev": true, "license": "MIT" }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -7762,6 +11853,16 @@ "node": ">=8" } }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -7774,19 +11875,19 @@ } }, "node_modules/webdriver": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-9.23.2.tgz", - "integrity": "sha512-HZy3eydZbmex0pbyLwHaDsAyZ+S+V4XQTdGK/nAOi4uPa74U6yT9vXqtb+3B+5/LDM7L8kTD6Z3b1y4gB4pmTw==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-9.25.0.tgz", + "integrity": "sha512-XnABKdrp83zX3xVltmX0OcFzn8zOzWGtZQxIUKY0+INB0g9Nnnfu7G75W0G+0y4nyb3zH8mavGzDBiXctdEd3Q==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "^20.1.0", "@types/ws": "^8.5.3", - "@wdio/config": "9.23.2", + "@wdio/config": "9.25.0", "@wdio/logger": "9.18.0", - "@wdio/protocols": "9.23.2", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/protocols": "9.25.0", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "deepmerge-ts": "^7.0.3", "https-proxy-agent": "^7.0.6", "undici": "^6.21.3", @@ -7797,30 +11898,69 @@ } }, "node_modules/webdriver/node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" } }, + "node_modules/webdriver/node_modules/@wdio/types": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.25.0.tgz", + "integrity": "sha512-ovSEcUBLz6gVDIsBZYKQXz8EGU37jS8sqbmlOe5+jB4XbsTBCyTLjQK/rO7LWQAKJcs0vBq+Pd+VrlsFtA7tTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^20.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/webdriver/node_modules/@wdio/utils": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-9.25.0.tgz", + "integrity": "sha512-w/ej8gZkc2tZr8L91ATyA1AWrbPDYDOvblQ7r+zt1uPRobuA4H98GME7Zm7i3FIP695BvV4G35Gcs5NssZW1pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@puppeteer/browsers": "^2.2.0", + "@wdio/logger": "9.18.0", + "@wdio/types": "9.25.0", + "decamelize": "^6.0.0", + "deepmerge-ts": "^7.0.3", + "edgedriver": "^6.1.2", + "geckodriver": "^6.1.0", + "get-port": "^7.0.0", + "import-meta-resolve": "^4.0.0", + "locate-app": "^2.2.24", + "mitt": "^3.0.1", + "safaridriver": "^1.0.0", + "split2": "^4.2.0", + "wait-port": "^1.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, "node_modules/webdriverio": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-9.23.2.tgz", - "integrity": "sha512-VjfTw1bRJdBrzjoCu7BGThxn1JK2V7mAGvxibaBrCNIayPPQjLhVDNJPOVEiR7txM6zmOUWxhkCDxHjhMYirfQ==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-9.25.0.tgz", + "integrity": "sha512-ualC/LtWGjL5rwGAbUUzURKqKoHJG2/qecEppcS9k4n1IX3MlbzGXuL/qpXiRbs/h4981HpRbZAKBxRYqwUe3g==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "^20.11.30", "@types/sinonjs__fake-timers": "^8.1.5", - "@wdio/config": "9.23.2", + "@wdio/config": "9.25.0", "@wdio/logger": "9.18.0", - "@wdio/protocols": "9.23.2", + "@wdio/protocols": "9.25.0", "@wdio/repl": "9.16.2", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "archiver": "^7.0.1", "aria-query": "^5.3.0", "cheerio": "^1.0.0-rc.12", @@ -7837,7 +11977,7 @@ "rgb2hex": "0.2.5", "serialize-error": "^12.0.0", "urlpattern-polyfill": "^10.0.0", - "webdriver": "9.23.2" + "webdriver": "9.25.0" }, "engines": { "node": ">=18.20.0" @@ -7861,6 +12001,45 @@ "undici-types": "~6.21.0" } }, + "node_modules/webdriverio/node_modules/@wdio/types": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.25.0.tgz", + "integrity": "sha512-ovSEcUBLz6gVDIsBZYKQXz8EGU37jS8sqbmlOe5+jB4XbsTBCyTLjQK/rO7LWQAKJcs0vBq+Pd+VrlsFtA7tTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^20.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/webdriverio/node_modules/@wdio/utils": { + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-9.25.0.tgz", + "integrity": "sha512-w/ej8gZkc2tZr8L91ATyA1AWrbPDYDOvblQ7r+zt1uPRobuA4H98GME7Zm7i3FIP695BvV4G35Gcs5NssZW1pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@puppeteer/browsers": "^2.2.0", + "@wdio/logger": "9.18.0", + "@wdio/types": "9.25.0", + "decamelize": "^6.0.0", + "deepmerge-ts": "^7.0.3", + "edgedriver": "^6.1.2", + "geckodriver": "^6.1.0", + "get-port": "^7.0.0", + "import-meta-resolve": "^4.0.0", + "locate-app": "^2.2.24", + "mitt": "^3.0.1", + "safaridriver": "^1.0.0", + "split2": "^4.2.0", + "wait-port": "^1.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, "node_modules/whatwg-encoding": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", @@ -7924,6 +12103,13 @@ "node": ">=0.10.0" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, "node_modules/workerpool": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", @@ -8042,6 +12228,20 @@ "dev": true, "license": "ISC" }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/ws": { "version": "8.19.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", @@ -8105,6 +12305,13 @@ "node": ">=10" } }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/playgrounds/jest/package.json b/playgrounds/jest/package.json index fbf402289..eba1e3087 100644 --- a/playgrounds/jest/package.json +++ b/playgrounds/jest/package.json @@ -6,22 +6,25 @@ "scripts": { "preinstall": "cd ../.. && npm i && npm run compile", "typecheck": "tsc --noEmit", - "test": "wdio run wdio.conf.ts", + "test": "NODE_OPTIONS=--experimental-vm-modules jest", "lint": "eslint .", "checks:all": "npm run typecheck && npm run lint && npm test", "snapshots:update": "npm run test -- --spec snapshot.test.ts --updateSnapshots" }, "devDependencies": { "@types/jest": "^30.0.0", - "@types/node": "^22.10.5", - "@wdio/cli": "^9.4.0", - "@wdio/globals": "^9.4.0", - "@wdio/local-runner": "^9.4.0", + "@types/node": "^24.12.0", + "@wdio/cli": "^9.25.0", + "@wdio/globals": "^9.23.0", + "@wdio/local-runner": "^9.25.0", "@wdio/mocha-framework": "^9.4.0", - "@wdio/spec-reporter": "^9.4.0", - "@wdio/visual-service": "^9.1.2", - "eslint": "^9.39.2", + "@wdio/spec-reporter": "^9.25.0", + "@wdio/visual-service": "^9.1.6", + "eslint": "^9.39.4", + "eslint-plugin-jest": "^29.15.0", "expect-webdriverio": "file:../..", + "jest": "^30.3.0", + "ts-jest": "^29.4.6", "ts-node": "^10.9.2", "typescript": "^5.9.3" } diff --git a/playgrounds/jest/test/specs/__snapshots__/snapshot.test.ts.snap b/playgrounds/jest/test/specs/__snapshots__/snapshot.test.ts.snap deleted file mode 100644 index c43152608..000000000 --- a/playgrounds/jest/test/specs/__snapshots__/snapshot.test.ts.snap +++ /dev/null @@ -1,42 +0,0 @@ -// Snapshot v1 - -exports[`DOM snapshots > should match command result snapshot 1`] = ` -{ - "parsed": { - "string": "400", - "type": "number", - "unit": "", - "value": 400, - }, - "property": "font-weight", - "value": 400, -} -`; - -exports[`DOM snapshots > should match element outerHTML snapshot 1`] = ` -"" -`; - -exports[`Multiple element snapshots > should snapshot navigation links 1`] = ` -[ - "/", - "/docs/gettingstarted", - "/docs/api", - "/blog", - "/docs/contribute", -] -`; - -exports[`Object snapshots > should match arbitrary object snapshot 1`] = ` -{ - "features": [ - "browser", - "mobile", - "desktop", - ], - "framework": "WebdriverIO", - "type": "automation", -} -`; diff --git a/playgrounds/jest/test/specs/basic-matchers.test.ts b/playgrounds/jest/test/specs/basic-matchers.test.ts index 1b439c839..67fa970f7 100644 --- a/playgrounds/jest/test/specs/basic-matchers.test.ts +++ b/playgrounds/jest/test/specs/basic-matchers.test.ts @@ -1,41 +1,46 @@ -import { browser, $, $$ } from '@wdio/globals' - describe('Basic Expect Matchers', () => { beforeEach(async () => { - await browser.url('https://webdriver.io') + await standalone.url('https://webdriver.io') + await expect(standalone).toHaveTitle('WebdriverIO', { containing: true }) }) describe('Boolean matchers', () => { it('should verify truthy values', async () => { - const element = await $('.navbar') + const element = await standalone.$('.navbar') const isDisplayed = await element.isDisplayed() expect(isDisplayed).toBe(true) expect(isDisplayed).toBeTruthy() }) it('should verify falsy values', async () => { - const element = await $('.non-existent-element') + const element = await standalone.$('.non-existent-element') const exists = await element.isExisting() expect(exists).toBe(false) expect(exists).toBeFalsy() }) }) + describe('Unique Jest matchers', () => { + it('should verify the expect is the real Jest one', async () => { + expect({Jest: true}).toMatchObject({Jest: true}) + }) + }) + describe('String matchers', () => { it('should match exact text', async () => { - const title = await browser.getTitle() + const title = await standalone.getTitle() expect(title).toContain('WebdriverIO') }) it('should match with regex', async () => { - const url = await browser.getUrl() + const url = await standalone.getUrl() expect(url).toMatch(/^https:\/\/webdriver\.io/) }) }) describe('Number matchers', () => { it('should compare numbers', async () => { - const navLinks = await $$('nav a') + const navLinks = await standalone.$$('nav a') const count = navLinks.length expect(count).toBeGreaterThan(5) @@ -47,10 +52,11 @@ describe('Basic Expect Matchers', () => { describe('Array matchers', () => { it('should verify array contents', async () => { - const navLinks = await $$('nav a') + const navLinks = await standalone.$$('nav a') const hrefs: string[] = [] for (const link of navLinks) { - hrefs.push(await link.getAttribute('href')) + const href = await link.getAttribute('href') + if (href) hrefs.push(href) } expect(hrefs).toBeInstanceOf(Array) @@ -61,7 +67,7 @@ describe('Basic Expect Matchers', () => { describe('Object matchers', () => { it('should match object properties', async () => { - const capabilities = await browser.capabilities + const capabilities = await standalone.capabilities expect(capabilities).toHaveProperty('browserName') expect(capabilities).toMatchObject({ @@ -72,7 +78,7 @@ describe('Basic Expect Matchers', () => { describe('Negation', () => { it('should work with not', async () => { - const title = await browser.getTitle() + const title = await standalone.getTitle() expect(title).not.toBe('') expect(title).not.toContain('Firefox') @@ -81,12 +87,12 @@ describe('Basic Expect Matchers', () => { describe('Async/Promise matchers', () => { it('should handle promises', async () => { - const url = browser.getUrl() + const url = standalone.getUrl() await expect(url).resolves.toMatch(/webdriver/) }) it('should not reject', async () => { - const title = browser.getTitle() + const title = standalone.getTitle() await expect(title).resolves.toBeDefined() }) }) diff --git a/playgrounds/jest/test/specs/network-matchers.test.ts b/playgrounds/jest/test/specs/network-matchers.test.ts new file mode 100644 index 000000000..64a86725c --- /dev/null +++ b/playgrounds/jest/test/specs/network-matchers.test.ts @@ -0,0 +1,35 @@ +describe('Network Matchers', () => { + it('should assert on network calls', async () => { + const mock = await standalone.mock('https://webdriver.io/api/foo', { + method: 'POST' + }) + mock.respond({ success: true }, { + statusCode: 200, + headers: { Authorization: 'bar' } + }) + + await standalone.url('https://webdriver.io/') + + await standalone.execute(async () => { + await fetch('https://webdriver.io/api/foo', { + method: 'POST', + headers: { Authorization: 'foo' }, + body: JSON.stringify({ title: 'foo', description: 'bar' }) + }) + }) + + await expect(mock).toBeRequested() + await expect(mock).toBeRequestedTimes(1) + + // Detailed check (simplified to match available Bidi fields) + await expect(mock).toBeRequestedWith({ + url: 'https://webdriver.io/api/foo', + method: 'POST' + }) + + // Asymmetric matcher as argument (Validating the specific fix) + await expect(mock).toBeRequestedWith(expect.objectContaining({ + method: 'POST' + })) + }) +}) diff --git a/playgrounds/jest/test/specs/snapshot.test.ts b/playgrounds/jest/test/specs/snapshot.test.ts deleted file mode 100644 index 4fbb621bd..000000000 --- a/playgrounds/jest/test/specs/snapshot.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -describe('Snapshot Testing', () => { - beforeEach(async () => { - await browser.url('https://webdriver.io') - }) - - describe('Object snapshots', () => { - it('should match arbitrary object snapshot', () => { - const data = { - framework: 'WebdriverIO', - type: 'automation', - features: ['browser', 'mobile', 'desktop'] - } - expect(data).toMatchSnapshot() - }) - - it('should match inline snapshot', () => { - const config = { timeout: 5000, retries: 3 } - expect(config).toMatchInlineSnapshot(` -{ - "retries": 3, - "timeout": 5000, -} -`) - }) - }) - - describe('DOM snapshots', () => { - it('should match element outerHTML snapshot', async () => { - const logo = await $('.navbar__logo') - await expect(logo).toMatchSnapshot() - }) - - it('should match command result snapshot', async () => { - const heading = await $$('h1')[1] - const cssProperty = await heading.getCSSProperty('font-weight') - expect(cssProperty).toMatchSnapshot() - }) - }) - - describe('Multiple element snapshots', () => { - it('should snapshot navigation links', async () => { - const navLinks = await $$('nav a') - const hrefs = [] - for (let i = 0; i < Math.min(5, await navLinks.length); i++) { - hrefs.push(await navLinks[i].getAttribute('href')) - } - expect(hrefs).toMatchSnapshot() - }) - }) -}) diff --git a/playgrounds/jest/test/specs/soft-expect.test.ts b/playgrounds/jest/test/specs/soft-expect.test.ts deleted file mode 100644 index a81d05471..000000000 --- a/playgrounds/jest/test/specs/soft-expect.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { browser, $, $$ } from '@wdio/globals' - -describe('Soft Assertions with expect.soft', () => { - beforeEach(async () => { - await browser.url('https://webdriver.io') - }) - - describe('Basic soft assertions', () => { - it('should collect multiple failures before asserting', async () => { - const heading = await $('h1') - const searchButton = await $('.DocSearch-Button') - - // These assertions won't stop test execution immediately - await expect.soft(heading).toHaveText(expect.stringContaining('Next-gen')) - await expect.soft(searchButton).toBeDisplayed() - await expect.soft(browser).toHaveUrl(expect.stringContaining('webdriver.io')) - - // All soft assertions are evaluated at the end - }) - - it('should continue execution even with failures', async () => { - const nav = await $('nav') - - // This will fail but won't stop execution - await expect.soft(nav).toHaveText('Wrong text') - - // This will still run - await expect.soft(nav).toExist() - await expect.soft(nav).toBeDisplayed() - }) - }) - - describe('Multiple element checks', () => { - it('should validate multiple elements with soft assertions', async () => { - const searchButton = await $('.DocSearch-Button') - const nav = await $('nav') - const heading = await $('h1') - - await expect.soft(searchButton).toExist() - await expect.soft(searchButton).toBeClickable() - await expect.soft(searchButton).toBeDisplayed() - - await expect.soft(nav).toExist() - await expect.soft(nav).toBeDisplayed() - - await expect.soft(heading).toExist() - await expect.soft(heading).toHaveText(expect.stringContaining('automation')) - }) - }) - - describe('Browser validations', () => { - it('should validate browser state with soft assertions', async () => { - await expect.soft(browser).toHaveTitle('WebdriverIO · Next-gen browser and mobile automation test framework for Node.js | WebdriverIO') - await expect.soft(browser).toHaveTitle(expect.stringContaining('WebdriverIO')) - await expect.soft(browser).toHaveUrl('https://webdriver.io/') - await expect.soft(browser).toHaveUrl(expect.stringContaining('webdriver')) - }) - }) - - describe('Array elements validation', () => { - it('should validate multiple elements in array', async () => { - const navLinks = await $$('nav a') - - await expect.soft(navLinks).toBeElementsArrayOfSize({ gte: 40 }) - await expect.soft(navLinks).toBeElementsArrayOfSize({ lte: 50 }) - - // Check first 3 elements - await expect.soft(navLinks[0]).toBeDisplayed() - await expect.soft(navLinks[0]).toHaveAttribute('href', expect.any(String)) - await expect.soft(navLinks[1]).toBeDisplayed() - await expect.soft(navLinks[1]).toHaveAttribute('href', expect.any(String)) - await expect.soft(navLinks[2]).toBeDisplayed() - await expect.soft(navLinks[2]).toHaveAttribute('href', expect.any(String)) - }) - }) - - describe('Mixed soft and hard assertions', () => { - it('should allow mixing soft and hard assertions', async () => { - const searchButton = await $('.DocSearch-Button') - - // Hard assertion - will fail immediately if not met - await expect(searchButton).toExist() - - // Soft assertions - will collect failures - await expect.soft(searchButton).toBeDisplayed() - await expect.soft(searchButton).toBeClickable() - await expect.soft(searchButton).toHaveElementClass('DocSearch-Button') - - // Another hard assertion - await expect(browser).toHaveUrl('https://webdriver.io/') - }) - }) - - describe('Attribute validation', () => { - it('should validate multiple attributes with soft expect', async () => { - const docsLink = await $('a[href="/docs/gettingstarted"]') - - await expect.soft(docsLink).toHaveAttribute('href', '/docs/gettingstarted') - await expect.soft(docsLink).toHaveAttribute('class', expect.stringContaining('navbar')) - await expect.soft(docsLink).toHaveText('Docs') - }) - }) - - describe('Negated soft assertions', () => { - it('should work with not', async () => { - const nonExistent = await $('.non-existent-element-xyz') - - await expect.soft(nonExistent).not.toBeDisplayed() - await expect.soft(nonExistent).not.toHaveText('anything') - await expect.soft(nonExistent).not.toBeClickable() - }) - }) - - describe('Complex validation scenarios', () => { - it('should validate complex page structure', async () => { - // Validate navigation - const nav = await $('nav') - await expect.soft(nav).toExist() - await expect.soft(nav).toBeDisplayed() - - // Validate multiple links - const navLinks = await $$('nav a') - await expect.soft(navLinks).toBeElementsArrayOfSize({ gte: 40 }) - - // Validate search functionality - const searchButton = await $('.DocSearch-Button') - await expect.soft(searchButton).toBeClickable() - await expect.soft(searchButton).toHaveElementProperty('type', 'button') - - // Validate heading - const heading = await $('h1') - await expect.soft(heading).toExist() - await expect.soft(heading).toHaveText(expect.stringContaining('Next-gen')) - - // All assertions evaluated at end - }) - }) -}) diff --git a/playgrounds/jest/test/specs/visual-snapshot.test.ts b/playgrounds/jest/test/specs/visual-snapshot.test.ts deleted file mode 100644 index 64f1c4bce..000000000 --- a/playgrounds/jest/test/specs/visual-snapshot.test.ts +++ /dev/null @@ -1,105 +0,0 @@ -describe('Visual Snapshot Testing', () => { - beforeEach(async () => { - await browser.url('https://webdriver.io/docs/gettingstarted') - }) - - describe('Element Visual Snapshots', () => { - it('should match element visual snapshot with auto-generated name', async () => { - const logo = await $('.navbar__logo') - await expect(logo).toMatchElementSnapshot('logo') - }) - - it('should match element visual snapshot with custom name', async () => { - const logo = await $('.navbar__logo') - await expect(logo).toMatchElementSnapshot('wdioLogo') - }) - - it('should match element visual snapshot with zero mismatch', async () => { - const logo = await $('.navbar__logo') - await expect(logo).toMatchElementSnapshot('wdioLogo', 0) - }) - - it('should match element visual snapshot with options', async () => { - const logo = await $('.navbar__logo') - await expect(logo).toMatchElementSnapshot('wdioLogo', { - // Visual comparison options - blockOutStatusBar: true, - blockOutToolBar: true, - }) - }) - - it('should match element visual snapshot with mismatch percentage', async () => { - const heading = await $('h1') - // Allow up to 5% mismatch - await expect(heading).toMatchElementSnapshot('mainHeading', 5) - }) - }) - - describe('Screen Visual Snapshots', () => { - it('should match screen visual snapshot', async () => { - await expect(browser).toMatchScreenSnapshot('gettingStartedPage') - }) - - it('should match screen snapshot with zero mismatch', async () => { - await expect(browser).toMatchScreenSnapshot('homepage', 0) - }) - - it('should match screen snapshot with options', async () => { - await expect(browser).toMatchScreenSnapshot('homepage', { - // Visual comparison options - hideScrollBars: true, - }) - }) - - it('should match screen snapshot with mismatch percentage', async () => { - // Allow up to 2% mismatch - await expect(browser).toMatchScreenSnapshot('dynamicContent', 2) - }) - }) - - describe('Full Page Visual Snapshots', () => { - it('should match full page visual snapshot', async () => { - await expect(browser).toMatchFullPageSnapshot('fullPage', 0.3) - }) - - it('should match full page snapshot with zero mismatch', async () => { - await expect(browser).toMatchFullPageSnapshot('fullPageExact', 0.3) - }) - - // Skipping flaky test - it.skip('should match full page snapshot with options', async () => { - await expect(browser).toMatchFullPageSnapshot('fullPage', { - // Full page screenshot options - fullPageScrollTimeout: 1500, - hideScrollBars: true, - }) - }) - - it('should match full page with mismatch tolerance', async () => { - // Allow up to 3% mismatch for animations - await expect(browser).toMatchFullPageSnapshot('fullPageDynamic', 3) - }) - }) - - describe('Tabbable Page Visual Snapshots', () => { - it('should match tabbable page visual snapshot', async () => { - await expect(browser).toMatchTabbablePageSnapshot('tabbable', 0.3) - }) - - it('should match tabbable page with zero mismatch', async () => { - await expect(browser).toMatchTabbablePageSnapshot('tabbableExact', 0.3) - }) - - it('should match tabbable page with options', async () => { - await expect(browser).toMatchTabbablePageSnapshot('tabbable', 0.3, { - // Tabbable page options - hideScrollBars: true, - }) - }) - - it('should match tabbable page with mismatch tolerance', async () => { - // Allow up to 1% mismatch - await expect(browser).toMatchTabbablePageSnapshot('tabbableWithTolerance', 1) - }) - }) -}) diff --git a/playgrounds/jest/test/specs/wdio-matchers.test.ts b/playgrounds/jest/test/specs/wdio-matchers.test.ts index 8c94b8521..cad1cff58 100644 --- a/playgrounds/jest/test/specs/wdio-matchers.test.ts +++ b/playgrounds/jest/test/specs/wdio-matchers.test.ts @@ -1,113 +1,111 @@ -import { browser, $, $$ } from '@wdio/globals' - describe('WebdriverIO Custom Matchers', () => { beforeEach(async () => { - await browser.url('https://webdriver.io') + await standalone.url('https://webdriver.io') }) describe('Browser matchers', () => { it('should verify browser title', async () => { - await expect(browser).toHaveTitle('WebdriverIO · Next-gen browser and mobile automation test framework for Node.js | WebdriverIO') + await expect(standalone).toHaveTitle('WebdriverIO · Next-gen browser and mobile automation test framework for Node.js | WebdriverIO') }) it('should verify browser title contains text', async () => { - await expect(browser).toHaveTitle(expect.stringContaining('WebdriverIO')) + await expect(standalone).toHaveTitle(expect.stringContaining('WebdriverIO')) }) it('should verify browser URL', async () => { - await expect(browser).toHaveUrl('https://webdriver.io/') + await expect(standalone).toHaveUrl('https://webdriver.io/') }) it('should verify URL contains path', async () => { - await expect(browser).toHaveUrl(expect.stringContaining('webdriver.io')) + await expect(standalone).toHaveUrl(expect.stringContaining('webdriver.io')) }) }) describe('Element existence matchers', () => { it('should verify element exists', async () => { - const searchButton = await $('.DocSearch-Button') + const searchButton = await standalone.$('.DocSearch-Button') await expect(searchButton).toExist() await expect(searchButton).toBeExisting() }) it('should verify element does not exist', async () => { - const nonExistent = await $('.non-existent-element') + const nonExistent = await standalone.$('.non-existent-element') await expect(nonExistent).not.toExist() }) }) describe('Element visibility matchers', () => { it('should verify element is displayed', async () => { - const nav = await $('nav') + const nav = await standalone.$('nav') await expect(nav).toBeDisplayed() }) it('should verify element is displayed in viewport', async () => { - const searchButton = await $('.DocSearch-Button') + const searchButton = await standalone.$('.DocSearch-Button') await expect(searchButton).toBeDisplayedInViewport() }) }) describe('Element state matchers', () => { it('should verify element is clickable', async () => { - const searchButton = await $('.DocSearch-Button') + const searchButton = await standalone.$('.DocSearch-Button') await expect(searchButton).toBeClickable() }) it('should verify element is enabled', async () => { - const searchButton = await $('.DocSearch-Button') + const searchButton = await standalone.$('.DocSearch-Button') await expect(searchButton).toBeEnabled() }) it('should verify button is not disabled', async () => { - const searchButton = await $('.DocSearch-Button') + const searchButton = await standalone.$('.DocSearch-Button') await expect(searchButton).not.toBeDisabled() }) }) describe('Element text matchers', () => { it('should verify element text', async () => { - const docsLink = await $('=Docs') + const docsLink = await standalone.$('=Docs') await expect(docsLink).toBeDisplayed() await expect(docsLink).toHaveText('Docs') }) it('should verify element contains text', async () => { - const heading = await $$('h1')[1] // Second h1 has text + const heading = await standalone.$$('h1')[1] // Second h1 has text await expect(heading).toHaveText(expect.stringContaining('Open Source')) }) it('should verify text with options', async () => { - const heading = await $$('h1')[1] // Second h1 has text + const heading = await standalone.$$('h1')[1] // Second h1 has text await expect(heading).toHaveText('OPEN SOURCE', { ignoreCase: true, containing: true }) }) }) describe('Element attribute matchers', () => { it('should verify element has attribute', async () => { - const docsLink = await $('a[href="/docs/gettingstarted"]') + const docsLink = await standalone.$('a[href="/docs/gettingstarted"]') await expect(docsLink).toHaveAttribute('href', '/docs/gettingstarted') }) it('should verify attribute contains value', async () => { - const docsLink = await $('a[href="/docs/gettingstarted"]') + const docsLink = await standalone.$('a[href="/docs/gettingstarted"]') await expect(docsLink).toHaveAttribute('href', expect.stringContaining('docs')) }) it('should verify element has class', async () => { - const searchButton = await $('.DocSearch-Button') + const searchButton = await standalone.$('.DocSearch-Button') await expect(searchButton).toHaveElementClass('DocSearch-Button') }) it('should verify element has multiple classes', async () => { - const searchButton = await $('.DocSearch-Button') + const searchButton = await standalone.$('.DocSearch-Button') await expect(searchButton).toHaveElementClass(expect.stringContaining('DocSearch')) }) }) describe('Element property matchers', () => { it('should verify element property', async () => { - const searchButton = await $('.DocSearch-Button') + const searchButton = await standalone.$('.DocSearch-Button') await expect(searchButton).toHaveElementProperty('type', 'button') }) }) @@ -115,15 +113,15 @@ describe('WebdriverIO Custom Matchers', () => { describe('Element value matchers', () => { it('should verify input value', async () => { // Navigate to a page with inputs - await browser.url('https://the-internet.herokuapp.com/login') - const username = await $('#username') + await standalone.url('https://the-internet.herokuapp.com/login') + const username = await standalone.$('#username') await username.setValue('testuser') await expect(username).toHaveValue('testuser') }) it('should verify value contains text', async () => { - await browser.url('https://the-internet.herokuapp.com/login') - const username = await $('#username') + await standalone.url('https://the-internet.herokuapp.com/login') + const username = await standalone.$('#username') await username.setValue('testuser123') await expect(username).toHaveValue(expect.stringContaining('testuser')) }) @@ -131,12 +129,12 @@ describe('WebdriverIO Custom Matchers', () => { describe('Elements array matchers', () => { it('should verify elements array size', async () => { - const navLinks = await $$('nav a') + const navLinks = await standalone.$$('nav a') await expect(navLinks).toBeElementsArrayOfSize(49) }) it('should verify elements array size with comparison', async () => { - const navLinks = await $$('nav a') + const navLinks = await standalone.$$('nav a') await expect(navLinks).toBeElementsArrayOfSize({ gte: 40 }) await expect(navLinks).toBeElementsArrayOfSize({ lte: 50 }) }) @@ -144,12 +142,12 @@ describe('WebdriverIO Custom Matchers', () => { describe('Focus matchers', () => { it('should verify element is focused', async () => { - const searchButton = await $('.DocSearch-Button') + const searchButton = await standalone.$('.DocSearch-Button') await searchButton.click() // The search modal input should be focused after clicking - await browser.pause(500) // Wait for modal to open - const searchInput = await $('.DocSearch-Input') + await standalone.pause(500) // Wait for modal to open + const searchInput = await standalone.$('.DocSearch-Input') if (await searchInput.isExisting()) { await expect(searchInput).toBeFocused() } @@ -158,19 +156,19 @@ describe('WebdriverIO Custom Matchers', () => { describe('With wait options', () => { it('should wait for condition to be met', async () => { - const heading = await $('h1') + const heading = await standalone.$('h1') await expect(heading).toBeDisplayed({ wait: 5000 }) }) it('should use custom interval', async () => { - const nav = await $('nav') + const nav = await standalone.$('nav') await expect(nav).toExist({ wait: 3000, interval: 100 }) }) }) describe('Negated matchers', () => { it('should work with not', async () => { - const nonExistent = await $('.non-existent-element-xyz') + const nonExistent = await standalone.$('.non-existent-element-xyz') await expect(nonExistent).not.toBeDisplayed() await expect(nonExistent).not.toExist() }) diff --git a/playgrounds/jest/tsconfig.json b/playgrounds/jest/tsconfig.json index 7b5a23e8d..c73e16977 100644 --- a/playgrounds/jest/tsconfig.json +++ b/playgrounds/jest/tsconfig.json @@ -5,10 +5,8 @@ "moduleResolution": "bundler", "types": [ "node", - "expect-webdriverio/expect-global", "@types/jest", "expect-webdriverio/jest", - "@wdio/globals/types", // Need to be last to so the above from the projects have priority "@wdio/visual-service" ], "resolveJsonModule": true, diff --git a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/dynamicContent-chrome-jest-756x556.png b/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/dynamicContent-chrome-jest-756x556.png deleted file mode 100644 index 59ee7054c..000000000 Binary files a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/dynamicContent-chrome-jest-756x556.png and /dev/null differ diff --git a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/fullPage-chrome-jest-756x556.png b/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/fullPage-chrome-jest-756x556.png deleted file mode 100644 index 4ad572a99..000000000 Binary files a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/fullPage-chrome-jest-756x556.png and /dev/null differ diff --git a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/fullPageDynamic-chrome-jest-756x556.png b/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/fullPageDynamic-chrome-jest-756x556.png deleted file mode 100644 index 97da608a4..000000000 Binary files a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/fullPageDynamic-chrome-jest-756x556.png and /dev/null differ diff --git a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/fullPageExact-chrome-jest-756x556.png b/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/fullPageExact-chrome-jest-756x556.png deleted file mode 100644 index 4ad572a99..000000000 Binary files a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/fullPageExact-chrome-jest-756x556.png and /dev/null differ diff --git a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/gettingStartedPage-chrome-jest-756x556.png b/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/gettingStartedPage-chrome-jest-756x556.png deleted file mode 100644 index 59ee7054c..000000000 Binary files a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/gettingStartedPage-chrome-jest-756x556.png and /dev/null differ diff --git a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/homepage-chrome-jest-756x556.png b/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/homepage-chrome-jest-756x556.png deleted file mode 100644 index 59ee7054c..000000000 Binary files a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/homepage-chrome-jest-756x556.png and /dev/null differ diff --git a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/logo-chrome-jest-756x556.png b/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/logo-chrome-jest-756x556.png deleted file mode 100644 index 8b1c24538..000000000 Binary files a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/logo-chrome-jest-756x556.png and /dev/null differ diff --git a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/mainHeading-chrome-jest-756x556.png b/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/mainHeading-chrome-jest-756x556.png deleted file mode 100644 index de5fb0968..000000000 Binary files a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/mainHeading-chrome-jest-756x556.png and /dev/null differ diff --git a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/tabbable-chrome-jest-756x556.png b/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/tabbable-chrome-jest-756x556.png deleted file mode 100644 index 6244c17f1..000000000 Binary files a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/tabbable-chrome-jest-756x556.png and /dev/null differ diff --git a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/tabbableExact-chrome-jest-756x556.png b/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/tabbableExact-chrome-jest-756x556.png deleted file mode 100644 index 10abe69cd..000000000 Binary files a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/tabbableExact-chrome-jest-756x556.png and /dev/null differ diff --git a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/tabbableWithTolerance-chrome-jest-756x556.png b/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/tabbableWithTolerance-chrome-jest-756x556.png deleted file mode 100644 index 10abe69cd..000000000 Binary files a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/tabbableWithTolerance-chrome-jest-756x556.png and /dev/null differ diff --git a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/wdioLogo-chrome-jest-756x556.png b/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/wdioLogo-chrome-jest-756x556.png deleted file mode 100644 index 8b1c24538..000000000 Binary files a/playgrounds/jest/visual-snapshot/baseline/desktop_chrome/wdioLogo-chrome-jest-756x556.png and /dev/null differ diff --git a/playgrounds/jest/wdio.conf.ts b/playgrounds/jest/wdio.conf.ts index d0cd9fde7..34062cc31 100644 --- a/playgrounds/jest/wdio.conf.ts +++ b/playgrounds/jest/wdio.conf.ts @@ -1,32 +1,12 @@ +import { Capabilities } from "@wdio/types"; -import { join } from 'node:path' -import type { VisualServiceOptions } from '@wdio/visual-service' -import { SoftAssertionService, setOptions } from 'expect-webdriverio' - -export const config: WebdriverIO.Config = { - // - // ==================== - // Runner Configuration - // ==================== - // - runner: 'local', - - // - // ================== - // Specify Test Files - // ================== - // - specs: [ - './test/specs/**/*.test.ts' - ], - +export const config: Capabilities.WebdriverIOConfig = { // // ============ // Capabilities // ============ // - maxInstances: 10, - capabilities: [{ + capabilities:{ browserName: 'chrome', 'goog:chromeOptions': { args: ['--headless', '--disable-gpu'] @@ -34,51 +14,6 @@ export const config: WebdriverIO.Config = { 'wdio-ics:options': { logName: 'chrome-jest' } - }], - - // - // =================== - // Test Configurations - // =================== - // - logLevel: 'info', - bail: 0, - baseUrl: 'http://localhost', - waitforTimeout: 10000, - connectionRetryTimeout: 120000, - connectionRetryCount: 3, - services: [ - [SoftAssertionService, {}], - [ - 'visual', - { - baselineFolder: join(process.cwd(), 'visual-snapshot/baseline'), - formatImageName: '{tag}-{logName}-{width}x{height}', - screenshotPath: join(process.cwd(), 'visual-snapshot/.temp'), - savePerInstance: true, - autoSaveBaseline: true, - compareOptions: { - // Block out the changing elements - blockOutStatusBar: true, - blockOutToolBar: true - } - } satisfies VisualServiceOptions - ] - ], - framework: 'mocha', - reporters: ['spec'], - mochaOpts: { - ui: 'bdd', - timeout: 60000 - }, - - // - // ===== - // Hooks - // ===== - // - // eslint-disable-next-line @typescript-eslint/no-unused-vars - before: function (_capabilities, _specs) { - setOptions({ wait: 500 }) }, + logLevel: 'info', } diff --git a/playgrounds/mocha/README.md b/playgrounds/mocha/README.md index 3f5458e37..bb45887df 100644 --- a/playgrounds/mocha/README.md +++ b/playgrounds/mocha/README.md @@ -1,6 +1,15 @@ -# expect-webdriverio Playground - Mocha +# Mocha Playground -This playground project uses the local build of expect-webdriverio with WebDriverIO and Mocha framework. +This playground project uses the local build of `expect-webdriverio` with WebDriverIO and the Mocha framework. It serves as the default, out-of-the-box experience where all features are fully supported and work easily. + +## Features and Support + +Because Mocha is the standard framework for `expect-webdriverio`, all features work natively without conflicts: + +* **Soft Assertions**: Fully supported using the `SoftAssertionService` plugin in the `wdio.conf.ts` services. +* **Snapshots**: Basic text/data snapshot testing works seamlessly. +* **Visual Snapshots**: Visual snapshot testing directly integrates via `@wdio/visual-service`. +* **Global Options Configuration**: Easily set global wait times and other configurations (e.g., `setOptions({ wait: 250 })` in the `before` hook). ## Setup @@ -21,9 +30,10 @@ This playground project uses the local build of expect-webdriverio with WebDrive ## Structure -- `test/specs/` - E2E test files -- `wdio.conf.ts` - WebDriverIO configuration with Mocha -- Uses local build from `../../lib/index.js` +- `test/specs/` - E2E test files covering various feature sets (basic matchers, soft expectations, snapshots, visual comparisons). +- `wdio.conf.ts` - WebDriverIO configuration demonstrating how to wire up the `SoftAssertionService`, the Visual service, and global `expect-webdriverio` options. +- `visual-snapshot/` - Directory for storing and comparing visual screenshot baselines and temp images. +- Uses local build from `/expect-webdriverio/lib/index.js`. ## Tests diff --git a/playgrounds/mocha/eslint.config.mjs b/playgrounds/mocha/eslint.config.mjs index a60c4b397..4fecb2048 100644 --- a/playgrounds/mocha/eslint.config.mjs +++ b/playgrounds/mocha/eslint.config.mjs @@ -1,6 +1,7 @@ import tsEslintPlugin from '@typescript-eslint/eslint-plugin'; import tsParser from '@typescript-eslint/parser'; +import mochaPlugin from 'eslint-plugin-mocha'; export default { files: ['**/*.ts', '**/*.js'], @@ -21,9 +22,11 @@ export default { }, plugins: { '@typescript-eslint': tsEslintPlugin, + 'mocha': mochaPlugin, }, rules: { ...tsEslintPlugin.configs['recommended'].rules, '@typescript-eslint/no-floating-promises': 'error', + 'mocha/no-exclusive-tests': 'error', }, }; diff --git a/playgrounds/mocha/package-lock.json b/playgrounds/mocha/package-lock.json index 358be4919..892fd343c 100644 --- a/playgrounds/mocha/package-lock.json +++ b/playgrounds/mocha/package-lock.json @@ -9,19 +9,20 @@ "version": "1.0.0", "hasInstallScript": true, "devDependencies": { - "@wdio/cli": "^9.4.0", - "@wdio/local-runner": "^9.4.0", - "@wdio/mocha-framework": "^9.4.0", - "@wdio/spec-reporter": "^9.4.0", - "@wdio/visual-service": "^9.1.2", - "eslint": "^9.39.2", + "@wdio/cli": "^9.25.0", + "@wdio/local-runner": "^9.25.0", + "@wdio/mocha-framework": "^9.25.0", + "@wdio/spec-reporter": "^9.25.0", + "@wdio/visual-service": "^9.1.6", + "eslint": "^9.39.4", + "eslint-plugin-mocha": "^11.2.0", "expect-webdriverio": "file:../..", "ts-node": "^10.9.2", "typescript": "^5.9.3" } }, "../..": { - "version": "5.6.4", + "version": "5.6.5", "dev": true, "license": "MIT", "dependencies": { @@ -31,24 +32,24 @@ "jest-matcher-utils": "^30.2.0" }, "devDependencies": { - "@jest/globals": "^30.2.0", + "@jest/globals": "^30.3.0", "@types/debug": "^4.1.12", - "@types/jasmine": "^5.1.8", + "@types/jasmine": "^5.1.15", "@types/jest": "^30.0.0", "@types/mocha": "^10.0.10", - "@types/node": "^24.10.1", - "@vitest/coverage-v8": "^4.0.16", - "@wdio/eslint": "^0.1.2", - "@wdio/types": "^9.20.0", - "eslint": "^9.39.2", + "@types/node": "^24.12.0", + "@vitest/coverage-v8": "^4.1.0", + "@wdio/eslint": "^0.1.3", + "@wdio/types": "^9.25.0", + "eslint": "^9.39.4", "husky": "^9.1.7", "npm-run-all2": "^8.0.4", - "release-it": "^19.1.0", - "rimraf": "^6.1.2", + "release-it": "^19.2.4", + "rimraf": "^6.1.3", "shelljs": "^0.10.0", "typescript": "^5.9.3", - "vitest": "^4.0.16", - "webdriverio": "^9.21.0" + "vitest": "^4.1.0", + "webdriverio": "^9.25.0" }, "engines": { "node": ">=20" @@ -71,9 +72,9 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", - "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, "license": "MIT", "dependencies": { @@ -580,15 +581,15 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", - "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", - "minimatch": "^3.1.2" + "minimatch": "^3.1.5" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -645,20 +646,20 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", - "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", + "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", - "minimatch": "^3.1.2", + "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" }, "engines": { @@ -679,16 +680,6 @@ "concat-map": "0.0.1" } }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", @@ -703,9 +694,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", - "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", "dev": true, "license": "MIT", "engines": { @@ -1875,23 +1866,23 @@ } }, "node_modules/@wdio/cli": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-9.23.2.tgz", - "integrity": "sha512-D6KZGomfNmjFhSWYdfR7Ojik5qWEpPoR4g5LQPzbFwiii/RkTudLcMFcCO6s7HTMLDQDWryOStV2KK6KqrIF8A==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-9.25.0.tgz", + "integrity": "sha512-7m6Au8U0Fz+/n6vlchxHd5ogYESjz2XEYVnmcqnDapCAUo570Ilb86Muz69AFrBiZ6D+xkesQTwlWOdNRjIY1w==", "dev": true, "license": "MIT", "dependencies": { "@vitest/snapshot": "^2.1.1", - "@wdio/config": "9.23.2", + "@wdio/config": "9.25.0", "@wdio/globals": "9.23.0", "@wdio/logger": "9.18.0", - "@wdio/protocols": "9.23.2", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/protocols": "9.25.0", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "async-exit-hook": "^2.0.1", "chalk": "^5.4.1", "chokidar": "^4.0.0", - "create-wdio": "9.21.0", + "create-wdio": "9.25.0", "dotenv": "^17.2.0", "import-meta-resolve": "^4.0.0", "lodash.flattendeep": "^4.4.0", @@ -1899,7 +1890,7 @@ "lodash.union": "^4.6.0", "read-pkg-up": "^10.0.0", "tsx": "^4.7.2", - "webdriverio": "9.23.2", + "webdriverio": "9.25.0", "yargs": "^17.7.2" }, "bin": { @@ -1910,32 +1901,33 @@ } }, "node_modules/@wdio/config": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-9.23.2.tgz", - "integrity": "sha512-19Z+AIQ1NUpr6ncTumjSthm6A7c3DbaGTp+VCdcyN+vHYOK4WsWIomSk+uSbFosYFQVGRjCaHaeGSnC8GNPGYQ==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-9.25.0.tgz", + "integrity": "sha512-EWa7l1rrbSNthCRDpdBw7ESAa1/jAjSsWCGkaVAO0HMOGlQjzvYI6gNi4KUeymnurDZ2IPr0jr+f9We6AWi6QA==", "dev": true, "license": "MIT", "dependencies": { "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "deepmerge-ts": "^7.0.3", "glob": "^10.2.2", - "import-meta-resolve": "^4.0.0" + "import-meta-resolve": "^4.0.0", + "jiti": "^2.6.1" }, "engines": { "node": ">=18.20.0" } }, "node_modules/@wdio/dot-reporter": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/dot-reporter/-/dot-reporter-9.23.2.tgz", - "integrity": "sha512-3+5y7P4GS7UTIgr6zPhxKHMmDSwiNjgdwnWIUYXr2eQLcpnPGhc9GL1IEDgQEAcziXG9BfaKzZQHi+vH89PR5w==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/dot-reporter/-/dot-reporter-9.25.0.tgz", + "integrity": "sha512-yFlyHfCJOERWIgiFzbyliCr6YxEYZDM3rykCHmpIlbAOwATxjIh26fvkKI8/23LDqMybym8Pn/Yjj/W78/KgIg==", "dev": true, "license": "MIT", "dependencies": { - "@wdio/reporter": "9.23.2", - "@wdio/types": "9.23.2", + "@wdio/reporter": "9.25.0", + "@wdio/types": "9.25.0", "chalk": "^5.0.1" }, "engines": { @@ -1965,9 +1957,9 @@ } }, "node_modules/@wdio/image-comparison-core": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@wdio/image-comparison-core/-/image-comparison-core-1.1.2.tgz", - "integrity": "sha512-Wvm4iGwONoWlcw7xMGl4UxNYj6aqqrQJXMAJlNik4bpubiGKIVa0NRG05kRVqn8UvOwS1CHfd/9xdXw5a+1DAA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@wdio/image-comparison-core/-/image-comparison-core-1.1.4.tgz", + "integrity": "sha512-WUT+YmzPj4nWSuWACuuKqJXDYAZd4Od3Up+6hRAI1ZA5yV+KEcT8yb7taWY1hjWHqlbCjbuJUaQD80u/7ToqDA==", "dev": true, "license": "MIT", "dependencies": { @@ -1977,18 +1969,18 @@ } }, "node_modules/@wdio/local-runner": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-9.23.2.tgz", - "integrity": "sha512-tS8l2iaQc5aQav2LYYXx296F9KpdrU4/dmw5t9n9baXgdu8CKyGEd9orhTFQ7fYR55wFJ/85toQNOvIQHtIZrA==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-9.25.0.tgz", + "integrity": "sha512-E6pEeQouVLle19Gk55Y/JxPGMzT2jhmHS80yjT3g481Q1EML9y8m3T6UMemAUnz70FGneP0aCcuFKJdmkF9dKw==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "^20.1.0", "@wdio/logger": "9.18.0", "@wdio/repl": "9.16.2", - "@wdio/runner": "9.23.2", - "@wdio/types": "9.23.2", - "@wdio/xvfb": "9.23.2", + "@wdio/runner": "9.25.0", + "@wdio/types": "9.25.0", + "@wdio/xvfb": "9.25.0", "exit-hook": "^4.0.0", "expect-webdriverio": "^5.3.4", "split2": "^4.1.0", @@ -2033,17 +2025,17 @@ } }, "node_modules/@wdio/mocha-framework": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-9.23.2.tgz", - "integrity": "sha512-V1wx8A8vMAExricXlCv0jzQOJTAgvgM/646QFr65U028+lqAGU23EkFp5H1WJj9I9jCHJTfMkxtUrPv0v7y63A==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-9.25.0.tgz", + "integrity": "sha512-30qPP7w0UGG49LB3nAMxVf9Q9GA8q/NeDPHjBsXCjpSnO0AswtjFktb91hkqQqssrlGMQV+QyQuBD+kMxkhrDQ==", "dev": true, "license": "MIT", "dependencies": { "@types/mocha": "^10.0.6", "@types/node": "^20.11.28", "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "mocha": "^10.3.0" }, "engines": { @@ -2068,9 +2060,9 @@ "license": "MIT" }, "node_modules/@wdio/protocols": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-9.23.2.tgz", - "integrity": "sha512-pmCYOYI2N89QCC8IaiHwaWyP0mR8T1iKkEGpoTq2XVihp7VK/lfPvieyeZT5/e28MadYLJsDQ603pbu5J1NRDg==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-9.25.0.tgz", + "integrity": "sha512-PErbZqdpFmE69bRuku3OR34Ro2xuZNNLXYFOcJnjXJVzf5+ApDyGHYrMlvhtrrSy9/55LUybk851ppjS+3RoDA==", "dev": true, "license": "MIT" }, @@ -2105,15 +2097,15 @@ "license": "MIT" }, "node_modules/@wdio/reporter": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-9.23.2.tgz", - "integrity": "sha512-+L1knNyQl+Xs+/VkM5JOX/HINe+g3ZVWt0Scsb9DcOCll8xG8jisxArutZLo+UuV6Bm1BzqfJJb/+ae04EuRAQ==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-9.25.0.tgz", + "integrity": "sha512-zmyjr7/EoGwlmrICNzhRL3k0dlJoqdQShzHd5l8V1axYsaC3UHGy2oNDXwKD/OjhEThJsGHxwjyUDkKYhbZdCw==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "^20.1.0", "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", + "@wdio/types": "9.25.0", "diff": "^8.0.2", "object-inspect": "^1.12.0" }, @@ -2122,9 +2114,9 @@ } }, "node_modules/@wdio/reporter/node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", "dev": true, "license": "MIT", "dependencies": { @@ -2139,22 +2131,22 @@ "license": "MIT" }, "node_modules/@wdio/runner": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-9.23.2.tgz", - "integrity": "sha512-joFHYO4jnDixsBRM6tJ/nVeH15UNIthIAp2Yky+yPsh1HkM+x9gZG5ZT0TnSXw/E2tQRb2yO3d+jsEHedsE0jw==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-9.25.0.tgz", + "integrity": "sha512-Oe7NnFWJICF5g+LGLVWi3x41aL2ZRto3bOQZlBjNnGFRkx+BPz7qHdENueflfh7VCX9o3qRns6cQ3CEuurLaNg==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "^20.11.28", - "@wdio/config": "9.23.2", - "@wdio/dot-reporter": "9.23.2", + "@wdio/config": "9.25.0", + "@wdio/dot-reporter": "9.25.0", "@wdio/globals": "9.23.0", "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "deepmerge-ts": "^7.0.3", - "webdriver": "9.23.2", - "webdriverio": "9.23.2" + "webdriver": "9.25.0", + "webdriverio": "9.25.0" }, "engines": { "node": ">=18.20.0" @@ -2173,9 +2165,9 @@ } }, "node_modules/@wdio/runner/node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", "dev": true, "license": "MIT", "dependencies": { @@ -2190,14 +2182,14 @@ "license": "MIT" }, "node_modules/@wdio/spec-reporter": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-9.23.2.tgz", - "integrity": "sha512-9uwbrOFgPuF5NqixiU9db46HNJERN04beefNh4f4usJSP41Mbru0isps64qKkWSpFJhYl1LZrSGELezxH9bZ6A==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-9.25.0.tgz", + "integrity": "sha512-15+YnhnXDW7dAJ4PP+qZ2imAbVcMMSwewtjVrKRWK0OsMASXRXka/zV3jViRp1Rf+WCGp76HMxhv7YOygfE68A==", "dev": true, "license": "MIT", "dependencies": { - "@wdio/reporter": "9.23.2", - "@wdio/types": "9.23.2", + "@wdio/reporter": "9.25.0", + "@wdio/types": "9.25.0", "chalk": "^5.1.2", "easy-table": "^1.2.0", "pretty-ms": "^9.0.0" @@ -2207,9 +2199,9 @@ } }, "node_modules/@wdio/types": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.23.2.tgz", - "integrity": "sha512-ryfrERGsNp+aCcrTE1rFU6cbmDj8GHZ04R9k52KNt2u1a6bv3Eh5A/cUA0hXuMdEUfsc8ePLYdwQyOLFydZ0ig==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.25.0.tgz", + "integrity": "sha512-ovSEcUBLz6gVDIsBZYKQXz8EGU37jS8sqbmlOe5+jB4XbsTBCyTLjQK/rO7LWQAKJcs0vBq+Pd+VrlsFtA7tTQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2237,15 +2229,15 @@ "license": "MIT" }, "node_modules/@wdio/utils": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-9.23.2.tgz", - "integrity": "sha512-+QfgXUWeA940AXT5l5UlrBKoHBk9GLSQE3BA+7ra1zWuFvv6SHG6M2mwplcPlOlymJMqXy8e7ZgLEoLkXuvC1Q==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-9.25.0.tgz", + "integrity": "sha512-w/ej8gZkc2tZr8L91ATyA1AWrbPDYDOvblQ7r+zt1uPRobuA4H98GME7Zm7i3FIP695BvV4G35Gcs5NssZW1pw==", "dev": true, "license": "MIT", "dependencies": { "@puppeteer/browsers": "^2.2.0", "@wdio/logger": "9.18.0", - "@wdio/types": "9.23.2", + "@wdio/types": "9.25.0", "decamelize": "^6.0.0", "deepmerge-ts": "^7.0.3", "edgedriver": "^6.1.2", @@ -2263,23 +2255,23 @@ } }, "node_modules/@wdio/visual-service": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@wdio/visual-service/-/visual-service-9.1.2.tgz", - "integrity": "sha512-FYyv4kXWqm4LmX62VwC/uR0khRFlSmvUVDyyKWLiIMdzQGiXLYOotxGs5E/wQcHHZPPv+/1wWFJLoE3w1rWt+w==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/@wdio/visual-service/-/visual-service-9.1.6.tgz", + "integrity": "sha512-oQIzo0I6kX/IV7rferoLllf8vnTtDOHpbdBMeio8+fsJqC39eKOpWp1+fiGyByrO9zF0GMJELM/r76ZiEeV+qA==", "dev": true, "license": "MIT", "dependencies": { "@wdio/globals": "^9.23.0", - "@wdio/image-comparison-core": "1.1.2", + "@wdio/image-comparison-core": "1.1.4", "@wdio/logger": "^9.18.0", "@wdio/types": "^9.20.0", "expect-webdriverio": "^5.6.1" } }, "node_modules/@wdio/xvfb": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/@wdio/xvfb/-/xvfb-9.23.2.tgz", - "integrity": "sha512-48KiET6Phmu7SIQgpTXSn7eRJK6MJdTKib2MLT5WTKIJ+t0OyGKl/ESXi6tzFrGFPzLkvogSIRy8O2sKM0PcbA==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/@wdio/xvfb/-/xvfb-9.25.0.tgz", + "integrity": "sha512-qbsdWm1sP5CGikz3n3dwoVGqbRyBsERGzckDMsQeQ9QVTG6OsNOm4KiVejdiwdPXqDjLUnBv8xGtfuFrftFwcA==", "dev": true, "license": "MIT", "dependencies": { @@ -2361,9 +2353,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -3034,9 +3026,9 @@ "license": "MIT" }, "node_modules/commander": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", - "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", "dev": true, "license": "MIT", "engines": { @@ -3122,9 +3114,9 @@ "license": "MIT" }, "node_modules/create-wdio": { - "version": "9.21.0", - "resolved": "https://registry.npmjs.org/create-wdio/-/create-wdio-9.21.0.tgz", - "integrity": "sha512-L6gsQLArY3AH5uTGpf3VfUezIsmZKufkF3ixSWqCuA/m458YVKeGghu1bBOWBdDIzqa6GX4e29dv0uVam0CTpw==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/create-wdio/-/create-wdio-9.25.0.tgz", + "integrity": "sha512-ZnkJVDx3HB7UNH2t1kxK1VoNWQAQhLYyTjSEdpcFTHoj/QUrzS7K9nW99Q6WT0mgsedbtl86VMq4IXfy6f8Jrw==", "dev": true, "license": "MIT", "dependencies": { @@ -3634,25 +3626,25 @@ } }, "node_modules/eslint": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", - "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.1", + "@eslint/config-array": "^0.21.2", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.2", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "ajv": "^6.12.4", + "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", @@ -3671,7 +3663,7 @@ "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", + "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, @@ -3693,6 +3685,33 @@ } } }, + "node_modules/eslint-plugin-mocha": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-11.2.0.tgz", + "integrity": "sha512-nMdy3tEXZac8AH5Z/9hwUkSfWu8xHf4XqwB5UEQzyTQGKcNlgFeciRAjLjliIKC3dR1Ex/a2/5sqgQzvYRkkkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.1", + "globals": "^15.14.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0" + } + }, + "node_modules/eslint-plugin-mocha/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint-scope": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", @@ -3784,16 +3803,6 @@ "node": ">=10.13.0" } }, - "node_modules/eslint/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", @@ -4147,9 +4156,9 @@ } }, "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4580,6 +4589,16 @@ ], "license": "BSD-3-Clause" }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/image-q": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz", @@ -4887,6 +4906,16 @@ "node": ">=18" } }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/jpeg-js": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", @@ -6554,9 +6583,9 @@ "license": "MIT" }, "node_modules/sax": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", - "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.5.0.tgz", + "integrity": "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -6754,9 +6783,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.22", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", - "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", "dev": true, "license": "CC0-1.0" }, @@ -7179,9 +7208,9 @@ } }, "node_modules/undici": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz", - "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==", + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz", + "integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==", "dev": true, "license": "MIT", "engines": { @@ -7340,19 +7369,19 @@ } }, "node_modules/webdriver": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-9.23.2.tgz", - "integrity": "sha512-HZy3eydZbmex0pbyLwHaDsAyZ+S+V4XQTdGK/nAOi4uPa74U6yT9vXqtb+3B+5/LDM7L8kTD6Z3b1y4gB4pmTw==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-9.25.0.tgz", + "integrity": "sha512-XnABKdrp83zX3xVltmX0OcFzn8zOzWGtZQxIUKY0+INB0g9Nnnfu7G75W0G+0y4nyb3zH8mavGzDBiXctdEd3Q==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "^20.1.0", "@types/ws": "^8.5.3", - "@wdio/config": "9.23.2", + "@wdio/config": "9.25.0", "@wdio/logger": "9.18.0", - "@wdio/protocols": "9.23.2", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/protocols": "9.25.0", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "deepmerge-ts": "^7.0.3", "https-proxy-agent": "^7.0.6", "undici": "^6.21.3", @@ -7363,9 +7392,9 @@ } }, "node_modules/webdriver/node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", "dev": true, "license": "MIT", "dependencies": { @@ -7380,20 +7409,20 @@ "license": "MIT" }, "node_modules/webdriverio": { - "version": "9.23.2", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-9.23.2.tgz", - "integrity": "sha512-VjfTw1bRJdBrzjoCu7BGThxn1JK2V7mAGvxibaBrCNIayPPQjLhVDNJPOVEiR7txM6zmOUWxhkCDxHjhMYirfQ==", + "version": "9.25.0", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-9.25.0.tgz", + "integrity": "sha512-ualC/LtWGjL5rwGAbUUzURKqKoHJG2/qecEppcS9k4n1IX3MlbzGXuL/qpXiRbs/h4981HpRbZAKBxRYqwUe3g==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "^20.11.30", "@types/sinonjs__fake-timers": "^8.1.5", - "@wdio/config": "9.23.2", + "@wdio/config": "9.25.0", "@wdio/logger": "9.18.0", - "@wdio/protocols": "9.23.2", + "@wdio/protocols": "9.25.0", "@wdio/repl": "9.16.2", - "@wdio/types": "9.23.2", - "@wdio/utils": "9.23.2", + "@wdio/types": "9.25.0", + "@wdio/utils": "9.25.0", "archiver": "^7.0.1", "aria-query": "^5.3.0", "cheerio": "^1.0.0-rc.12", @@ -7410,7 +7439,7 @@ "rgb2hex": "0.2.5", "serialize-error": "^12.0.0", "urlpattern-polyfill": "^10.0.0", - "webdriver": "9.23.2" + "webdriver": "9.25.0" }, "engines": { "node": ">=18.20.0" diff --git a/playgrounds/mocha/package.json b/playgrounds/mocha/package.json index c68cc0f91..1474eb3e5 100644 --- a/playgrounds/mocha/package.json +++ b/playgrounds/mocha/package.json @@ -12,12 +12,13 @@ "snapshots:update": "npm run test -- --spec snapshot.test.ts --updateSnapshots" }, "devDependencies": { - "@wdio/cli": "^9.4.0", - "@wdio/local-runner": "^9.4.0", - "@wdio/mocha-framework": "^9.4.0", - "@wdio/spec-reporter": "^9.4.0", - "@wdio/visual-service": "^9.1.2", - "eslint": "^9.39.2", + "@wdio/cli": "^9.25.0", + "@wdio/local-runner": "^9.25.0", + "@wdio/mocha-framework": "^9.25.0", + "@wdio/spec-reporter": "^9.25.0", + "@wdio/visual-service": "^9.1.6", + "eslint": "^9.39.4", + "eslint-plugin-mocha": "^11.2.0", "expect-webdriverio": "file:../..", "ts-node": "^10.9.2", "typescript": "^5.9.3" diff --git a/playgrounds/mocha/test/specs/basic-matchers.test.ts b/playgrounds/mocha/test/specs/basic-matchers.test.ts index 2bafa160f..aeeb6b1f1 100644 --- a/playgrounds/mocha/test/specs/basic-matchers.test.ts +++ b/playgrounds/mocha/test/specs/basic-matchers.test.ts @@ -5,6 +5,64 @@ describe('Basic Expect Matchers', () => { await browser.url('https://webdriver.io') }) + describe('Expect matchers', () => { + it('Basic matchers', async () => { + // Equality + expect(2 + 2).toBe(4); + expect({a: 1}).toEqual({a: 1}); + expect([1, 2, 3]).toStrictEqual([1, 2, 3]); + expect(2 + 2).not.toBe(5); + + // Truthiness + expect(null).toBeNull(); + expect(undefined).toBeUndefined(); + expect(0).toBeFalsy(); + expect(1).toBeTruthy(); + expect(NaN).toBeNaN(); + + // Numbers + expect(4).toBeGreaterThan(3); + expect(4).toBeGreaterThanOrEqual(4); + expect(4).toBeLessThan(5); + expect(4).toBeLessThanOrEqual(4); + expect(0.2 + 0.1).toBeCloseTo(0.3, 5); + + // Strings + expect('team').toMatch(/team/); + expect('Christoph').toContain('stop'); + + // Arrays and iterables + expect([1, 2, 3]).toContain(2); + expect([{a: 1}, {b: 2}]).toContainEqual({a: 1}); + expect([1, 2, 3]).toHaveLength(3); + + // Objects + expect({a: 1, b: 2}).toHaveProperty('a'); + expect({a: {b: 2}}).toHaveProperty('a.b', 2); + + // Errors + expect(() => { throw new Error('error!') }).toThrow('error!'); + expect(() => { throw new TypeError('wrong type') }).toThrow(TypeError); + + // Asymmetric matchers + expect({foo: 'bar', baz: 1}).toEqual(expect.objectContaining({foo: expect.any(String)})); + expect([1, 2, 3]).toEqual(expect.arrayContaining([2])); + expect('abc').toEqual(expect.stringContaining('b')); + expect('abc').toEqual(expect.stringMatching(/b/)); + expect(123).toEqual(expect.any(Number)); + expect({ foo: 'bar' }).toEqual({ foo: expect.anything() }); + expect({ num: 1.1 }).toEqual({ num: expect.closeTo(1.101, 2) }); + expect(() => { expect('title').toBe(expect.stringContaining('title')) }).toThrow(); + + // Others + expect(new Set([1, 2, 3])).toContain(2); + + // .resolves / .rejects (async) + await expect(Promise.resolve(42)).resolves.toBe(42); + await expect(Promise.reject(new Error('fail'))).rejects.toThrow('fail'); + }); + }); + describe('Boolean matchers', () => { it('should verify truthy values', async () => { const element = await $('.navbar') @@ -50,7 +108,8 @@ describe('Basic Expect Matchers', () => { const navLinks = await $$('nav a') const hrefs: string[] = [] for (const link of navLinks) { - hrefs.push(await link.getAttribute('href')) + const href = await link.getAttribute('href') + if (href) hrefs.push(href) } expect(hrefs).toBeInstanceOf(Array) diff --git a/playgrounds/mocha/test/specs/network-matchers.test.ts b/playgrounds/mocha/test/specs/network-matchers.test.ts new file mode 100644 index 000000000..f25686f70 --- /dev/null +++ b/playgrounds/mocha/test/specs/network-matchers.test.ts @@ -0,0 +1,37 @@ +import { browser } from '@wdio/globals' + +describe('Network Matchers', () => { + it('should assert on network calls', async () => { + const mock = await browser.mock('https://webdriver.io/api/foo', { + method: 'POST' + }) + mock.respond({ success: true }, { + statusCode: 200, + headers: { Authorization: 'bar' } + }) + + await browser.url('https://webdriver.io/') + + await browser.execute(async () => { + await fetch('https://webdriver.io/api/foo', { + method: 'POST', + headers: { Authorization: 'foo' }, + body: JSON.stringify({ title: 'foo', description: 'bar' }) + }) + }) + + await expect(mock).toBeRequested() + await expect(mock).toBeRequestedTimes(1) + + // Detailed check (simplified to match available Bidi fields) + await expect(mock).toBeRequestedWith({ + url: 'https://webdriver.io/api/foo', + method: 'POST' + }) + + // Asymmetric matcher as argument (Validating the specific fix) + await expect(mock).toBeRequestedWith(expect.objectContaining({ + method: 'POST' + })) + }) +}) diff --git a/playgrounds/mocha/wdio.conf.ts b/playgrounds/mocha/wdio.conf.ts index 8d159d3dc..0981c5940 100644 --- a/playgrounds/mocha/wdio.conf.ts +++ b/playgrounds/mocha/wdio.conf.ts @@ -18,7 +18,11 @@ export const config: WebdriverIO.Config = { // specs: [ './test/specs/**/*.test.ts', + //'./test/specs/**/basic-matchers.test.ts', //'./test/specs/**/visual-snapshot.test.ts' + //'./test/specs/**/soft-expect.test.ts', + //'./test/specs/**/snapshot.test.ts' + //'./test/specs/**/wdio-matchers.test.ts' ], // diff --git a/src/index.ts b/src/index.ts index c245f2455..945dc2d1b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,19 +1,28 @@ /// import { expect as expectLib } from 'expect' -import type { WdioMatchersObject } from './types.js' +import type { WdioMatchersObject, RawMatcherFn } from './types.js' import * as wdioMatchers from './matchers.js' import { DEFAULT_OPTIONS, defaultOptionsList } from './constants.js' import createSoftExpect from './softExpect.js' import { SoftAssertService } from './softAssert.js' -export const matchers: WdioMatchersObject = new Map() -const filteredMatchers = {} +/** + * Contains only the custom WDIO matchers to be used with `expect.extend()`. + */ +export const wdioCustomMatchers: WdioMatchersObject = {} + +/** + * @deprecated use `wdioCustomMatchers` instead + */ +export const matchers = new Map() + +const filteredMatchers: WdioMatchersObject = {} const extend = expectLib.extend // filter out matchers that aren't a function Object.keys(wdioMatchers).forEach(matcher => { if (typeof wdioMatchers[matcher as keyof typeof wdioMatchers] === 'function') { - filteredMatchers[matcher as keyof typeof filteredMatchers] = wdioMatchers[matcher as keyof typeof filteredMatchers] + filteredMatchers[matcher] = wdioMatchers[matcher as keyof typeof wdioMatchers] as RawMatcherFn } }) @@ -22,7 +31,10 @@ expectLib.extend = (m) => { return } - Object.entries(m).forEach(([name, matcher]) => matchers.set(name, matcher)) + Object.entries(m).forEach(([name, matcher]) => { + wdioCustomMatchers[name] = matcher + matchers.set(name, matcher) + }) return extend(m) } diff --git a/src/softExpect.ts b/src/softExpect.ts index 31edd5402..28b72e3eb 100644 --- a/src/softExpect.ts +++ b/src/softExpect.ts @@ -1,4 +1,4 @@ -import { expect, matchers } from './index.js' +import { expect, wdioCustomMatchers } from './index.js' import { SoftAssertService } from './softAssert.js' /** @@ -24,7 +24,7 @@ const createSoftExpect = (actual: T): ExpectWebdriverIO.Matchers(actual: T, softService: SoftAssertService) => { return new Proxy({} as ExpectWebdriverIO.Matchers, T>, { get(target, prop) { const propName = String(prop) - if (matchers.has(propName)) { + if (propName in wdioCustomMatchers) { return createSoftMatcher(actual, propName, softService, 'not') } return undefined @@ -56,7 +56,7 @@ const createSoftChainProxy = (actual: T, chainType: string, softService: Soft return new Proxy({} as ExpectWebdriverIO.Matchers, T>, { get(target, prop) { const propName = String(prop) - if (matchers.has(propName)) { + if (propName in wdioCustomMatchers) { return createSoftMatcher(actual, propName, softService, chainType) } return undefined diff --git a/src/types.ts b/src/types.ts index 7fb7d2420..ef955ebac 100644 --- a/src/types.ts +++ b/src/types.ts @@ -15,4 +15,4 @@ export type RawMatcherFn = { (this: Context, actual: unknown, ...expected: unknown[]): ExpectationResult; } -export type WdioMatchersObject = Map +export type WdioMatchersObject = Record diff --git a/src/utils.ts b/src/utils.ts index 3987241ab..bb7c18abf 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -11,24 +11,40 @@ import { enhanceError, enhanceErrorBe, numberError } from './util/formatMessage. const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) -const asymmetricMatcher = - typeof Symbol === 'function' && Symbol.for - ? Symbol.for('jest.asymmetricMatcher') - : 0x13_57_a5 +export function isWdioAsymmetricMatcher(expected: unknown): expected is WdioAsymmetricMatcher { + return isAsymmetricMatcher(expected) && 'sample' in expected +} + +export function isJasmineAsymmetricMatcher(expected: unknown): expected is JasmineAsymmetricMatcher { + return isAsymmetricMatcher(expected) && 'expected' in expected +} -export function isAsymmetricMatcher(expected: unknown): expected is WdioAsymmetricMatcher { +export function isAsymmetricMatcher(expected: unknown): expected is WdioAsymmetricMatcher | JasmineAsymmetricMatcher { return ( typeof expected === 'object' && - expected && - '$$typeof' in expected && + !!expected && 'asymmetricMatch' in expected && - expected.$$typeof === asymmetricMatcher && - Boolean(expected.asymmetricMatch) - ) as boolean + !!expected.asymmetricMatch + ) } -function isStringContainingMatcher(expected: unknown): expected is WdioAsymmetricMatcher { - return isAsymmetricMatcher(expected) && ['StringContaining', 'StringNotContaining'].includes(expected.toString()) +export function isStringContainingMatcherLike(expected: unknown): expected is WdioAsymmetricMatcher | JasmineAsymmetricMatcher { + return !!expected && expected.constructor.name === 'StringContaining' +} + +export function isStrictlyStringContainingMatcher(expected: unknown): expected is WdioAsymmetricMatcher | JasmineAsymmetricMatcher { + return isStringContainingMatcherLike(expected) && (!isWdioAsymmetricMatcher(expected) || expected.toString().includes('StringContaining')) +} + +export function getAsymmetricMatcherValue( + expected: WdioAsymmetricMatcher | JasmineAsymmetricMatcher +): T { + if ('expected' in expected) { + return expected.expected + } else if ('sample' in expected) { + return expected.sample + } + throw new Error(`Could not extract value from asymmetric matcher: ${String(expected)}`) } /** @@ -141,7 +157,7 @@ const compareNumbers = (actual: number, options: ExpectWebdriverIO.NumberOptions export const compareText = ( actual: string, - expected: string | RegExp | WdioAsymmetricMatcher, + expected: string | RegExp | WdioAsymmetricMatcher | JasmineAsymmetricMatcher, { ignoreCase = false, trim = true, @@ -169,10 +185,11 @@ export const compareText = ( actual = actual.toLowerCase() if (typeof expected === 'string') { expected = expected.toLowerCase() - } else if (isStringContainingMatcher(expected)) { - expected = (expected.toString() === 'StringContaining' - ? expect.stringContaining(expected.sample?.toString().toLowerCase()) - : expect.not.stringContaining(expected.sample?.toString().toLowerCase())) as WdioAsymmetricMatcher + } else if (isStringContainingMatcherLike(expected)) { + const sample = getAsymmetricMatcherValue(expected).toString().toLocaleLowerCase() + expected = (isStrictlyStringContainingMatcher(expected) + ? expect.stringContaining(sample) + : expect.not.stringContaining(sample)) as WdioAsymmetricMatcher } } @@ -256,7 +273,7 @@ export const compareTextWithArray = ( if (typeof item === 'string') { return item.toLowerCase() } - if (isStringContainingMatcher(item)) { + if (isStringContainingMatcherLike(item)) { return (item.toString() === 'StringContaining' ? expect.stringContaining(item.sample?.toString().toLowerCase()) : expect.not.stringContaining(item.sample?.toString().toLowerCase())) as WdioAsymmetricMatcher diff --git a/test-types/jasmine-async/types-jasmine_async.test.ts b/test-types/jasmine-async/types-jasmine_async.test.ts deleted file mode 100644 index 01f9611e4..000000000 --- a/test-types/jasmine-async/types-jasmine_async.test.ts +++ /dev/null @@ -1,811 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import { expect as wdioExpect } from 'expect-webdriverio' -describe('type assertions', () => { - const chainableElement = {} as unknown as ChainablePromiseElement - const chainableArray = {} as ChainablePromiseArray - - const element: WebdriverIO.Element = {} as unknown as WebdriverIO.Element - const elementArray: WebdriverIO.ElementArray = [] as unknown as WebdriverIO.ElementArray - - const networkMock: WebdriverIO.Mock = {} as unknown as WebdriverIO.Mock - - // Type assertions - let expectPromiseVoid: Promise - let expectVoid: void - let expectPromiseUnknown: Promise - - describe('Browser', () => { - const browser: WebdriverIO.Browser = {} as unknown as WebdriverIO.Browser - - describe('toHaveUrl', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = expectAsync(browser).toHaveUrl('https://example.com') - expectPromiseVoid = expectAsync(browser).not.toHaveUrl('https://example.com') - - // Asymmetric matchers - expectPromiseVoid = expectAsync(browser).toHaveUrl(wdioExpect.stringContaining('WebdriverIO')) - expectPromiseVoid = expectAsync(browser).toHaveUrl(wdioExpect.not.stringContaining('WebdriverIO')) - expectPromiseVoid = expectAsync(browser).toHaveUrl(wdioExpect.any(String)) - expectPromiseVoid = expectAsync(browser).toHaveUrl(wdioExpect.anything()) - - // @ts-expect-error - expectVoid = expectAsync(browser).toHaveUrl('https://example.com') - // @ts-expect-error - expectVoid = expectAsync(browser).not.toHaveUrl('https://example.com') - // @ts-expect-error - expectVoid = expectAsync(browser).toHaveUrl(wdioExpect.stringContaining('WebdriverIO')) - - // @ts-expect-error - await expectAsync(browser).toHaveUrl(6) - }) - - it('should have ts errors when actual is not a Browser element', async () => { - // @ts-expect-error - await expectAsync(element).toHaveUrl('https://example.com') - // @ts-expect-error - await expectAsync(element).not.toHaveUrl('https://example.com') - // @ts-expect-error - await expectAsync(true).toHaveUrl('https://example.com') - // @ts-expect-error - await expectAsync(true).not.toHaveUrl('https://example.com') - }) - }) - - describe('toHaveTitle', () => { - it('should be supported correctly', async () => { - const test = expectAsync('text') - expectPromiseVoid = expectAsync(browser).toHaveTitle('https://example.com') - expectPromiseVoid = expectAsync(browser).not.toHaveTitle('https://example.com') - - // Asymmetric matchers - expectPromiseVoid = expectAsync(browser).toHaveTitle(wdioExpect.stringContaining('WebdriverIO')) - expectPromiseVoid = expectAsync(browser).toHaveTitle(wdioExpect.any(String)) - expectPromiseVoid = expectAsync(browser).toHaveTitle(wdioExpect.anything()) - - // @ts-expect-error - expectVoid = expectAsync(browser).toHaveTitle('https://example.com') - // @ts-expect-error - expectVoid = expectAsync(browser).not.toHaveTitle('https://example.com') - // @ts-expect-error - expectVoid = expectAsync(browser).toHaveTitle(wdioExpect.stringContaining('WebdriverIO')) - }) - - it('should have ts errors when actual is not a Browser element', async () => { - // @ts-expect-error - await expectAsync(element).toHaveTitle('https://example.com') - // @ts-expect-error - await expectAsync(element).not.toHaveTitle('https://example.com') - // @ts-expect-error - await expectAsync(true).toHaveTitle('https://example.com') - // @ts-expect-error - await expectAsync(true).not.toHaveTitle('https://example.com') - }) - }) - }) - - describe('element', () => { - - describe('toBeDisabled', () => { - it('should be supported correctly', async () => { - // Element - expectPromiseVoid = expectAsync(element).toBeDisabled() - expectPromiseVoid = expectAsync(element).not.toBeDisabled() - - // Element array - expectPromiseVoid = expectAsync(elementArray).toBeDisabled() - expectPromiseVoid = expectAsync(elementArray).not.toBeDisabled() - - // Chainable element - expectPromiseVoid = expectAsync(chainableElement).toBeDisabled() - expectPromiseVoid = expectAsync(chainableElement).not.toBeDisabled() - - // Chainable element array - expectPromiseVoid = expectAsync(chainableArray).toBeDisabled() - expectPromiseVoid = expectAsync(chainableArray).not.toBeDisabled() - - // @ts-expect-error - expectVoid = expectAsync(element).toBeDisabled() - // @ts-expect-error - expectVoid = expectAsync(element).not.toBeDisabled() - }) - - it('should have ts errors when actual is not an element', async () => { - // @ts-expect-error - await expectAsync(browser).toBeDisabled() - // @ts-expect-error - await expectAsync(browser).not.toBeDisabled() - // @ts-expect-error - await expectAsync(true).toBeDisabled() - // @ts-expect-error - await expectAsync(true).not.toBeDisabled() - }) - }) - - describe('toHaveText', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = expectAsync(element).toHaveText('text') - expectPromiseVoid = expectAsync(element).toHaveText(/text/) - expectPromiseVoid = expectAsync(element).toHaveText(['text1', 'text2']) - expectPromiseVoid = expectAsync(element).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')]) - expectPromiseVoid = expectAsync(element).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expectAsync(element).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')]) - await expectAsync(element).toHaveText( - 'My-Ex-Am-Ple', - { - replace: [[/-/g, ' '], [/[A-Z]+/g, (match: string) => match.toLowerCase()]] - } - ) - - expectPromiseVoid = expectAsync(element).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expectAsync(element).toHaveText('text') - // @ts-expect-error - await expectAsync(element).toHaveText(6) - - expectPromiseVoid = expectAsync(chainableElement).toHaveText('text') - expectPromiseVoid = expectAsync(chainableElement).toHaveText(/text/) - expectPromiseVoid = expectAsync(chainableElement).toHaveText(['text1', 'text2']) - expectPromiseVoid = expectAsync(chainableElement).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')]) - expectPromiseVoid = expectAsync(chainableElement).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expectAsync(chainableElement).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')]) - - expectPromiseVoid = expectAsync(chainableElement).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expectAsync(chainableElement).toHaveText('text') - // @ts-expect-error - await expectAsync(chainableElement).toHaveText(6) - - expectPromiseVoid = expectAsync(elementArray).toHaveText('text') - expectPromiseVoid = expectAsync(elementArray).toHaveText(/text/) - expectPromiseVoid = expectAsync(elementArray).toHaveText(['text1', 'text2']) - expectPromiseVoid = expectAsync(elementArray).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')]) - expectPromiseVoid = expectAsync(elementArray).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expectAsync(elementArray).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')]) - - expectPromiseVoid = expectAsync(elementArray).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expectAsync(elementArray).toHaveText('text') - // @ts-expect-error - await expectAsync(elementArray).toHaveText(6) - - expectPromiseVoid = expectAsync(chainableArray).toHaveText('text') - expectPromiseVoid = expectAsync(chainableArray).toHaveText(/text/) - expectPromiseVoid = expectAsync(chainableArray).toHaveText(['text1', 'text2']) - expectPromiseVoid = expectAsync(chainableArray).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')]) - expectPromiseVoid = expectAsync(chainableArray).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expectAsync(chainableArray).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')]) - - expectPromiseVoid = expectAsync(chainableArray).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expectAsync(chainableArray).toHaveText('text') - // @ts-expect-error - await expectAsync(chainableArray).toHaveText(6) - - // @ts-expect-error - await expectAsync(browser).toHaveText('text') - }) - - it('should have ts errors when actual is not an element', async () => { - // @ts-expect-error - await expectAsync(browser).toHaveText('text') - // @ts-expect-error - await expectAsync(browser).not.toHaveText('text') - // @ts-expect-error - await expectAsync(true).toHaveText('text') - // @ts-expect-error - await expectAsync(true).toHaveText('text') - }) - - it('should have ts errors when actual is string or Promise', async () => { - // @ts-expect-error - await expectAsync('text').toHaveText('text') - // @ts-expect-error - await expectAsync('text').not.toHaveText('text') - // @ts-expect-error - await expectAsync(Promise.resolve('text')).toHaveText('text') - // @ts-expect-error - await expectAsync(Promise.resolve('text')).toHaveText('text') - }) - }) - - describe('toHaveHeight', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = expectAsync(element).toHaveHeight(100) - expectPromiseVoid = expectAsync(element).toHaveHeight(100, { message: 'Custom error message' }) - expectPromiseVoid = expectAsync(element).not.toHaveHeight(100) - expectPromiseVoid = expectAsync(element).not.toHaveHeight(100, { message: 'Custom error message' }) - - expectPromiseVoid = expectAsync(element).toHaveHeight({ width: 100, height: 200 }) - expectPromiseVoid = expectAsync(element).toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' }) - expectPromiseVoid = expectAsync(element).not.toHaveHeight({ width: 100, height: 200 }) - expectPromiseVoid = expectAsync(element).not.toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' }) - - // @ts-expect-error - expectVoid = expectAsync(element).toHaveHeight(100) - // @ts-expect-error - expectVoid = expectAsync(element).not.toHaveHeight(100) - - // @ts-expect-error - expectVoid = expectAsync(element).toHaveHeight({ width: 100, height: 200 }) - // @ts-expect-error - expectVoid = expectAsync(element).not.toHaveHeight({ width: 100, height: 200 }) - - // @ts-expect-error - await expectAsync(browser).toHaveHeight(100) - }) - - it('should have ts errors when actual is string or Promise', async () => { - // @ts-expect-error - await expectAsync('text').toHaveText('text') - // @ts-expect-error - await expectAsync('text').not.toHaveText('text') - // @ts-expect-error - await expectAsync(Promise.resolve('text')).toHaveText('text') - // @ts-expect-error - await expectAsync(Promise.resolve('text')).toHaveText('text') - }) - }) - - describe('toMatchSnapshot', () => { - - it('should be supported correctly', async () => { - expectPromiseVoid = expectAsync(element).toMatchSnapshot() - expectPromiseVoid = expectAsync(element).toMatchSnapshot('test label') - expectPromiseVoid = expectAsync(element).not.toMatchSnapshot('test label') - - expectPromiseVoid = expectAsync(chainableElement).toMatchSnapshot() - expectPromiseVoid = expectAsync(chainableElement).toMatchSnapshot('test label') - expectPromiseVoid = expectAsync(chainableElement).not.toMatchSnapshot('test label') - }) - }) - - describe('toMatchInlineSnapshot', () => { - - it('should be correctly supported', async () => { - expectPromiseVoid = expectAsync(element).toMatchInlineSnapshot() - expectPromiseVoid = expectAsync(element).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = expectAsync(element).toMatchInlineSnapshot('test snapshot', 'test label') - - expectPromiseVoid = expectAsync(chainableElement).toMatchInlineSnapshot() - expectPromiseVoid = expectAsync(chainableElement).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = expectAsync(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label') - - //@ts-expect-error - expectVoid = expectAsync(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label') - }) - - it('should be correctly supported with getCSSProperty()', async () => { - expectPromiseVoid = expectAsync(element.getCSSProperty('test')).toMatchInlineSnapshot() - expectPromiseVoid = expectAsync(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = expectAsync(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label') - - expectPromiseVoid = expectAsync(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot() - expectPromiseVoid = expectAsync(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = expectAsync(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label') - - //@ts-expect-error - expectVoid = expectAsync(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label') - }) - }) - - describe('toBeElementsArrayOfSize', async () => { - - it('should work correctly when actual is chainableArray', async () => { - expectPromiseVoid = expectAsync(chainableArray).toBeElementsArrayOfSize(5) - expectPromiseVoid = expectAsync(chainableArray).toBeElementsArrayOfSize({ lte: 10 }) - - // @ts-expect-error - expectVoid = expectAsync(chainableArray).toBeElementsArrayOfSize(5) - // @ts-expect-error - expectVoid = expectAsync(chainableArray).toBeElementsArrayOfSize({ lte: 10 }) - }) - - it('should not work when actual is not chainableArray', async () => { - // @ts-expect-error - await expectAsync(chainableElement).toBeElementsArrayOfSize(5) - // @ts-expect-error - await expectAsync(chainableElement).toBeElementsArrayOfSize({ lte: 10 }) - // @ts-expect-error - await expectAsync(true).toBeElementsArrayOfSize(5) - // @ts-expect-error - await expectAsync(true).toBeElementsArrayOfSize({ lte: 10 }) - }) - }) - }) - - describe('Custom matchers', () => { - describe('using `ExpectWebdriverIO` namespace augmentation', () => { - - it('should supported correctly a promise custom matcher with only chainableElement as actual', async () => { - expectPromiseVoid = expectAsync(chainableElement).toBeCustomPromise() - expectPromiseVoid = expectAsync(chainableElement).toBeCustomPromise(wdioExpect.stringContaining('test')) - expectPromiseVoid = expectAsync(chainableElement).not.toBeCustomPromise(wdioExpect.not.stringContaining('test')) - - // @ts-expect-error - expectAsync('test').toBeCustomPromise() - // @ts-expect-error - expectVoid = expectAsync(chainableElement).toBeCustomPromise() - // @ts-expect-error - expectVoid = expectAsync(chainableElement).toBeCustomPromise(wdioExpect.stringContaining('test')) - // @ts-expect-error - expectVoid = expectAsync(chainableElement).not.toBeCustomPromise(wdioExpect.stringContaining('test')) - // @ts-expect-error - expectAsync(chainableElement).toBeCustomPromise(wdioExpect.stringContaining(6)) - }) - - it('should support custom asymmetric matcher', async () => { - const expectString1 : ExpectWebdriverIO.PartialMatcher = wdioExpect.toBeCustom() - const expectString2 : ExpectWebdriverIO.PartialMatcher = wdioExpect.not.toBeCustom() - - expectPromiseVoid = expectAsync(chainableElement).toBeCustomPromise(wdioExpect.toBeCustom()) - - // @ts-expect-error - expectPromiseVoid = wdioExpect.toBeCustom() - // @ts-expect-error - expectPromiseVoid = wdioExpect.not.toBeCustom() - - //@ts-expect-error - expectVoid = expectAsync(chainableElement).toBeCustomPromise(wdioExpect.toBeCustom()) - }) - }) - - describe('using `expect` module declaration', () => { - - it('should support a simple matcher', async () => { - expectPromiseVoid = expectAsync(5).toBeWithinRange(1, 10) - - // Or as an asymmetric matcher: - expectPromiseVoid = expectAsync({ value: 5 }).toEqual({ - value: wdioExpect.toBeWithinRange(1, 10) - }) - - // @ts-expect-error - expectVoid = expectAsync(5).toBeWithinRange(1, '10') - // @ts-expect-error - expectAsync(5).toBeWithinRange('1') - }) - - it('should support a simple custom matcher with a chainable element matcher with promise', async () => { - expectPromiseVoid = expectAsync(chainableElement).toHaveSimpleCustomProperty('text') - expectPromiseVoid = expectAsync(chainableElement).toHaveSimpleCustomProperty(wdioExpect.stringContaining('text')) - expectPromiseVoid = expectAsync(chainableElement).not.toHaveSimpleCustomProperty(wdioExpect.not.stringContaining('text')) - - // Or as a custom asymmetric matcher: - expectPromiseVoid = expectAsync(chainableElement).toHaveSimpleCustomProperty( - wdioExpect.toHaveSimpleCustomProperty('string') - ) - const expectString1:string = wdioExpect.toHaveSimpleCustomProperty('string') - const expectString2:string = wdioExpect.not.toHaveSimpleCustomProperty('string') - - // @ts-expect-error - expectVoid = wdioExpect.toHaveSimpleCustomProperty(chainableElement) - // @ts-expect-error - expectVoid = wdioExpect.not.toHaveSimpleCustomProperty(chainableElement) - - // @ts-expect-error - expectVoid = wdioExpect.toHaveSimpleCustomProperty(chainableElement) - }) - - it('should support a chainable element matcher with promise', async () => { - expectPromiseVoid = expectAsync(chainableElement).toHaveCustomProperty('text') - expectPromiseVoid = expectAsync(chainableElement).toHaveCustomProperty(wdioExpect.stringContaining('text')) - expectPromiseVoid = expectAsync(chainableElement).not.toHaveCustomProperty(wdioExpect.not.stringContaining('text')) - - // Or as a custom asymmetric matcher: - expectPromiseVoid = expectAsync(chainableElement).toHaveCustomProperty( - await wdioExpect.toHaveCustomProperty(chainableElement) - ) - const expectPromiseWdioElement1: Promise> = wdioExpect.toHaveCustomProperty(chainableElement) - const expectPromiseWdioElement2: Promise> = wdioExpect.not.toHaveCustomProperty(chainableElement) - - // @ts-expect-error - expectVoid = wdioExpect.toHaveCustomProperty(chainableElement) - // @ts-expect-error - expectVoid = wdioExpect.not.toHaveCustomProperty(chainableElement) - - // @ts-expect-error - expectVoid = wdioExpect.toHaveCustomProperty(chainableElement) - // @ts-expect-error - wdioExpect.toHaveCustomProperty('test') - - await expectAsync(chainableElement).toHaveCustomProperty( - await wdioExpect.toHaveCustomProperty(chainableElement) - ) - }) - }) - }) - - describe('toBe', () => { - it('should expect void type when actual is a boolean', async () => { - expectVoid = expect(true).toBe(true) - expectVoid = expect(true).not.toBe(true) - - expectPromiseVoid = expectAsync(true).toBe(true) - expectPromiseVoid = expectAsync(true).not.toBe(true) - }) - - it('should expect Promise when actual is a chainable since toBe does not need to be awaited', async () => { - expectPromiseVoid = expectAsync(chainableElement).toBe(true) - expectPromiseVoid = expectAsync(chainableElement).not.toBe(true) - }) - - it('should expect Promise type when actual is a Promise since it is expectAsync', async () => { - const promiseBoolean = Promise.resolve(true) - - expectPromiseUnknown = expectAsync(promiseBoolean).toBe(true) - expectPromiseUnknown = expectAsync(promiseBoolean).not.toBe(true) - - expectPromiseVoid = expectAsync(promiseBoolean).toBe(true) - expectPromiseVoid = expectAsync(promiseBoolean).toBe(true) - }) - - it('should work with string', async () => { - expectPromiseUnknown = expectAsync('text').toBe(true) - expectPromiseUnknown = expectAsync('text').not.toBe(true) - expectPromiseUnknown = expectAsync('text').toBe(wdioExpect.stringContaining('text')) - expectPromiseUnknown = expectAsync('text').not.toBe(wdioExpect.stringContaining('text')) - - expectPromiseVoid = expectAsync('text').toBe(true) - expectPromiseVoid = expectAsync('text').not.toBe(true) - expectPromiseVoid = expectAsync('text').toBe(wdioExpect.stringContaining('text')) - expectPromiseVoid = expectAsync('text').not.toBe(wdioExpect.stringContaining('text')) - }) - }) - - describe('Promise type assertions', () => { - const booleanPromise: Promise = Promise.resolve(true) - - it('should expect a Promise of type', async () => { - const expectPromiseBoolean1: jasmine.AsyncMatchers = expectAsync(booleanPromise) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const expectPromiseBoolean2: jasmine.AsyncMatchers = expectAsync(booleanPromise).not - }) - - it('should work with resolves & rejects correctly', async () => { - //@ts-expect-error - expectAsync(booleanPromise).resolves.toBe(true) - //@ts-expect-error - expectAsync(booleanPromise).rejects.toBe(true) - }) - - it('should not support chainable and expect PromiseVoid with toBe', async () => { - expectPromiseVoid = expectAsync(chainableElement).toBe(true) - expectPromiseVoid = expectAsync(chainableElement).not.toBe(true) - }) - }) - - describe('Network Matchers', () => { - const promiseNetworkMock = Promise.resolve(networkMock) - - it('should not have ts errors when typing to Promise', async () => { - expectPromiseVoid = expectAsync(promiseNetworkMock).toBeRequested() - expectPromiseVoid = expectAsync(promiseNetworkMock).toBeRequestedTimes(2) - expectPromiseVoid = expectAsync(promiseNetworkMock).toBeRequestedTimes({ gte: 5, lte: 10 }) - - expectPromiseVoid = expectAsync(promiseNetworkMock).not.toBeRequested() - expectPromiseVoid = expectAsync(promiseNetworkMock).not.toBeRequestedTimes(2) - expectPromiseVoid = expectAsync(promiseNetworkMock).not.toBeRequestedTimes({ gte: 5, lte: 10 }) - - expectPromiseVoid = expectAsync(promiseNetworkMock).toBeRequestedWith({ - url: 'http://localhost:8080/api', - method: 'POST', - statusCode: 200, - requestHeaders: { Authorization: 'foo' }, - responseHeaders: { Authorization: 'bar' }, - postData: { title: 'foo', description: 'bar' }, - response: { success: true }, - }) - - expectPromiseVoid = expectAsync(promiseNetworkMock).toBeRequestedWith({ - url: wdioExpect.stringContaining('test'), - method: 'POST', - statusCode: 200, - requestHeaders: wdioExpect.objectContaining({ Authorization: 'foo' }), - responseHeaders: wdioExpect.objectContaining({ Authorization: 'bar' }), - postData: wdioExpect.objectContaining({ title: 'foo', description: 'bar' }), - response: wdioExpect.objectContaining({ success: true }), - }) - - expectPromiseVoid = expectAsync(promiseNetworkMock).toBeRequestedWith({ - url: wdioExpect.stringMatching(/.*\/api\/.*/i), - method: ['POST', 'PUT'], - statusCode: [401, 403], - requestHeaders: headers => headers.Authorization.startsWith('Bearer '), - postData: wdioExpect.objectContaining({ released: true, title: wdioExpect.stringContaining('foobar') }), - response: (r: { data: { items: unknown[] } }) => Array.isArray(r) && r.data.items.length === 20 - }) - }) - - it('should have ts errors when typing to void', async () => { - // @ts-expect-error - expectVoid = expectAsync(promiseNetworkMock).toBeRequested() - // @ts-expect-error - expectVoid = expectAsync(promiseNetworkMock).toBeRequestedTimes(2) // await expectAsync(mock).toBeRequestedTimes({ eq: 2 }) - // @ts-expect-error - expectVoid = expectAsync(promiseNetworkMock).toBeRequestedTimes({ gte: 5, lte: 10 }) // request called at least 5 times but less than 11 - - // @ts-expect-error - expectVoid = expectAsync(promiseNetworkMock).not.toBeRequested() - // @ts-expect-error - expectVoid = expectAsync(promiseNetworkMock).not.toBeRequestedTimes(2) // await expectAsync(mock).toBeRequestedTimes({ eq: 2 }) - // @ts-expect-error - expectVoid = expectAsync(promiseNetworkMock).not.toBeRequestedTimes({ gte: 5, lte: 10 }) // request called at least 5 times but less than 11 - - // @ts-expect-error - expectVoid = expectAsync(promiseNetworkMock).toBeRequestedWith({ - url: 'http://localhost:8080/api', - method: 'POST', - statusCode: 200, - requestHeaders: { Authorization: 'foo' }, - responseHeaders: { Authorization: 'bar' }, - postData: { title: 'foo', description: 'bar' }, - response: { success: true }, - }) - - // @ts-expect-error - expectVoid = expectAsync(promiseNetworkMock).toBeRequestedWith(wdioExpect.objectContaining({ - response: { success: true }, - })) - }) - }) - - describe('Expect', () => { - it('should have ts errors when using a non existing wdioExpect.function', async () => { - // @ts-expect-error - wdioExpect.unimplementedFunction() - }) - - it('should support stringContaining, anything and more', async () => { - wdioExpect.stringContaining('WebdriverIO') - wdioExpect.stringMatching(/WebdriverIO/) - wdioExpect.arrayContaining(['WebdriverIO', 'Test']) - wdioExpect.objectContaining({ name: 'WebdriverIO' }) - // Was not there but works! - wdioExpect.closeTo(5, 10) - wdioExpect.arrayContaining(['WebdriverIO', 'Test']) - // New from jest 30!! - wdioExpect.arrayOf(wdioExpect.stringContaining('WebdriverIO')) - - wdioExpect.anything() - wdioExpect.any(Function) - wdioExpect.any(Number) - wdioExpect.any(Boolean) - wdioExpect.any(String) - wdioExpect.any(Symbol) - wdioExpect.any(Date) - wdioExpect.any(Error) - - wdioExpect.not.stringContaining('WebdriverIO') - wdioExpect.not.stringMatching(/WebdriverIO/) - wdioExpect.not.arrayContaining(['WebdriverIO', 'Test']) - wdioExpect.not.objectContaining({ name: 'WebdriverIO' }) - wdioExpect.not.closeTo(5, 10) - wdioExpect.not.arrayContaining(['WebdriverIO', 'Test']) - wdioExpect.not.arrayOf(wdioExpect.stringContaining('WebdriverIO')) - }) - - describe('Soft Assertions', async () => { - const actualString: string = 'Test Page' - const actualPromiseString: Promise = Promise.resolve('Test Page') - - describe('wdioExpect.soft', () => { - it('should not need to be awaited/be a promise if actual is non-promise type', async () => { - const expectWdioMatcher1: WdioCustomMatchers = wdioExpect.soft(actualString) - expectVoid = wdioExpect.soft(actualString).toBe('Test Page') - expectVoid = wdioExpect.soft(actualString).not.toBe('Test Page') - expectVoid = wdioExpect.soft(actualString).not.toBe(wdioExpect.stringContaining('Test Page')) - - // @ts-expect-error - expectPromiseVoid = wdioExpect.soft(actualString).toBe('Test Page') - // @ts-expect-error - expectPromiseVoid = wdioExpect.soft(actualString).not.toBe('Test Page') - // @ts-expect-error - expectPromiseVoid = wdioExpect.soft(actualString).not.toBe(wdioExpect.stringContaining('Test Page')) - }) - - it('should need to be awaited/be a promise if actual is promise type', async () => { - const expectWdioMatcher1: ExpectWebdriverIO.MatchersAndInverse, Promise> = wdioExpect.soft(actualPromiseString) - expectPromiseVoid = wdioExpect.soft(actualPromiseString).toBe('Test Page') - expectPromiseVoid = wdioExpect.soft(actualPromiseString).not.toBe('Test Page') - expectPromiseVoid = wdioExpect.soft(actualPromiseString).not.toBe(wdioExpect.stringContaining('Test Page')) - - // @ts-expect-error - expectVoid = wdioExpect.soft(actualPromiseString).toBe('Test Page') - // @ts-expect-error - expectVoid = wdioExpect.soft(actualPromiseString).not.toBe('Test Page') - // @ts-expect-error - expectVoid = wdioExpect.soft(actualPromiseString).not.toBe(wdioExpect.stringContaining('Test Page')) - }) - - it('should support chainable element', async () => { - const expectElement: WdioCustomMatchers = wdioExpect.soft(element) - const expectElementChainable: WdioCustomMatchers = wdioExpect.soft(chainableElement) - - // // @ts-expect-error - // const expectElement2: WdioCustomMatchers, WebdriverIO.Element> = wdioExpect.soft(element) - // // @ts-expect-error - // const expectElementChainable2: WdioCustomMatchers, typeof chainableElement> = wdioExpect.soft(chainableElement) - }) - - it('should support chainable element with wdio Matchers', async () => { - expectPromiseVoid = wdioExpect.soft(element).toBeDisplayed() - expectPromiseVoid = wdioExpect.soft(chainableElement).toBeDisplayed() - expectPromiseVoid = wdioExpect.soft(chainableArray).toBeDisplayed() - await wdioExpect.soft(element).toBeDisplayed() - await wdioExpect.soft(chainableElement).toBeDisplayed() - await wdioExpect.soft(chainableArray).toBeDisplayed() - - expectPromiseVoid = wdioExpect.soft(element).not.toBeDisplayed() - expectPromiseVoid = wdioExpect.soft(chainableElement).not.toBeDisplayed() - expectPromiseVoid = wdioExpect.soft(chainableArray).not.toBeDisplayed() - await wdioExpect.soft(element).not.toBeDisplayed() - await wdioExpect.soft(chainableElement).not.toBeDisplayed() - await wdioExpect.soft(chainableArray).not.toBeDisplayed() - - // @ts-expect-error - expectVoid = wdioExpect.soft(element).toBeDisplayed() - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).toBeDisplayed() - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableArray).toBeDisplayed() - - // @ts-expect-error - expectVoid = wdioExpect.soft(element).not.toBeDisplayed() - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).not.toBeDisplayed() - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableArray).not.toBeDisplayed() - }) - it('should work with custom matcher and custom asymmetric matchers from `expect` module', async () => { - expectPromiseVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty('text') - expectPromiseVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty(wdioExpect.stringContaining('text')) - expectPromiseVoid = wdioExpect.soft(chainableElement).not.toHaveCustomProperty(wdioExpect.not.stringContaining('text')) - expectPromiseVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty( - wdioExpect.toHaveCustomProperty(chainableElement) - ) - - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty('text') - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty(wdioExpect.stringContaining('text')) - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).not.toHaveCustomProperty(wdioExpect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty( - wdioExpect.toHaveCustomProperty(chainableElement) - ) - - expectPromiseVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty('text') - expectPromiseVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty(wdioExpect.stringContaining('text')) - expectPromiseVoid = wdioExpect.soft(chainableElement).not.toHaveCustomProperty(wdioExpect.not.stringContaining('text')) - expectPromiseVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty( - wdioExpect.toHaveCustomProperty(chainableElement) - ) - - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty('text') - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty(wdioExpect.stringContaining('text')) - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).not.toHaveCustomProperty(wdioExpect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty( - wdioExpect.toHaveCustomProperty(chainableElement) - ) - }) - - it('should work with custom matcher and custom asymmetric matchers from `ExpectWebDriverIO` namespace', async () => { - expectPromiseVoid = wdioExpect.soft(chainableElement).toBeCustomPromise('text') - expectPromiseVoid = wdioExpect.soft(chainableElement).toBeCustomPromise(wdioExpect.stringContaining('text')) - expectPromiseVoid = wdioExpect.soft(chainableElement).not.toBeCustomPromise(wdioExpect.not.stringContaining('text')) - expectPromiseVoid = wdioExpect.soft(chainableElement).toBeCustomPromise( - wdioExpect.toBeCustomPromise(chainableElement) - ) - - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).toBeCustomPromise('text') - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).toBeCustomPromise(wdioExpect.stringContaining('text')) - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).not.toBeCustomPromise(wdioExpect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).toBeCustomPromise( - wdioExpect.toBeCustomPromise(chainableElement) - ) - - expectPromiseVoid = wdioExpect.soft(chainableElement).toBeCustomPromise('text') - expectPromiseVoid = wdioExpect.soft(chainableElement).toBeCustomPromise(wdioExpect.stringContaining('text')) - expectPromiseVoid = wdioExpect.soft(chainableElement).not.toBeCustomPromise(wdioExpect.not.stringContaining('text')) - expectPromiseVoid = wdioExpect.soft(chainableElement).toBeCustomPromise( - wdioExpect.toBeCustomPromise(chainableElement) - ) - - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).toBeCustomPromise('text') - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).toBeCustomPromise(wdioExpect.stringContaining('text')) - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).not.toBeCustomPromise(wdioExpect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).toBeCustomPromise( - wdioExpect.toBeCustomPromise(chainableElement) - ) - }) - }) - - describe('wdioExpect.getSoftFailures', () => { - it('should be of type `SoftFailure`', async () => { - const expectSoftFailure1: ExpectWebdriverIO.SoftFailure[] = wdioExpect.getSoftFailures() - - // @ts-expect-error - expectVoid = wdioExpect.getSoftFailures() - }) - }) - - describe('wdioExpect.assertSoftFailures', () => { - it('should be of type void', async () => { - expectVoid = wdioExpect.assertSoftFailures() - - // @ts-expect-error - expectPromiseVoid = wdioExpect.assertSoftFailures() - }) - }) - - describe('wdioExpect.clearSoftFailures', () => { - it('should be of type void', async () => { - expectVoid = wdioExpect.clearSoftFailures() - - // @ts-expect-error - expectPromiseVoid = wdioExpect.clearSoftFailures() - }) - }) - }) - }) - - describe('Asymmetric matchers', () => { - const string: string = 'WebdriverIO is a test framework' - const array: string[] = ['WebdriverIO', 'Test'] - const object: { name: string } = { name: 'WebdriverIO' } - const number: number = 1 - - it('should have no ts error using asymmetric matchers', async () => { - expectAsync(string).toEqual(wdioExpect.stringContaining('WebdriverIO')) - expectAsync(array).toEqual(wdioExpect.arrayContaining(['WebdriverIO', 'Test'])) - expectAsync(object).toEqual(wdioExpect.objectContaining({ name: 'WebdriverIO' })) - // This one is tested and is working correctly, surprisingly! - expectAsync(number).toEqual(wdioExpect.closeTo(1.0001, 0.0001)) - // New from jest 30, should work! - expectAsync(['apple', 'banana', 'cherry']).toEqual(wdioExpect.arrayOf(wdioExpect.any(String))) - }) - }) - - describe('Jasmine only cases', () => { - let expectPromiseLikeVoid: PromiseLike - it('should support expectAsync correctly for non wdio types', async () => { - expectPromiseLikeVoid = expectAsync(Promise.resolve('test')).toBeResolved() - expectPromiseLikeVoid = expectAsync(Promise.resolve('test')).toBeResolvedTo(wdioExpect.stringContaining('test error')) - expectPromiseLikeVoid = expectAsync(Promise.resolve('test')).not.toBeResolvedTo(wdioExpect.not.stringContaining('test error')) - expectPromiseLikeVoid = expectAsync(Promise.resolve('test')).toBeRejected() - expectPromiseLikeVoid = expectAsync(Promise.resolve('test')).not.toBeResolved() - expectPromiseLikeVoid = expectAsync(Promise.resolve('test')).not.toBeRejected() - - // @ts-expect-error - expectVoid = expectAsync(Promise.resolve('test')).toBeResolved() - // @ts-expect-error - expectVoid = expectAsync(Promise.resolve('test')).toBeRejected() - - // @ts-expect-error - expectVoid = expectAsync(Promise.resolve('test')).toBeResolved() - }) - it('jasmine special asymmetric matcher', async () => { - // Note: Even though the below is valid syntax, jasmine prefix for asymmetric matchers is not supported by wdioExpect. - expectAsync({}).toEqual(jasmine.any(Object)) - expectAsync(12).toEqual(jasmine.any(Number)) - }) - - }) -}) diff --git a/test-types/jasmine-async/customMatchers/customMatchers-module-expect.d.ts b/test-types/jasmine-global-expect-async/customMatchers/customMatchers-module-expect.d.ts similarity index 100% rename from test-types/jasmine-async/customMatchers/customMatchers-module-expect.d.ts rename to test-types/jasmine-global-expect-async/customMatchers/customMatchers-module-expect.d.ts diff --git a/test-types/jasmine-async/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts b/test-types/jasmine-global-expect-async/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts similarity index 100% rename from test-types/jasmine-async/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts rename to test-types/jasmine-global-expect-async/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts diff --git a/test-types/jasmine-global-expect-async/jasmine-expect-global.test-d.ts b/test-types/jasmine-global-expect-async/jasmine-expect-global.test-d.ts new file mode 100644 index 000000000..1e2cb4743 --- /dev/null +++ b/test-types/jasmine-global-expect-async/jasmine-expect-global.test-d.ts @@ -0,0 +1,463 @@ +import { expect as wdioExpect } from 'expect-webdriverio' +import { expectTypeOf } from 'vitest' + +describe('Jasmine global type augmentations under `wdio/jasmine-framework`', () => { + const chainableElement = {} as unknown as ChainablePromiseElement + const chainableArray = {} as ChainablePromiseArray + + const element: WebdriverIO.Element = {} as unknown as WebdriverIO.Element + const elementArray: WebdriverIO.ElementArray = [] as unknown as WebdriverIO.ElementArray + const browser: WebdriverIO.Browser = {} as unknown as WebdriverIO.Browser + + const networkMock: WebdriverIO.Mock = {} as unknown as WebdriverIO.Mock + + describe('Augment global expect (forced from jasmine.expectAsync) properly', () => { + + describe('Browser', () => { + const browser: WebdriverIO.Browser = {} as unknown as WebdriverIO.Browser + + describe('toHaveUrl', () => { + it('should return Promise', async () => { + expectTypeOf(expect(browser).toHaveUrl('https://example.com')).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveUrl('https://example.com', { message: 'foo' })).toEqualTypeOf>() + expectTypeOf(expect(browser).not.toHaveUrl('https://example.com')).toEqualTypeOf>() + expectTypeOf(expect(browser).not.toHaveUrl('https://example.com', { message: 'foo' })).toEqualTypeOf>() + + // Asymmetric matchers + expectTypeOf(expect(browser).toHaveUrl(wdioExpect.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveUrl(wdioExpect.not.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveUrl(wdioExpect.any(String))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveUrl(wdioExpect.anything())).toEqualTypeOf>() + + expectTypeOf(expect(browser).toHaveUrl(jasmine.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveUrl(jasmine.any(String))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveUrl(jasmine.anything())).toEqualTypeOf>() + + expectTypeOf(expect(browser).toHaveUrl).parameter(0).extract().toBeNever() + }) + + it('should have ts errors when actual is not a Browser element', async () => { + expectTypeOf(expect(element).toHaveUrl).toBeNever() + expectTypeOf(expect(element).not.toHaveUrl).toBeNever() + expectTypeOf(expect(true).toHaveUrl).toBeNever() + expectTypeOf(expect(true).not.toHaveUrl).toBeNever() + }) + }) + + describe('toHaveTitle', () => { + it('should return Promise', async () => { + expectTypeOf(expect(browser).toHaveTitle('https://example.com')).toEqualTypeOf>() + expectTypeOf(expect(browser).not.toHaveTitle('https://example.com')).toEqualTypeOf>() + + // Asymmetric matchers + expectTypeOf(expect(browser).toHaveTitle(wdioExpect.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveTitle(wdioExpect.any(String))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveTitle(wdioExpect.anything())).toEqualTypeOf>() + + expectTypeOf(expect(browser).toHaveTitle(jasmine.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveTitle(jasmine.any(String))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveTitle(jasmine.anything())).toEqualTypeOf>() + }) + + it('should have ts errors when actual is not a Browser element', async () => { + expectTypeOf(expect(element).toHaveTitle).toBeNever() + expectTypeOf(expect(element).not.toHaveTitle).toBeNever() + expectTypeOf(expect(true).toHaveTitle).toBeNever() + expectTypeOf(expect(true).not.toHaveTitle).toBeNever() + }) + }) + }) + + describe('element', () => { + + describe('toBeDisabled', () => { + it('should return Promise', async () => { + // Element + expectTypeOf(expect(element).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expect(element).not.toBeDisabled()).toEqualTypeOf>() + + // Element array + expectTypeOf(expect(elementArray).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expect(elementArray).not.toBeDisabled()).toEqualTypeOf>() + + // Chainable element + expectTypeOf(expect(chainableElement).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toBeDisabled()).toEqualTypeOf>() + + // Chainable element array + expectTypeOf(expect(chainableArray).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).not.toBeDisabled()).toEqualTypeOf>() + }) + + it('should have ts errors when actual is not an element', async () => { + expectTypeOf(expect(browser).toBeDisabled).toBeNever() + expectTypeOf(expect(browser).not.toBeDisabled).toBeNever() + expectTypeOf(expect(true).toBeDisabled).toBeNever() + expectTypeOf(expect(true).not.toBeDisabled).toBeNever() + }) + }) + + describe('toHaveText', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText([jasmine.stringContaining('text1'), jasmine.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')])).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText( + 'My-Ex-Am-Ple', + { + replace: [[/-/g, ' '], [/[A-Z]+/g, (match: string) => match.toLowerCase()]] + } + )).toEqualTypeOf>() + + expectTypeOf(expect(element).not.toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expect(chainableElement).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText([jasmine.stringContaining('text1'), jasmine.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')])).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement).not.toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expect(elementArray).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText([jasmine.stringContaining('text1'), jasmine.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')])).toEqualTypeOf>() + + expectTypeOf(expect(elementArray).not.toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expect(chainableArray).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText([jasmine.stringContaining('text1'), jasmine.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')])).toEqualTypeOf>() + + expectTypeOf(expect(chainableArray).not.toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expect(browser).toHaveText).toBeNever() + }) + + it('should have ts errors when actual is not an element', async () => { + expectTypeOf(expect(browser).toHaveText).toBeNever() + expectTypeOf(expect(browser).not.toHaveText).toBeNever() + expectTypeOf(expect(true).toHaveText).toBeNever() + expectTypeOf(expect(true).toHaveText).toBeNever() + }) + + it('should have ts errors when actual is string or Promise', async () => { + expectTypeOf(expect('text').toHaveText).toBeNever() + expectTypeOf(expect('text').not.toHaveText).toBeNever() + expectTypeOf(expect(Promise.resolve('text')).toHaveText).toBeNever() + expectTypeOf(expect(Promise.resolve('text')).toHaveText).toBeNever() + }) + }) + + describe('toHaveHeight', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveHeight(100)).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveHeight(100, { message: 'Custom error message' })).toEqualTypeOf>() + expectTypeOf(expect(element).not.toHaveHeight(100)).toEqualTypeOf>() + expectTypeOf(expect(element).not.toHaveHeight(100, { message: 'Custom error message' })).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveHeight({ width: 100, height: 200 })).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' })).toEqualTypeOf>() + expectTypeOf(expect(element).not.toHaveHeight({ width: 100, height: 200 })).toEqualTypeOf>() + expectTypeOf(expect(element).not.toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' })).toEqualTypeOf>() + + expectTypeOf(expect(browser).toHaveHeight).toBeNever() + }) + + it('should have ts errors when actual is string or Promise', async () => { + expectTypeOf(expect('text').toHaveText).toBeNever() + expectTypeOf(expect('text').not.toHaveText).toBeNever() + expectTypeOf(expect(Promise.resolve('text')).toHaveText).toBeNever() + expectTypeOf(expect(Promise.resolve('text')).toHaveText).toBeNever() + }) + }) + + describe('toMatchSnapshot', () => { + + it('should return Promise', async () => { + expectTypeOf(expect(element).toMatchSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(element).toMatchSnapshot('test label')).toEqualTypeOf>() + expectTypeOf(expect(element).not.toMatchSnapshot('test label')).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement).toMatchSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toMatchSnapshot('test label')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toMatchSnapshot('test label')).toEqualTypeOf>() + }) + }) + + describe('toMatchInlineSnapshot', () => { + + it('should return Promise', async () => { + expectTypeOf(expect(element).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(element).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expect(element).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + }) + + it('should return Promise with getCSSProperty()', async () => { + expectTypeOf(expect(element.getCSSProperty('test')).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expect(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + }) + }) + + describe('toBeElementsArrayOfSize', async () => { + + it('should work correctly when actual is chainableArray', async () => { + expectTypeOf(expect(chainableArray).toBeElementsArrayOfSize(5)).toEqualTypeOf & Promise>() + expectTypeOf(expect(chainableArray).toBeElementsArrayOfSize({ lte: 10 })).toEqualTypeOf & Promise>() + expectTypeOf(expect(chainableArray).toBeElementsArrayOfSize(5, { message: 'foo' })).toEqualTypeOf & Promise>() + }) + + it('should not work when actual is not chainableArray', async () => { + expectTypeOf(expect(chainableElement).toBeElementsArrayOfSize).toBeNever() + expectTypeOf(expect(true).toBeElementsArrayOfSize).toBeNever() + }) + }) + }) + + describe('Custom matchers', () => { + describe('using `ExpectWebdriverIO` namespace augmentation', () => { + it('should return Promise for a non-promise custom matcher', async () => { + expectTypeOf(expect('test').toBeCustom()).toEqualTypeOf>() + expectTypeOf(expect('test').not.toBeCustom()).toEqualTypeOf>() + }) + }) + }) + + describe('Jasmine vs Jest pollution', () => { + it('should not include Jest expect library matchers on expect', () => { + // toHaveProperty is a Jest matcher, not Jasmine + expectTypeOf(expect('foo')).not.toHaveProperty('toHaveProperty') + expectTypeOf(expect('foo')).not.toHaveProperty('toMatchObject') + expectTypeOf(expect('foo')).not.toHaveProperty('toStrictEqual') + expectTypeOf(expect('foo')).not.toHaveProperty('toHaveLength') + }) + }) + + describe('Promise type assertions', () => { + const booleanPromise: Promise = Promise.resolve(true) + + it('should not compile', async () => { + expectTypeOf(expect(booleanPromise)).not.toHaveProperty('resolves') + expectTypeOf(expect(booleanPromise)).not.toHaveProperty('rejects') + }) + + }) + + describe('Network Matchers', () => { + const promiseNetworkMock = Promise.resolve(networkMock) + + it('should return Promise', async () => { + expectTypeOf(expect(promiseNetworkMock).toBeRequested()).toEqualTypeOf>() + expectTypeOf(expect(promiseNetworkMock).toBeRequestedTimes(2)).toEqualTypeOf>() + expectTypeOf(expect(promiseNetworkMock).toBeRequestedTimes(2, { message: 'foo' })).toEqualTypeOf>() + expectTypeOf(expect(promiseNetworkMock).toBeRequestedTimes({ gte: 5, lte: 10 })).toEqualTypeOf>() + + expectTypeOf(expect(promiseNetworkMock).not.toBeRequested()).toEqualTypeOf>() + expectTypeOf(expect(promiseNetworkMock).not.toBeRequestedTimes(2)).toEqualTypeOf>() + expectTypeOf(expect(promiseNetworkMock).not.toBeRequestedTimes({ gte: 5, lte: 10 })).toEqualTypeOf>() + + expectTypeOf(expect(promiseNetworkMock).toBeRequestedWith({ + url: 'http://localhost:8080/api', + method: 'POST', + statusCode: 200, + requestHeaders: { Authorization: 'foo' }, + responseHeaders: { Authorization: 'bar' }, + postData: { title: 'foo', description: 'bar' }, + response: { success: true }, + })).toEqualTypeOf>() + + expectTypeOf(expect(promiseNetworkMock).toBeRequestedWith({ + url: wdioExpect.stringContaining('test'), + method: 'POST', + statusCode: 200, + requestHeaders: wdioExpect.objectContaining({ Authorization: 'foo' }), + responseHeaders: wdioExpect.objectContaining({ Authorization: 'bar' }), + postData: wdioExpect.objectContaining({ title: 'foo', description: 'bar' }), + response: wdioExpect.objectContaining({ success: true }), + })).toEqualTypeOf>() + + expectTypeOf(expect(promiseNetworkMock).toBeRequestedWith({ + url: jasmine.stringContaining('test'), + method: 'POST', + statusCode: 200, + requestHeaders: jasmine.objectContaining({ Authorization: 'foo' }), + responseHeaders: jasmine.objectContaining({ Authorization: 'bar' }), + postData: jasmine.objectContaining({ title: 'foo', description: 'bar' }), + response: jasmine.objectContaining({ success: true }), + })).toEqualTypeOf>() + + expectTypeOf(expect(promiseNetworkMock).toBeRequestedWith({ + url: wdioExpect.stringMatching(/.*\/api\/.*/i), + method: ['POST', 'PUT'], + statusCode: [401, 403], + requestHeaders: headers => headers.Authorization.startsWith('Bearer '), + postData: wdioExpect.objectContaining({ released: true, title: wdioExpect.stringContaining('foobar') }), + response: (r: { data: { items: unknown[] } }) => Array.isArray(r) && r.data.items.length === 20 + })).toEqualTypeOf>() + + expectTypeOf(expect(promiseNetworkMock).toBeRequestedWith(jasmine.objectContaining({ + method: 'POST' + }))).toEqualTypeOf>() + }) + }) + }) + + describe('Wdio expect from direct import is still properly defined', () => { + it('should support stringContaining, anything and more', async () => { + wdioExpect.stringContaining('WebdriverIO') + wdioExpect.stringMatching(/WebdriverIO/) + wdioExpect.arrayContaining(['WebdriverIO', 'Test']) + wdioExpect.objectContaining({ name: 'WebdriverIO' }) + // Was not there but works! + wdioExpect.closeTo(5, 10) + wdioExpect.arrayContaining(['WebdriverIO', 'Test']) + // New from jest 30!! + wdioExpect.arrayOf(wdioExpect.stringContaining('WebdriverIO')) + + wdioExpect.anything() + wdioExpect.any(Function) + wdioExpect.any(Number) + wdioExpect.any(Boolean) + wdioExpect.any(String) + wdioExpect.any(Symbol) + wdioExpect.any(Date) + wdioExpect.any(Error) + + wdioExpect.not.stringContaining('WebdriverIO') + wdioExpect.not.stringMatching(/WebdriverIO/) + wdioExpect.not.arrayContaining(['WebdriverIO', 'Test']) + wdioExpect.not.objectContaining({ name: 'WebdriverIO' }) + wdioExpect.not.closeTo(5, 10) + wdioExpect.not.arrayContaining(['WebdriverIO', 'Test']) + wdioExpect.not.arrayOf(wdioExpect.stringContaining('WebdriverIO')) + }) + + it('should support WDIO matchers', async () => { + expectTypeOf(wdioExpect(browser).toHaveTitle('foo')).toEqualTypeOf>() + expectTypeOf(wdioExpect(element).toBeClickable()).toEqualTypeOf>() + }) + + it('should support standard Jest expect Library Matchers', async () => { + expectTypeOf(wdioExpect({ a: 1 }).toHaveProperty('a')).toEqualTypeOf() + expectTypeOf(wdioExpect([1, 2]).toHaveLength(2)).toEqualTypeOf() + expectTypeOf(wdioExpect({ a: 1 }).toMatchObject({ a: 1 })).toEqualTypeOf() + }) + + it('should support custom matchers', async () => { + expectTypeOf(wdioExpect('test').toBeCustom()).toEqualTypeOf() + }) + + describe('Support soft Assertions on wdioExpect only (not supported on expect global since its Jasmine)', async () => { + const actualString: string = 'Test Page' + const actualPromiseString: Promise = Promise.resolve('Test Page') + + describe('wdioExpect.soft', () => { + it('should not need to be awaited/be a promise if actual is non-promise type', async () => { + expectTypeOf(wdioExpect.soft(actualString)).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(actualString).toBe('Test Page')).toEqualTypeOf() + expectTypeOf(wdioExpect.soft(actualString).not.toBe('Test Page')).toEqualTypeOf() + expectTypeOf(wdioExpect.soft(actualString).not.toBe(wdioExpect.stringContaining('Test Page'))).toEqualTypeOf() + }) + + it('should need to be awaited/be a promise if actual is promise type', async () => { + expectTypeOf(wdioExpect.soft(actualPromiseString)).toEqualTypeOf, Promise> & ExpectWebdriverIO.PromiseMatchers>>() + expectTypeOf(wdioExpect.soft(actualPromiseString).toBe('Test Page')).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(actualPromiseString).not.toBe('Test Page')).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(actualPromiseString).not.toBe(wdioExpect.stringContaining('Test Page'))).toEqualTypeOf>() + }) + + it('should support chainable element', async () => { + expectTypeOf(wdioExpect.soft(element)).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(chainableElement)).toEqualTypeOf>() + }) + + it('should support chainable element with wdio Matchers', async () => { + expectTypeOf(wdioExpect.soft(element).toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(chainableElement).toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(chainableArray).toBeDisplayed()).toEqualTypeOf>() + + expectTypeOf(wdioExpect.soft(element).not.toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(chainableElement).not.toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(chainableArray).not.toBeDisplayed()).toEqualTypeOf>() + }) + }) + }) + + }) + + describe('Jasmine only cases', () => { + it('should support expect correctly for non wdio types', async () => { + expectTypeOf(expect(Promise.resolve('test')).toBeResolved()).toMatchTypeOf>() + expectTypeOf(expect(Promise.resolve('test')).toBeResolvedTo(wdioExpect.stringContaining('test error'))).toMatchTypeOf>() + expectTypeOf(expect(Promise.resolve('test')).toBeResolvedTo(jasmine.stringContaining('test error'))).toMatchTypeOf>() + expectTypeOf(expect(Promise.resolve('test')).not.toBeResolvedTo(wdioExpect.not.stringContaining('test error'))).toMatchTypeOf>() + expectTypeOf(expect(Promise.resolve('test')).not.toBeResolvedTo(jasmine.stringContaining('test error'))).toMatchTypeOf>() + expectTypeOf(expect(Promise.resolve('test')).toBeRejected()).toMatchTypeOf>() + expectTypeOf(expect(Promise.resolve('test')).not.toBeResolved()).toMatchTypeOf>() + expectTypeOf(expect(Promise.resolve('test')).not.toBeRejected()).toMatchTypeOf>() + + expectTypeOf(expect(Promise.resolve('test')).toBeResolved()).not.toEqualTypeOf() + expectTypeOf(expect(Promise.resolve('test')).toBeRejected()).not.toEqualTypeOf() + + expectTypeOf(expect(Promise.resolve('test')).toBeResolved()).not.toEqualTypeOf() + }) + + it('should return Promise for standard Jasmine sync matchers', async () => { + expectTypeOf(expect(true).toBe(true)).toEqualTypeOf>() + expectTypeOf(expect(1).toEqual(1)).toEqualTypeOf>() + expectTypeOf(expect('foo').toMatch('foo')).toEqualTypeOf>() + expectTypeOf(expect(true).toBeTruthy()).toEqualTypeOf>() + expectTypeOf(expect(false).toBeFalsy()).toEqualTypeOf>() + expectTypeOf(expect(undefined).toBeUndefined()).toEqualTypeOf>() + expectTypeOf(expect(null).toBeNull()).toEqualTypeOf>() + }) + + it('jasmine special asymmetric matcher', async () => { + expect({}).toEqual(jasmine.any(Object)) + expect(12).toEqual(jasmine.any(Number)) + }) + }) + + describe('withContext', () => { + it('should be chainable and preserve return type', async () => { + // Async WDIO matcher with context + expectTypeOf(expect(browser).withContext('foo').toHaveTitle('bar')).toEqualTypeOf>() + + // Async Custom matcher with context + expectTypeOf(expect('test').withContext('foo').toBeCustom()).toEqualTypeOf>() + + // Async Jasmine built-in matcher with context + expectTypeOf(expect(Promise.resolve(true)).withContext('foo').toBeResolved()).toExtend>() + + // Sync matcher with context + expectTypeOf(expect(true).withContext('foo').toBe(true)).toEqualTypeOf>() + }) + }) +}) diff --git a/test-types/jasmine-async/tsconfig.json b/test-types/jasmine-global-expect-async/tsconfig.json similarity index 60% rename from test-types/jasmine-async/tsconfig.json rename to test-types/jasmine-global-expect-async/tsconfig.json index 90080327e..9eaf4a73a 100644 --- a/test-types/jasmine-async/tsconfig.json +++ b/test-types/jasmine-global-expect-async/tsconfig.json @@ -3,11 +3,11 @@ "noEmit": true, "noImplicitAny": true, "target": "es2022", - "module": "node18", + "module": "NodeNext", "skipLibCheck": true, "types": [ - "@types/jasmine", - "../../jasmine.d.ts" + "../../jasmine-wdio-expect-async.d.ts", + "@types/jasmine" ] } -} \ No newline at end of file +} diff --git a/test-types/jasmine/customMatchers.d.ts b/test-types/jasmine/customMatchers.d.ts new file mode 100644 index 000000000..e27c356e1 --- /dev/null +++ b/test-types/jasmine/customMatchers.d.ts @@ -0,0 +1,17 @@ +/** + * Custom matchers under the `ExpectWebdriverIO` namespace. + * @see {@link https://webdriver.io/docs/custommatchers/#typescript-support} + */ +declare namespace ExpectWebdriverIO { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface Matchers { + toBeCustomWdio(): Promise; + } +} + +declare namespace jasmine { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface AsyncMatchers { + toBeCustomJasmine(): Promise; + } +} diff --git a/test-types/jasmine/customMatchers/customMatchers-module-expect.d.ts b/test-types/jasmine/customMatchers/customMatchers-module-expect.d.ts deleted file mode 100644 index 125fb77c7..000000000 --- a/test-types/jasmine/customMatchers/customMatchers-module-expect.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -import 'expect' - -/** - * Custom matchers under the `expect` module. - * @see {@link https://jestjs.io/docs/expect#expectextendmatchers} - */ -declare module 'expect' { - interface AsymmetricMatchers { - toBeWithinRange(floor: number, ceiling: number): void - toHaveSimpleCustomProperty(string: string): string - toHaveCustomProperty(element: ChainablePromiseElement | WebdriverIO.Element): Promise> - } - - interface Matchers { - toBeWithinRange(floor: number, ceiling: number): R - toHaveSimpleCustomProperty(string: string | ExpectWebdriverIO.PartialMatcher): R - toHaveCustomProperty: - // Useful to typecheck the custom matcher so it is only used on elements - T extends ChainablePromiseElement | WebdriverIO.Element ? - (test: string | ExpectWebdriverIO.PartialMatcher | - // Needed for the custom asymmetric matcher defined above to be typed correctly - Promise>) - // Using `never` blocks the call on non-element types - => R : never; - } -} \ No newline at end of file diff --git a/test-types/jasmine/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts b/test-types/jasmine/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts deleted file mode 100644 index 89423c9d3..000000000 --- a/test-types/jasmine/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Custom matchers under the `ExpectWebdriverIO` namespace. - * @see {@link https://webdriver.io/docs/custommatchers/#typescript-support} - */ -declare namespace ExpectWebdriverIO { - interface AsymmetricMatchers { - toBeCustom(): ExpectWebdriverIO.PartialMatcher; - toBeCustomPromise(chainableElement: ChainablePromiseElement): Promise>; - } - interface Matchers { - toBeCustom(): R; - toBeCustomPromise: T extends ChainablePromiseElement ? (expected?: string | ExpectWebdriverIO.PartialMatcher | Promise>) => R : never; - } -} \ No newline at end of file diff --git a/test-types/jasmine/jasmine.test-d.ts b/test-types/jasmine/jasmine.test-d.ts new file mode 100644 index 000000000..f75435f6f --- /dev/null +++ b/test-types/jasmine/jasmine.test-d.ts @@ -0,0 +1,449 @@ + +import { expect as wdioExpect } from 'expect-webdriverio' +import { expectTypeOf } from 'vitest' + +describe('Jasmine type agumentations', () => { + const chainableElement = {} as unknown as ChainablePromiseElement + const chainableArray = {} as ChainablePromiseArray + + const element: WebdriverIO.Element = {} as unknown as WebdriverIO.Element + const elementArray: WebdriverIO.ElementArray = [] as unknown as WebdriverIO.ElementArray + const browser: WebdriverIO.Browser = {} as unknown as WebdriverIO.Browser + + const networkMock: WebdriverIO.Mock = {} as unknown as WebdriverIO.Mock + + describe('Augment expectAsync properly', () => { + + describe('Browser', () => { + const browser: WebdriverIO.Browser = {} as unknown as WebdriverIO.Browser + + describe('toHaveUrl', () => { + it('should return Promise', async () => { + expectTypeOf(expectAsync(browser).toHaveUrl('https://example.com')).toEqualTypeOf>() + expectTypeOf(expectAsync(browser).toHaveUrl('https://example.com', { message: 'foo' })).toEqualTypeOf>() + expectTypeOf(expectAsync(browser).not.toHaveUrl('https://example.com')).toEqualTypeOf>() + expectTypeOf(expectAsync(browser).not.toHaveUrl('https://example.com', { message: 'foo' })).toEqualTypeOf>() + + // Asymmetric matchers + expectTypeOf(expectAsync(browser).toHaveUrl(wdioExpect.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expectAsync(browser).toHaveUrl(wdioExpect.not.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expectAsync(browser).toHaveUrl(wdioExpect.any(String))).toEqualTypeOf>() + expectTypeOf(expectAsync(browser).toHaveUrl(wdioExpect.anything())).toEqualTypeOf>() + + expectTypeOf(expectAsync(browser).toHaveUrl(jasmine.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expectAsync(browser).toHaveUrl(jasmine.any(String))).toEqualTypeOf>() + expectTypeOf(expectAsync(browser).toHaveUrl(jasmine.anything())).toEqualTypeOf>() + + expectTypeOf(expectAsync(browser).toHaveUrl).parameter(0).extract().toBeNever() + }) + + it('should have ts errors when actual is not a Browser element', async () => { + expectTypeOf(expectAsync(element).toHaveUrl).toBeNever() + expectTypeOf(expectAsync(element).not.toHaveUrl).toBeNever() + expectTypeOf(expectAsync(true).toHaveUrl).toBeNever() + expectTypeOf(expectAsync(true).not.toHaveUrl).toBeNever() + }) + }) + + describe('toHaveTitle', () => { + it('should return Promise', async () => { + expectTypeOf(expectAsync(browser).toHaveTitle('https://example.com')).toEqualTypeOf>() + expectTypeOf(expectAsync(browser).not.toHaveTitle('https://example.com')).toEqualTypeOf>() + + // Asymmetric matchers + expectTypeOf(expectAsync(browser).toHaveTitle(wdioExpect.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expectAsync(browser).toHaveTitle(wdioExpect.any(String))).toEqualTypeOf>() + expectTypeOf(expectAsync(browser).toHaveTitle(wdioExpect.anything())).toEqualTypeOf>() + + expectTypeOf(expectAsync(browser).toHaveTitle(jasmine.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expectAsync(browser).toHaveTitle(jasmine.any(String))).toEqualTypeOf>() + expectTypeOf(expectAsync(browser).toHaveTitle(jasmine.anything())).toEqualTypeOf>() + }) + + it('should have ts errors when actual is not a Browser element', async () => { + expectTypeOf(expectAsync(element).toHaveTitle).toBeNever() + expectTypeOf(expectAsync(element).not.toHaveTitle).toBeNever() + expectTypeOf(expectAsync(true).toHaveTitle).toBeNever() + expectTypeOf(expectAsync(true).not.toHaveTitle).toBeNever() + }) + }) + }) + + describe('element', () => { + + describe('toBeDisabled', () => { + it('should return Promise', async () => { + // Element + expectTypeOf(expectAsync(element).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expectAsync(element).not.toBeDisabled()).toEqualTypeOf>() + + // Element array + expectTypeOf(expectAsync(elementArray).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expectAsync(elementArray).not.toBeDisabled()).toEqualTypeOf>() + + // Chainable element + expectTypeOf(expectAsync(chainableElement).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableElement).not.toBeDisabled()).toEqualTypeOf>() + + // Chainable element array + expectTypeOf(expectAsync(chainableArray).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableArray).not.toBeDisabled()).toEqualTypeOf>() + }) + + it('should have ts errors when actual is not an element', async () => { + expectTypeOf(expectAsync(browser).toBeDisabled).toBeNever() + expectTypeOf(expectAsync(browser).not.toBeDisabled).toBeNever() + expectTypeOf(expectAsync(true).toBeDisabled).toBeNever() + expectTypeOf(expectAsync(true).not.toBeDisabled).toBeNever() + }) + }) + + describe('toHaveText', () => { + it('should return Promise', async () => { + expectTypeOf(expectAsync(element).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expectAsync(element).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expectAsync(element).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expectAsync(element).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expectAsync(element).toHaveText([jasmine.stringContaining('text1'), jasmine.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expectAsync(element).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expectAsync(element).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')])).toEqualTypeOf>() + expectTypeOf(expectAsync(element).toHaveText( + 'My-Ex-Am-Ple', + { + replace: [[/-/g, ' '], [/[A-Z]+/g, (match: string) => match.toLowerCase()]] + } + )).toEqualTypeOf>() + + expectTypeOf(expectAsync(element).not.toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expectAsync(element).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expectAsync(chainableElement).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableElement).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableElement).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableElement).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableElement).toHaveText([jasmine.stringContaining('text1'), jasmine.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableElement).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableElement).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')])).toEqualTypeOf>() + + expectTypeOf(expectAsync(chainableElement).not.toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableElement).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expectAsync(elementArray).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expectAsync(elementArray).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expectAsync(elementArray).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expectAsync(elementArray).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expectAsync(elementArray).toHaveText([jasmine.stringContaining('text1'), jasmine.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expectAsync(elementArray).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expectAsync(elementArray).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')])).toEqualTypeOf>() + + expectTypeOf(expectAsync(elementArray).not.toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expectAsync(elementArray).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expectAsync(chainableArray).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableArray).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableArray).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableArray).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableArray).toHaveText([jasmine.stringContaining('text1'), jasmine.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableArray).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableArray).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')])).toEqualTypeOf>() + + expectTypeOf(expectAsync(chainableArray).not.toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableArray).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expectAsync(browser).toHaveText).toBeNever() + }) + + it('should have ts errors when actual is not an element', async () => { + expectTypeOf(expectAsync(browser).toHaveText).toBeNever() + expectTypeOf(expectAsync(browser).not.toHaveText).toBeNever() + expectTypeOf(expectAsync(true).toHaveText).toBeNever() + expectTypeOf(expectAsync(true).toHaveText).toBeNever() + }) + + it('should have ts errors when actual is string or Promise', async () => { + expectTypeOf(expectAsync('text').toHaveText).toBeNever() + expectTypeOf(expectAsync('text').not.toHaveText).toBeNever() + expectTypeOf(expectAsync(Promise.resolve('text')).toHaveText).toBeNever() + expectTypeOf(expectAsync(Promise.resolve('text')).toHaveText).toBeNever() + }) + }) + + describe('toHaveHeight', () => { + it('should return Promise', async () => { + expectTypeOf(expectAsync(element).toHaveHeight(100)).toEqualTypeOf>() + expectTypeOf(expectAsync(element).toHaveHeight(100, { message: 'Custom error message' })).toEqualTypeOf>() + expectTypeOf(expectAsync(element).not.toHaveHeight(100)).toEqualTypeOf>() + expectTypeOf(expectAsync(element).not.toHaveHeight(100, { message: 'Custom error message' })).toEqualTypeOf>() + + expectTypeOf(expectAsync(element).toHaveHeight({ width: 100, height: 200 })).toEqualTypeOf>() + expectTypeOf(expectAsync(element).toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' })).toEqualTypeOf>() + expectTypeOf(expectAsync(element).not.toHaveHeight({ width: 100, height: 200 })).toEqualTypeOf>() + expectTypeOf(expectAsync(element).not.toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' })).toEqualTypeOf>() + + expectTypeOf(expectAsync(browser).toHaveHeight).toBeNever() + }) + + it('should have ts errors when actual is string or Promise', async () => { + expectTypeOf(expectAsync('text').toHaveText).toBeNever() + expectTypeOf(expectAsync('text').not.toHaveText).toBeNever() + expectTypeOf(expectAsync(Promise.resolve('text')).toHaveText).toBeNever() + expectTypeOf(expectAsync(Promise.resolve('text')).toHaveText).toBeNever() + }) + }) + + describe('toMatchSnapshot', () => { + + it('should return Promise', async () => { + expectTypeOf(expectAsync(element).toMatchSnapshot()).toEqualTypeOf>() + expectTypeOf(expectAsync(element).toMatchSnapshot('test label')).toEqualTypeOf>() + expectTypeOf(expectAsync(element).not.toMatchSnapshot('test label')).toEqualTypeOf>() + + expectTypeOf(expectAsync(chainableElement).toMatchSnapshot()).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableElement).toMatchSnapshot('test label')).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableElement).not.toMatchSnapshot('test label')).toEqualTypeOf>() + }) + }) + + describe('toMatchInlineSnapshot', () => { + + it('should return Promise', async () => { + expectTypeOf(expectAsync(element).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expectAsync(element).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expectAsync(element).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + + expectTypeOf(expectAsync(chainableElement).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableElement).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + }) + + it('should return Promise with getCSSProperty()', async () => { + expectTypeOf(expectAsync(element.getCSSProperty('test')).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expectAsync(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expectAsync(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + + expectTypeOf(expectAsync(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expectAsync(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + }) + }) + + describe('toBeElementsArrayOfSize', async () => { + + it('should work correctly when actual is chainableArray', async () => { + expectTypeOf(expectAsync(chainableArray).toBeElementsArrayOfSize(5)).toEqualTypeOf & Promise>() + expectTypeOf(expectAsync(chainableArray).toBeElementsArrayOfSize({ lte: 10 })).toEqualTypeOf & Promise>() + expectTypeOf(expectAsync(chainableArray).toBeElementsArrayOfSize(5, { message: 'foo' })).toEqualTypeOf & Promise>() + }) + + it('should not work when actual is not chainableArray', async () => { + expectTypeOf(expectAsync(chainableElement).toBeElementsArrayOfSize).toBeNever() + expectTypeOf(expectAsync(true).toBeElementsArrayOfSize).toBeNever() + }) + }) + }) + + describe('Custom matchers', () => { + describe('using `ExpectWebdriverIO` namespace augmentation', () => { + it('should return Promise for a non-promise custom matcher', async () => { + expectTypeOf(expectAsync('test').toBeCustomWdio()).toEqualTypeOf>() + expectTypeOf(expectAsync('test').not.toBeCustomWdio()).toEqualTypeOf>() + + expectTypeOf(expectAsync('test').toBeCustomJasmine()).toEqualTypeOf>() + expectTypeOf(expectAsync('test').not.toBeCustomJasmine()).toEqualTypeOf>() + }) + }) + }) + + describe('Jasmine vs Jest pollution', () => { + it('should not include Jest expect library matchers on expectAsync', () => { + // toHaveProperty is a Jest matcher, not Jasmine + expectTypeOf(expectAsync('foo')).not.toHaveProperty('toHaveProperty') + expectTypeOf(expectAsync('foo')).not.toHaveProperty('toMatchObject') + expectTypeOf(expectAsync('foo')).not.toHaveProperty('toStrictEqual') + expectTypeOf(expectAsync('foo')).not.toHaveProperty('toHaveLength') + }) + }) + + describe('Promise type assertions', () => { + const booleanPromise: Promise = Promise.resolve(true) + + it('should not compile', async () => { + expectTypeOf(expectAsync(booleanPromise)).not.toHaveProperty('resolves') + expectTypeOf(expectAsync(booleanPromise)).not.toHaveProperty('rejects') + }) + + }) + + describe('Network Matchers', () => { + const promiseNetworkMock = Promise.resolve(networkMock) + + it('should return Promise', async () => { + expectTypeOf(expectAsync(promiseNetworkMock).toBeRequested()).toEqualTypeOf>() + expectTypeOf(expectAsync(promiseNetworkMock).toBeRequestedTimes(2)).toEqualTypeOf>() + expectTypeOf(expectAsync(promiseNetworkMock).toBeRequestedTimes(2, { message: 'foo' })).toEqualTypeOf>() + expectTypeOf(expectAsync(promiseNetworkMock).toBeRequestedTimes({ gte: 5, lte: 10 })).toEqualTypeOf>() + + expectTypeOf(expectAsync(promiseNetworkMock).not.toBeRequested()).toEqualTypeOf>() + expectTypeOf(expectAsync(promiseNetworkMock).not.toBeRequestedTimes(2)).toEqualTypeOf>() + expectTypeOf(expectAsync(promiseNetworkMock).not.toBeRequestedTimes({ gte: 5, lte: 10 })).toEqualTypeOf>() + + expectTypeOf(expectAsync(promiseNetworkMock).toBeRequestedWith({ + url: 'http://localhost:8080/api', + method: 'POST', + statusCode: 200, + requestHeaders: { Authorization: 'foo' }, + responseHeaders: { Authorization: 'bar' }, + postData: { title: 'foo', description: 'bar' }, + response: { success: true }, + })).toEqualTypeOf>() + + expectTypeOf(expectAsync(promiseNetworkMock).toBeRequestedWith({ + url: wdioExpect.stringContaining('test'), + method: 'POST', + statusCode: 200, + requestHeaders: wdioExpect.objectContaining({ Authorization: 'foo' }), + responseHeaders: wdioExpect.objectContaining({ Authorization: 'bar' }), + postData: wdioExpect.objectContaining({ title: 'foo', description: 'bar' }), + response: wdioExpect.objectContaining({ success: true }), + })).toEqualTypeOf>() + + expectTypeOf(expectAsync(promiseNetworkMock).toBeRequestedWith({ + url: jasmine.stringContaining('test'), + method: 'POST', + statusCode: 200, + requestHeaders: jasmine.objectContaining({ Authorization: 'foo' }), + responseHeaders: jasmine.objectContaining({ Authorization: 'bar' }), + postData: jasmine.objectContaining({ title: 'foo', description: 'bar' }), + response: jasmine.objectContaining({ success: true }), + })).toEqualTypeOf>() + + expectTypeOf(expectAsync(promiseNetworkMock).toBeRequestedWith({ + url: wdioExpect.stringMatching(/.*\/api\/.*/i), + method: ['POST', 'PUT'], + statusCode: [401, 403], + requestHeaders: headers => headers.Authorization.startsWith('Bearer '), + postData: wdioExpect.objectContaining({ released: true, title: wdioExpect.stringContaining('foobar') }), + response: (r: { data: { items: unknown[] } }) => Array.isArray(r) && r.data.items.length === 20 + })).toEqualTypeOf>() + + expectTypeOf(expectAsync(promiseNetworkMock).toBeRequestedWith(jasmine.objectContaining({ + method: 'POST' + }))).toEqualTypeOf>() + + expectTypeOf(expectAsync(promiseNetworkMock).toBeRequestedWith(wdioExpect.objectContaining({ + method: 'POST' + }))).toEqualTypeOf>() + }) + }) + }) + + describe('Standard Synchronous Jasmine Matchers', () => { + it('should return void', () => { + expectTypeOf(expect(true).toBe(true)).toEqualTypeOf() + expectTypeOf(expect({ a: 1 }).toEqual({ a: 1 })).toEqualTypeOf() + expectTypeOf(expect(true).toBeTruthy()).toEqualTypeOf() + }) + }) + + describe('withContext', () => { + it('should be chainable and preserve return type', async () => { + // Async WDIO matcher with context + expectTypeOf(expectAsync(browser).withContext('foo').toHaveTitle('bar')).toEqualTypeOf>() + + // Async Custom matcher with context + expectTypeOf(expectAsync('test').withContext('foo').toBeCustomJasmine()).toEqualTypeOf>() + + // Async Jasmine built-in matcher with context + expectTypeOf(expectAsync(Promise.resolve(true)).withContext('foo').toBeResolved()).toEqualTypeOf>() + + // Sync matcher with context + expectTypeOf(expect(true).withContext('foo').toBe(true)).toEqualTypeOf() + }) + }) + + describe('Wdio expect from direct import is still properly defined', () => { + it('should support stringContaining, anything and more', async () => { + wdioExpect.stringContaining('WebdriverIO') + wdioExpect.stringMatching(/WebdriverIO/) + wdioExpect.arrayContaining(['WebdriverIO', 'Test']) + wdioExpect.objectContaining({ name: 'WebdriverIO' }) + // Was not there but works! + wdioExpect.closeTo(5, 10) + wdioExpect.arrayContaining(['WebdriverIO', 'Test']) + // New from jest 30!! + wdioExpect.arrayOf(wdioExpect.stringContaining('WebdriverIO')) + + wdioExpect.anything() + wdioExpect.any(Function) + wdioExpect.any(Number) + wdioExpect.any(Boolean) + wdioExpect.any(String) + wdioExpect.any(Symbol) + wdioExpect.any(Date) + wdioExpect.any(Error) + + wdioExpect.not.stringContaining('WebdriverIO') + wdioExpect.not.stringMatching(/WebdriverIO/) + wdioExpect.not.arrayContaining(['WebdriverIO', 'Test']) + wdioExpect.not.objectContaining({ name: 'WebdriverIO' }) + wdioExpect.not.closeTo(5, 10) + wdioExpect.not.arrayContaining(['WebdriverIO', 'Test']) + wdioExpect.not.arrayOf(wdioExpect.stringContaining('WebdriverIO')) + }) + + it('should support WDIO matchers', async () => { + expectTypeOf(wdioExpect(browser).toHaveTitle('foo')).toEqualTypeOf>() + expectTypeOf(wdioExpect(element).toBeClickable()).toEqualTypeOf>() + + expectTypeOf(wdioExpect(browser).toHaveTitle(wdioExpect.stringContaining('foo'))).toEqualTypeOf>() + expectTypeOf(wdioExpect(browser).toHaveTitle(jasmine.stringMatching('foo'))).toEqualTypeOf>() + }) + + it('should support standard Jest expect Library Matchers', async () => { + expectTypeOf(wdioExpect({ a: 1 }).toHaveProperty('a')).toEqualTypeOf() + expectTypeOf(wdioExpect([1, 2]).toHaveLength(2)).toEqualTypeOf() + expectTypeOf(wdioExpect({ a: 1 }).toMatchObject({ a: 1 })).toEqualTypeOf() + }) + + it('should support custom matchers', async () => { + expectTypeOf(wdioExpect('test').toBeCustomWdio()).toEqualTypeOf>() + }) + + describe('Support soft Assertions on wdioExpect only (not supported on expect global since its Jasmine)', async () => { + const actualString: string = 'Test Page' + const actualPromiseString: Promise = Promise.resolve('Test Page') + + describe('wdioExpect.soft', () => { + it('should not need to be awaited/be a promise if actual is non-promise type', async () => { + expectTypeOf(wdioExpect.soft(actualString)).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(actualString).toBe('Test Page')).toEqualTypeOf() + expectTypeOf(wdioExpect.soft(actualString).not.toBe('Test Page')).toEqualTypeOf() + expectTypeOf(wdioExpect.soft(actualString).not.toBe(wdioExpect.stringContaining('Test Page'))).toEqualTypeOf() + }) + + it('should need to be awaited/be a promise if actual is promise type', async () => { + expectTypeOf(wdioExpect.soft(actualPromiseString)).toEqualTypeOf, Promise> & ExpectWebdriverIO.PromiseMatchers>>() + expectTypeOf(wdioExpect.soft(actualPromiseString).toBe('Test Page')).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(actualPromiseString).not.toBe('Test Page')).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(actualPromiseString).not.toBe(wdioExpect.stringContaining('Test Page'))).toEqualTypeOf>() + }) + + it('should support chainable element', async () => { + expectTypeOf(wdioExpect.soft(element)).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(chainableElement)).toEqualTypeOf>() + }) + + it('should support chainable element with wdio Matchers', async () => { + expectTypeOf(wdioExpect.soft(element).toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(chainableElement).toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(chainableArray).toBeDisplayed()).toEqualTypeOf>() + + expectTypeOf(wdioExpect.soft(element).not.toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(chainableElement).not.toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(wdioExpect.soft(chainableArray).not.toBeDisplayed()).toEqualTypeOf>() + }) + }) + }) + + }) +}) diff --git a/test-types/jasmine/tsconfig.json b/test-types/jasmine/tsconfig.json index 3b199e0ef..5ef7b9ad9 100644 --- a/test-types/jasmine/tsconfig.json +++ b/test-types/jasmine/tsconfig.json @@ -3,12 +3,11 @@ "noEmit": true, "noImplicitAny": true, "target": "es2022", - "module": "node18", + "module": "NodeNext", "skipLibCheck": true, "types": [ "@types/jasmine", "../../jasmine.d.ts", - "../../jasmine-wdio-expect-async.d.ts" ] } -} \ No newline at end of file +} diff --git a/test-types/jasmine/types-jasmine.test.ts b/test-types/jasmine/types-jasmine.test.ts deleted file mode 100644 index 8861766ce..000000000 --- a/test-types/jasmine/types-jasmine.test.ts +++ /dev/null @@ -1,834 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ - -// Desired since we do not want to overwrite the global `expect` from Jasmine -import { expect as wdioExpect } from 'expect-webdriverio' -describe('type assertions', () => { - const chainableElement = {} as unknown as ChainablePromiseElement - const chainableArray = {} as ChainablePromiseArray - - const element: WebdriverIO.Element = {} as unknown as WebdriverIO.Element - const elementArray: WebdriverIO.ElementArray = [] as unknown as WebdriverIO.ElementArray - - const networkMock: WebdriverIO.Mock = {} as unknown as WebdriverIO.Mock - - // Type assertions - let expectPromiseVoid: Promise - let expectVoid: void - - describe('Browser', () => { - const browser: WebdriverIO.Browser = {} as unknown as WebdriverIO.Browser - - describe('toHaveUrl', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = wdioExpect(browser).toHaveUrl('https://example.com') - expectPromiseVoid = wdioExpect(browser).not.toHaveUrl('https://example.com') - - // Asymmetric matchers - expectPromiseVoid = wdioExpect(browser).toHaveUrl(wdioExpect.stringContaining('WebdriverIO')) - expectPromiseVoid = wdioExpect(browser).toHaveUrl(wdioExpect.not.stringContaining('WebdriverIO')) - expectPromiseVoid = wdioExpect(browser).toHaveUrl(wdioExpect.any(String)) - expectPromiseVoid = wdioExpect(browser).toHaveUrl(wdioExpect.anything()) - - // @ts-expect-error - expectVoid = wdioExpect(browser).toHaveUrl('https://example.com') - // @ts-expect-error - expectVoid = wdioExpect(browser).not.toHaveUrl('https://example.com') - // @ts-expect-error - expectVoid = wdioExpect(browser).toHaveUrl(wdioExpect.stringContaining('WebdriverIO')) - - // @ts-expect-error - await wdioExpect(browser).toHaveUrl(6) - }) - - it('should have ts errors when actual is not a Browser element', async () => { - // @ts-expect-error - await wdioExpect(element).toHaveUrl('https://example.com') - // @ts-expect-error - await wdioExpect(element).not.toHaveUrl('https://example.com') - // @ts-expect-error - await wdioExpect(true).toHaveUrl('https://example.com') - // @ts-expect-error - await wdioExpect(true).not.toHaveUrl('https://example.com') - }) - }) - - describe('toHaveTitle', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = wdioExpect(browser).toHaveTitle('https://example.com') - expectPromiseVoid = wdioExpect(browser).not.toHaveTitle('https://example.com') - - // Asymmetric matchers - expectPromiseVoid = wdioExpect(browser).toHaveTitle(wdioExpect.stringContaining('WebdriverIO')) - expectPromiseVoid = wdioExpect(browser).toHaveTitle(wdioExpect.any(String)) - expectPromiseVoid = wdioExpect(browser).toHaveTitle(wdioExpect.anything()) - - // @ts-expect-error - expectVoid = wdioExpect(browser).toHaveTitle('https://example.com') - // @ts-expect-error - expectVoid = wdioExpect(browser).not.toHaveTitle('https://example.com') - // @ts-expect-error - expectVoid = wdioExpect(browser).toHaveTitle(wdioExpect.stringContaining('WebdriverIO')) - }) - - it('should have ts errors when actual is not a Browser element', async () => { - // @ts-expect-error - await wdioExpect(element).toHaveTitle('https://example.com') - // @ts-expect-error - await wdioExpect(element).not.toHaveTitle('https://example.com') - // @ts-expect-error - await wdioExpect(true).toHaveTitle('https://example.com') - // @ts-expect-error - await wdioExpect(true).not.toHaveTitle('https://example.com') - }) - }) - }) - - describe('element', () => { - - describe('toBeDisabled', () => { - it('should be supported correctly', async () => { - // Element - expectPromiseVoid = wdioExpect(element).toBeDisabled() - expectPromiseVoid = wdioExpect(element).not.toBeDisabled() - - // Element array - expectPromiseVoid = wdioExpect(elementArray).toBeDisabled() - expectPromiseVoid = wdioExpect(elementArray).not.toBeDisabled() - - // Chainable element - expectPromiseVoid = wdioExpect(chainableElement).toBeDisabled() - expectPromiseVoid = wdioExpect(chainableElement).not.toBeDisabled() - - // Chainable element array - expectPromiseVoid = wdioExpect(chainableArray).toBeDisabled() - expectPromiseVoid = wdioExpect(chainableArray).not.toBeDisabled() - - // @ts-expect-error - expectVoid = wdioExpect(element).toBeDisabled() - // @ts-expect-error - expectVoid = wdioExpect(element).not.toBeDisabled() - }) - - it('should have ts errors when actual is not an element', async () => { - // @ts-expect-error - await wdioExpect(browser).toBeDisabled() - // @ts-expect-error - await wdioExpect(browser).not.toBeDisabled() - // @ts-expect-error - await wdioExpect(true).toBeDisabled() - // @ts-expect-error - await wdioExpect(true).not.toBeDisabled() - }) - }) - - describe('toHaveText', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = wdioExpect(element).toHaveText('text') - expectPromiseVoid = wdioExpect(element).toHaveText(/text/) - expectPromiseVoid = wdioExpect(element).toHaveText(['text1', 'text2']) - expectPromiseVoid = wdioExpect(element).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')]) - expectPromiseVoid = wdioExpect(element).toHaveText([/text1/, /text2/]) - expectPromiseVoid = wdioExpect(element).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')]) - await wdioExpect(element).toHaveText( - 'My-Ex-Am-Ple', - { - replace: [[/-/g, ' '], [/[A-Z]+/g, (match: string) => match.toLowerCase()]] - } - ) - - expectPromiseVoid = wdioExpect(element).not.toHaveText('text') - - // @ts-expect-error - expectVoid = wdioExpect(element).toHaveText('text') - // @ts-expect-error - await wdioExpect(element).toHaveText(6) - - expectPromiseVoid = wdioExpect(chainableElement).toHaveText('text') - expectPromiseVoid = wdioExpect(chainableElement).toHaveText(/text/) - expectPromiseVoid = wdioExpect(chainableElement).toHaveText(['text1', 'text2']) - expectPromiseVoid = wdioExpect(chainableElement).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')]) - expectPromiseVoid = wdioExpect(chainableElement).toHaveText([/text1/, /text2/]) - expectPromiseVoid = wdioExpect(chainableElement).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')]) - - expectPromiseVoid = wdioExpect(chainableElement).not.toHaveText('text') - - // @ts-expect-error - expectVoid = wdioExpect(chainableElement).toHaveText('text') - // @ts-expect-error - await wdioExpect(chainableElement).toHaveText(6) - - expectPromiseVoid = wdioExpect(elementArray).toHaveText('text') - expectPromiseVoid = wdioExpect(elementArray).toHaveText(/text/) - expectPromiseVoid = wdioExpect(elementArray).toHaveText(['text1', 'text2']) - expectPromiseVoid = wdioExpect(elementArray).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')]) - expectPromiseVoid = wdioExpect(elementArray).toHaveText([/text1/, /text2/]) - expectPromiseVoid = wdioExpect(elementArray).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')]) - - expectPromiseVoid = wdioExpect(elementArray).not.toHaveText('text') - - // @ts-expect-error - expectVoid = wdioExpect(elementArray).toHaveText('text') - // @ts-expect-error - await wdioExpect(elementArray).toHaveText(6) - - expectPromiseVoid = wdioExpect(chainableArray).toHaveText('text') - expectPromiseVoid = wdioExpect(chainableArray).toHaveText(/text/) - expectPromiseVoid = wdioExpect(chainableArray).toHaveText(['text1', 'text2']) - expectPromiseVoid = wdioExpect(chainableArray).toHaveText([wdioExpect.stringContaining('text1'), wdioExpect.stringContaining('text2')]) - expectPromiseVoid = wdioExpect(chainableArray).toHaveText([/text1/, /text2/]) - expectPromiseVoid = wdioExpect(chainableArray).toHaveText(['text1', /text1/, wdioExpect.stringContaining('text3')]) - - expectPromiseVoid = wdioExpect(chainableArray).not.toHaveText('text') - - // @ts-expect-error - expectVoid = wdioExpect(chainableArray).toHaveText('text') - // @ts-expect-error - await wdioExpect(chainableArray).toHaveText(6) - - // @ts-expect-error - await wdioExpect(browser).toHaveText('text') - }) - - it('should have ts errors when actual is not an element', async () => { - // @ts-expect-error - await wdioExpect(browser).toHaveText('text') - // @ts-expect-error - await wdioExpect(browser).not.toHaveText('text') - // @ts-expect-error - await wdioExpect(true).toHaveText('text') - // @ts-expect-error - await wdioExpect(true).toHaveText('text') - }) - - it('should have ts errors when actual is string or Promise', async () => { - // @ts-expect-error - await wdioExpect('text').toHaveText('text') - // @ts-expect-error - await wdioExpect('text').not.toHaveText('text') - // @ts-expect-error - await wdioExpect(Promise.resolve('text')).toHaveText('text') - // @ts-expect-error - await wdioExpect(Promise.resolve('text')).toHaveText('text') - }) - }) - - describe('toHaveHeight', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = wdioExpect(element).toHaveHeight(100) - expectPromiseVoid = wdioExpect(element).toHaveHeight(100, { message: 'Custom error message' }) - expectPromiseVoid = wdioExpect(element).not.toHaveHeight(100) - expectPromiseVoid = wdioExpect(element).not.toHaveHeight(100, { message: 'Custom error message' }) - - expectPromiseVoid = wdioExpect(element).toHaveHeight({ width: 100, height: 200 }) - expectPromiseVoid = wdioExpect(element).toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' }) - expectPromiseVoid = wdioExpect(element).not.toHaveHeight({ width: 100, height: 200 }) - expectPromiseVoid = wdioExpect(element).not.toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' }) - - // @ts-expect-error - expectVoid = wdioExpect(element).toHaveHeight(100) - // @ts-expect-error - expectVoid = wdioExpect(element).not.toHaveHeight(100) - - // @ts-expect-error - expectVoid = wdioExpect(element).toHaveHeight({ width: 100, height: 200 }) - // @ts-expect-error - expectVoid = wdioExpect(element).not.toHaveHeight({ width: 100, height: 200 }) - - // @ts-expect-error - await wdioExpect(browser).toHaveHeight(100) - }) - - it('should have ts errors when actual is string or Promise', async () => { - // @ts-expect-error - await wdioExpect('text').toHaveText('text') - // @ts-expect-error - await wdioExpect('text').not.toHaveText('text') - // @ts-expect-error - await wdioExpect(Promise.resolve('text')).toHaveText('text') - // @ts-expect-error - await wdioExpect(Promise.resolve('text')).toHaveText('text') - }) - }) - - describe('toMatchSnapshot', () => { - - it('should be supported correctly', async () => { - expectPromiseVoid = wdioExpect(element).toMatchSnapshot() - expectPromiseVoid = wdioExpect(element).toMatchSnapshot('test label') - expectPromiseVoid = wdioExpect(element).not.toMatchSnapshot('test label') - - expectPromiseVoid = wdioExpect(chainableElement).toMatchSnapshot() - expectPromiseVoid = wdioExpect(chainableElement).toMatchSnapshot('test label') - expectPromiseVoid = wdioExpect(chainableElement).not.toMatchSnapshot('test label') - - //@ts-expect-error - expectVoid = wdioExpect(element).toMatchSnapshot() - //@ts-expect-error - expectVoid = wdioExpect(element).not.toMatchSnapshot() - //@ts-expect-error - expectVoid = wdioExpect(chainableElement).toMatchSnapshot() - //@ts-expect-error - expectVoid = wdioExpect(chainableElement).not.toMatchSnapshot() - }) - }) - - describe('toMatchInlineSnapshot', () => { - - it('should be correctly supported', async () => { - expectPromiseVoid = wdioExpect(element).toMatchInlineSnapshot() - expectPromiseVoid = wdioExpect(element).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = wdioExpect(element).toMatchInlineSnapshot('test snapshot', 'test label') - - expectPromiseVoid = wdioExpect(chainableElement).toMatchInlineSnapshot() - expectPromiseVoid = wdioExpect(chainableElement).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = wdioExpect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label') - - //@ts-expect-error - expectVoid = wdioExpect(element).toMatchInlineSnapshot() - //@ts-expect-error - expectVoid = wdioExpect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label') - }) - - it('should be correctly supported with getCSSProperty()', async () => { - expectPromiseVoid = wdioExpect(element.getCSSProperty('test')).toMatchInlineSnapshot() - expectPromiseVoid = wdioExpect(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = wdioExpect(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label') - - expectPromiseVoid = wdioExpect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot() - expectPromiseVoid = wdioExpect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = wdioExpect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label') - - //@ts-expect-error - expectVoid = wdioExpect(element).toMatchInlineSnapshot() - //@ts-expect-error - expectVoid = wdioExpect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label') - }) - }) - - describe('toBeElementsArrayOfSize', async () => { - - it('should work correctly when actual is chainableArray', async () => { - expectPromiseVoid = wdioExpect(chainableArray).toBeElementsArrayOfSize(5) - expectPromiseVoid = wdioExpect(chainableArray).toBeElementsArrayOfSize({ lte: 10 }) - - // @ts-expect-error - expectVoid = wdioExpect(chainableArray).toBeElementsArrayOfSize(5) - // @ts-expect-error - expectVoid = wdioExpect(chainableArray).toBeElementsArrayOfSize({ lte: 10 }) - }) - - it('should not work when actual is not chainableArray', async () => { - // @ts-expect-error - await wdioExpect(chainableElement).toBeElementsArrayOfSize(5) - // @ts-expect-error - await wdioExpect(chainableElement).toBeElementsArrayOfSize({ lte: 10 }) - // @ts-expect-error - await wdioExpect(true).toBeElementsArrayOfSize(5) - // @ts-expect-error - await wdioExpect(true).toBeElementsArrayOfSize({ lte: 10 }) - }) - }) - }) - - describe('Custom matchers', () => { - describe('using `ExpectWebdriverIO` namespace augmentation', () => { - it('should supported correctly a non-promise custom matcher', async () => { - expectPromiseVoid = wdioExpect('test').toBeCustom() - expectPromiseVoid = wdioExpect('test').not.toBeCustom() - - // @ts-expect-error - expectVoid = wdioExpect('test').toBeCustom() - // @ts-expect-error - expectVoid = wdioExpect('test').not.toBeCustom() - - expectPromiseVoid = wdioExpect(1).toBeWithinRange(0, 2) - }) - - it('should supported correctly a promise custom matcher with only chainableElement as actual', async () => { - expectPromiseVoid = wdioExpect(chainableElement).toBeCustomPromise() - expectPromiseVoid = wdioExpect(chainableElement).toBeCustomPromise(wdioExpect.stringContaining('test')) - expectPromiseVoid = wdioExpect(chainableElement).not.toBeCustomPromise(wdioExpect.not.stringContaining('test')) - - // @ts-expect-error - wdioExpect('test').toBeCustomPromise() - // @ts-expect-error - expectVoid = wdioExpect(chainableElement).toBeCustomPromise() - // @ts-expect-error - expectVoid = wdioExpect(chainableElement).toBeCustomPromise(wdioExpect.stringContaining('test')) - // @ts-expect-error - expectVoid = wdioExpect(chainableElement).not.toBeCustomPromise(wdioExpect.stringContaining('test')) - // @ts-expect-error - wdioExpect(chainableElement).toBeCustomPromise(wdioExpect.stringContaining(6)) - }) - - it('should support custom asymmetric matcher', async () => { - const expectString1 : ExpectWebdriverIO.PartialMatcher = wdioExpect.toBeCustom() - const expectString2 : ExpectWebdriverIO.PartialMatcher = wdioExpect.not.toBeCustom() - - expectPromiseVoid = wdioExpect(chainableElement).toBeCustomPromise(wdioExpect.toBeCustom()) - - // @ts-expect-error - expectPromiseVoid = wdioExpect.toBeCustom() - // @ts-expect-error - expectPromiseVoid = wdioExpect.not.toBeCustom() - - //@ts-expect-error - expectVoid = wdioExpect(chainableElement).toBeCustomPromise(wdioExpect.toBeCustom()) - }) - }) - - describe('using `expect` module declaration', () => { - - it('should support a simple matcher', async () => { - expectPromiseVoid = wdioExpect(5).toBeWithinRange(1, 10) - - // Or as an asymmetric matcher: - expectPromiseVoid = wdioExpect({ value: 5 }).toEqual({ - value: wdioExpect.toBeWithinRange(1, 10) - }) - - // @ts-expect-error - expectVoid = wdioExpect(5).toBeWithinRange(1, '10') - // @ts-expect-error - expectPromiseVoid = wdioExpect(5).toBeWithinRange('1') - }) - - it('should support a simple custom matcher with a chainable element matcher with promise', async () => { - wdioExpect(chainableElement) - expectPromiseVoid = wdioExpect(chainableElement).toHaveSimpleCustomProperty('text') - expectPromiseVoid = wdioExpect(chainableElement).toHaveSimpleCustomProperty(wdioExpect.stringContaining('text')) - expectPromiseVoid = wdioExpect(chainableElement).not.toHaveSimpleCustomProperty(wdioExpect.not.stringContaining('text')) - - // Or as a custom asymmetric matcher: - expectPromiseVoid = wdioExpect(chainableElement).toHaveSimpleCustomProperty( - wdioExpect.toHaveSimpleCustomProperty('string') - ) - const expectString1:string = wdioExpect.toHaveSimpleCustomProperty('string') - const expectString2:string = wdioExpect.not.toHaveSimpleCustomProperty('string') - - // @ts-expect-error - expectVoid = wdioExpect.toHaveSimpleCustomProperty(chainableElement) - // @ts-expect-error - expectVoid = wdioExpect.not.toHaveSimpleCustomProperty(chainableElement) - - // @ts-expect-error - expectVoid = wdioExpect.toHaveSimpleCustomProperty(chainableElement) - }) - - it('should support a chainable element matcher with promise', async () => { - expectPromiseVoid = wdioExpect(chainableElement).toHaveCustomProperty('text') - expectPromiseVoid = wdioExpect(chainableElement).toHaveCustomProperty(wdioExpect.stringContaining('text')) - expectPromiseVoid = wdioExpect(chainableElement).not.toHaveCustomProperty(wdioExpect.not.stringContaining('text')) - - // Or as a custom asymmetric matcher: - expectPromiseVoid = wdioExpect(chainableElement).toHaveCustomProperty( - await wdioExpect.toHaveCustomProperty(chainableElement) - ) - const expectPromiseWdioElement1: Promise> = wdioExpect.toHaveCustomProperty(chainableElement) - const expectPromiseWdioElement2: Promise> = wdioExpect.not.toHaveCustomProperty(chainableElement) - - // @ts-expect-error - expectVoid = wdioExpect.toHaveCustomProperty(chainableElement) - // @ts-expect-error - expectVoid = wdioExpect.not.toHaveCustomProperty(chainableElement) - - // @ts-expect-error - expectVoid = wdioExpect.toHaveCustomProperty(chainableElement) - // @ts-expect-error - wdioExpect.toHaveCustomProperty('test') - - await wdioExpect(chainableElement).toHaveCustomProperty( - await wdioExpect.toHaveCustomProperty(chainableElement) - ) - }) - }) - }) - - describe('toBe', () => { - - it('should expect void type when actual is a boolean', async () => { - expectPromiseVoid = wdioExpect(true).toBe(true) - expectPromiseVoid = wdioExpect(true).not.toBe(true) - - //@ts-expect-error - expectVoid = wdioExpect(true).toBe(true) - //@ts-expect-error - expectVoid = wdioExpect(true).not.toBe(true) - }) - - it('should not expect Promise when actual is a chainable since toBe does not need to be awaited', async () => { - expectPromiseVoid = wdioExpect(chainableElement).toBe(true) - expectPromiseVoid = wdioExpect(chainableElement).not.toBe(true) - - //@ts-expect-error - expectVoid = wdioExpect(chainableElement).toBe(true) - //@ts-expect-error - expectVoid = wdioExpect(chainableElement).not.toBe(true) - }) - - it('should still expect void type when actual is a Promise since we do not overload them', async () => { - const promiseBoolean = Promise.resolve(true) - - expectPromiseVoid = wdioExpect(promiseBoolean).toBe(true) - expectPromiseVoid = wdioExpect(promiseBoolean).not.toBe(true) - - //@ts-expect-error - expectVoid = wdioExpect(promiseBoolean).toBe(true) - //@ts-expect-error - expectVoid = wdioExpect(promiseBoolean).toBe(true) - }) - - it('should work with string', async () => { - expectPromiseVoid = wdioExpect('text').toBe(true) - expectPromiseVoid = wdioExpect('text').not.toBe(true) - expectPromiseVoid = wdioExpect('text').toBe(wdioExpect.stringContaining('text')) - expectPromiseVoid = wdioExpect('text').not.toBe(wdioExpect.stringContaining('text')) - - //@ts-expect-error - expectVoid = wdioExpect('text').toBe(true) - //@ts-expect-error - expectVoid = wdioExpect('text').not.toBe(true) - //@ts-expect-error - expectVoid = wdioExpect('text').toBe(wdioExpect.stringContaining('text')) - //@ts-expect-error - expectVoid = wdioExpect('text').not.toBe(wdioExpect.stringContaining('text')) - }) - }) - - describe('Promise type assertions', () => { - const booleanPromise: Promise = Promise.resolve(true) - - it('should not compile', async () => { - //@ts-expect-error - wdioExpect(booleanPromise).resolves.toBe(true) - //@ts-expect-error - wdioExpect(booleanPromise).rejects.toBe(true) - }) - - }) - - describe('Network Matchers', () => { - const promiseNetworkMock = Promise.resolve(networkMock) - - it('should not have ts errors when typing to Promise', async () => { - expectPromiseVoid = wdioExpect(promiseNetworkMock).toBeRequested() - expectPromiseVoid = wdioExpect(promiseNetworkMock).toBeRequestedTimes(2) - expectPromiseVoid = wdioExpect(promiseNetworkMock).toBeRequestedTimes({ gte: 5, lte: 10 }) - - expectPromiseVoid = wdioExpect(promiseNetworkMock).not.toBeRequested() - expectPromiseVoid = wdioExpect(promiseNetworkMock).not.toBeRequestedTimes(2) - expectPromiseVoid = wdioExpect(promiseNetworkMock).not.toBeRequestedTimes({ gte: 5, lte: 10 }) - - expectPromiseVoid = wdioExpect(promiseNetworkMock).toBeRequestedWith({ - url: 'http://localhost:8080/api', - method: 'POST', - statusCode: 200, - requestHeaders: { Authorization: 'foo' }, - responseHeaders: { Authorization: 'bar' }, - postData: { title: 'foo', description: 'bar' }, - response: { success: true }, - }) - - expectPromiseVoid = wdioExpect(promiseNetworkMock).toBeRequestedWith({ - url: wdioExpect.stringContaining('test'), - method: 'POST', - statusCode: 200, - requestHeaders: wdioExpect.objectContaining({ Authorization: 'foo' }), - responseHeaders: wdioExpect.objectContaining({ Authorization: 'bar' }), - postData: wdioExpect.objectContaining({ title: 'foo', description: 'bar' }), - response: wdioExpect.objectContaining({ success: true }), - }) - - expectPromiseVoid = wdioExpect(promiseNetworkMock).toBeRequestedWith({ - url: wdioExpect.stringMatching(/.*\/api\/.*/i), - method: ['POST', 'PUT'], - statusCode: [401, 403], - requestHeaders: headers => headers.Authorization.startsWith('Bearer '), - postData: wdioExpect.objectContaining({ released: true, title: wdioExpect.stringContaining('foobar') }), - response: (r: { data: { items: unknown[] } }) => Array.isArray(r) && r.data.items.length === 20 - }) - }) - - it('should have ts errors when typing to void', async () => { - // @ts-expect-error - expectVoid = wdioExpect(promiseNetworkMock).toBeRequested() - // @ts-expect-error - expectVoid = wdioExpect(promiseNetworkMock).toBeRequestedTimes(2) // await wdioExpect(mock).toBeRequestedTimes({ eq: 2 }) - // @ts-expect-error - expectVoid = wdioExpect(promiseNetworkMock).toBeRequestedTimes({ gte: 5, lte: 10 }) // request called at least 5 times but less than 11 - - // @ts-expect-error - expectVoid = wdioExpect(promiseNetworkMock).not.toBeRequested() - // @ts-expect-error - expectVoid = wdioExpect(promiseNetworkMock).not.toBeRequestedTimes(2) // await wdioExpect(mock).toBeRequestedTimes({ eq: 2 }) - // @ts-expect-error - expectVoid = wdioExpect(promiseNetworkMock).not.toBeRequestedTimes({ gte: 5, lte: 10 }) // request called at least 5 times but less than 11 - - // @ts-expect-error - expectVoid = wdioExpect(promiseNetworkMock).toBeRequestedWith({ - url: 'http://localhost:8080/api', - method: 'POST', - statusCode: 200, - requestHeaders: { Authorization: 'foo' }, - responseHeaders: { Authorization: 'bar' }, - postData: { title: 'foo', description: 'bar' }, - response: { success: true }, - }) - - // @ts-expect-error - expectVoid = wdioExpect(promiseNetworkMock).toBeRequestedWith(wdioExpect.objectContaining({ - response: { success: true }, - })) - }) - }) - - describe('Expect', () => { - it('should have ts errors when using a non existing wdioExpect.function', async () => { - // @ts-expect-error - wdioExpect.unimplementedFunction() - }) - - it('should support stringContaining, anything and more', async () => { - wdioExpect.stringContaining('WebdriverIO') - wdioExpect.stringMatching(/WebdriverIO/) - wdioExpect.arrayContaining(['WebdriverIO', 'Test']) - wdioExpect.objectContaining({ name: 'WebdriverIO' }) - // Was not there but works! - wdioExpect.closeTo(5, 10) - wdioExpect.arrayContaining(['WebdriverIO', 'Test']) - // New from jest 30!! - wdioExpect.arrayOf(wdioExpect.stringContaining('WebdriverIO')) - - wdioExpect.anything() - wdioExpect.any(Function) - wdioExpect.any(Number) - wdioExpect.any(Boolean) - wdioExpect.any(String) - wdioExpect.any(Symbol) - wdioExpect.any(Date) - wdioExpect.any(Error) - - wdioExpect.not.stringContaining('WebdriverIO') - wdioExpect.not.stringMatching(/WebdriverIO/) - wdioExpect.not.arrayContaining(['WebdriverIO', 'Test']) - wdioExpect.not.objectContaining({ name: 'WebdriverIO' }) - wdioExpect.not.closeTo(5, 10) - wdioExpect.not.arrayContaining(['WebdriverIO', 'Test']) - wdioExpect.not.arrayOf(wdioExpect.stringContaining('WebdriverIO')) - }) - - describe('Soft Assertions', async () => { - const actualString: string = 'Test Page' - const actualPromiseString: Promise = Promise.resolve('Test Page') - - describe('wdioExpect.soft', () => { - it('should not need to be awaited/be a promise if actual is non-promise type', async () => { - const expectWdioMatcher1: WdioCustomMatchers = wdioExpect.soft(actualString) - expectVoid = wdioExpect.soft(actualString).toBe('Test Page') - expectVoid = wdioExpect.soft(actualString).not.toBe('Test Page') - expectVoid = wdioExpect.soft(actualString).not.toBe(wdioExpect.stringContaining('Test Page')) - - // @ts-expect-error - expectPromiseVoid = wdioExpect.soft(actualString).toBe('Test Page') - // @ts-expect-error - expectPromiseVoid = wdioExpect.soft(actualString).not.toBe('Test Page') - // @ts-expect-error - expectPromiseVoid = wdioExpect.soft(actualString).not.toBe(wdioExpect.stringContaining('Test Page')) - }) - - it('should need to be awaited/be a promise if actual is promise type', async () => { - const expectWdioMatcher1: ExpectWebdriverIO.MatchersAndInverse, Promise> = wdioExpect.soft(actualPromiseString) - expectPromiseVoid = wdioExpect.soft(actualPromiseString).toBe('Test Page') - expectPromiseVoid = wdioExpect.soft(actualPromiseString).not.toBe('Test Page') - expectPromiseVoid = wdioExpect.soft(actualPromiseString).not.toBe(wdioExpect.stringContaining('Test Page')) - - // @ts-expect-error - expectVoid = wdioExpect.soft(actualPromiseString).toBe('Test Page') - // @ts-expect-error - expectVoid = wdioExpect.soft(actualPromiseString).not.toBe('Test Page') - // @ts-expect-error - expectVoid = wdioExpect.soft(actualPromiseString).not.toBe(wdioExpect.stringContaining('Test Page')) - }) - - it('should support chainable element', async () => { - const expectElement: ExpectWebdriverIO.MatchersAndInverse = wdioExpect.soft(element) - const expectElementChainable: ExpectWebdriverIO.MatchersAndInverse = wdioExpect.soft(chainableElement) - - // @ts-expect-error - const expectElement2: ExpectWebdriverIO.MatchersAndInverse, WebdriverIO.Element> = wdioExpect.soft(element) - // @ts-expect-error - const expectElementChainable2: ExpectWebdriverIO.MatchersAndInverse, typeof chainableElement> = wdioExpect.soft(chainableElement) - }) - - it('should support chainable element with wdio Matchers', async () => { - expectPromiseVoid = wdioExpect.soft(element).toBeDisplayed() - expectPromiseVoid = wdioExpect.soft(chainableElement).toBeDisplayed() - expectPromiseVoid = wdioExpect.soft(chainableArray).toBeDisplayed() - await wdioExpect.soft(element).toBeDisplayed() - await wdioExpect.soft(chainableElement).toBeDisplayed() - await wdioExpect.soft(chainableArray).toBeDisplayed() - - expectPromiseVoid = wdioExpect.soft(element).not.toBeDisplayed() - expectPromiseVoid = wdioExpect.soft(chainableElement).not.toBeDisplayed() - expectPromiseVoid = wdioExpect.soft(chainableArray).not.toBeDisplayed() - await wdioExpect.soft(element).not.toBeDisplayed() - await wdioExpect.soft(chainableElement).not.toBeDisplayed() - await wdioExpect.soft(chainableArray).not.toBeDisplayed() - - // @ts-expect-error - expectVoid = wdioExpect.soft(element).toBeDisplayed() - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).toBeDisplayed() - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableArray).toBeDisplayed() - - // @ts-expect-error - expectVoid = wdioExpect.soft(element).not.toBeDisplayed() - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableElement).not.toBeDisplayed() - // @ts-expect-error - expectVoid = wdioExpect.soft(chainableArray).not.toBeDisplayed() - }) - - // Those should return a Promise but soft assertions is not even working at runtime. - // See Jasmine point 6 in the following issue: https://github.com/webdriverio/expect-webdriverio/issues/1893 - // it('should work with custom matcher and custom asymmetric matchers from `expect` module', async () => { - // expectPromiseVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty('text') - // expectPromiseVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty(wdioExpect.stringContaining('text')) - // expectPromiseVoid = wdioExpect.soft(chainableElement).not.toHaveCustomProperty(wdioExpect.not.stringContaining('text')) - // expectPromiseVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty( - // wdioExpect.toHaveCustomProperty(chainableElement) - // ) - - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty('text') - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty(wdioExpect.stringContaining('text')) - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).not.toHaveCustomProperty(wdioExpect.not.stringContaining('text')) - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty( - // wdioExpect.toHaveCustomProperty(chainableElement) - // ) - - // expectPromiseVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty('text') - // expectPromiseVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty(wdioExpect.stringContaining('text')) - // expectPromiseVoid = wdioExpect.soft(chainableElement).not.toHaveCustomProperty(wdioExpect.not.stringContaining('text')) - // expectPromiseVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty( - // wdioExpect.toHaveCustomProperty(chainableElement) - // ) - - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty('text') - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty(wdioExpect.stringContaining('text')) - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).not.toHaveCustomProperty(wdioExpect.not.stringContaining('text')) - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).toHaveCustomProperty( - // wdioExpect.toHaveCustomProperty(chainableElement) - // ) - // }) - - // it('should work with custom matcher and custom asymmetric matchers from `ExpectWebDriverIO` namespace', async () => { - // expectPromiseVoid = wdioExpect.soft(chainableElement).toBeCustomPromise('text') - // expectPromiseVoid = wdioExpect.soft(chainableElement).toBeCustomPromise(wdioExpect.stringContaining('text')) - // expectPromiseVoid = wdioExpect.soft(chainableElement).not.toBeCustomPromise(wdioExpect.not.stringContaining('text')) - // expectPromiseVoid = wdioExpect.soft(chainableElement).toBeCustomPromise( - // wdioExpect.toBeCustomPromise(chainableElement) - // ) - - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).toBeCustomPromise('text') - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).toBeCustomPromise(wdioExpect.stringContaining('text')) - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).not.toBeCustomPromise(wdioExpect.not.stringContaining('text')) - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).toBeCustomPromise( - // wdioExpect.toBeCustomPromise(chainableElement) - // ) - - // expectPromiseVoid = wdioExpect.soft(chainableElement).toBeCustomPromise('text') - // expectPromiseVoid = wdioExpect.soft(chainableElement).toBeCustomPromise(wdioExpect.stringContaining('text')) - // expectPromiseVoid = wdioExpect.soft(chainableElement).not.toBeCustomPromise(wdioExpect.not.stringContaining('text')) - // expectPromiseVoid = wdioExpect.soft(chainableElement).toBeCustomPromise( - // wdioExpect.toBeCustomPromise(chainableElement) - // ) - - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).toBeCustomPromise('text') - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).toBeCustomPromise(wdioExpect.stringContaining('text')) - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).not.toBeCustomPromise(wdioExpect.not.stringContaining('text')) - // // @ts-expect-error - // expectVoid = wdioExpect.soft(chainableElement).toBeCustomPromise( - // wdioExpect.toBeCustomPromise(chainableElement) - // ) - // }) - }) - - describe('wdioExpect.getSoftFailures', () => { - it('should be of type `SoftFailure`', async () => { - const expectSoftFailure1: ExpectWebdriverIO.SoftFailure[] = wdioExpect.getSoftFailures() - - // @ts-expect-error - expectVoid = wdioExpect.getSoftFailures() - }) - }) - - describe('wdioExpect.assertSoftFailures', () => { - it('should be of type void', async () => { - expectVoid = wdioExpect.assertSoftFailures() - - // @ts-expect-error - expectPromiseVoid = wdioExpect.assertSoftFailures() - }) - }) - - describe('wdioExpect.clearSoftFailures', () => { - it('should be of type void', async () => { - expectVoid = wdioExpect.clearSoftFailures() - - // @ts-expect-error - expectPromiseVoid = wdioExpect.clearSoftFailures() - }) - }) - }) - }) - - describe('Asymmetric matchers', () => { - const string: string = 'WebdriverIO is a test framework' - const array: string[] = ['WebdriverIO', 'Test'] - const object: { name: string } = { name: 'WebdriverIO' } - const number: number = 1 - - it('should have no ts error using asymmetric matchers', async () => { - wdioExpect(string).toEqual(wdioExpect.stringContaining('WebdriverIO')) - wdioExpect(array).toEqual(wdioExpect.arrayContaining(['WebdriverIO', 'Test'])) - wdioExpect(object).toEqual(wdioExpect.objectContaining({ name: 'WebdriverIO' })) - wdioExpect(number).toEqual(wdioExpect.closeTo(1.0001, 0.0001)) - wdioExpect(['apple', 'banana', 'cherry']).toEqual(wdioExpect.arrayOf(wdioExpect.any(String))) - }) - }) - - describe('Jasmine only cases', () => { - let expectPromiseLikeVoid: PromiseLike - - it('should not overwrite the jasmine global expect', async () => { - const expectVoid: jasmine.ArrayLikeMatchers = expect('test') - }) - it('should support expectAsync correctly for non wdio types', async () => { - expectPromiseLikeVoid = expectAsync(Promise.resolve('test')).toBeResolved() - expectPromiseLikeVoid = expectAsync(Promise.resolve('test')).toBeResolvedTo(wdioExpect.stringContaining('test error')) - expectPromiseLikeVoid = expectAsync(Promise.resolve('test')).not.toBeResolvedTo(wdioExpect.not.stringContaining('test error')) - expectPromiseLikeVoid = expectAsync(Promise.resolve('test')).toBeRejected() - expectPromiseLikeVoid = expectAsync(Promise.resolve('test')).not.toBeResolved() - expectPromiseLikeVoid = expectAsync(Promise.resolve('test')).not.toBeRejected() - }) - it('should work with Jasmine withContext', async () => { - await expect('title').withContext('checking title').toBe('title') - }) - }) -}) diff --git a/test-types/jest-@jest_global/customMatchers/customMatchers-module-expect.d.ts b/test-types/jest-@jest_global/customMatchers/customMatchers-module-expect.d.ts deleted file mode 100644 index 750d6e1ff..000000000 --- a/test-types/jest-@jest_global/customMatchers/customMatchers-module-expect.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -import 'expect' - -/** - * Custom matchers under the `expect` module. - * @see {@link https://jestjs.io/docs/expect#expectextendmatchers} - */ -declare module 'expect' { - interface AsymmetricMatchers { - toBeWithinRange(floor: number, ceiling: number): void - toHaveSimpleCustomProperty(string: string): string - toHaveCustomProperty(element: ChainablePromiseElement | WebdriverIO.Element): Promise> - } - - interface Matchers { - toBeWithinRange(floor: number, ceiling: number): R - toHaveSimpleCustomProperty(string: string | ExpectWebdriverIO.PartialMatcher): Promise - toHaveCustomProperty: - // Useful to typecheck the custom matcher so it is only used on elements - T extends ChainablePromiseElement | WebdriverIO.Element ? - (test: string | ExpectWebdriverIO.PartialMatcher | - // Needed for the custom asymmetric matcher defined above to be typed correctly - Promise>) - // Using `never` blocks the call on non-element types - => Promise : never; - } -} \ No newline at end of file diff --git a/test-types/jest-@jest_global/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts b/test-types/jest-@jest_global/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts deleted file mode 100644 index 7a833bd87..000000000 --- a/test-types/jest-@jest_global/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Custom matchers under the `ExpectWebdriverIO` namespace. - * @see {@link https://webdriver.io/docs/custommatchers/#typescript-support} - */ -declare namespace ExpectWebdriverIO { - interface AsymmetricMatchers { - toBeCustom(): ExpectWebdriverIO.PartialMatcher; - toBeCustomPromise(chainableElement: ChainablePromiseElement): Promise>; - } - interface Matchers { - toBeCustom(): R; - toBeCustomPromise: T extends ChainablePromiseElement ? (expected?: string | ExpectWebdriverIO.PartialMatcher | Promise>) => Promise : never; - } -} \ No newline at end of file diff --git a/test-types/jest-@jest_global/tsconfig.json b/test-types/jest-@jest_global/tsconfig.json deleted file mode 100644 index 06f3ef3c7..000000000 --- a/test-types/jest-@jest_global/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "compilerOptions": { - "noEmit": true, - "noImplicitAny": true, - "target": "es2022", - "module": "node18", - "skipLibCheck": true, - } -} diff --git a/test-types/jest-@jest_global/types-jest.test.ts b/test-types/jest-@jest_global/types-jest.test.ts deleted file mode 100644 index 193856f87..000000000 --- a/test-types/jest-@jest_global/types-jest.test.ts +++ /dev/null @@ -1,925 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ - -import { expect } from 'expect-webdriverio' -import { describe, it, expect as jestExpect } from '@jest/globals' - -describe('type assertions', async () => { - const chainableElement = {} as unknown as ChainablePromiseElement - const chainableArray = {} as ChainablePromiseArray - - const element: WebdriverIO.Element = {} as unknown as WebdriverIO.Element - const elementArray: WebdriverIO.ElementArray = [] as unknown as WebdriverIO.ElementArray - - const networkMock: WebdriverIO.Mock = {} as unknown as WebdriverIO.Mock - - // Type assertions - let expectPromiseVoid: Promise - let expectVoid: void - - describe('Browser', () => { - const browser: WebdriverIO.Browser = {} as unknown as WebdriverIO.Browser - - describe('toHaveUrl', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = expect(browser).toHaveUrl('https://example.com') - expectPromiseVoid = expect(browser).not.toHaveUrl('https://example.com') - - // Asymmetric matchers - expectPromiseVoid = expect(browser).toHaveUrl(expect.stringContaining('WebdriverIO')) - expectPromiseVoid = expect(browser).toHaveUrl(expect.not.stringContaining('WebdriverIO')) - expectPromiseVoid = expect(browser).toHaveUrl(expect.any(String)) - expectPromiseVoid = expect(browser).toHaveUrl(expect.anything()) - - // @ts-expect-error - expectVoid = expect(browser).toHaveUrl('https://example.com') - // @ts-expect-error - expectVoid = expect(browser).not.toHaveUrl('https://example.com') - // @ts-expect-error - expectVoid = expect(browser).toHaveUrl(expect.stringContaining('WebdriverIO')) - - // @ts-expect-error - await expect(browser).toHaveUrl(6) - }) - - it('should have ts errors when actual is not a Browser element', async () => { - // @ts-expect-error - await expect(element).toHaveUrl('https://example.com') - // @ts-expect-error - await expect(element).not.toHaveUrl('https://example.com') - // @ts-expect-error - await expect(true).toHaveUrl('https://example.com') - // @ts-expect-error - await expect(true).not.toHaveUrl('https://example.com') - }) - }) - - describe('toHaveTitle', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = expect(browser).toHaveTitle('https://example.com') - expectPromiseVoid = expect(browser).not.toHaveTitle('https://example.com') - - // Asymmetric matchers - expectPromiseVoid = expect(browser).toHaveTitle(expect.stringContaining('WebdriverIO')) - expectPromiseVoid = expect(browser).toHaveTitle(expect.any(String)) - expectPromiseVoid = expect(browser).toHaveTitle(expect.anything()) - - // @ts-expect-error - expectVoid = expect(browser).toHaveTitle('https://example.com') - // @ts-expect-error - expectVoid = expect(browser).not.toHaveTitle('https://example.com') - // @ts-expect-error - expectVoid = expect(browser).toHaveTitle(expect.stringContaining('WebdriverIO')) - }) - - it('should have ts errors when actual is not a Browser element', async () => { - // @ts-expect-error - await expect(element).toHaveTitle('https://example.com') - // @ts-expect-error - await expect(element).not.toHaveTitle('https://example.com') - // @ts-expect-error - await expect(true).toHaveTitle('https://example.com') - // @ts-expect-error - await expect(true).not.toHaveTitle('https://example.com') - }) - }) - }) - - describe('element', () => { - - describe('toBeDisabled', () => { - it('should be supported correctly', async () => { - // Element - expectPromiseVoid = expect(element).toBeDisabled() - expectPromiseVoid = expect(element).not.toBeDisabled() - - // Element array - expectPromiseVoid = expect(elementArray).toBeDisabled() - expectPromiseVoid = expect(elementArray).not.toBeDisabled() - - // Chainable element - expectPromiseVoid = expect(chainableElement).toBeDisabled() - expectPromiseVoid = expect(chainableElement).not.toBeDisabled() - - // Chainable element array - expectPromiseVoid = expect(chainableArray).toBeDisabled() - expectPromiseVoid = expect(chainableArray).not.toBeDisabled() - - // @ts-expect-error - expectVoid = expect(element).toBeDisabled() - // @ts-expect-error - expectVoid = expect(element).not.toBeDisabled() - }) - - it('should have ts errors when actual is not an element', async () => { - // @ts-expect-error - await expect(browser).toBeDisabled() - // @ts-expect-error - await expect(browser).not.toBeDisabled() - // @ts-expect-error - await expect(true).toBeDisabled() - // @ts-expect-error - await expect(true).not.toBeDisabled() - }) - }) - - describe('toHaveText', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = expect(element).toHaveText('text') - expectPromiseVoid = expect(element).toHaveText(/text/) - expectPromiseVoid = expect(element).toHaveText(['text1', 'text2']) - expectPromiseVoid = expect(element).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')]) - expectPromiseVoid = expect(element).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expect(element).toHaveText(['text1', /text1/, expect.stringContaining('text3')]) - await expect(element).toHaveText( - 'My-Ex-Am-Ple', - { - replace: [[/-/g, ' '], [/[A-Z]+/g, (match: string) => match.toLowerCase()]] - } - ) - - expectPromiseVoid = expect(element).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expect(element).toHaveText('text') - // @ts-expect-error - await expect(element).toHaveText(6) - - expectPromiseVoid = expect(chainableElement).toHaveText('text') - expectPromiseVoid = expect(chainableElement).toHaveText(/text/) - expectPromiseVoid = expect(chainableElement).toHaveText(['text1', 'text2']) - expectPromiseVoid = expect(chainableElement).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')]) - expectPromiseVoid = expect(chainableElement).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expect(chainableElement).toHaveText(['text1', /text1/, expect.stringContaining('text3')]) - - expectPromiseVoid = expect(chainableElement).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expect(chainableElement).toHaveText('text') - // @ts-expect-error - await expect(chainableElement).toHaveText(6) - - expectPromiseVoid = expect(elementArray).toHaveText('text') - expectPromiseVoid = expect(elementArray).toHaveText(/text/) - expectPromiseVoid = expect(elementArray).toHaveText(['text1', 'text2']) - expectPromiseVoid = expect(elementArray).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')]) - expectPromiseVoid = expect(elementArray).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expect(elementArray).toHaveText(['text1', /text1/, expect.stringContaining('text3')]) - - expectPromiseVoid = expect(elementArray).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expect(elementArray).toHaveText('text') - // @ts-expect-error - await expect(elementArray).toHaveText(6) - - expectPromiseVoid = expect(chainableArray).toHaveText('text') - expectPromiseVoid = expect(chainableArray).toHaveText(/text/) - expectPromiseVoid = expect(chainableArray).toHaveText(['text1', 'text2']) - expectPromiseVoid = expect(chainableArray).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')]) - expectPromiseVoid = expect(chainableArray).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expect(chainableArray).toHaveText(['text1', /text1/, expect.stringContaining('text3')]) - - expectPromiseVoid = expect(chainableArray).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expect(chainableArray).toHaveText('text') - // @ts-expect-error - await expect(chainableArray).toHaveText(6) - - // @ts-expect-error - await expect(browser).toHaveText('text') - }) - - it('should have ts errors when actual is not an element', async () => { - // @ts-expect-error - await expect(browser).toHaveText('text') - // @ts-expect-error - await expect(browser).not.toHaveText('text') - // @ts-expect-error - await expect(true).toHaveText('text') - // @ts-expect-error - await expect(true).toHaveText('text') - }) - - it('should have ts errors when actual is string or Promise', async () => { - // @ts-expect-error - await expect('text').toHaveText('text') - // @ts-expect-error - await expect('text').not.toHaveText('text') - // @ts-expect-error - await expect(Promise.resolve('text')).toHaveText('text') - // @ts-expect-error - await expect(Promise.resolve('text')).toHaveText('text') - }) - }) - - describe('toHaveHeight', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = expect(element).toHaveHeight(100) - expectPromiseVoid = expect(element).toHaveHeight(100, { message: 'Custom error message' }) - expectPromiseVoid = expect(element).not.toHaveHeight(100) - expectPromiseVoid = expect(element).not.toHaveHeight(100, { message: 'Custom error message' }) - - expectPromiseVoid = expect(element).toHaveHeight({ width: 100, height: 200 }) - expectPromiseVoid = expect(element).toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' }) - expectPromiseVoid = expect(element).not.toHaveHeight({ width: 100, height: 200 }) - expectPromiseVoid = expect(element).not.toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' }) - - // @ts-expect-error - expectVoid = expect(element).toHaveHeight(100) - // @ts-expect-error - expectVoid = expect(element).not.toHaveHeight(100) - - // @ts-expect-error - expectVoid = expect(element).toHaveHeight({ width: 100, height: 200 }) - // @ts-expect-error - expectVoid = expect(element).not.toHaveHeight({ width: 100, height: 200 }) - - // @ts-expect-error - await expect(browser).toHaveHeight(100) - }) - - it('should have ts errors when actual is string or Promise', async () => { - // @ts-expect-error - await expect('text').toHaveText('text') - // @ts-expect-error - await expect('text').not.toHaveText('text') - // @ts-expect-error - await expect(Promise.resolve('text')).toHaveText('text') - // @ts-expect-error - await expect(Promise.resolve('text')).toHaveText('text') - }) - }) - - describe('toMatchSnapshot', () => { - - it('should be supported correctly', async () => { - expectVoid = expect(element).toMatchSnapshot() - expectVoid = expect(element).toMatchSnapshot('test label') - expectVoid = expect(element).not.toMatchSnapshot('test label') - - expectPromiseVoid = expect(chainableElement).toMatchSnapshot() - expectPromiseVoid = expect(chainableElement).toMatchSnapshot('test label') - expectPromiseVoid = expect(chainableElement).not.toMatchSnapshot('test label') - - //@ts-expect-error - expectPromiseVoid = expect(element).toMatchSnapshot() - //@ts-expect-error - expectPromiseVoid = expect(element).not.toMatchSnapshot() - //@ts-expect-error - expectVoid = expect(chainableElement).toMatchSnapshot() - //@ts-expect-error - expectVoid = expect(chainableElement).not.toMatchSnapshot() - }) - }) - - describe('toMatchInlineSnapshot', () => { - - it('should be correctly supported', async () => { - expectVoid = expect(element).toMatchInlineSnapshot() - expectVoid = expect(element).toMatchInlineSnapshot('test snapshot') - expectVoid = expect(element).toMatchInlineSnapshot('test snapshot', 'test label') - - expectPromiseVoid = expect(chainableElement).toMatchInlineSnapshot() - expectPromiseVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label') - - //@ts-expect-error - expectPromiseVoid = expect(element).toMatchInlineSnapshot() - //@ts-expect-error - expectVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label') - }) - - it('should be correctly supported with getCSSProperty()', async () => { - expectPromiseVoid = expect(element.getCSSProperty('test')).toMatchInlineSnapshot() - expectPromiseVoid = expect(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = expect(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label') - - expectPromiseVoid = expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot() - expectPromiseVoid = expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label') - - //@ts-expect-error - expectPromiseVoid = expect(element).toMatchInlineSnapshot() - //@ts-expect-error - expectVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label') - }) - }) - - describe('toBeElementsArrayOfSize', async () => { - - it('should work correctly when actual is chainableArray', async () => { - expectPromiseVoid = expect(chainableArray).toBeElementsArrayOfSize(5) - expectPromiseVoid = expect(chainableArray).toBeElementsArrayOfSize({ lte: 10 }) - - // @ts-expect-error - expectVoid = expect(chainableArray).toBeElementsArrayOfSize(5) - // @ts-expect-error - expectVoid = expect(chainableArray).toBeElementsArrayOfSize({ lte: 10 }) - }) - - it('should not work when actual is not chainableArray', async () => { - // @ts-expect-error - await expect(chainableElement).toBeElementsArrayOfSize(5) - // @ts-expect-error - await expect(chainableElement).toBeElementsArrayOfSize({ lte: 10 }) - // @ts-expect-error - await expect(true).toBeElementsArrayOfSize(5) - // @ts-expect-error - await expect(true).toBeElementsArrayOfSize({ lte: 10 }) - }) - }) - }) - - describe('Custom matchers', () => { - describe('using `ExpectWebdriverIO` namespace augmentation', () => { - it('should supported correctly a non-promise custom matcher', async () => { - expectVoid = expect('test').toBeCustom() - expectVoid = expect('test').not.toBeCustom() - - // @ts-expect-error - expectPromiseVoid = expect('test').toBeCustom() - // @ts-expect-error - expectPromiseVoid = expect('test').not.toBeCustom() - - expectVoid = expect(1).toBeWithinRange(0, 2) - }) - - it('should supported correctly a promise custom matcher with only chainableElement as actual', async () => { - expectPromiseVoid = expect(chainableElement).toBeCustomPromise() - expectPromiseVoid = expect(chainableElement).toBeCustomPromise(expect.stringContaining('test')) - expectPromiseVoid = expect(chainableElement).not.toBeCustomPromise(expect.not.stringContaining('test')) - - // @ts-expect-error - expect('test').toBeCustomPromise() - // @ts-expect-error - expectVoid = expect(chainableElement).toBeCustomPromise() - // @ts-expect-error - expectVoid = expect(chainableElement).toBeCustomPromise(expect.stringContaining('test')) - // @ts-expect-error - expectVoid = expect(chainableElement).not.toBeCustomPromise(expect.stringContaining('test')) - // @ts-expect-error - expect(chainableElement).toBeCustomPromise(expect.stringContaining(6)) - }) - - it('should support custom asymmetric matcher', async () => { - const expectString1 : ExpectWebdriverIO.PartialMatcher = expect.toBeCustom() - const expectString2 : ExpectWebdriverIO.PartialMatcher = expect.not.toBeCustom() - - expectPromiseVoid = expect(chainableElement).toBeCustomPromise(expect.toBeCustom()) - - // @ts-expect-error - expectPromiseVoid = expect.toBeCustom() - // @ts-expect-error - expectPromiseVoid = expect.not.toBeCustom() - - //@ts-expect-error - expectVoid = expect(chainableElement).toBeCustomPromise(expect.toBeCustom()) - }) - }) - - describe('using `expect` module declaration', () => { - - it('should support a simple matcher', async () => { - expectVoid = expect(5).toBeWithinRange(1, 10) - - // Or as an asymmetric matcher: - expectVoid = expect({ value: 5 }).toEqual({ - value: expect.toBeWithinRange(1, 10) - }) - - // @ts-expect-error - expectVoid = expect(5).toBeWithinRange(1, '10') - // @ts-expect-error - expectPromiseVoid = expect(5).toBeWithinRange('1') - }) - - it('should support a simple custom matcher with a chainable element matcher with promise', async () => { - expectPromiseVoid = expect(chainableElement).toHaveSimpleCustomProperty('text') - expectPromiseVoid = expect(chainableElement).toHaveSimpleCustomProperty(expect.stringContaining('text')) - expectPromiseVoid = expect(chainableElement).not.toHaveSimpleCustomProperty(expect.not.stringContaining('text')) - - // Or as a custom asymmetric matcher: - expectPromiseVoid = expect(chainableElement).toHaveSimpleCustomProperty( - expect.toHaveSimpleCustomProperty('string') - ) - const expectString1:string = expect.toHaveSimpleCustomProperty('string') - const expectString2:string = expect.not.toHaveSimpleCustomProperty('string') - - // @ts-expect-error - expectVoid = expect.toHaveSimpleCustomProperty(chainableElement) - // @ts-expect-error - expectVoid = expect.not.toHaveSimpleCustomProperty(chainableElement) - - // @ts-expect-error - expectVoid = expect.toHaveSimpleCustomProperty(chainableElement) - }) - - it('should support a chainable element matcher with promise', async () => { - expectPromiseVoid = expect(chainableElement).toHaveCustomProperty('text') - expectPromiseVoid = expect(chainableElement).toHaveCustomProperty(expect.stringContaining('text')) - expectPromiseVoid = expect(chainableElement).not.toHaveCustomProperty(expect.not.stringContaining('text')) - - // Or as a custom asymmetric matcher: - expectPromiseVoid = expect(chainableElement).toHaveCustomProperty( - await expect.toHaveCustomProperty(chainableElement) - ) - const expectPromiseWdioElement1: Promise> = expect.toHaveCustomProperty(chainableElement) - const expectPromiseWdioElement2: Promise> = expect.not.toHaveCustomProperty(chainableElement) - - // @ts-expect-error - expectVoid = expect.toHaveCustomProperty(chainableElement) - // @ts-expect-error - expectVoid = expect.not.toHaveCustomProperty(chainableElement) - - // @ts-expect-error - expectVoid = expect.toHaveCustomProperty(chainableElement) - // @ts-expect-error - expect.toHaveCustomProperty('test') - - await expect(chainableElement).toHaveCustomProperty( - await expect.toHaveCustomProperty(chainableElement) - ) - }) - }) - }) - - describe('toBe', () => { - - it('should expect void type when actual is a boolean', async () => { - expectVoid = expect(true).toBe(true) - expectVoid = expect(true).not.toBe(true) - - //@ts-expect-error - expectPromiseVoid = expect(true).toBe(true) - //@ts-expect-error - expectPromiseVoid = expect(true).not.toBe(true) - }) - - it('should not expect Promise when actual is a chainable since toBe does not need to be awaited', async () => { - expectVoid = expect(chainableElement).toBe(true) - expectVoid = expect(chainableElement).not.toBe(true) - - //@ts-expect-error - expectPromiseVoid = expect(chainableElement).toBe(true) - //@ts-expect-error - expectPromiseVoid = expect(chainableElement).not.toBe(true) - }) - - it('should still expect void type when actual is a Promise since we do not overload them', async () => { - const promiseBoolean = Promise.resolve(true) - - expectVoid = expect(promiseBoolean).toBeDefined() - expectVoid = expect(promiseBoolean).not.toBeDefined() - - //@ts-expect-error - expectPromiseVoid = expect(promiseBoolean).toBeDefined() - //@ts-expect-error - expectPromiseVoid = expect(promiseBoolean).toBe(true) - }) - - it('should work with string', async () => { - expectVoid = expect('text').toBe(true) - expectVoid = expect('text').not.toBe(true) - expectVoid = expect('text').toBe(expect.stringContaining('text')) - expectVoid = expect('text').not.toBe(expect.stringContaining('text')) - - //@ts-expect-error - expectPromiseVoid = expect('text').toBe(true) - //@ts-expect-error - expectPromiseVoid = expect('text').not.toBe(true) - //@ts-expect-error - expectPromiseVoid = expect('text').toBe(expect.stringContaining('text')) - //@ts-expect-error - expectPromiseVoid = expect('text').not.toBe(expect.stringContaining('text')) - }) - }) - - describe('Promise type assertions', () => { - const booleanPromise: Promise = Promise.resolve(true) - - it('should work with resolves & rejects correctly', async () => { - expectPromiseVoid = expect(booleanPromise).resolves.toBe(true) - expectPromiseVoid = expect(booleanPromise).rejects.toBe(true) - - //@ts-expect-error - expectVoid = expect(booleanPromise).resolves.toBe(true) - //@ts-expect-error - expectVoid = expect(booleanPromise).rejects.toBe(true) - - }) - - it('should not support chainable and expect PromiseVoid with toBe', async () => { - //@ts-expect-error - expectPromiseVoid = expect(chainableElement).toBe(true) - //@ts-expect-error - expectPromiseVoid = expect(chainableElement).not.toBe(true) - }) - }) - - describe('Network Matchers', () => { - const promiseNetworkMock = Promise.resolve(networkMock) - - it('should not have ts errors when typing to Promise', async () => { - expectPromiseVoid = expect(promiseNetworkMock).toBeRequested() - expectPromiseVoid = expect(promiseNetworkMock).toBeRequestedTimes(2) - expectPromiseVoid = expect(promiseNetworkMock).toBeRequestedTimes({ gte: 5, lte: 10 }) - - expectPromiseVoid = expect(promiseNetworkMock).not.toBeRequested() - expectPromiseVoid = expect(promiseNetworkMock).not.toBeRequestedTimes(2) - expectPromiseVoid = expect(promiseNetworkMock).not.toBeRequestedTimes({ gte: 5, lte: 10 }) - - expectPromiseVoid = expect(promiseNetworkMock).toBeRequestedWith({ - url: 'http://localhost:8080/api', - method: 'POST', - statusCode: 200, - requestHeaders: { Authorization: 'foo' }, - responseHeaders: { Authorization: 'bar' }, - postData: { title: 'foo', description: 'bar' }, - response: { success: true }, - }) - - expectPromiseVoid = expect(promiseNetworkMock).toBeRequestedWith({ - url: expect.stringContaining('test'), - method: 'POST', - statusCode: 200, - requestHeaders: expect.objectContaining({ Authorization: 'foo' }), - responseHeaders: expect.objectContaining({ Authorization: 'bar' }), - postData: expect.objectContaining({ title: 'foo', description: 'bar' }), - response: expect.objectContaining({ success: true }), - }) - - expectPromiseVoid = expect(promiseNetworkMock).toBeRequestedWith({ - url: expect.stringMatching(/.*\/api\/.*/i), - method: ['POST', 'PUT'], - statusCode: [401, 403], - requestHeaders: headers => headers.Authorization.startsWith('Bearer '), - postData: expect.objectContaining({ released: true, title: expect.stringContaining('foobar') }), - response: (r: { data: { items: unknown[] } }) => Array.isArray(r) && r.data.items.length === 20 - }) - }) - - it('should have ts errors when typing to void', async () => { - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).toBeRequested() - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).toBeRequestedTimes(2) // await expect(mock).toBeRequestedTimes({ eq: 2 }) - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).toBeRequestedTimes({ gte: 5, lte: 10 }) // request called at least 5 times but less than 11 - - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).not.toBeRequested() - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).not.toBeRequestedTimes(2) // await expect(mock).toBeRequestedTimes({ eq: 2 }) - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).not.toBeRequestedTimes({ gte: 5, lte: 10 }) // request called at least 5 times but less than 11 - - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).toBeRequestedWith({ - url: 'http://localhost:8080/api', - method: 'POST', - statusCode: 200, - requestHeaders: { Authorization: 'foo' }, - responseHeaders: { Authorization: 'bar' }, - postData: { title: 'foo', description: 'bar' }, - response: { success: true }, - }) - - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).toBeRequestedWith(expect.objectContaining({ - response: { success: true }, - })) - }) - }) - - describe('Expect', () => { - it('should have ts errors when using a non existing expect.function', async () => { - // @ts-expect-error - expect.unimplementedFunction() - }) - - it('should support stringContaining, anything and more', async () => { - expect.stringContaining('WebdriverIO') - expect.stringMatching(/WebdriverIO/) - expect.arrayContaining(['WebdriverIO', 'Test']) - expect.objectContaining({ name: 'WebdriverIO' }) - // Was not there but works! - expect.closeTo(5, 10) - expect.arrayContaining(['WebdriverIO', 'Test']) - // New from jest 30!! - expect.arrayOf(expect.stringContaining('WebdriverIO')) - - expect.anything() - expect.any(Function) - expect.any(Number) - expect.any(Boolean) - expect.any(String) - expect.any(Symbol) - expect.any(Date) - expect.any(Error) - - expect.not.stringContaining('WebdriverIO') - expect.not.stringMatching(/WebdriverIO/) - expect.not.arrayContaining(['WebdriverIO', 'Test']) - expect.not.objectContaining({ name: 'WebdriverIO' }) - expect.not.closeTo(5, 10) - expect.not.arrayContaining(['WebdriverIO', 'Test']) - expect.not.arrayOf(expect.stringContaining('WebdriverIO')) - - // expect.not.anything() - // expect.not.any(Function) - // expect.not.any(Number) - // expect.not.any(Boolean) - // expect.not.any(String) - // expect.not.any(Symbol) - // expect.not.any(Date) - // expect.not.any(Error) - }) - - describe('Soft Assertions', async () => { - const actualString: string = 'test' - const actualPromiseString: Promise = Promise.resolve('test') - - describe('expect.soft', () => { - it('should not need to be awaited/be a promise if actual is non-promise type', async () => { - const expectWdioMatcher1: WdioCustomMatchers = expect.soft(actualString) - expectVoid = expect.soft(actualString).toBe('Test Page') - expectVoid = expect.soft(actualString).not.toBe('Test Page') - expectVoid = expect.soft(actualString).not.toBe(expect.stringContaining('Test Page')) - - // @ts-expect-error - expectPromiseVoid = expect.soft(actualString).toBe('Test Page') - // @ts-expect-error - expectPromiseVoid = expect.soft(actualString).not.toBe('Test Page') - // @ts-expect-error - expectPromiseVoid = expect.soft(actualString).not.toBe(expect.stringContaining('Test Page')) - }) - - it('should need to be awaited/be a promise if actual is promise type', async () => { - const expectWdioMatcher1: ExpectWebdriverIO.MatchersAndInverse, Promise> = expect.soft(actualPromiseString) - expectPromiseVoid = expect.soft(actualPromiseString).toBe('Test Page') - expectPromiseVoid = expect.soft(actualPromiseString).not.toBe('Test Page') - expectPromiseVoid = expect.soft(actualPromiseString).not.toBe(expect.stringContaining('Test Page')) - - // @ts-expect-error - expectVoid = expect.soft(actualPromiseString).toBe('Test Page') - // @ts-expect-error - expectVoid = expect.soft(actualPromiseString).not.toBe('Test Page') - // @ts-expect-error - expectVoid = expect.soft(actualPromiseString).not.toBe(expect.stringContaining('Test Page')) - }) - - it('should support chainable element', async () => { - const expectElement: ExpectWebdriverIO.MatchersAndInverse = expect.soft(element) - const expectElementChainable: ExpectWebdriverIO.MatchersAndInverse = expect.soft(chainableElement) - - // @ts-expect-error - const expectElement2: ExpectWebdriverIO.MatchersAndInverse, WebdriverIO.Element> = expect.soft(element) - // @ts-expect-error - const expectElementChainable2: ExpectWebdriverIO.MatchersAndInverse, typeof chainableElement> = expect.soft(chainableElement) - }) - - it('should support chainable element with wdio Matchers', async () => { - expectPromiseVoid = expect.soft(element).toBeDisplayed() - expectPromiseVoid = expect.soft(chainableElement).toBeDisplayed() - expectPromiseVoid = expect.soft(chainableArray).toBeDisplayed() - await expect.soft(element).toBeDisplayed() - await expect.soft(chainableElement).toBeDisplayed() - await expect.soft(chainableArray).toBeDisplayed() - - expectPromiseVoid = expect.soft(element).not.toBeDisplayed() - expectPromiseVoid = expect.soft(chainableElement).not.toBeDisplayed() - expectPromiseVoid = expect.soft(chainableArray).not.toBeDisplayed() - await expect.soft(element).not.toBeDisplayed() - await expect.soft(chainableElement).not.toBeDisplayed() - await expect.soft(chainableArray).not.toBeDisplayed() - - // @ts-expect-error - expectVoid = expect.soft(element).toBeDisplayed() - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeDisplayed() - // @ts-expect-error - expectVoid = expect.soft(chainableArray).toBeDisplayed() - - // @ts-expect-error - expectVoid = expect.soft(element).not.toBeDisplayed() - // @ts-expect-error - expectVoid = expect.soft(chainableElement).not.toBeDisplayed() - // @ts-expect-error - expectVoid = expect.soft(chainableArray).not.toBeDisplayed() - }) - - it('should work with custom matcher and custom asymmetric matchers from `expect` module', async () => { - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty('text') - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty(expect.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).not.toHaveCustomProperty(expect.not.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty( - expect.toHaveCustomProperty(chainableElement) - ) - - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty('text') - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty(expect.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).not.toHaveCustomProperty(expect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty( - expect.toHaveCustomProperty(chainableElement) - ) - - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty('text') - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty(expect.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).not.toHaveCustomProperty(expect.not.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty( - expect.toHaveCustomProperty(chainableElement) - ) - - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty('text') - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty(expect.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).not.toHaveCustomProperty(expect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty( - expect.toHaveCustomProperty(chainableElement) - ) - }) - - it('should work with custom matcher and custom asymmetric matchers from `ExpectWebDriverIO` namespace', async () => { - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise('text') - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise(expect.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).not.toBeCustomPromise(expect.not.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise( - expect.toBeCustomPromise(chainableElement) - ) - - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise('text') - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise(expect.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).not.toBeCustomPromise(expect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise( - expect.toBeCustomPromise(chainableElement) - ) - - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise('text') - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise(expect.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).not.toBeCustomPromise(expect.not.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise( - expect.toBeCustomPromise(chainableElement) - ) - - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise('text') - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise(expect.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).not.toBeCustomPromise(expect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise( - expect.toBeCustomPromise(chainableElement) - ) - }) - }) - - describe('expect.getSoftFailures', () => { - it('should be of type `SoftFailure`', async () => { - const expectSoftFailure1: ExpectWebdriverIO.SoftFailure[] = expect.getSoftFailures() - - // @ts-expect-error - expectVoid = expect.getSoftFailures() - }) - }) - - describe('expect.assertSoftFailures', () => { - it('should be of type void', async () => { - expectVoid = expect.assertSoftFailures() - - // @ts-expect-error - expectPromiseVoid = expect.assertSoftFailures() - }) - }) - - describe('expect.clearSoftFailures', () => { - it('should be of type void', async () => { - expectVoid = expect.clearSoftFailures() - - // @ts-expect-error - expectPromiseVoid = expect.clearSoftFailures() - }) - }) - }) - }) - - describe('Asymmetric matchers', () => { - const string: string = 'WebdriverIO is a test framework' - const array: string[] = ['WebdriverIO', 'Test'] - const object: { name: string } = { name: 'WebdriverIO' } - const number: number = 1 - - it('should have no ts error using asymmetric matchers', async () => { - expect(string).toEqual(expect.stringContaining('WebdriverIO')) - expect(array).toEqual(expect.arrayContaining(['WebdriverIO', 'Test'])) - expect(object).toEqual(expect.objectContaining({ name: 'WebdriverIO' })) - // This one is tested and is working correctly, surprisingly! - expect(number).toEqual(expect.closeTo(1.0001, 0.0001)) - // New from jest 30, should work! - expect(['apple', 'banana', 'cherry']).toEqual(expect.arrayOf(expect.any(String))) - }) - }) - - describe('@types/jest only - original Matchers', () => { - - it('should support mock matchers existing only on JestExpect', () => { - const mockFn = () => {} - - // Jest-specific mock matchers - expect(mockFn).toHaveBeenCalled() - }) - - describe('Jest-specific Promise matchers', () => { - it('should support resolves and rejects', async () => { - const stringPromise = Promise.resolve('Hello Jest') - const rejectedPromise = Promise.reject(new Error('Failed')) - - expectPromiseVoid = jestExpect(stringPromise).resolves.toBe('Hello Jest') - expectPromiseVoid = jestExpect(rejectedPromise).rejects.toThrow('Failed') - - // @ts-expect-error - expectVoid = jestExpect(stringPromise).resolves.toBe('Hello Jest') - // @ts-expect-error - expectVoid = jestExpect(rejectedPromise).rejects.toThrow('Failed') - }) - }) - - describe('toMatchSnapshot & toMatchInlineSnapshot', () => { - const snapshotName: string = 'test-snapshot' - - it('should work with string', async () => { - const jsonString: string = '{}' - const propertyMatchers = 'test' - expectVoid = jestExpect(jsonString).toMatchSnapshot(propertyMatchers) - expectVoid = jestExpect(jsonString).toMatchSnapshot(propertyMatchers, snapshotName) - expectVoid = jestExpect(jsonString).toMatchInlineSnapshot(propertyMatchers) - expectVoid = jestExpect(jsonString).toMatchInlineSnapshot(propertyMatchers, snapshotName) - - expectVoid = jestExpect(jsonString).not.toMatchSnapshot(propertyMatchers) - expectVoid = jestExpect(jsonString).not.toMatchSnapshot(propertyMatchers, snapshotName) - expectVoid = jestExpect(jsonString).not.toMatchInlineSnapshot(propertyMatchers) - expectVoid = jestExpect(jsonString).not.toMatchInlineSnapshot(propertyMatchers, snapshotName) - - // @ts-expect-error - expectPromiseVoid = jestExpect(jsonString).toMatchSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = jestExpect(jsonString).toMatchSnapshot(propertyMatchers, snapshotName) - // @ts-expect-error - expectPromiseVoid = jestExpect(jsonString).toMatchInlineSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = jestExpect(jsonString).toMatchInlineSnapshot(propertyMatchers, snapshotName) - // @ts-expect-error - expectPromiseVoid = jestExpect(jsonString).not.toMatchSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = jestExpect(jsonString).not.toMatchSnapshot(propertyMatchers, snapshotName) - // @ts-expect-error - expectPromiseVoid = jestExpect(jsonString).not.toMatchInlineSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = jestExpect(jsonString).not.toMatchInlineSnapshot(propertyMatchers, snapshotName) - }) - - it('should with object', async () => { - const treeObject = { 1: 'test', 2: 'test2' } - const propertyMatchers = { 1: 'test' } - expectVoid = jestExpect(treeObject).toMatchSnapshot(propertyMatchers) - expectVoid = jestExpect(treeObject).toMatchSnapshot(propertyMatchers, snapshotName) - expectVoid = jestExpect(treeObject).toMatchInlineSnapshot(propertyMatchers) - expectVoid = jestExpect(treeObject).toMatchInlineSnapshot(propertyMatchers, snapshotName) - - expectVoid = jestExpect(treeObject).not.toMatchSnapshot(propertyMatchers) - expectVoid = jestExpect(treeObject).not.toMatchSnapshot(propertyMatchers, snapshotName) - expectVoid = jestExpect(treeObject).not.toMatchInlineSnapshot(propertyMatchers) - expectVoid = jestExpect(treeObject).not.toMatchInlineSnapshot(propertyMatchers, snapshotName) - - // @ts-expect-error - expectPromiseVoid = jestExpect(treeObject).toMatchSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = jestExpect(treeObject).toMatchSnapshot(propertyMatchers, snapshotName) - // @ts-expect-error - expectPromiseVoid = jestExpect(treeObject).toMatchInlineSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = jestExpect(treeObject).toMatchInlineSnapshot(propertyMatchers, snapshotName) - // @ts-expect-error - expectPromiseVoid = jestExpect(treeObject).not.toMatchSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = jestExpect(treeObject).not.toMatchSnapshot(propertyMatchers, snapshotName) - // @ts-expect-error - expectPromiseVoid = jestExpect(treeObject).not.toMatchInlineSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = jestExpect(treeObject).not.toMatchInlineSnapshot(propertyMatchers, snapshotName) - }) - }) - }) -}) diff --git a/test-types/jest-@types_jest/customMatchers/customMatchers-module-expect.d.ts b/test-types/jest-@types_jest/customMatchers/customMatchers-module-expect.d.ts index 750d6e1ff..28ce914dc 100644 --- a/test-types/jest-@types_jest/customMatchers/customMatchers-module-expect.d.ts +++ b/test-types/jest-@types_jest/customMatchers/customMatchers-module-expect.d.ts @@ -2,19 +2,25 @@ import 'expect' /** * Custom matchers under the `expect` module. + * + * LIMITATION: This augmentation get apply only on `expect.soft(...)`. + * It does NOT affect the global `expect(...)` in Jest which uses `namespace jest`. + * + * For universal support, prefer augmenting `ExpectWebdriverIO` namespace. + * * @see {@link https://jestjs.io/docs/expect#expectextendmatchers} */ declare module 'expect' { interface AsymmetricMatchers { - toBeWithinRange(floor: number, ceiling: number): void - toHaveSimpleCustomProperty(string: string): string - toHaveCustomProperty(element: ChainablePromiseElement | WebdriverIO.Element): Promise> + toBeWithinRangeExpect(floor: number, ceiling: number): void + toHaveSimpleCustomPropertyExpect(string: string): string + toHaveCustomPropertyExpect(element: ChainablePromiseElement | WebdriverIO.Element): Promise> } interface Matchers { - toBeWithinRange(floor: number, ceiling: number): R - toHaveSimpleCustomProperty(string: string | ExpectWebdriverIO.PartialMatcher): Promise - toHaveCustomProperty: + toBeWithinRangeExpect(floor: number, ceiling: number): R + toHaveSimpleCustomPropertyExpect(string: string | ExpectWebdriverIO.PartialMatcher): Promise + toHaveCustomPropertyExpect: // Useful to typecheck the custom matcher so it is only used on elements T extends ChainablePromiseElement | WebdriverIO.Element ? (test: string | ExpectWebdriverIO.PartialMatcher | @@ -23,4 +29,4 @@ declare module 'expect' { // Using `never` blocks the call on non-element types => Promise : never; } -} \ No newline at end of file +} diff --git a/test-types/jest-@types_jest/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts b/test-types/jest-@types_jest/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts index 7a833bd87..6d88f5c74 100644 --- a/test-types/jest-@types_jest/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts +++ b/test-types/jest-@types_jest/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts @@ -1,14 +1,18 @@ /** * Custom matchers under the `ExpectWebdriverIO` namespace. + * + * RECOMMENDED: This augmentation works universally. + * It is supported by both the global `expect` in Jest/Jasmine AND `expect.soft`. + * * @see {@link https://webdriver.io/docs/custommatchers/#typescript-support} */ declare namespace ExpectWebdriverIO { interface AsymmetricMatchers { - toBeCustom(): ExpectWebdriverIO.PartialMatcher; - toBeCustomPromise(chainableElement: ChainablePromiseElement): Promise>; + toBeCustomWdio(): ExpectWebdriverIO.PartialMatcher; + toBeCustomPromiseWdio(chainableElement: ChainablePromiseElement): Promise>; } interface Matchers { - toBeCustom(): R; - toBeCustomPromise: T extends ChainablePromiseElement ? (expected?: string | ExpectWebdriverIO.PartialMatcher | Promise>) => Promise : never; + toBeCustomWdio(): R; + toBeCustomPromiseWdio: T extends ChainablePromiseElement ? (expected?: string | ExpectWebdriverIO.PartialMatcher | Promise>) => Promise : never; } -} \ No newline at end of file +} diff --git a/test-types/jest-@types_jest/customMatchers/customMatchers-namespace-jest.d.ts b/test-types/jest-@types_jest/customMatchers/customMatchers-namespace-jest.d.ts new file mode 100644 index 000000000..cca2bbb96 --- /dev/null +++ b/test-types/jest-@types_jest/customMatchers/customMatchers-namespace-jest.d.ts @@ -0,0 +1,34 @@ +declare namespace jest { + /** + * Custom matchers under the `jest` namespace. + * + * LIMITATION: This augmentation only works for the global `expect(...)` in the Jest environment. + * It does NOT support `expect.soft(...)` which uses the standalone `expect` types. + * + * For universal support, prefer augmenting `ExpectWebdriverIO` namespace. + */ + interface Expect { + toBeWithinRangeJest(floor: number, ceiling: number): void + toHaveSimpleCustomPropertyJest(string: string): string + toHaveCustomPropertyJest(element: ChainablePromiseElement | WebdriverIO.Element): Promise> + } + + interface InverseAsymmetricMatchers { + toBeWithinRangeJest(floor: number, ceiling: number): void + toHaveSimpleCustomPropertyJest(string: string): string + toHaveCustomPropertyJest(element: ChainablePromiseElement | WebdriverIO.Element): Promise> + } + + interface Matchers { + toBeWithinRangeJest(floor: number, ceiling: number): R + toHaveSimpleCustomPropertyJest(string: string | ExpectWebdriverIO.PartialMatcher): Promise + toHaveCustomPropertyJest: + // Useful to typecheck the custom matcher so it is only used on elements + T extends ChainablePromiseElement | WebdriverIO.Element ? + (test: string | ExpectWebdriverIO.PartialMatcher | + // Needed for the custom asymmetric matcher defined above to be typed correctly + Promise>) + // Using `never` blocks the call on non-element types + => Promise : never; + } +} diff --git a/test-types/jest-@types_jest/jest.test-d.ts b/test-types/jest-@types_jest/jest.test-d.ts new file mode 100644 index 000000000..11f89cc1b --- /dev/null +++ b/test-types/jest-@types_jest/jest.test-d.ts @@ -0,0 +1,705 @@ +import { expectTypeOf } from 'vitest' +import type { ChainablePromiseElement, ChainablePromiseArray } from 'webdriverio' + +describe('Jest augmentation typing assertions tests paired with `@types/jest`', () => { + const chainableElement = {} as unknown as ChainablePromiseElement + const chainableArray = {} as ChainablePromiseArray + + const element: WebdriverIO.Element = {} as unknown as WebdriverIO.Element + const elementArray: WebdriverIO.ElementArray = [] as unknown as WebdriverIO.ElementArray + const elements: WebdriverIO.Element[] = [] as unknown as WebdriverIO.Element[] + + const networkMock: WebdriverIO.Mock = {} as unknown as WebdriverIO.Mock + const browser: WebdriverIO.Browser = {} as unknown as WebdriverIO.Browser + + describe('Browser', () => { + describe('toHaveUrl', () => { + it('should return Promise', async () => { + expectTypeOf(expect(browser).toHaveUrl('https://example.com')).toEqualTypeOf>() + expectTypeOf(expect(browser).not.toHaveUrl('https://example.com')).toEqualTypeOf>() + + // Asymmetric matchers + expectTypeOf(expect(browser).toHaveUrl(expect.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveUrl(expect.not.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveUrl(expect.any(String))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveUrl(expect.anything())).toEqualTypeOf>() + + expectTypeOf(expect(browser).toHaveUrl).parameter(0).extract().toBeNever() + }) + + it('should have ts errors when actual is not a Browser element', async () => { + expectTypeOf(expect(element).toHaveUrl).toBeNever() + expectTypeOf(expect(true).toHaveUrl).toBeNever() + }) + }) + + describe('toHaveTitle', () => { + it('should return Promise', async () => { + expectTypeOf(expect(browser).toHaveTitle('https://example.com')).toEqualTypeOf>() + expectTypeOf(expect(browser).not.toHaveTitle('https://example.com')).toEqualTypeOf>() + + // Asymmetric matchers + expectTypeOf(expect(browser).toHaveTitle(expect.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveTitle(expect.any(String))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveTitle(expect.anything())).toEqualTypeOf>() + }) + + it('should have ts errors when actual is not a Browser element', async () => { + expectTypeOf(expect(element).toHaveTitle).toBeNever() + expectTypeOf(expect(true).toHaveTitle).toBeNever() + }) + }) + + describe('toHaveClipboardText', () => { + it('should return Promise', async () => { + expectTypeOf(expect(browser).toHaveClipboardText('text')).toEqualTypeOf>() + expectTypeOf(expect(browser).not.toHaveClipboardText('text')).toEqualTypeOf>() + + // Asymmetric matchers + expectTypeOf(expect(browser).toHaveClipboardText(expect.stringContaining('text'))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveClipboardText(expect.any(String))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveClipboardText(expect.anything())).toEqualTypeOf>() + }) + + it('should have ts errors when actual is not a Browser element', async () => { + expectTypeOf(expect(element).toHaveClipboardText).toBeNever() + expectTypeOf(expect(true).toHaveClipboardText).toBeNever() + }) + }) + }) + + describe('element', () => { + + describe('toBeDisabled', () => { + it('should return Promise', async () => { + // Element + expectTypeOf(expect(element).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expect(element).not.toBeDisabled()).toEqualTypeOf>() + + // Element array + expectTypeOf(expect(elementArray).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expect(elementArray).not.toBeDisabled()).toEqualTypeOf>() + + // Chainable element + expectTypeOf(expect(chainableElement).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toBeDisabled()).toEqualTypeOf>() + + // Chainable element array + expectTypeOf(expect(chainableArray).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).not.toBeDisabled()).toEqualTypeOf>() + }) + + it('should have ts errors when actual is not an element', async () => { + expectTypeOf(expect(browser).toBeDisabled).toBeNever() + expectTypeOf(expect(true).toBeDisabled).toBeNever() + }) + }) + + describe('toHaveText', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText(['text1', /text1/, expect.stringContaining('text3')])).toEqualTypeOf>() + await expect(element).toHaveText( + 'My-Ex-Am-Ple', + { + replace: [[/-/g, ' '], [/[A-Z]+/g, (match: string) => match.toLowerCase()]] + } + ) + + expectTypeOf(expect(element).not.toHaveText('text')).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expect(chainableElement).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText(['text1', /text1/, expect.stringContaining('text3')])).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement).not.toHaveText('text')).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expect(elementArray).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText(['text1', /text1/, expect.stringContaining('text3')])).toEqualTypeOf>() + + expectTypeOf(expect(elementArray).not.toHaveText('text')).toEqualTypeOf>() + + expectTypeOf(expect(elementArray).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expect(chainableArray).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText(['text1', /text1/, expect.stringContaining('text3')])).toEqualTypeOf>() + + expectTypeOf(expect(chainableArray).not.toHaveText('text')).toEqualTypeOf>() + + expectTypeOf(expect(chainableArray).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expect(browser).toHaveText).toBeNever() + }) + + it('should have ts errors when actual is not an element', async () => { + expectTypeOf(expect(browser).toHaveText).toBeNever() + expectTypeOf(expect(true).toHaveText).toBeNever() + }) + + it('should have ts errors when actual is string or Promise', async () => { + expectTypeOf(expect('text').toHaveText).toBeNever() + expectTypeOf(expect(Promise.resolve('text')).toHaveText).toBeNever() + expectTypeOf(expect(Promise.resolve('text')).toHaveText).toBeNever() + }) + }) + + describe('toHaveHeight', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveHeight(100)).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveHeight(100, { message: 'Custom error message' })).toEqualTypeOf>() + expectTypeOf(expect(element).not.toHaveHeight(100)).toEqualTypeOf>() + expectTypeOf(expect(element).not.toHaveHeight(100, { message: 'Custom error message' })).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveHeight({ width: 100, height: 200 })).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' })).toEqualTypeOf>() + expectTypeOf(expect(element).not.toHaveHeight({ width: 100, height: 200 })).toEqualTypeOf>() + expectTypeOf(expect(element).not.toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' })).toEqualTypeOf>() + + expectTypeOf(expect(browser).toHaveHeight).toBeNever() + }) + + it('should have ts errors when actual is string or Promise', async () => { + expectTypeOf(expect('text').toHaveHeight).toBeNever() + expectTypeOf(expect(Promise.resolve('text')).toHaveHeight).toBeNever() + expectTypeOf(expect(Promise.resolve('text')).toHaveHeight).toBeNever() + }) + }) + + describe('toMatchSnapshot', () => { + + it('should return Promise', async () => { + expectTypeOf(expect(element).toMatchSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(element).toMatchSnapshot('test label')).toEqualTypeOf>() + expectTypeOf(expect(element).not.toMatchSnapshot('test label')).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement).toMatchSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toMatchSnapshot('test label')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toMatchSnapshot('test label')).toEqualTypeOf>() + }) + }) + + describe('toMatchInlineSnapshot', () => { + + it('should return Promise', async () => { + expectTypeOf(expect(element).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(element).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expect(element).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + }) + + it('should return Promise with getCSSProperty()', async () => { + expectTypeOf(expect(element.getCSSProperty('test')).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expect(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + + expectTypeOf(expect(element).toMatchInlineSnapshot()).toEqualTypeOf>() + }) + }) + + describe('toBeElementsArrayOfSize', async () => { + + it('should return Promise when actual is chainableArray', async () => { + expectTypeOf(expect(chainableArray).toBeElementsArrayOfSize(5)).toMatchTypeOf>() + expectTypeOf(expect(chainableArray).toBeElementsArrayOfSize({ lte: 10 })).toMatchTypeOf>() + }) + + it('should return Promise when actual is element array', async () => { + expectTypeOf(expect(elementArray).toBeElementsArrayOfSize(5)).toMatchTypeOf>() + expectTypeOf(expect(elementArray).toBeElementsArrayOfSize({ lte: 10 })).toMatchTypeOf>() + }) + + it('should return Promise when actual is element[]', async () => { + expectTypeOf(expect(elements).toBeElementsArrayOfSize(5)).toMatchTypeOf>() + expectTypeOf(expect(elements).toBeElementsArrayOfSize({ lte: 10 })).toMatchTypeOf>() + }) + + it('should not work when actual is not chainableArray', async () => { + expectTypeOf(expect(chainableElement).toBeElementsArrayOfSize).toBeNever() + expectTypeOf(expect(true).toBeElementsArrayOfSize).toBeNever() + }) + }) + }) + + describe('Custom matchers', () => { + describe('using `ExpectWebdriverIO` namespace augmentation', () => { + it('should supported correctly a non-promise custom matcher', async () => { + expectTypeOf(expect('test').toBeCustomWdio()).toEqualTypeOf() + expectTypeOf(expect('test').not.toBeCustomWdio()).toEqualTypeOf() + }) + + it('should supported correctly a promise custom matcher with only chainableElement as actual', async () => { + expectTypeOf(expect(chainableElement).toBeCustomPromiseWdio()).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toBeCustomPromiseWdio(expect.stringContaining('test'))).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toBeCustomPromiseWdio(expect.not.stringContaining('test'))).toEqualTypeOf>() + + expectTypeOf(expect('test').toBeCustomPromiseWdio).toBeNever() + expectTypeOf(expect(chainableElement).toBeCustomPromiseWdio).parameter(0).extract().toBeNever() + }) + + it('should support custom asymmetric matcher', async () => { + expectTypeOf(expect.toBeCustomWdio()).toEqualTypeOf>() + expectTypeOf(expect.not.toBeCustomWdio()).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement).toBeCustomPromiseWdio(expect.toBeCustomWdio())).toEqualTypeOf>() + + expectTypeOf(expect.toBeCustomWdio()).not.toEqualTypeOf>() + expectTypeOf(expect.not.toBeCustomWdio()).not.toEqualTypeOf>() + + expectTypeOf(expect(chainableElement).toBeCustomPromiseWdio(expect.toBeCustomWdio())).not.toEqualTypeOf() + }) + }) + + describe('using `jest` namespace augmentation', () => { + + it('should support a simple matcher', async () => { + expectTypeOf(expect(5).toBeWithinRangeJest(1, 10)).toEqualTypeOf() + + // Or as an asymmetric matcher: + expectTypeOf(expect({ value: 5 }).toEqual({ + value: expect.toBeWithinRangeJest(1, 10) + })).toEqualTypeOf() + }) + + it('should support a simple custom matcher with a chainable element matcher with promise', async () => { + expectTypeOf(expect(chainableElement).toHaveSimpleCustomPropertyJest('text')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveSimpleCustomPropertyJest(expect.stringContaining('text'))).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toHaveSimpleCustomPropertyJest(expect.not.stringContaining('text'))).toEqualTypeOf>() + + // Or as a custom asymmetric matcher: + expectTypeOf(expect(chainableElement).toHaveSimpleCustomPropertyJest( + expect.toHaveSimpleCustomPropertyJest('string') + )).toEqualTypeOf>() + expectTypeOf(expect.toHaveSimpleCustomPropertyJest('string')).toEqualTypeOf() + expectTypeOf(expect.not.toHaveSimpleCustomPropertyJest('string')).toEqualTypeOf() + }) + + it('should support a chainable element matcher with promise', async () => { + expectTypeOf(expect(chainableElement).toHaveCustomPropertyJest('text')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveCustomPropertyJest(expect.stringContaining('text'))).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toHaveCustomPropertyJest(expect.not.stringContaining('text'))).toEqualTypeOf>() + + // Or as a custom asymmetric matcher: + expectTypeOf(expect(chainableElement).toHaveCustomPropertyJest( + await expect.toHaveCustomPropertyJest(chainableElement) + )).toEqualTypeOf>() + expectTypeOf(expect.toHaveCustomPropertyJest(chainableElement)).toEqualTypeOf>>() + expectTypeOf(expect.not.toHaveCustomPropertyJest(chainableElement)).toEqualTypeOf>>() + + expectTypeOf(expect.toHaveCustomPropertyJest(chainableElement)).not.toEqualTypeOf() + expectTypeOf(expect.not.toHaveCustomPropertyJest(chainableElement)).not.toEqualTypeOf() + + expectTypeOf(expect.toHaveCustomPropertyJest(chainableElement)).not.toEqualTypeOf() + + await expect(chainableElement).toHaveCustomPropertyJest( + await expect.toHaveCustomPropertyJest(chainableElement) + ) + }) + }) + }) + + describe('toBe', () => { + + it('should return void when actual is a boolean', async () => { + expectTypeOf(expect(true).toBe(true)).toEqualTypeOf() + expectTypeOf(expect(true).not.toBe(true)).toEqualTypeOf() + + expectTypeOf(expect(true).toBe(true)).not.toEqualTypeOf>() + expectTypeOf(expect(true).not.toBe(true)).not.toEqualTypeOf>() + }) + + it('should return void when actual is a chainable', async () => { + expectTypeOf(expect(chainableElement).toBe(true)).toEqualTypeOf() + expectTypeOf(expect(chainableElement).not.toBe(true)).toEqualTypeOf() + + expectTypeOf(expect(chainableElement).toBe(true)).not.toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toBe(true)).not.toEqualTypeOf>() + }) + + it('should return void when actual is a Promise', async () => { + const promiseBoolean = Promise.resolve(true) + + expectTypeOf(expect(promiseBoolean).toBeDefined()).toEqualTypeOf() + expectTypeOf(expect(promiseBoolean).not.toBeDefined()).toEqualTypeOf() + + expectTypeOf(expect(promiseBoolean).toBeDefined()).not.toEqualTypeOf>() + expectTypeOf(expect(promiseBoolean).toBeDefined()).not.toEqualTypeOf>() + }) + + it('should return void when actual is a String', async () => { + expectTypeOf(expect('text').toBe(true)).toEqualTypeOf() + expectTypeOf(expect('text').not.toBe(true)).toEqualTypeOf() + expectTypeOf(expect('text').toBe(expect.stringContaining('text'))).toEqualTypeOf() + expectTypeOf(expect('text').not.toBe(expect.stringContaining('text'))).toEqualTypeOf() + + expectTypeOf(expect('text').toBe(true)).not.toEqualTypeOf>() + expectTypeOf(expect('text').not.toBe(true)).not.toEqualTypeOf>() + expectTypeOf(expect('text').toBe(expect.stringContaining('text'))).not.toEqualTypeOf>() + expectTypeOf(expect('text').not.toBe(expect.stringContaining('text'))).not.toEqualTypeOf>() + }) + }) + + describe('Promise type assertions', () => { + const booleanPromise: Promise = Promise.resolve(true) + + it('should have expect return Matchers with a Promise', async () => { + expectTypeOf(expect(booleanPromise)).toMatchTypeOf>>() + expectTypeOf(expect(booleanPromise).not).toMatchTypeOf>>() + }) + + it('should return Promise for resolves & rejects', async () => { + expectTypeOf(expect(booleanPromise).resolves.toBe(true)).toEqualTypeOf>() + expectTypeOf(expect(booleanPromise).rejects.toBe(true)).toEqualTypeOf>() + expectTypeOf(expect(booleanPromise).rejects.not.toBe(true)).toEqualTypeOf>() + expectTypeOf(expect(booleanPromise).resolves.not.toBe(true)).toEqualTypeOf>() + + expectTypeOf(expect(booleanPromise).resolves.toBe(true)).not.toEqualTypeOf() + expectTypeOf(expect(booleanPromise).rejects.toBe(true)).not.toEqualTypeOf() + }) + + it('should not support chainable and expect PromiseVoid with toBe', async () => { + expectTypeOf(expect(chainableElement).toBe(true)).not.toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toBe(true)).not.toEqualTypeOf>() + }) + }) + + describe('Network Matchers', () => { + const promiseNetworkMock = Promise.resolve(networkMock) + + it('should return Promise', async () => { + expectTypeOf(expect(promiseNetworkMock).toBeRequested()).toEqualTypeOf>() + expectTypeOf(expect(promiseNetworkMock).toBeRequestedTimes(2)).toEqualTypeOf>() + expectTypeOf(expect(promiseNetworkMock).toBeRequestedTimes({ gte: 5, lte: 10 })).toEqualTypeOf>() + + expectTypeOf(expect(promiseNetworkMock).not.toBeRequested()).toEqualTypeOf>() + expectTypeOf(expect(promiseNetworkMock).not.toBeRequestedTimes(2)).toEqualTypeOf>() + expectTypeOf(expect(promiseNetworkMock).not.toBeRequestedTimes({ gte: 5, lte: 10 })).toEqualTypeOf>() + + expectTypeOf(expect(promiseNetworkMock).toBeRequestedWith({ + url: 'http://localhost:8080/api', + method: 'POST', + statusCode: 200, + requestHeaders: { Authorization: 'foo' }, + responseHeaders: { Authorization: 'bar' }, + postData: { title: 'foo', description: 'bar' }, + response: { success: true }, + })).toEqualTypeOf>() + + expectTypeOf(expect(promiseNetworkMock).toBeRequestedWith({ + url: expect.stringContaining('test'), + method: 'POST', + statusCode: 200, + requestHeaders: expect.objectContaining({ Authorization: 'foo' }), + responseHeaders: expect.objectContaining({ Authorization: 'bar' }), + postData: expect.objectContaining({ title: 'foo', description: 'bar' }), + response: expect.objectContaining({ success: true }), + })).toEqualTypeOf>() + + expectTypeOf(expect(promiseNetworkMock).toBeRequestedWith({ + url: expect.stringMatching(/.*\/api\/.*/i), + method: ['POST', 'PUT'], + statusCode: [401, 403], + requestHeaders: headers => headers.Authorization.startsWith('Bearer '), + postData: expect.objectContaining({ released: true, title: expect.stringContaining('foobar') }), + response: (r: { data: { items: unknown[] } }) => Array.isArray(r) && r.data.items.length === 20 + })).toEqualTypeOf>() + }) + }) + + describe('Standard Jest Matchers', () => { + it('should return void', async () => { + const obj = { a: 1 } + expectTypeOf(expect(obj).toHaveProperty('a')).toEqualTypeOf() + expectTypeOf(expect(obj).toMatchObject({ a: 1 })).toEqualTypeOf() + expectTypeOf(expect(obj).toStrictEqual({ a: 1 })).toEqualTypeOf() + expectTypeOf(expect([1, 2]).toHaveLength(2)).toEqualTypeOf() + }) + }) + + describe('More WDIO Matchers', () => { + describe('Attribute Matchers', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveAttribute('class')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveAttribute('class', 'val')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveAttribute('class', expect.stringContaining('val'))).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveAttr('class')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveAttr('class', 'val')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveAttr('class', expect.stringContaining('val'))).toEqualTypeOf>() + }) + }) + + describe('Class Matchers', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveClass('class')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveClass(expect.stringContaining('class'))).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveElementClass('class')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveElementClass(expect.stringContaining('class'))).toEqualTypeOf>() + }) + }) + + describe('Property Matchers', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveValue('val')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveValue(expect.stringContaining('val'))).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveElementProperty('prop')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveElementProperty('prop', 'val')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveElementProperty('prop', expect.stringContaining('val'))).toEqualTypeOf>() + }) + }) + + describe('Link Matchers', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveHref('href')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveHref(expect.stringContaining('href'))).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveLink('href')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveLink(expect.stringContaining('href'))).toEqualTypeOf>() + }) + }) + + describe('Identity & Other Matchers', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveId('id')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveId(expect.stringContaining('id'))).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveHTML('html')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveHTML(expect.stringContaining('html'))).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveComputedLabel('label')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveComputedLabel(expect.stringContaining('label'))).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveComputedRole('role')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveComputedRole(expect.stringContaining('role'))).toEqualTypeOf>() + }) + }) + + describe('State Matchers', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toBeClickable()).toEqualTypeOf>() + expectTypeOf(expect(element).toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(expect(element).toExist()).toEqualTypeOf>() + expectTypeOf(expect(element).toBePresent()).toEqualTypeOf>() + expectTypeOf(expect(element).toBeExisting()).toEqualTypeOf>() + expectTypeOf(expect(element).toBeDisplayedInViewport()).toEqualTypeOf>() + expectTypeOf(expect(element).toBeEnabled()).toEqualTypeOf>() + expectTypeOf(expect(element).toBeFocused()).toEqualTypeOf>() + expectTypeOf(expect(element).toBeSelected()).toEqualTypeOf>() + expectTypeOf(expect(element).toBeChecked()).toEqualTypeOf>() + }) + }) + + describe('Structure Matchers', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveChildren()).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveSize({ width: 10, height: 10 })).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveWidth(10)).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveStyle({ color: 'red' })).toEqualTypeOf>() + }) + }) + }) + + describe('Expect', () => { + it('should support stringContaining, anything and more', async () => { + expect.stringContaining('WebdriverIO') + expect.stringMatching(/WebdriverIO/) + expect.arrayContaining(['WebdriverIO', 'Test']) + expect.objectContaining({ name: 'WebdriverIO' }) + expect.closeTo(5, 10) + expect.arrayContaining(['WebdriverIO', 'Test']) + expect.arrayOf(expect.stringContaining('WebdriverIO')) + + expect.anything() + expect.any(Function) + expect.any(Number) + expect.any(Boolean) + expect.any(String) + expect.any(Symbol) + expect.any(Date) + expect.any(Error) + + expect.not.stringContaining('WebdriverIO') + expect.not.stringMatching(/WebdriverIO/) + expect.not.arrayContaining(['WebdriverIO', 'Test']) + expect.not.objectContaining({ name: 'WebdriverIO' }) + expect.not.closeTo(5, 10) + expect.not.arrayContaining(['WebdriverIO', 'Test']) + expect.not.arrayOf(expect.stringContaining('WebdriverIO')) + }) + + describe('Soft Assertions', async () => { + const actualString: string = 'Test Page' + const actualPromiseString: Promise = Promise.resolve('Test Page') + + describe('expect.soft', () => { + it('should return void if actual is non-promise type', async () => { + expectTypeOf(expect.soft(actualString)).toMatchTypeOf>() + expectTypeOf(expect.soft(actualString).toBe('Test Page')).toEqualTypeOf() + expectTypeOf(expect.soft(actualString).not.toBe('Test Page')).toEqualTypeOf() + expectTypeOf(expect.soft(actualString).not.toBe(expect.stringContaining('Test Page'))).toEqualTypeOf() + }) + + it('should return Promise if actual is promise type', async () => { + expectTypeOf(expect.soft(actualPromiseString)).toMatchTypeOf, Promise>>() + expectTypeOf(expect.soft(actualPromiseString).toBe('Test Page')).toEqualTypeOf>() + expectTypeOf(expect.soft(actualPromiseString).not.toBe('Test Page')).toEqualTypeOf>() + expectTypeOf(expect.soft(actualPromiseString).not.toBe(expect.stringContaining('Test Page'))).toEqualTypeOf>() + }) + + it('should support chainable element', async () => { + expectTypeOf(expect.soft(element)).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement)).toEqualTypeOf>() + }) + + it('should return Promise with WDIO matchers', async () => { + expectTypeOf(expect.soft(element).toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableArray).toBeDisplayed()).toEqualTypeOf>() + await expect.soft(element).toBeDisplayed() + await expect.soft(chainableElement).toBeDisplayed() + await expect.soft(chainableArray).toBeDisplayed() + + expectTypeOf(expect.soft(element).not.toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).not.toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableArray).not.toBeDisplayed()).toEqualTypeOf>() + await expect.soft(element).not.toBeDisplayed() + await expect.soft(chainableElement).not.toBeDisplayed() + await expect.soft(chainableArray).not.toBeDisplayed() + }) + + it('should work with custom matcher and custom asymmetric matchers from `expect` module', async () => { + expectTypeOf(expect.soft(chainableElement).toHaveCustomPropertyExpect('text')).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).toHaveCustomPropertyExpect(expect.stringContaining('text'))).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).not.toHaveCustomPropertyExpect(expect.not.stringContaining('text'))).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).toHaveCustomPropertyExpect( + expect.toHaveCustomPropertyExpect(chainableElement) + )).toEqualTypeOf>() + }) + + it('should work with custom matcher and custom asymmetric matchers from `ExpectWebDriverIO` namespace', async () => { + expectTypeOf(expect.soft(chainableElement).toBeCustomPromiseWdio('text')).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).toBeCustomPromiseWdio(expect.stringContaining('text'))).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).not.toBeCustomPromiseWdio(expect.not.stringContaining('text'))).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).toBeCustomPromiseWdio( + expect.toBeCustomPromiseWdio(chainableElement) + )).toEqualTypeOf>() + }) + }) + + describe('expect.getSoftFailures', () => { + it('should return `SoftFailure[]`', async () => { + expectTypeOf(expect.getSoftFailures()).toEqualTypeOf() + }) + }) + + describe('expect.assertSoftFailures', () => { + it('should return void', async () => { + expectTypeOf(expect.assertSoftFailures()).toEqualTypeOf() + }) + }) + + describe('expect.clearSoftFailures', () => { + it('should return void', async () => { + expectTypeOf(expect.clearSoftFailures()).toEqualTypeOf() + }) + }) + }) + }) + + describe('Asymmetric matchers', () => { + const string: string = 'WebdriverIO is a test framework' + const array: string[] = ['WebdriverIO', 'Test'] + const object: { name: string } = { name: 'WebdriverIO' } + const number: number = 1 + + it('should have no ts error using asymmetric matchers', async () => { + expect(string).toEqual(expect.stringContaining('WebdriverIO')) + expect(array).toEqual(expect.arrayContaining(['WebdriverIO', 'Test'])) + expect(object).toEqual(expect.objectContaining({ name: 'WebdriverIO' })) + // This one is tested and is working correctly, surprisingly! + expect(number).toEqual(expect.closeTo(1.0001, 0.0001)) + // New from jest 30, should work! + expect(['apple', 'banana', 'cherry']).toEqual(expect.arrayOf(expect.any(String))) + }) + }) + + describe('@types/jest only - original Matchers', () => { + describe('toMatchSnapshot & toMatchInlineSnapshot', () => { + const snapshotName: string = 'test-snapshot' + + it('should work with string', async () => { + const jsonString: string = '{}' + const propertyMatchers = 'test' + expectTypeOf(expect(jsonString).toMatchSnapshot(propertyMatchers)).toEqualTypeOf() + expectTypeOf(expect(jsonString).toMatchSnapshot(propertyMatchers, snapshotName)).toEqualTypeOf() + expectTypeOf(expect(jsonString).toMatchInlineSnapshot(propertyMatchers)).toEqualTypeOf() + expectTypeOf(expect(jsonString).toMatchInlineSnapshot(propertyMatchers, snapshotName)).toEqualTypeOf() + + expectTypeOf(expect(jsonString).not.toMatchSnapshot(propertyMatchers)).toEqualTypeOf() + expectTypeOf(expect(jsonString).not.toMatchSnapshot(propertyMatchers, snapshotName)).toEqualTypeOf() + expectTypeOf(expect(jsonString).not.toMatchInlineSnapshot(propertyMatchers)).toEqualTypeOf() + expectTypeOf(expect(jsonString).not.toMatchInlineSnapshot(propertyMatchers, snapshotName)).toEqualTypeOf() + + expectTypeOf(expect(jsonString).toMatchSnapshot(propertyMatchers)).not.toEqualTypeOf>() + expectTypeOf(expect(jsonString).toMatchSnapshot(propertyMatchers, snapshotName)).not.toEqualTypeOf>() + expectTypeOf(expect(jsonString).toMatchInlineSnapshot(propertyMatchers)).not.toEqualTypeOf>() + expectTypeOf(expect(jsonString).toMatchInlineSnapshot(propertyMatchers, snapshotName)).not.toEqualTypeOf>() + expectTypeOf(expect(jsonString).not.toMatchSnapshot(propertyMatchers)).not.toEqualTypeOf>() + expectTypeOf(expect(jsonString).not.toMatchSnapshot(propertyMatchers, snapshotName)).not.toEqualTypeOf>() + expectTypeOf(expect(jsonString).not.toMatchInlineSnapshot(propertyMatchers)).not.toEqualTypeOf>() + expectTypeOf(expect(jsonString).not.toMatchInlineSnapshot(propertyMatchers, snapshotName)).not.toEqualTypeOf>() + }) + + it('should with object', async () => { + const treeObject = { 1: 'test', 2: 'test2' } + const propertyMatchers = { 1: 'test' } + expectTypeOf(expect(treeObject).toMatchSnapshot(propertyMatchers)).toEqualTypeOf() + expectTypeOf(expect(treeObject).toMatchSnapshot(propertyMatchers, snapshotName)).toEqualTypeOf() + expectTypeOf(expect(treeObject).toMatchInlineSnapshot(propertyMatchers)).toEqualTypeOf() + expectTypeOf(expect(treeObject).toMatchInlineSnapshot(propertyMatchers, snapshotName)).toEqualTypeOf() + + expectTypeOf(expect(treeObject).not.toMatchSnapshot(propertyMatchers)).toEqualTypeOf() + expectTypeOf(expect(treeObject).not.toMatchSnapshot(propertyMatchers, snapshotName)).toEqualTypeOf() + expectTypeOf(expect(treeObject).not.toMatchInlineSnapshot(propertyMatchers)).toEqualTypeOf() + expectTypeOf(expect(treeObject).not.toMatchInlineSnapshot(propertyMatchers, snapshotName)).toEqualTypeOf() + + expectTypeOf(expect(treeObject).toMatchSnapshot(propertyMatchers)).not.toEqualTypeOf>() + expectTypeOf(expect(treeObject).toMatchSnapshot(propertyMatchers, snapshotName)).not.toEqualTypeOf>() + expectTypeOf(expect(treeObject).toMatchInlineSnapshot(propertyMatchers)).not.toEqualTypeOf>() + expectTypeOf(expect(treeObject).toMatchInlineSnapshot(propertyMatchers, snapshotName)).not.toEqualTypeOf>() + expectTypeOf(expect(treeObject).not.toMatchSnapshot(propertyMatchers)).not.toEqualTypeOf>() + expectTypeOf(expect(treeObject).not.toMatchSnapshot(propertyMatchers, snapshotName)).not.toEqualTypeOf>() + expectTypeOf(expect(treeObject).not.toMatchInlineSnapshot(propertyMatchers)).not.toEqualTypeOf>() + expectTypeOf(expect(treeObject).not.toMatchInlineSnapshot(propertyMatchers, snapshotName)).not.toEqualTypeOf>() + }) + }) + }) +}) + diff --git a/test-types/jest-@types_jest/types-jest.test.ts b/test-types/jest-@types_jest/types-jest.test.ts deleted file mode 100644 index 445b7758a..000000000 --- a/test-types/jest-@types_jest/types-jest.test.ts +++ /dev/null @@ -1,908 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ - -describe('type assertions', async () => { - const chainableElement = {} as unknown as ChainablePromiseElement - const chainableArray = {} as ChainablePromiseArray - - const element: WebdriverIO.Element = {} as unknown as WebdriverIO.Element - const elementArray: WebdriverIO.ElementArray = [] as unknown as WebdriverIO.ElementArray - - const networkMock: WebdriverIO.Mock = {} as unknown as WebdriverIO.Mock - - // Type assertions - let expectPromiseVoid: Promise - let expectVoid: void - - describe('Browser', () => { - const browser: WebdriverIO.Browser = {} as unknown as WebdriverIO.Browser - - describe('toHaveUrl', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = expect(browser).toHaveUrl('https://example.com') - expectPromiseVoid = expect(browser).not.toHaveUrl('https://example.com') - - // Asymmetric matchers - expectPromiseVoid = expect(browser).toHaveUrl(expect.stringContaining('WebdriverIO')) - expectPromiseVoid = expect(browser).toHaveUrl(expect.not.stringContaining('WebdriverIO')) - expectPromiseVoid = expect(browser).toHaveUrl(expect.any(String)) - expectPromiseVoid = expect(browser).toHaveUrl(expect.anything()) - - // @ts-expect-error - expectVoid = expect(browser).toHaveUrl('https://example.com') - // @ts-expect-error - expectVoid = expect(browser).not.toHaveUrl('https://example.com') - // @ts-expect-error - expectVoid = expect(browser).toHaveUrl(expect.stringContaining('WebdriverIO')) - - // @ts-expect-error - await expect(browser).toHaveUrl(6) - }) - - it('should have ts errors when actual is not a Browser element', async () => { - // @ts-expect-error - await expect(element).toHaveUrl('https://example.com') - // @ts-expect-error - await expect(element).not.toHaveUrl('https://example.com') - // @ts-expect-error - await expect(true).toHaveUrl('https://example.com') - // @ts-expect-error - await expect(true).not.toHaveUrl('https://example.com') - }) - }) - - describe('toHaveTitle', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = expect(browser).toHaveTitle('https://example.com') - expectPromiseVoid = expect(browser).not.toHaveTitle('https://example.com') - - // Asymmetric matchers - expectPromiseVoid = expect(browser).toHaveTitle(expect.stringContaining('WebdriverIO')) - expectPromiseVoid = expect(browser).toHaveTitle(expect.any(String)) - expectPromiseVoid = expect(browser).toHaveTitle(expect.anything()) - - // @ts-expect-error - expectVoid = expect(browser).toHaveTitle('https://example.com') - // @ts-expect-error - expectVoid = expect(browser).not.toHaveTitle('https://example.com') - // @ts-expect-error - expectVoid = expect(browser).toHaveTitle(expect.stringContaining('WebdriverIO')) - }) - - it('should have ts errors when actual is not a Browser element', async () => { - // @ts-expect-error - await expect(element).toHaveTitle('https://example.com') - // @ts-expect-error - await expect(element).not.toHaveTitle('https://example.com') - // @ts-expect-error - await expect(true).toHaveTitle('https://example.com') - // @ts-expect-error - await expect(true).not.toHaveTitle('https://example.com') - }) - }) - }) - - describe('element', () => { - - describe('toBeDisabled', () => { - it('should be supported correctly', async () => { - // Element - expectPromiseVoid = expect(element).toBeDisabled() - expectPromiseVoid = expect(element).not.toBeDisabled() - - // Element array - expectPromiseVoid = expect(elementArray).toBeDisabled() - expectPromiseVoid = expect(elementArray).not.toBeDisabled() - - // Chainable element - expectPromiseVoid = expect(chainableElement).toBeDisabled() - expectPromiseVoid = expect(chainableElement).not.toBeDisabled() - - // Chainable element array - expectPromiseVoid = expect(chainableArray).toBeDisabled() - expectPromiseVoid = expect(chainableArray).not.toBeDisabled() - - // @ts-expect-error - expectVoid = expect(element).toBeDisabled() - // @ts-expect-error - expectVoid = expect(element).not.toBeDisabled() - }) - - it('should have ts errors when actual is not an element', async () => { - // @ts-expect-error - await expect(browser).toBeDisabled() - // @ts-expect-error - await expect(browser).not.toBeDisabled() - // @ts-expect-error - await expect(true).toBeDisabled() - // @ts-expect-error - await expect(true).not.toBeDisabled() - }) - }) - - describe('toHaveText', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = expect(element).toHaveText('text') - expectPromiseVoid = expect(element).toHaveText(/text/) - expectPromiseVoid = expect(element).toHaveText(['text1', 'text2']) - expectPromiseVoid = expect(element).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')]) - expectPromiseVoid = expect(element).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expect(element).toHaveText(['text1', /text1/, expect.stringContaining('text3')]) - await expect(element).toHaveText( - 'My-Ex-Am-Ple', - { - replace: [[/-/g, ' '], [/[A-Z]+/g, (match: string) => match.toLowerCase()]] - } - ) - - expectPromiseVoid = expect(element).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expect(element).toHaveText('text') - // @ts-expect-error - await expect(element).toHaveText(6) - - expectPromiseVoid = expect(chainableElement).toHaveText('text') - expectPromiseVoid = expect(chainableElement).toHaveText(/text/) - expectPromiseVoid = expect(chainableElement).toHaveText(['text1', 'text2']) - expectPromiseVoid = expect(chainableElement).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')]) - expectPromiseVoid = expect(chainableElement).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expect(chainableElement).toHaveText(['text1', /text1/, expect.stringContaining('text3')]) - - expectPromiseVoid = expect(chainableElement).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expect(chainableElement).toHaveText('text') - // @ts-expect-error - await expect(chainableElement).toHaveText(6) - - expectPromiseVoid = expect(elementArray).toHaveText('text') - expectPromiseVoid = expect(elementArray).toHaveText(/text/) - expectPromiseVoid = expect(elementArray).toHaveText(['text1', 'text2']) - expectPromiseVoid = expect(elementArray).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')]) - expectPromiseVoid = expect(elementArray).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expect(elementArray).toHaveText(['text1', /text1/, expect.stringContaining('text3')]) - - expectPromiseVoid = expect(elementArray).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expect(elementArray).toHaveText('text') - // @ts-expect-error - await expect(elementArray).toHaveText(6) - - expectPromiseVoid = expect(chainableArray).toHaveText('text') - expectPromiseVoid = expect(chainableArray).toHaveText(/text/) - expectPromiseVoid = expect(chainableArray).toHaveText(['text1', 'text2']) - expectPromiseVoid = expect(chainableArray).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')]) - expectPromiseVoid = expect(chainableArray).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expect(chainableArray).toHaveText(['text1', /text1/, expect.stringContaining('text3')]) - - expectPromiseVoid = expect(chainableArray).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expect(chainableArray).toHaveText('text') - // @ts-expect-error - await expect(chainableArray).toHaveText(6) - - // @ts-expect-error - await expect(browser).toHaveText('text') - }) - - it('should have ts errors when actual is not an element', async () => { - // @ts-expect-error - await expect(browser).toHaveText('text') - // @ts-expect-error - await expect(browser).not.toHaveText('text') - // @ts-expect-error - await expect(true).toHaveText('text') - // @ts-expect-error - await expect(true).toHaveText('text') - }) - - it('should have ts errors when actual is string or Promise', async () => { - // @ts-expect-error - await expect('text').toHaveText('text') - // @ts-expect-error - await expect('text').not.toHaveText('text') - // @ts-expect-error - await expect(Promise.resolve('text')).toHaveText('text') - // @ts-expect-error - await expect(Promise.resolve('text')).toHaveText('text') - }) - }) - - describe('toHaveHeight', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = expect(element).toHaveHeight(100) - expectPromiseVoid = expect(element).toHaveHeight(100, { message: 'Custom error message' }) - expectPromiseVoid = expect(element).not.toHaveHeight(100) - expectPromiseVoid = expect(element).not.toHaveHeight(100, { message: 'Custom error message' }) - - expectPromiseVoid = expect(element).toHaveHeight({ width: 100, height: 200 }) - expectPromiseVoid = expect(element).toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' }) - expectPromiseVoid = expect(element).not.toHaveHeight({ width: 100, height: 200 }) - expectPromiseVoid = expect(element).not.toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' }) - - // @ts-expect-error - expectVoid = expect(element).toHaveHeight(100) - // @ts-expect-error - expectVoid = expect(element).not.toHaveHeight(100) - - // @ts-expect-error - expectVoid = expect(element).toHaveHeight({ width: 100, height: 200 }) - // @ts-expect-error - expectVoid = expect(element).not.toHaveHeight({ width: 100, height: 200 }) - - // @ts-expect-error - await expect(browser).toHaveHeight(100) - }) - - it('should have ts errors when actual is string or Promise', async () => { - // @ts-expect-error - await expect('text').toHaveText('text') - // @ts-expect-error - await expect('text').not.toHaveText('text') - // @ts-expect-error - await expect(Promise.resolve('text')).toHaveText('text') - // @ts-expect-error - await expect(Promise.resolve('text')).toHaveText('text') - }) - }) - - describe('toMatchSnapshot', () => { - - it('should be supported correctly', async () => { - expectVoid = expect(element).toMatchSnapshot() - expectVoid = expect(element).toMatchSnapshot('test label') - expectVoid = expect(element).not.toMatchSnapshot('test label') - - expectPromiseVoid = expect(chainableElement).toMatchSnapshot() - expectPromiseVoid = expect(chainableElement).toMatchSnapshot('test label') - expectPromiseVoid = expect(chainableElement).not.toMatchSnapshot('test label') - - //@ts-expect-error - expectPromiseVoid = expect(element).toMatchSnapshot() - //@ts-expect-error - expectPromiseVoid = expect(element).not.toMatchSnapshot() - //@ts-expect-error - expectVoid = expect(chainableElement).toMatchSnapshot() - //@ts-expect-error - expectVoid = expect(chainableElement).not.toMatchSnapshot() - }) - }) - - describe('toMatchInlineSnapshot', () => { - - it('should be correctly supported', async () => { - expectVoid = expect(element).toMatchInlineSnapshot() - expectVoid = expect(element).toMatchInlineSnapshot('test snapshot') - expectVoid = expect(element).toMatchInlineSnapshot('test snapshot', 'test label') - - expectPromiseVoid = expect(chainableElement).toMatchInlineSnapshot() - expectPromiseVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label') - - //@ts-expect-error - expectPromiseVoid = expect(element).toMatchInlineSnapshot() - //@ts-expect-error - expectVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label') - }) - - it('should be correctly supported with getCSSProperty()', async () => { - expectPromiseVoid = expect(element.getCSSProperty('test')).toMatchInlineSnapshot() - expectPromiseVoid = expect(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = expect(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label') - - expectPromiseVoid = expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot() - expectPromiseVoid = expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label') - - //@ts-expect-error - expectPromiseVoid = expect(element).toMatchInlineSnapshot() - //@ts-expect-error - expectVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label') - }) - }) - - describe('toBeElementsArrayOfSize', async () => { - - it('should work correctly when actual is chainableArray', async () => { - expectPromiseVoid = expect(chainableArray).toBeElementsArrayOfSize(5) - expectPromiseVoid = expect(chainableArray).toBeElementsArrayOfSize({ lte: 10 }) - - // @ts-expect-error - expectVoid = expect(chainableArray).toBeElementsArrayOfSize(5) - // @ts-expect-error - expectVoid = expect(chainableArray).toBeElementsArrayOfSize({ lte: 10 }) - }) - - it('should not work when actual is not chainableArray', async () => { - // @ts-expect-error - await expect(chainableElement).toBeElementsArrayOfSize(5) - // @ts-expect-error - await expect(chainableElement).toBeElementsArrayOfSize({ lte: 10 }) - // @ts-expect-error - await expect(true).toBeElementsArrayOfSize(5) - // @ts-expect-error - await expect(true).toBeElementsArrayOfSize({ lte: 10 }) - }) - }) - }) - - describe('Custom matchers', () => { - describe('using `ExpectWebdriverIO` namespace augmentation', () => { - it('should supported correctly a non-promise custom matcher', async () => { - expectVoid = expect('test').toBeCustom() - expectVoid = expect('test').not.toBeCustom() - - // @ts-expect-error - expectPromiseVoid = expect('test').toBeCustom() - // @ts-expect-error - expectPromiseVoid = expect('test').not.toBeCustom() - - expectVoid = expect(1).toBeWithinRange(0, 2) - }) - - it('should supported correctly a promise custom matcher with only chainableElement as actual', async () => { - expectPromiseVoid = expect(chainableElement).toBeCustomPromise() - expectPromiseVoid = expect(chainableElement).toBeCustomPromise(expect.stringContaining('test')) - expectPromiseVoid = expect(chainableElement).not.toBeCustomPromise(expect.not.stringContaining('test')) - - // @ts-expect-error - expect('test').toBeCustomPromise() - // @ts-expect-error - expectVoid = expect(chainableElement).toBeCustomPromise() - // @ts-expect-error - expectVoid = expect(chainableElement).toBeCustomPromise(expect.stringContaining('test')) - // @ts-expect-error - expectVoid = expect(chainableElement).not.toBeCustomPromise(expect.stringContaining('test')) - // @ts-expect-error - expect(chainableElement).toBeCustomPromise(expect.stringContaining(6)) - }) - - it('should support custom asymmetric matcher', async () => { - const expectString1 : ExpectWebdriverIO.PartialMatcher = expect.toBeCustom() - const expectString2 : ExpectWebdriverIO.PartialMatcher = expect.not.toBeCustom() - - expectPromiseVoid = expect(chainableElement).toBeCustomPromise(expect.toBeCustom()) - - // @ts-expect-error - expectPromiseVoid = expect.toBeCustom() - // @ts-expect-error - expectPromiseVoid = expect.not.toBeCustom() - - //@ts-expect-error - expectVoid = expect(chainableElement).toBeCustomPromise(expect.toBeCustom()) - }) - }) - - describe('using `expect` module declaration', () => { - - it('should support a simple matcher', async () => { - expectVoid = expect(5).toBeWithinRange(1, 10) - - // Or as an asymmetric matcher: - expectVoid = expect({ value: 5 }).toEqual({ - value: expect.toBeWithinRange(1, 10) - }) - - // @ts-expect-error - expectVoid = expect(5).toBeWithinRange(1, '10') - // @ts-expect-error - expectPromiseVoid = expect(5).toBeWithinRange('1') - }) - - it('should support a simple custom matcher with a chainable element matcher with promise', async () => { - expectPromiseVoid = expect(chainableElement).toHaveSimpleCustomProperty('text') - expectPromiseVoid = expect(chainableElement).toHaveSimpleCustomProperty(expect.stringContaining('text')) - expectPromiseVoid = expect(chainableElement).not.toHaveSimpleCustomProperty(expect.not.stringContaining('text')) - - // Or as a custom asymmetric matcher: - expectPromiseVoid = expect(chainableElement).toHaveSimpleCustomProperty( - expect.toHaveSimpleCustomProperty('string') - ) - const expectString1:string = expect.toHaveSimpleCustomProperty('string') - const expectString2:string = expect.not.toHaveSimpleCustomProperty('string') - - // @ts-expect-error - expectVoid = expect.toHaveSimpleCustomProperty(chainableElement) - // @ts-expect-error - expectVoid = expect.not.toHaveSimpleCustomProperty(chainableElement) - - // @ts-expect-error - expectVoid = expect.toHaveSimpleCustomProperty(chainableElement) - }) - - it('should support a chainable element matcher with promise', async () => { - expectPromiseVoid = expect(chainableElement).toHaveCustomProperty('text') - expectPromiseVoid = expect(chainableElement).toHaveCustomProperty(expect.stringContaining('text')) - expectPromiseVoid = expect(chainableElement).not.toHaveCustomProperty(expect.not.stringContaining('text')) - - // Or as a custom asymmetric matcher: - expectPromiseVoid = expect(chainableElement).toHaveCustomProperty( - await expect.toHaveCustomProperty(chainableElement) - ) - const expectPromiseWdioElement1: Promise> = expect.toHaveCustomProperty(chainableElement) - const expectPromiseWdioElement2: Promise> = expect.not.toHaveCustomProperty(chainableElement) - - // @ts-expect-error - expectVoid = expect.toHaveCustomProperty(chainableElement) - // @ts-expect-error - expectVoid = expect.not.toHaveCustomProperty(chainableElement) - - // @ts-expect-error - expectVoid = expect.toHaveCustomProperty(chainableElement) - // @ts-expect-error - expect.toHaveCustomProperty('test') - - await expect(chainableElement).toHaveCustomProperty( - await expect.toHaveCustomProperty(chainableElement) - ) - }) - }) - }) - - describe('toBe', () => { - - it('should expect void type when actual is a boolean', async () => { - expectVoid = expect(true).toBe(true) - expectVoid = expect(true).not.toBe(true) - - //@ts-expect-error - expectPromiseVoid = expect(true).toBe(true) - //@ts-expect-error - expectPromiseVoid = expect(true).not.toBe(true) - }) - - it('should not expect Promise when actual is a chainable since toBe does not need to be awaited', async () => { - expectVoid = expect(chainableElement).toBe(true) - expectVoid = expect(chainableElement).not.toBe(true) - - //@ts-expect-error - expectPromiseVoid = expect(chainableElement).toBe(true) - //@ts-expect-error - expectPromiseVoid = expect(chainableElement).not.toBe(true) - }) - - it('should still expect void type when actual is a Promise since we do not overload them', async () => { - const promiseBoolean = Promise.resolve(true) - - expectVoid = expect(promiseBoolean).toBe(true) - expectVoid = expect(promiseBoolean).not.toBe(true) - - //@ts-expect-error - expectPromiseVoid = expect(promiseBoolean).toBe(true) - //@ts-expect-error - expectPromiseVoid = expect(promiseBoolean).toBe(true) - }) - - it('should work with string', async () => { - expectVoid = expect('text').toBe(true) - expectVoid = expect('text').not.toBe(true) - expectVoid = expect('text').toBe(expect.stringContaining('text')) - expectVoid = expect('text').not.toBe(expect.stringContaining('text')) - - //@ts-expect-error - expectPromiseVoid = expect('text').toBe(true) - //@ts-expect-error - expectPromiseVoid = expect('text').not.toBe(true) - //@ts-expect-error - expectPromiseVoid = expect('text').toBe(expect.stringContaining('text')) - //@ts-expect-error - expectPromiseVoid = expect('text').not.toBe(expect.stringContaining('text')) - }) - }) - - describe('Promise type assertions', () => { - const booleanPromise: Promise = Promise.resolve(true) - - it('should expect a Promise of type', async () => { - const expectPromiseBoolean1: jest.JestMatchers> = expect(booleanPromise) - const expectPromiseBoolean2: jest.Matchers> = expect(booleanPromise).not - - // @ts-expect-error - const expectPromiseBoolean3: jest.JestMatchers = expect(booleanPromise) - //// @ts-expect-error - // const expectPromiseBoolean4: jest.Matchers = expect(booleanPromise).not - }) - - it('should work with resolves & rejects correctly', async () => { - expectPromiseVoid = expect(booleanPromise).resolves.toBe(true) - expectPromiseVoid = expect(booleanPromise).rejects.toBe(true) - - //@ts-expect-error - expectVoid = expect(booleanPromise).resolves.toBe(true) - //@ts-expect-error - expectVoid = expect(booleanPromise).rejects.toBe(true) - - }) - - it('should not support chainable and expect PromiseVoid with toBe', async () => { - //@ts-expect-error - expectPromiseVoid = expect(chainableElement).toBe(true) - //@ts-expect-error - expectPromiseVoid = expect(chainableElement).not.toBe(true) - }) - }) - - describe('Network Matchers', () => { - const promiseNetworkMock = Promise.resolve(networkMock) - - it('should not have ts errors when typing to Promise', async () => { - expectPromiseVoid = expect(promiseNetworkMock).toBeRequested() - expectPromiseVoid = expect(promiseNetworkMock).toBeRequestedTimes(2) - expectPromiseVoid = expect(promiseNetworkMock).toBeRequestedTimes({ gte: 5, lte: 10 }) - - expectPromiseVoid = expect(promiseNetworkMock).not.toBeRequested() - expectPromiseVoid = expect(promiseNetworkMock).not.toBeRequestedTimes(2) - expectPromiseVoid = expect(promiseNetworkMock).not.toBeRequestedTimes({ gte: 5, lte: 10 }) - - expectPromiseVoid = expect(promiseNetworkMock).toBeRequestedWith({ - url: 'http://localhost:8080/api', - method: 'POST', - statusCode: 200, - requestHeaders: { Authorization: 'foo' }, - responseHeaders: { Authorization: 'bar' }, - postData: { title: 'foo', description: 'bar' }, - response: { success: true }, - }) - - expectPromiseVoid = expect(promiseNetworkMock).toBeRequestedWith({ - url: expect.stringContaining('test'), - method: 'POST', - statusCode: 200, - requestHeaders: expect.objectContaining({ Authorization: 'foo' }), - responseHeaders: expect.objectContaining({ Authorization: 'bar' }), - postData: expect.objectContaining({ title: 'foo', description: 'bar' }), - response: expect.objectContaining({ success: true }), - }) - - expectPromiseVoid = expect(promiseNetworkMock).toBeRequestedWith({ - url: expect.stringMatching(/.*\/api\/.*/i), - method: ['POST', 'PUT'], - statusCode: [401, 403], - requestHeaders: headers => headers.Authorization.startsWith('Bearer '), - postData: expect.objectContaining({ released: true, title: expect.stringContaining('foobar') }), - response: (r: { data: { items: unknown[] } }) => Array.isArray(r) && r.data.items.length === 20 - }) - }) - - it('should have ts errors when typing to void', async () => { - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).toBeRequested() - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).toBeRequestedTimes(2) // await expect(mock).toBeRequestedTimes({ eq: 2 }) - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).toBeRequestedTimes({ gte: 5, lte: 10 }) // request called at least 5 times but less than 11 - - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).not.toBeRequested() - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).not.toBeRequestedTimes(2) // await expect(mock).toBeRequestedTimes({ eq: 2 }) - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).not.toBeRequestedTimes({ gte: 5, lte: 10 }) // request called at least 5 times but less than 11 - - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).toBeRequestedWith({ - url: 'http://localhost:8080/api', - method: 'POST', - statusCode: 200, - requestHeaders: { Authorization: 'foo' }, - responseHeaders: { Authorization: 'bar' }, - postData: { title: 'foo', description: 'bar' }, - response: { success: true }, - }) - - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).toBeRequestedWith(expect.objectContaining({ - response: { success: true }, - })) - }) - }) - - describe('Expect', () => { - it('should have ts errors when using a non existing expect.function', async () => { - // @ts-expect-error - expect.unimplementedFunction() - }) - - it('should support stringContaining, anything and more', async () => { - expect.stringContaining('WebdriverIO') - expect.stringMatching(/WebdriverIO/) - expect.arrayContaining(['WebdriverIO', 'Test']) - expect.objectContaining({ name: 'WebdriverIO' }) - // Was not there but works! - expect.closeTo(5, 10) - expect.arrayContaining(['WebdriverIO', 'Test']) - // New from jest 30!! - expect.arrayOf(expect.stringContaining('WebdriverIO')) - - expect.anything() - expect.any(Function) - expect.any(Number) - expect.any(Boolean) - expect.any(String) - expect.any(Symbol) - expect.any(Date) - expect.any(Error) - - expect.not.stringContaining('WebdriverIO') - expect.not.stringMatching(/WebdriverIO/) - expect.not.arrayContaining(['WebdriverIO', 'Test']) - expect.not.objectContaining({ name: 'WebdriverIO' }) - expect.not.closeTo(5, 10) - expect.not.arrayContaining(['WebdriverIO', 'Test']) - expect.not.arrayOf(expect.stringContaining('WebdriverIO')) - expect.not.anything() - expect.not.any(Function) - expect.not.any(Number) - expect.not.any(Boolean) - expect.not.any(String) - expect.not.any(Symbol) - expect.not.any(Date) - expect.not.any(Error) - }) - - describe('Soft Assertions', async () => { - const actualString: string = 'test' - const actualPromiseString: Promise = Promise.resolve('test') - - describe('expect.soft', () => { - it('should not need to be awaited/be a promise if actual is non-promise type', async () => { - const expectWdioMatcher1: WdioCustomMatchers = expect.soft(actualString) - expectVoid = expect.soft(actualString).toBe('Test Page') - expectVoid = expect.soft(actualString).not.toBe('Test Page') - expectVoid = expect.soft(actualString).not.toBe(expect.stringContaining('Test Page')) - - // @ts-expect-error - expectPromiseVoid = expect.soft(actualString).toBe('Test Page') - // @ts-expect-error - expectPromiseVoid = expect.soft(actualString).not.toBe('Test Page') - // @ts-expect-error - expectPromiseVoid = expect.soft(actualString).not.toBe(expect.stringContaining('Test Page')) - }) - - it('should need to be awaited/be a promise if actual is promise type', async () => { - const expectWdioMatcher1: ExpectWebdriverIO.MatchersAndInverse, Promise> = expect.soft(actualPromiseString) - expectPromiseVoid = expect.soft(actualPromiseString).toBe('Test Page') - expectPromiseVoid = expect.soft(actualPromiseString).not.toBe('Test Page') - expectPromiseVoid = expect.soft(actualPromiseString).not.toBe(expect.stringContaining('Test Page')) - - // @ts-expect-error - expectVoid = expect.soft(actualPromiseString).toBe('Test Page') - // @ts-expect-error - expectVoid = expect.soft(actualPromiseString).not.toBe('Test Page') - // @ts-expect-error - expectVoid = expect.soft(actualPromiseString).not.toBe(expect.stringContaining('Test Page')) - }) - - it('should support chainable element', async () => { - const expectElement: ExpectWebdriverIO.MatchersAndInverse = expect.soft(element) - const expectElementChainable: ExpectWebdriverIO.MatchersAndInverse = expect.soft(chainableElement) - - // @ts-expect-error - const expectElement2: ExpectWebdriverIO.MatchersAndInverse, WebdriverIO.Element> = expect.soft(element) - // @ts-expect-error - const expectElementChainable2: ExpectWebdriverIO.MatchersAndInverse, typeof chainableElement> = expect.soft(chainableElement) - }) - - it('should support chainable element with wdio Matchers', async () => { - expectPromiseVoid = expect.soft(element).toBeDisplayed() - expectPromiseVoid = expect.soft(chainableElement).toBeDisplayed() - expectPromiseVoid = expect.soft(chainableArray).toBeDisplayed() - await expect.soft(element).toBeDisplayed() - await expect.soft(chainableElement).toBeDisplayed() - await expect.soft(chainableArray).toBeDisplayed() - - expectPromiseVoid = expect.soft(element).not.toBeDisplayed() - expectPromiseVoid = expect.soft(chainableElement).not.toBeDisplayed() - expectPromiseVoid = expect.soft(chainableArray).not.toBeDisplayed() - await expect.soft(element).not.toBeDisplayed() - await expect.soft(chainableElement).not.toBeDisplayed() - await expect.soft(chainableArray).not.toBeDisplayed() - - // @ts-expect-error - expectVoid = expect.soft(element).toBeDisplayed() - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeDisplayed() - // @ts-expect-error - expectVoid = expect.soft(chainableArray).toBeDisplayed() - - // @ts-expect-error - expectVoid = expect.soft(element).not.toBeDisplayed() - // @ts-expect-error - expectVoid = expect.soft(chainableElement).not.toBeDisplayed() - // @ts-expect-error - expectVoid = expect.soft(chainableArray).not.toBeDisplayed() - }) - - it('should work with custom matcher and custom asymmetric matchers from `expect` module', async () => { - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty('text') - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty(expect.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).not.toHaveCustomProperty(expect.not.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty( - expect.toHaveCustomProperty(chainableElement) - ) - - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty('text') - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty(expect.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).not.toHaveCustomProperty(expect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty( - expect.toHaveCustomProperty(chainableElement) - ) - - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty('text') - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty(expect.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).not.toHaveCustomProperty(expect.not.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty( - expect.toHaveCustomProperty(chainableElement) - ) - - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty('text') - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty(expect.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).not.toHaveCustomProperty(expect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty( - expect.toHaveCustomProperty(chainableElement) - ) - }) - - it('should work with custom matcher and custom asymmetric matchers from `ExpectWebDriverIO` namespace', async () => { - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise('text') - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise(expect.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).not.toBeCustomPromise(expect.not.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise( - expect.toBeCustomPromise(chainableElement) - ) - - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise('text') - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise(expect.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).not.toBeCustomPromise(expect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise( - expect.toBeCustomPromise(chainableElement) - ) - - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise('text') - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise(expect.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).not.toBeCustomPromise(expect.not.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise( - expect.toBeCustomPromise(chainableElement) - ) - - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise('text') - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise(expect.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).not.toBeCustomPromise(expect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise( - expect.toBeCustomPromise(chainableElement) - ) - }) - }) - - describe('expect.getSoftFailures', () => { - it('should be of type `SoftFailure`', async () => { - const expectSoftFailure1: ExpectWebdriverIO.SoftFailure[] = expect.getSoftFailures() - - // @ts-expect-error - expectVoid = expect.getSoftFailures() - }) - }) - - describe('expect.assertSoftFailures', () => { - it('should be of type void', async () => { - expectVoid = expect.assertSoftFailures() - - // @ts-expect-error - expectPromiseVoid = expect.assertSoftFailures() - }) - }) - - describe('expect.clearSoftFailures', () => { - it('should be of type void', async () => { - expectVoid = expect.clearSoftFailures() - - // @ts-expect-error - expectPromiseVoid = expect.clearSoftFailures() - }) - }) - }) - }) - - describe('Asymmetric matchers', () => { - const string: string = 'WebdriverIO is a test framework' - const array: string[] = ['WebdriverIO', 'Test'] - const object: { name: string } = { name: 'WebdriverIO' } - const number: number = 1 - - it('should have no ts error using asymmetric matchers', async () => { - expect(string).toEqual(expect.stringContaining('WebdriverIO')) - expect(array).toEqual(expect.arrayContaining(['WebdriverIO', 'Test'])) - expect(object).toEqual(expect.objectContaining({ name: 'WebdriverIO' })) - // This one is tested and is working correctly, surprisingly! - expect(number).toEqual(expect.closeTo(1.0001, 0.0001)) - // New from jest 30, should work! - expect(['apple', 'banana', 'cherry']).toEqual(expect.arrayOf(expect.any(String))) - }) - }) - - describe('@types/jest only - original Matchers', () => { - describe('toMatchSnapshot & toMatchInlineSnapshot', () => { - const snapshotName: string = 'test-snapshot' - - it('should work with string', async () => { - const jsonString: string = '{}' - const propertyMatchers = 'test' - expectVoid = expect(jsonString).toMatchSnapshot(propertyMatchers) - expectVoid = expect(jsonString).toMatchSnapshot(propertyMatchers, snapshotName) - expectVoid = expect(jsonString).toMatchInlineSnapshot(propertyMatchers) - expectVoid = expect(jsonString).toMatchInlineSnapshot(propertyMatchers, snapshotName) - - expectVoid = expect(jsonString).not.toMatchSnapshot(propertyMatchers) - expectVoid = expect(jsonString).not.toMatchSnapshot(propertyMatchers, snapshotName) - expectVoid = expect(jsonString).not.toMatchInlineSnapshot(propertyMatchers) - expectVoid = expect(jsonString).not.toMatchInlineSnapshot(propertyMatchers, snapshotName) - - // @ts-expect-error - expectPromiseVoid = expect(jsonString).toMatchSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = expect(jsonString).toMatchSnapshot(propertyMatchers, snapshotName) - // @ts-expect-error - expectPromiseVoid = expect(jsonString).toMatchInlineSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = expect(jsonString).toMatchInlineSnapshot(propertyMatchers, snapshotName) - // @ts-expect-error - expectPromiseVoid = expect(jsonString).not.toMatchSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = expect(jsonString).not.toMatchSnapshot(propertyMatchers, snapshotName) - // @ts-expect-error - expectPromiseVoid = expect(jsonString).not.toMatchInlineSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = expect(jsonString).not.toMatchInlineSnapshot(propertyMatchers, snapshotName) - }) - - it('should with object', async () => { - const treeObject = { 1: 'test', 2: 'test2' } - const propertyMatchers = { 1: 'test' } - expectVoid = expect(treeObject).toMatchSnapshot(propertyMatchers) - expectVoid = expect(treeObject).toMatchSnapshot(propertyMatchers, snapshotName) - expectVoid = expect(treeObject).toMatchInlineSnapshot(propertyMatchers) - expectVoid = expect(treeObject).toMatchInlineSnapshot(propertyMatchers, snapshotName) - - expectVoid = expect(treeObject).not.toMatchSnapshot(propertyMatchers) - expectVoid = expect(treeObject).not.toMatchSnapshot(propertyMatchers, snapshotName) - expectVoid = expect(treeObject).not.toMatchInlineSnapshot(propertyMatchers) - expectVoid = expect(treeObject).not.toMatchInlineSnapshot(propertyMatchers, snapshotName) - - // @ts-expect-error - expectPromiseVoid = expect(treeObject).toMatchSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = expect(treeObject).toMatchSnapshot(propertyMatchers, snapshotName) - // @ts-expect-error - expectPromiseVoid = expect(treeObject).toMatchInlineSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = expect(treeObject).toMatchInlineSnapshot(propertyMatchers, snapshotName) - // @ts-expect-error - expectPromiseVoid = expect(treeObject).not.toMatchSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = expect(treeObject).not.toMatchSnapshot(propertyMatchers, snapshotName) - // @ts-expect-error - expectPromiseVoid = expect(treeObject).not.toMatchInlineSnapshot(propertyMatchers) - // @ts-expect-error - expectPromiseVoid = expect(treeObject).not.toMatchInlineSnapshot(propertyMatchers, snapshotName) - }) - }) - }) -}) diff --git a/test-types/mocha/customMatchers/customMatchers-module-expect.d.ts b/test-types/mocha/customMatchers/customMatchers-module-expect.d.ts index 750d6e1ff..5624be0f4 100644 --- a/test-types/mocha/customMatchers/customMatchers-module-expect.d.ts +++ b/test-types/mocha/customMatchers/customMatchers-module-expect.d.ts @@ -6,15 +6,15 @@ import 'expect' */ declare module 'expect' { interface AsymmetricMatchers { - toBeWithinRange(floor: number, ceiling: number): void - toHaveSimpleCustomProperty(string: string): string - toHaveCustomProperty(element: ChainablePromiseElement | WebdriverIO.Element): Promise> + toBeWithinRangeExpect(floor: number, ceiling: number): void + toHaveSimpleCustomPropertyExpect(string: string): string + toHaveCustomPropertyExpect(element: ChainablePromiseElement | WebdriverIO.Element): Promise> } interface Matchers { - toBeWithinRange(floor: number, ceiling: number): R - toHaveSimpleCustomProperty(string: string | ExpectWebdriverIO.PartialMatcher): Promise - toHaveCustomProperty: + toBeWithinRangeExpect(floor: number, ceiling: number): R + toHaveSimpleCustomPropertyExpect(string: string | ExpectWebdriverIO.PartialMatcher): Promise + toHaveCustomPropertyExpect: // Useful to typecheck the custom matcher so it is only used on elements T extends ChainablePromiseElement | WebdriverIO.Element ? (test: string | ExpectWebdriverIO.PartialMatcher | @@ -23,4 +23,4 @@ declare module 'expect' { // Using `never` blocks the call on non-element types => Promise : never; } -} \ No newline at end of file +} diff --git a/test-types/mocha/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts b/test-types/mocha/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts index 7a833bd87..eb5fb6201 100644 --- a/test-types/mocha/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts +++ b/test-types/mocha/customMatchers/customMatchers-namespace-expectwebdriverio.d.ts @@ -4,11 +4,11 @@ */ declare namespace ExpectWebdriverIO { interface AsymmetricMatchers { - toBeCustom(): ExpectWebdriverIO.PartialMatcher; - toBeCustomPromise(chainableElement: ChainablePromiseElement): Promise>; + toBeCustomWdio(): ExpectWebdriverIO.PartialMatcher; + toBeCustomPromiseWdio(chainableElement: ChainablePromiseElement): Promise>; } interface Matchers { - toBeCustom(): R; - toBeCustomPromise: T extends ChainablePromiseElement ? (expected?: string | ExpectWebdriverIO.PartialMatcher | Promise>) => Promise : never; + toBeCustomWdio(): R; + toBeCustomPromiseWdio: T extends ChainablePromiseElement ? (expected?: string | ExpectWebdriverIO.PartialMatcher | Promise>) => Promise : never; } } \ No newline at end of file diff --git a/test-types/mocha/mocha.test-d.ts b/test-types/mocha/mocha.test-d.ts new file mode 100644 index 000000000..0d10ef892 --- /dev/null +++ b/test-types/mocha/mocha.test-d.ts @@ -0,0 +1,657 @@ +import type { ChainablePromiseElement, ChainablePromiseArray } from 'webdriverio' +import { expectTypeOf } from 'vitest' + +describe('WebDriverIO Expect Type Assertions under Mocha', () => { + const chainableElement = {} as unknown as ChainablePromiseElement + const chainableArray = {} as ChainablePromiseArray + + const element: WebdriverIO.Element = {} as unknown as WebdriverIO.Element + const elementArray: WebdriverIO.ElementArray = [] as unknown as WebdriverIO.ElementArray + const elements: WebdriverIO.Element[] = [] as unknown as WebdriverIO.Element[] + + const networkMock: WebdriverIO.Mock = {} as unknown as WebdriverIO.Mock + const browser: WebdriverIO.Browser = {} as unknown as WebdriverIO.Browser + + describe('Browser', () => { + describe('toHaveUrl', () => { + it('should return Promise', async () => { + expectTypeOf(expect(browser).toHaveUrl('https://example.com')).toEqualTypeOf>() + expectTypeOf(expect(browser).not.toHaveUrl('https://example.com')).toEqualTypeOf>() + + // Asymmetric matchers + expectTypeOf(expect(browser).toHaveUrl(expect.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveUrl(expect.not.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveUrl(expect.any(String))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveUrl(expect.anything())).toEqualTypeOf>() + + expectTypeOf(expect(browser).toHaveUrl).parameter(0).extract().toBeNever() + }) + + it('should have ts errors when actual is not a Browser element', async () => { + expectTypeOf(expect(element).toHaveUrl).toBeNever() + expectTypeOf(expect(true).toHaveUrl).toBeNever() + }) + }) + + describe('toHaveTitle', () => { + it('should return Promise', async () => { + expectTypeOf(expect(browser).toHaveTitle('https://example.com')).toEqualTypeOf>() + expectTypeOf(expect(browser).not.toHaveTitle('https://example.com')).toEqualTypeOf>() + + // Asymmetric matchers + expectTypeOf(expect(browser).toHaveTitle(expect.stringContaining('WebdriverIO'))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveTitle(expect.any(String))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveTitle(expect.anything())).toEqualTypeOf>() + }) + + it('should have ts errors when actual is not a Browser element', async () => { + expectTypeOf(expect(element).toHaveTitle).toBeNever() + expectTypeOf(expect(true).toHaveTitle).toBeNever() + }) + }) + + describe('toHaveClipboardText', () => { + it('should return Promise', async () => { + expectTypeOf(expect(browser).toHaveClipboardText('text')).toEqualTypeOf>() + expectTypeOf(expect(browser).not.toHaveClipboardText('text')).toEqualTypeOf>() + + // Asymmetric matchers + expectTypeOf(expect(browser).toHaveClipboardText(expect.stringContaining('text'))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveClipboardText(expect.any(String))).toEqualTypeOf>() + expectTypeOf(expect(browser).toHaveClipboardText(expect.anything())).toEqualTypeOf>() + }) + + it('should have ts errors when actual is not a Browser element', async () => { + expectTypeOf(expect(element).toHaveClipboardText).toBeNever() + expectTypeOf(expect(true).toHaveClipboardText).toBeNever() + }) + }) + }) + + describe('element', () => { + + describe('toBeDisabled', () => { + it('should return Promise', async () => { + // Element + expectTypeOf(expect(element).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expect(element).not.toBeDisabled()).toEqualTypeOf>() + + // Element array + expectTypeOf(expect(elementArray).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expect(elementArray).not.toBeDisabled()).toEqualTypeOf>() + + // Chainable element + expectTypeOf(expect(chainableElement).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toBeDisabled()).toEqualTypeOf>() + + // Chainable element array + expectTypeOf(expect(chainableArray).toBeDisabled()).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).not.toBeDisabled()).toEqualTypeOf>() + }) + + it('should have ts errors when actual is not an element', async () => { + expectTypeOf(expect(browser).toBeDisabled).toBeNever() + expectTypeOf(expect(true).toBeDisabled).toBeNever() + }) + }) + + describe('toHaveText', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText(expect.stringContaining('text'))).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveText(['text1', /text1/, expect.stringContaining('text3')])).toEqualTypeOf>() + await expect(element).toHaveText( + 'My-Ex-Am-Ple', + { + replace: [[/-/g, ' '], [/[A-Z]+/g, (match: string) => match.toLowerCase()]] + } + ) + + expectTypeOf(expect(element).not.toHaveText('text')).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expect(chainableElement).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveText(['text1', /text1/, expect.stringContaining('text3')])).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement).not.toHaveText('text')).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expect(elementArray).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expect(elementArray).toHaveText(['text1', /text1/, expect.stringContaining('text3')])).toEqualTypeOf>() + + expectTypeOf(expect(elementArray).not.toHaveText('text')).toEqualTypeOf>() + + expectTypeOf(expect(elementArray).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expect(chainableArray).toHaveText('text')).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText(/text/)).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText(['text1', 'text2'])).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')])).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText([/text1/, /text2/])).toEqualTypeOf>() + expectTypeOf(expect(chainableArray).toHaveText(['text1', /text1/, expect.stringContaining('text3')])).toEqualTypeOf>() + + expectTypeOf(expect(chainableArray).not.toHaveText('text')).toEqualTypeOf>() + + expectTypeOf(expect(chainableArray).toHaveText).parameter(0).extract().toBeNever() + + expectTypeOf(expect(browser).toHaveText).toBeNever() + }) + + it('should have ts errors when actual is not an element', async () => { + expectTypeOf(expect(browser).toHaveText).toBeNever() + expectTypeOf(expect(true).toHaveText).toBeNever() + }) + + it('should have ts errors when actual is string or Promise', async () => { + expectTypeOf(expect('text').toHaveText).toBeNever() + expectTypeOf(expect(Promise.resolve('text')).toHaveText).toBeNever() + expectTypeOf(expect(Promise.resolve('text')).toHaveText).toBeNever() + }) + }) + + describe('toHaveHeight', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveHeight(100)).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveHeight(100, { message: 'Custom error message' })).toEqualTypeOf>() + expectTypeOf(expect(element).not.toHaveHeight(100)).toEqualTypeOf>() + expectTypeOf(expect(element).not.toHaveHeight(100, { message: 'Custom error message' })).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveHeight({ width: 100, height: 200 })).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' })).toEqualTypeOf>() + expectTypeOf(expect(element).not.toHaveHeight({ width: 100, height: 200 })).toEqualTypeOf>() + expectTypeOf(expect(element).not.toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' })).toEqualTypeOf>() + + expectTypeOf(expect(browser).toHaveHeight).toBeNever() + }) + + it('should have ts errors when actual is string or Promise', async () => { + expectTypeOf(expect('text').toHaveHeight).toBeNever() + expectTypeOf(expect(Promise.resolve('text')).toHaveHeight).toBeNever() + expectTypeOf(expect(Promise.resolve('text')).toHaveHeight).toBeNever() + }) + }) + + describe('toMatchSnapshot', () => { + + it('should return Promise', async () => { + expectTypeOf(expect(element).toMatchSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(element).toMatchSnapshot('test label')).toEqualTypeOf>() + expectTypeOf(expect(element).not.toMatchSnapshot('test label')).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement).toMatchSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toMatchSnapshot('test label')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toMatchSnapshot('test label')).toEqualTypeOf>() + }) + }) + + describe('toMatchInlineSnapshot', () => { + + it('should return Promise', async () => { + expectTypeOf(expect(element).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(element).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expect(element).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + }) + + it('should return Promise with getCSSProperty()', async () => { + expectTypeOf(expect(element.getCSSProperty('test')).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expect(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot()).toEqualTypeOf>() + expectTypeOf(expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label')).toEqualTypeOf>() + + expectTypeOf(expect(element).toMatchInlineSnapshot()).toEqualTypeOf>() + }) + }) + + describe('toBeElementsArrayOfSize', async () => { + + it('should return Promise when actual is chainableArray', async () => { + expectTypeOf(expect(chainableArray).toBeElementsArrayOfSize(5)).toMatchTypeOf>() + expectTypeOf(expect(chainableArray).toBeElementsArrayOfSize({ lte: 10 })).toMatchTypeOf>() + }) + + it('should return Promise when actual is element array', async () => { + expectTypeOf(expect(elementArray).toBeElementsArrayOfSize(5)).toMatchTypeOf>() + expectTypeOf(expect(elementArray).toBeElementsArrayOfSize({ lte: 10 })).toMatchTypeOf>() + }) + + it('should return Promise when actual is element[]', async () => { + expectTypeOf(expect(elements).toBeElementsArrayOfSize(5)).toMatchTypeOf>() + expectTypeOf(expect(elements).toBeElementsArrayOfSize({ lte: 10 })).toMatchTypeOf>() + }) + + it('should not work when actual is not chainableArray', async () => { + expectTypeOf(expect(chainableElement).toBeElementsArrayOfSize).toBeNever() + expectTypeOf(expect(true).toBeElementsArrayOfSize).toBeNever() + }) + }) + }) + + describe('Custom matchers', () => { + describe('using `ExpectWebdriverIO` namespace augmentation', () => { + it('should supported correctly a non-promise custom matcher', async () => { + expectTypeOf(expect('test').toBeCustomWdio()).toEqualTypeOf() + expectTypeOf(expect('test').not.toBeCustomWdio()).toEqualTypeOf() + + expectTypeOf(expect(1).toBeWithinRangeExpect(0, 2)).toEqualTypeOf() + }) + + it('should supported correctly a promise custom matcher with only chainableElement as actual', async () => { + expectTypeOf(expect(chainableElement).toBeCustomPromiseWdio()).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toBeCustomPromiseWdio(expect.stringContaining('test'))).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toBeCustomPromiseWdio(expect.not.stringContaining('test'))).toEqualTypeOf>() + + expectTypeOf(expect('test').toBeCustomPromiseWdio).toBeNever() + expectTypeOf(expect(chainableElement).toBeCustomPromiseWdio).parameter(0).extract().toBeNever() + }) + + it('should support custom asymmetric matcher', async () => { + expectTypeOf(expect.toBeCustomWdio()).toEqualTypeOf>() + expectTypeOf(expect.not.toBeCustomWdio()).toEqualTypeOf>() + + expectTypeOf(expect(chainableElement).toBeCustomPromiseWdio(expect.toBeCustomWdio())).toEqualTypeOf>() + + expectTypeOf(expect.toBeCustomWdio()).not.toEqualTypeOf>() + expectTypeOf(expect.not.toBeCustomWdio()).not.toEqualTypeOf>() + + expectTypeOf(expect(chainableElement).toBeCustomPromiseWdio(expect.toBeCustomWdio())).not.toEqualTypeOf() + }) + }) + + describe('using `expect` module declaration', () => { + + it('should support a simple matcher', async () => { + expectTypeOf(expect(5).toBeWithinRangeExpect(1, 10)).toEqualTypeOf() + + // Or as an asymmetric matcher: + expectTypeOf(expect({ value: 5 }).toEqual({ + value: expect.toBeWithinRangeExpect(1, 10) + })).toEqualTypeOf() + }) + + it('should support a simple custom matcher with a chainable element matcher with promise', async () => { + expectTypeOf(expect(chainableElement).toHaveSimpleCustomPropertyExpect('text')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveSimpleCustomPropertyExpect(expect.stringContaining('text'))).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toHaveSimpleCustomPropertyExpect(expect.not.stringContaining('text'))).toEqualTypeOf>() + + // Or as a custom asymmetric matcher: + expectTypeOf(expect(chainableElement).toHaveSimpleCustomPropertyExpect( + expect.toHaveSimpleCustomPropertyExpect('string') + )).toEqualTypeOf>() + expectTypeOf(expect.toHaveSimpleCustomPropertyExpect('string')).toEqualTypeOf() + expectTypeOf(expect.not.toHaveSimpleCustomPropertyExpect('string')).toEqualTypeOf() + }) + + it('should support a chainable element matcher with promise', async () => { + expectTypeOf(expect(chainableElement).toHaveCustomPropertyExpect('text')).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).toHaveCustomPropertyExpect(expect.stringContaining('text'))).toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toHaveCustomPropertyExpect(expect.not.stringContaining('text'))).toEqualTypeOf>() + + // Or as a custom asymmetric matcher: + expectTypeOf(expect(chainableElement).toHaveCustomPropertyExpect( + await expect.toHaveCustomPropertyExpect(chainableElement) + )).toEqualTypeOf>() + expectTypeOf(expect.toHaveCustomPropertyExpect(chainableElement)).toEqualTypeOf>>() + expectTypeOf(expect.not.toHaveCustomPropertyExpect(chainableElement)).toEqualTypeOf>>() + + expectTypeOf(expect.toHaveCustomPropertyExpect(chainableElement)).not.toEqualTypeOf() + expectTypeOf(expect.not.toHaveCustomPropertyExpect(chainableElement)).not.toEqualTypeOf() + + expectTypeOf(expect.toHaveCustomPropertyExpect(chainableElement)).not.toEqualTypeOf() + + await expect(chainableElement).toHaveCustomPropertyExpect( + await expect.toHaveCustomPropertyExpect(chainableElement) + ) + }) + }) + }) + + describe('toBe', () => { + + it('should return void when actual is a boolean', async () => { + expectTypeOf(expect(true).toBe(true)).toEqualTypeOf() + expectTypeOf(expect(true).not.toBe(true)).toEqualTypeOf() + + expectTypeOf(expect(true).toBe(true)).not.toEqualTypeOf>() + expectTypeOf(expect(true).not.toBe(true)).not.toEqualTypeOf>() + }) + + it('should return void when actual is a chainable', async () => { + expectTypeOf(expect(chainableElement).toBe(true)).toEqualTypeOf() + expectTypeOf(expect(chainableElement).not.toBe(true)).toEqualTypeOf() + + expectTypeOf(expect(chainableElement).toBe(true)).not.toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toBe(true)).not.toEqualTypeOf>() + }) + + it('should return void when actual is a Promise', async () => { + const promiseBoolean = Promise.resolve(true) + + expectTypeOf(expect(promiseBoolean).toBeDefined()).toEqualTypeOf() + expectTypeOf(expect(promiseBoolean).not.toBeDefined()).toEqualTypeOf() + + expectTypeOf(expect(promiseBoolean).toBeDefined()).not.toEqualTypeOf>() + expectTypeOf(expect(promiseBoolean).toBeDefined()).not.toEqualTypeOf>() + }) + + it('should return void when actual is a String', async () => { + expectTypeOf(expect('text').toBe(true)).toEqualTypeOf() + expectTypeOf(expect('text').not.toBe(true)).toEqualTypeOf() + expectTypeOf(expect('text').toBe(expect.stringContaining('text'))).toEqualTypeOf() + expectTypeOf(expect('text').not.toBe(expect.stringContaining('text'))).toEqualTypeOf() + + expectTypeOf(expect('text').toBe(true)).not.toEqualTypeOf>() + expectTypeOf(expect('text').not.toBe(true)).not.toEqualTypeOf>() + expectTypeOf(expect('text').toBe(expect.stringContaining('text'))).not.toEqualTypeOf>() + expectTypeOf(expect('text').not.toBe(expect.stringContaining('text'))).not.toEqualTypeOf>() + }) + }) + + describe('Promise type assertions', () => { + const booleanPromise: Promise = Promise.resolve(true) + + it('should have expect return Matchers with a Promise', async () => { + expectTypeOf(expect(booleanPromise)).toMatchTypeOf> & ExpectLibInverse>> & ExpectWebdriverIO.PromiseMatchers>() + expectTypeOf(expect(booleanPromise).not).toMatchTypeOf>>() + }) + + it('should return Promise for resolves & rejects', async () => { + expectTypeOf(expect(booleanPromise).resolves.toBe(true)).toEqualTypeOf>() + expectTypeOf(expect(booleanPromise).rejects.toBe(true)).toEqualTypeOf>() + expectTypeOf(expect(booleanPromise).rejects.not.toBe(true)).toEqualTypeOf>() + expectTypeOf(expect(booleanPromise).resolves.not.toBe(true)).toEqualTypeOf>() + + expectTypeOf(expect(booleanPromise).resolves.toBe(true)).not.toEqualTypeOf() + expectTypeOf(expect(booleanPromise).rejects.toBe(true)).not.toEqualTypeOf() + }) + + it('should not support chainable and expect PromiseVoid with toBe', async () => { + expectTypeOf(expect(chainableElement).toBe(true)).not.toEqualTypeOf>() + expectTypeOf(expect(chainableElement).not.toBe(true)).not.toEqualTypeOf>() + }) + }) + + describe('Network Matchers', () => { + const promiseNetworkMock = Promise.resolve(networkMock) + + it('should return Promise', async () => { + expectTypeOf(expect(promiseNetworkMock).toBeRequested()).toEqualTypeOf>() + expectTypeOf(expect(promiseNetworkMock).toBeRequestedTimes(2)).toEqualTypeOf>() + expectTypeOf(expect(promiseNetworkMock).toBeRequestedTimes({ gte: 5, lte: 10 })).toEqualTypeOf>() + + expectTypeOf(expect(promiseNetworkMock).not.toBeRequested()).toEqualTypeOf>() + expectTypeOf(expect(promiseNetworkMock).not.toBeRequestedTimes(2)).toEqualTypeOf>() + expectTypeOf(expect(promiseNetworkMock).not.toBeRequestedTimes({ gte: 5, lte: 10 })).toEqualTypeOf>() + + expectTypeOf(expect(promiseNetworkMock).toBeRequestedWith({ + url: 'http://localhost:8080/api', + method: 'POST', + statusCode: 200, + requestHeaders: { Authorization: 'foo' }, + responseHeaders: { Authorization: 'bar' }, + postData: { title: 'foo', description: 'bar' }, + response: { success: true }, + })).toEqualTypeOf>() + + expectTypeOf(expect(promiseNetworkMock).toBeRequestedWith({ + url: expect.stringContaining('test'), + method: 'POST', + statusCode: 200, + requestHeaders: expect.objectContaining({ Authorization: 'foo' }), + responseHeaders: expect.objectContaining({ Authorization: 'bar' }), + postData: expect.objectContaining({ title: 'foo', description: 'bar' }), + response: expect.objectContaining({ success: true }), + })).toEqualTypeOf>() + + expectTypeOf(expect(promiseNetworkMock).toBeRequestedWith({ + url: expect.stringMatching(/.*\/api\/.*/i), + method: ['POST', 'PUT'], + statusCode: [401, 403], + requestHeaders: headers => headers.Authorization.startsWith('Bearer '), + postData: expect.objectContaining({ released: true, title: expect.stringContaining('foobar') }), + response: (r: { data: { items: unknown[] } }) => Array.isArray(r) && r.data.items.length === 20 + })).toEqualTypeOf>() + }) + }) + + describe('Standard Jest expect Library Matchers', () => { + it('should return void', async () => { + const obj = { a: 1 } + expectTypeOf(expect(obj).toHaveProperty('a')).toEqualTypeOf() + expectTypeOf(expect(obj).toMatchObject({ a: 1 })).toEqualTypeOf() + expectTypeOf(expect(obj).toStrictEqual({ a: 1 })).toEqualTypeOf() + expectTypeOf(expect([1, 2]).toHaveLength(2)).toEqualTypeOf() + }) + }) + + describe('More WDIO Matchers', () => { + describe('Attribute Matchers', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveAttribute('class')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveAttribute('class', 'val')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveAttribute('class', expect.stringContaining('val'))).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveAttr('class')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveAttr('class', 'val')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveAttr('class', expect.stringContaining('val'))).toEqualTypeOf>() + }) + }) + + describe('Class Matchers', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveClass('class')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveClass(expect.stringContaining('class'))).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveElementClass('class')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveElementClass(expect.stringContaining('class'))).toEqualTypeOf>() + }) + }) + + describe('Property Matchers', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveValue('val')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveValue(expect.stringContaining('val'))).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveElementProperty('prop')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveElementProperty('prop', 'val')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveElementProperty('prop', expect.stringContaining('val'))).toEqualTypeOf>() + }) + }) + + describe('Link Matchers', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveHref('href')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveHref(expect.stringContaining('href'))).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveLink('href')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveLink(expect.stringContaining('href'))).toEqualTypeOf>() + }) + }) + + describe('Identity & Other Matchers', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveId('id')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveId(expect.stringContaining('id'))).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveHTML('html')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveHTML(expect.stringContaining('html'))).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveComputedLabel('label')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveComputedLabel(expect.stringContaining('label'))).toEqualTypeOf>() + + expectTypeOf(expect(element).toHaveComputedRole('role')).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveComputedRole(expect.stringContaining('role'))).toEqualTypeOf>() + }) + }) + + describe('State Matchers', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toBeClickable()).toEqualTypeOf>() + expectTypeOf(expect(element).toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(expect(element).toExist()).toEqualTypeOf>() + expectTypeOf(expect(element).toBePresent()).toEqualTypeOf>() + expectTypeOf(expect(element).toBeExisting()).toEqualTypeOf>() + expectTypeOf(expect(element).toBeDisplayedInViewport()).toEqualTypeOf>() + expectTypeOf(expect(element).toBeEnabled()).toEqualTypeOf>() + expectTypeOf(expect(element).toBeFocused()).toEqualTypeOf>() + expectTypeOf(expect(element).toBeSelected()).toEqualTypeOf>() + expectTypeOf(expect(element).toBeChecked()).toEqualTypeOf>() + }) + }) + + describe('Structure Matchers', () => { + it('should return Promise', async () => { + expectTypeOf(expect(element).toHaveChildren()).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveSize({ width: 10, height: 10 })).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveWidth(10)).toEqualTypeOf>() + expectTypeOf(expect(element).toHaveStyle({ color: 'red' })).toEqualTypeOf>() + }) + }) + }) + + describe('Expect', () => { + it('should support stringContaining, anything and more', async () => { + expect.stringContaining('WebdriverIO') + expect.stringMatching(/WebdriverIO/) + expect.arrayContaining(['WebdriverIO', 'Test']) + expect.objectContaining({ name: 'WebdriverIO' }) + // Was not there but works! + expect.closeTo(5, 10) + expect.arrayContaining(['WebdriverIO', 'Test']) + // New from jest 30!! + expect.arrayOf(expect.stringContaining('WebdriverIO')) + + expect.anything() + expect.any(Function) + expect.any(Number) + expect.any(Boolean) + expect.any(String) + expect.any(Symbol) + expect.any(Date) + expect.any(Error) + + expect.not.stringContaining('WebdriverIO') + expect.not.stringMatching(/WebdriverIO/) + expect.not.arrayContaining(['WebdriverIO', 'Test']) + expect.not.objectContaining({ name: 'WebdriverIO' }) + expect.not.closeTo(5, 10) + expect.not.arrayContaining(['WebdriverIO', 'Test']) + expect.not.arrayOf(expect.stringContaining('WebdriverIO')) + }) + + describe('Soft Assertions', async () => { + const actualString: string = 'Test Page' + const actualPromiseString: Promise = Promise.resolve('Test Page') + + describe('expect.soft', () => { + it('should return void if actual is non-promise type', async () => { + expectTypeOf(expect.soft(actualString)).toMatchTypeOf>() + expectTypeOf(expect.soft(actualString).toBe('Test Page')).toEqualTypeOf() + expectTypeOf(expect.soft(actualString).not.toBe('Test Page')).toEqualTypeOf() + expectTypeOf(expect.soft(actualString).not.toBe(expect.stringContaining('Test Page'))).toEqualTypeOf() + }) + + it('should return Promise if actual is promise type', async () => { + expectTypeOf(expect.soft(actualPromiseString)).toMatchTypeOf, Promise>>() + expectTypeOf(expect.soft(actualPromiseString).toBe('Test Page')).toEqualTypeOf>() + expectTypeOf(expect.soft(actualPromiseString).not.toBe('Test Page')).toEqualTypeOf>() + expectTypeOf(expect.soft(actualPromiseString).not.toBe(expect.stringContaining('Test Page'))).toEqualTypeOf>() + }) + + it('should support chainable element', async () => { + expectTypeOf(expect.soft(element)).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement)).toEqualTypeOf>() + }) + + it('should return Promise with WDIO matchers', async () => { + expectTypeOf(expect.soft(element).toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableArray).toBeDisplayed()).toEqualTypeOf>() + await expect.soft(element).toBeDisplayed() + await expect.soft(chainableElement).toBeDisplayed() + await expect.soft(chainableArray).toBeDisplayed() + + expectTypeOf(expect.soft(element).not.toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).not.toBeDisplayed()).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableArray).not.toBeDisplayed()).toEqualTypeOf>() + await expect.soft(element).not.toBeDisplayed() + await expect.soft(chainableElement).not.toBeDisplayed() + await expect.soft(chainableArray).not.toBeDisplayed() + }) + + it('should work with custom matcher and custom asymmetric matchers from `expect` module', async () => { + expectTypeOf(expect.soft(chainableElement).toHaveCustomPropertyExpect('text')).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).toHaveCustomPropertyExpect(expect.stringContaining('text'))).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).not.toHaveCustomPropertyExpect(expect.not.stringContaining('text'))).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).toHaveCustomPropertyExpect( + expect.toHaveCustomPropertyExpect(chainableElement) + )).toEqualTypeOf>() + }) + + it('should work with custom matcher and custom asymmetric matchers from `ExpectWebDriverIO` namespace', async () => { + expectTypeOf(expect.soft(chainableElement).toBeCustomPromiseWdio('text')).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).toBeCustomPromiseWdio(expect.stringContaining('text'))).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).not.toBeCustomPromiseWdio(expect.not.stringContaining('text'))).toEqualTypeOf>() + expectTypeOf(expect.soft(chainableElement).toBeCustomPromiseWdio( + expect.toBeCustomPromiseWdio(chainableElement) + )).toEqualTypeOf>() + }) + }) + + describe('expect.getSoftFailures', () => { + it('should return `SoftFailure[]`', async () => { + expectTypeOf(expect.getSoftFailures()).toEqualTypeOf() + }) + }) + + describe('expect.assertSoftFailures', () => { + it('should return void', async () => { + expectTypeOf(expect.assertSoftFailures()).toEqualTypeOf() + }) + }) + + describe('expect.clearSoftFailures', () => { + it('should return void', async () => { + expectTypeOf(expect.clearSoftFailures()).toEqualTypeOf() + }) + }) + }) + }) + + describe('Asymmetric matchers', () => { + const string: string = 'WebdriverIO is a test framework' + const array: string[] = ['WebdriverIO', 'Test'] + const object: { name: string } = { name: 'WebdriverIO' } + const number: number = 1 + + it('should have no ts error using asymmetric matchers', async () => { + expect(string).toEqual(expect.stringContaining('WebdriverIO')) + expect(array).toEqual(expect.arrayContaining(['WebdriverIO', 'Test'])) + expect(object).toEqual(expect.objectContaining({ name: 'WebdriverIO' })) + // This one is tested and is working correctly, surprisingly! + expect(number).toEqual(expect.closeTo(1.0001, 0.0001)) + // New from jest 30, should work! + expect(['apple', 'banana', 'cherry']).toEqual(expect.arrayOf(expect.any(String))) + }) + }) +}) diff --git a/test-types/mocha/types-mocha.test.ts b/test-types/mocha/types-mocha.test.ts deleted file mode 100644 index 877ecdddf..000000000 --- a/test-types/mocha/types-mocha.test.ts +++ /dev/null @@ -1,862 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import type { ChainablePromiseElement, ChainablePromiseArray } from 'webdriverio' - -describe('type assertions', () => { - const chainableElement = {} as unknown as ChainablePromiseElement - const chainableArray = {} as ChainablePromiseArray - - const element: WebdriverIO.Element = {} as unknown as WebdriverIO.Element - const elementArray: WebdriverIO.ElementArray = [] as unknown as WebdriverIO.ElementArray - const elements: WebdriverIO.Element[] = [] as unknown as WebdriverIO.Element[] - - const networkMock: WebdriverIO.Mock = {} as unknown as WebdriverIO.Mock - - // Type assertions - let expectPromiseVoid: Promise - let expectVoid: void - - describe('Browser', () => { - const browser: WebdriverIO.Browser = {} as unknown as WebdriverIO.Browser - - describe('toHaveUrl', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = expect(browser).toHaveUrl('https://example.com') - expectPromiseVoid = expect(browser).not.toHaveUrl('https://example.com') - - // Asymmetric matchers - expectPromiseVoid = expect(browser).toHaveUrl(expect.stringContaining('WebdriverIO')) - expectPromiseVoid = expect(browser).toHaveUrl(expect.not.stringContaining('WebdriverIO')) - expectPromiseVoid = expect(browser).toHaveUrl(expect.any(String)) - expectPromiseVoid = expect(browser).toHaveUrl(expect.anything()) - - // @ts-expect-error - expectVoid = expect(browser).toHaveUrl('https://example.com') - // @ts-expect-error - expectVoid = expect(browser).not.toHaveUrl('https://example.com') - // @ts-expect-error - expectVoid = expect(browser).toHaveUrl(expect.stringContaining('WebdriverIO')) - - // @ts-expect-error - await expect(browser).toHaveUrl(6) - }) - - it('should have ts errors when actual is not a Browser element', async () => { - // @ts-expect-error - await expect(element).toHaveUrl('https://example.com') - // @ts-expect-error - await expect(element).not.toHaveUrl('https://example.com') - // @ts-expect-error - await expect(true).toHaveUrl('https://example.com') - // @ts-expect-error - await expect(true).not.toHaveUrl('https://example.com') - }) - }) - - describe('toHaveTitle', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = expect(browser).toHaveTitle('https://example.com') - expectPromiseVoid = expect(browser).not.toHaveTitle('https://example.com') - - // Asymmetric matchers - expectPromiseVoid = expect(browser).toHaveTitle(expect.stringContaining('WebdriverIO')) - expectPromiseVoid = expect(browser).toHaveTitle(expect.any(String)) - expectPromiseVoid = expect(browser).toHaveTitle(expect.anything()) - - // @ts-expect-error - expectVoid = expect(browser).toHaveTitle('https://example.com') - // @ts-expect-error - expectVoid = expect(browser).not.toHaveTitle('https://example.com') - // @ts-expect-error - expectVoid = expect(browser).toHaveTitle(expect.stringContaining('WebdriverIO')) - }) - - it('should have ts errors when actual is not a Browser element', async () => { - // @ts-expect-error - await expect(element).toHaveTitle('https://example.com') - // @ts-expect-error - await expect(element).not.toHaveTitle('https://example.com') - // @ts-expect-error - await expect(true).toHaveTitle('https://example.com') - // @ts-expect-error - await expect(true).not.toHaveTitle('https://example.com') - }) - }) - }) - - describe('element', () => { - - describe('toBeDisabled', () => { - it('should be supported correctly', async () => { - // Element - expectPromiseVoid = expect(element).toBeDisabled() - expectPromiseVoid = expect(element).not.toBeDisabled() - - // Element array - expectPromiseVoid = expect(elementArray).toBeDisabled() - expectPromiseVoid = expect(elementArray).not.toBeDisabled() - - // Chainable element - expectPromiseVoid = expect(chainableElement).toBeDisabled() - expectPromiseVoid = expect(chainableElement).not.toBeDisabled() - - // Chainable element array - expectPromiseVoid = expect(chainableArray).toBeDisabled() - expectPromiseVoid = expect(chainableArray).not.toBeDisabled() - - // @ts-expect-error - expectVoid = expect(element).toBeDisabled() - // @ts-expect-error - expectVoid = expect(element).not.toBeDisabled() - }) - - it('should have ts errors when actual is not an element', async () => { - // @ts-expect-error - await expect(browser).toBeDisabled() - // @ts-expect-error - await expect(browser).not.toBeDisabled() - // @ts-expect-error - await expect(true).toBeDisabled() - // @ts-expect-error - await expect(true).not.toBeDisabled() - }) - }) - - describe('toHaveText', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = expect(element).toHaveText('text') - expectPromiseVoid = expect(element).toHaveText(/text/) - expectPromiseVoid = expect(element).toHaveText(['text1', 'text2']) - expectPromiseVoid = expect(element).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')]) - expectPromiseVoid = expect(element).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expect(element).toHaveText(['text1', /text1/, expect.stringContaining('text3')]) - await expect(element).toHaveText( - 'My-Ex-Am-Ple', - { - replace: [[/-/g, ' '], [/[A-Z]+/g, (match: string) => match.toLowerCase()]] - } - ) - - expectPromiseVoid = expect(element).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expect(element).toHaveText('text') - // @ts-expect-error - await expect(element).toHaveText(6) - - expectPromiseVoid = expect(chainableElement).toHaveText('text') - expectPromiseVoid = expect(chainableElement).toHaveText(/text/) - expectPromiseVoid = expect(chainableElement).toHaveText(['text1', 'text2']) - expectPromiseVoid = expect(chainableElement).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')]) - expectPromiseVoid = expect(chainableElement).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expect(chainableElement).toHaveText(['text1', /text1/, expect.stringContaining('text3')]) - - expectPromiseVoid = expect(chainableElement).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expect(chainableElement).toHaveText('text') - // @ts-expect-error - await expect(chainableElement).toHaveText(6) - - expectPromiseVoid = expect(elementArray).toHaveText('text') - expectPromiseVoid = expect(elementArray).toHaveText(/text/) - expectPromiseVoid = expect(elementArray).toHaveText(['text1', 'text2']) - expectPromiseVoid = expect(elementArray).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')]) - expectPromiseVoid = expect(elementArray).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expect(elementArray).toHaveText(['text1', /text1/, expect.stringContaining('text3')]) - - expectPromiseVoid = expect(elementArray).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expect(elementArray).toHaveText('text') - // @ts-expect-error - await expect(elementArray).toHaveText(6) - - expectPromiseVoid = expect(chainableArray).toHaveText('text') - expectPromiseVoid = expect(chainableArray).toHaveText(/text/) - expectPromiseVoid = expect(chainableArray).toHaveText(['text1', 'text2']) - expectPromiseVoid = expect(chainableArray).toHaveText([expect.stringContaining('text1'), expect.stringContaining('text2')]) - expectPromiseVoid = expect(chainableArray).toHaveText([/text1/, /text2/]) - expectPromiseVoid = expect(chainableArray).toHaveText(['text1', /text1/, expect.stringContaining('text3')]) - - expectPromiseVoid = expect(chainableArray).not.toHaveText('text') - - // @ts-expect-error - expectVoid = expect(chainableArray).toHaveText('text') - // @ts-expect-error - await expect(chainableArray).toHaveText(6) - - // @ts-expect-error - await expect(browser).toHaveText('text') - }) - - it('should have ts errors when actual is not an element', async () => { - // @ts-expect-error - await expect(browser).toHaveText('text') - // @ts-expect-error - await expect(browser).not.toHaveText('text') - // @ts-expect-error - await expect(true).toHaveText('text') - // @ts-expect-error - await expect(true).toHaveText('text') - }) - - it('should have ts errors when actual is string or Promise', async () => { - // @ts-expect-error - await expect('text').toHaveText('text') - // @ts-expect-error - await expect('text').not.toHaveText('text') - // @ts-expect-error - await expect(Promise.resolve('text')).toHaveText('text') - // @ts-expect-error - await expect(Promise.resolve('text')).toHaveText('text') - }) - }) - - describe('toHaveHeight', () => { - it('should be supported correctly', async () => { - expectPromiseVoid = expect(element).toHaveHeight(100) - expectPromiseVoid = expect(element).toHaveHeight(100, { message: 'Custom error message' }) - expectPromiseVoid = expect(element).not.toHaveHeight(100) - expectPromiseVoid = expect(element).not.toHaveHeight(100, { message: 'Custom error message' }) - - expectPromiseVoid = expect(element).toHaveHeight({ width: 100, height: 200 }) - expectPromiseVoid = expect(element).toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' }) - expectPromiseVoid = expect(element).not.toHaveHeight({ width: 100, height: 200 }) - expectPromiseVoid = expect(element).not.toHaveHeight({ width: 100, height: 200 }, { message: 'Custom error message' }) - - // @ts-expect-error - expectVoid = expect(element).toHaveHeight(100) - // @ts-expect-error - expectVoid = expect(element).not.toHaveHeight(100) - - // @ts-expect-error - expectVoid = expect(element).toHaveHeight({ width: 100, height: 200 }) - // @ts-expect-error - expectVoid = expect(element).not.toHaveHeight({ width: 100, height: 200 }) - - // @ts-expect-error - await expect(browser).toHaveHeight(100) - }) - - it('should have ts errors when actual is string or Promise', async () => { - // @ts-expect-error - await expect('text').toHaveText('text') - // @ts-expect-error - await expect('text').not.toHaveText('text') - // @ts-expect-error - await expect(Promise.resolve('text')).toHaveText('text') - // @ts-expect-error - await expect(Promise.resolve('text')).toHaveText('text') - }) - }) - - describe('toMatchSnapshot', () => { - - it('should be supported correctly', async () => { - expectVoid = expect(element).toMatchSnapshot() - expectVoid = expect(element).toMatchSnapshot('test label') - expectVoid = expect(element).not.toMatchSnapshot('test label') - - expectPromiseVoid = expect(chainableElement).toMatchSnapshot() - expectPromiseVoid = expect(chainableElement).toMatchSnapshot('test label') - expectPromiseVoid = expect(chainableElement).not.toMatchSnapshot('test label') - - //@ts-expect-error - expectPromiseVoid = expect(element).toMatchSnapshot() - //@ts-expect-error - expectPromiseVoid = expect(element).not.toMatchSnapshot() - //@ts-expect-error - expectVoid = expect(chainableElement).toMatchSnapshot() - //@ts-expect-error - expectVoid = expect(chainableElement).not.toMatchSnapshot() - }) - }) - - describe('toMatchInlineSnapshot', () => { - - it('should be correctly supported', async () => { - expectVoid = expect(element).toMatchInlineSnapshot() - expectVoid = expect(element).toMatchInlineSnapshot('test snapshot') - expectVoid = expect(element).toMatchInlineSnapshot('test snapshot', 'test label') - - expectPromiseVoid = expect(chainableElement).toMatchInlineSnapshot() - expectPromiseVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label') - - //@ts-expect-error - expectPromiseVoid = expect(element).toMatchInlineSnapshot() - //@ts-expect-error - expectVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label') - }) - - it('should be correctly supported with getCSSProperty()', async () => { - expectPromiseVoid = expect(element.getCSSProperty('test')).toMatchInlineSnapshot() - expectPromiseVoid = expect(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = expect(element.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label') - - expectPromiseVoid = expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot() - expectPromiseVoid = expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot') - expectPromiseVoid = expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot('test snapshot', 'test label') - - expectVoid = expect(element).toMatchInlineSnapshot() - - //@ts-expect-error - expectPromiseVoid = expect(element).toMatchInlineSnapshot() - //@ts-expect-error - expectVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label') - - //@ts-expect-error - expectVoid = expect(element.getCSSProperty('test')).toMatchInlineSnapshot() - //@ts-expect-error - expectVoid = expect(chainableElement.getCSSProperty('test')).toMatchInlineSnapshot() - }) - }) - - describe('toBeElementsArrayOfSize', async () => { - - it('should work correctly when actual is chainableArray', async () => { - expectPromiseVoid = expect(chainableArray).toBeElementsArrayOfSize(5) - expectPromiseVoid = expect(chainableArray).toBeElementsArrayOfSize({ lte: 10 }) - - // @ts-expect-error - expectVoid = expect(chainableArray).toBeElementsArrayOfSize(5) - // @ts-expect-error - expectVoid = expect(chainableArray).toBeElementsArrayOfSize({ lte: 10 }) - }) - - it('should work correctly when actual is element array', async () => { - expectPromiseVoid = expect(elementArray).toBeElementsArrayOfSize(5) - expectPromiseVoid = expect(elementArray).toBeElementsArrayOfSize({ lte: 10 }) - - // @ts-expect-error - expectVoid = expect(elementArray).toBeElementsArrayOfSize(5) - // @ts-expect-error - expectVoid = expect(elementArray).toBeElementsArrayOfSize({ lte: 10 }) - }) - - it('should work correctly when actual is element[]', async () => { - expectPromiseVoid = expect(elements).toBeElementsArrayOfSize(5) - expectPromiseVoid = expect(elements).toBeElementsArrayOfSize({ lte: 10 }) - - // @ts-expect-error - expectVoid = expect(elements).toBeElementsArrayOfSize(5) - // @ts-expect-error - expectVoid = expect(elements).toBeElementsArrayOfSize({ lte: 10 }) - }) - - it('should not work when actual is not chainableArray', async () => { - // @ts-expect-error - await expect(chainableElement).toBeElementsArrayOfSize(5) - // @ts-expect-error - await expect(chainableElement).toBeElementsArrayOfSize({ lte: 10 }) - // @ts-expect-error - await expect(true).toBeElementsArrayOfSize(5) - // @ts-expect-error - await expect(true).toBeElementsArrayOfSize({ lte: 10 }) - }) - }) - }) - - describe('Custom matchers', () => { - describe('using `ExpectWebdriverIO` namespace augmentation', () => { - it('should supported correctly a non-promise custom matcher', async () => { - expectVoid = expect('test').toBeCustom() - expectVoid = expect('test').not.toBeCustom() - - // @ts-expect-error - expectPromiseVoid = expect('test').toBeCustom() - // @ts-expect-error - expectPromiseVoid = expect('test').not.toBeCustom() - - expectVoid = expect(1).toBeWithinRange(0, 2) - }) - - it('should supported correctly a promise custom matcher with only chainableElement as actual', async () => { - expectPromiseVoid = expect(chainableElement).toBeCustomPromise() - expectPromiseVoid = expect(chainableElement).toBeCustomPromise(expect.stringContaining('test')) - expectPromiseVoid = expect(chainableElement).not.toBeCustomPromise(expect.not.stringContaining('test')) - - // @ts-expect-error - expect('test').toBeCustomPromise() - // @ts-expect-error - expectVoid = expect(chainableElement).toBeCustomPromise() - // @ts-expect-error - expectVoid = expect(chainableElement).toBeCustomPromise(expect.stringContaining('test')) - // @ts-expect-error - expectVoid = expect(chainableElement).not.toBeCustomPromise(expect.stringContaining('test')) - // @ts-expect-error - expect(chainableElement).toBeCustomPromise(expect.stringContaining(6)) - }) - - it('should support custom asymmetric matcher', async () => { - const expectString1 : ExpectWebdriverIO.PartialMatcher = expect.toBeCustom() - const expectString2 : ExpectWebdriverIO.PartialMatcher = expect.not.toBeCustom() - - expectPromiseVoid = expect(chainableElement).toBeCustomPromise(expect.toBeCustom()) - - // @ts-expect-error - expectPromiseVoid = expect.toBeCustom() - // @ts-expect-error - expectPromiseVoid = expect.not.toBeCustom() - - //@ts-expect-error - expectVoid = expect(chainableElement).toBeCustomPromise(expect.toBeCustom()) - }) - }) - - describe('using `expect` module declaration', () => { - - it('should support a simple matcher', async () => { - expectVoid = expect(5).toBeWithinRange(1, 10) - - // Or as an asymmetric matcher: - expectVoid = expect({ value: 5 }).toEqual({ - value: expect.toBeWithinRange(1, 10) - }) - - // @ts-expect-error - expectVoid = expect(5).toBeWithinRange(1, '10') - // @ts-expect-error - expectPromiseVoid = expect(5).toBeWithinRange('1') - }) - - it('should support a simple custom matcher with a chainable element matcher with promise', async () => { - expectPromiseVoid = expect(chainableElement).toHaveSimpleCustomProperty('text') - expectPromiseVoid = expect(chainableElement).toHaveSimpleCustomProperty(expect.stringContaining('text')) - expectPromiseVoid = expect(chainableElement).not.toHaveSimpleCustomProperty(expect.not.stringContaining('text')) - - // Or as a custom asymmetric matcher: - expectPromiseVoid = expect(chainableElement).toHaveSimpleCustomProperty( - expect.toHaveSimpleCustomProperty('string') - ) - const expectString1:string = expect.toHaveSimpleCustomProperty('string') - const expectString2:string = expect.not.toHaveSimpleCustomProperty('string') - - // @ts-expect-error - expectVoid = expect.toHaveSimpleCustomProperty(chainableElement) - // @ts-expect-error - expectVoid = expect.not.toHaveSimpleCustomProperty(chainableElement) - - // @ts-expect-error - expectVoid = expect.toHaveSimpleCustomProperty(chainableElement) - }) - - it('should support a chainable element matcher with promise', async () => { - expectPromiseVoid = expect(chainableElement).toHaveCustomProperty('text') - expectPromiseVoid = expect(chainableElement).toHaveCustomProperty(expect.stringContaining('text')) - expectPromiseVoid = expect(chainableElement).not.toHaveCustomProperty(expect.not.stringContaining('text')) - - // Or as a custom asymmetric matcher: - expectPromiseVoid = expect(chainableElement).toHaveCustomProperty( - await expect.toHaveCustomProperty(chainableElement) - ) - const expectPromiseWdioElement1: Promise> = expect.toHaveCustomProperty(chainableElement) - const expectPromiseWdioElement2: Promise> = expect.not.toHaveCustomProperty(chainableElement) - - // @ts-expect-error - expectVoid = expect.toHaveCustomProperty(chainableElement) - // @ts-expect-error - expectVoid = expect.not.toHaveCustomProperty(chainableElement) - - // @ts-expect-error - expectVoid = expect.toHaveCustomProperty(chainableElement) - // @ts-expect-error - expect.toHaveCustomProperty('test') - - await expect(chainableElement).toHaveCustomProperty( - await expect.toHaveCustomProperty(chainableElement) - ) - }) - }) - }) - - describe('toBe', () => { - - it('should expect void type when actual is a boolean', async () => { - expectVoid = expect(true).toBe(true) - expectVoid = expect(true).not.toBe(true) - - //@ts-expect-error - expectPromiseVoid = expect(true).toBe(true) - //@ts-expect-error - expectPromiseVoid = expect(true).not.toBe(true) - }) - - it('should not expect Promise when actual is a chainable since toBe does not need to be awaited', async () => { - expectVoid = expect(chainableElement).toBe(true) - expectVoid = expect(chainableElement).not.toBe(true) - - //@ts-expect-error - expectPromiseVoid = expect(chainableElement).toBe(true) - //@ts-expect-error - expectPromiseVoid = expect(chainableElement).not.toBe(true) - }) - - it('should still expect void type when actual is a Promise since we do not overload them', async () => { - const promiseBoolean = Promise.resolve(true) - - expectVoid = expect(promiseBoolean).toBeDefined() - expectVoid = expect(promiseBoolean).not.toBeDefined() - - //@ts-expect-error - expectPromiseVoid = expect(promiseBoolean).toBeDefined() - //@ts-expect-error - expectPromiseVoid = expect(promiseBoolean).toBeDefined() - }) - - it('should work with string', async () => { - expectVoid = expect('text').toBe(true) - expectVoid = expect('text').not.toBe(true) - expectVoid = expect('text').toBe(expect.stringContaining('text')) - expectVoid = expect('text').not.toBe(expect.stringContaining('text')) - - //@ts-expect-error - expectPromiseVoid = expect('text').toBe(true) - //@ts-expect-error - expectPromiseVoid = expect('text').not.toBe(true) - //@ts-expect-error - expectPromiseVoid = expect('text').toBe(expect.stringContaining('text')) - //@ts-expect-error - expectPromiseVoid = expect('text').not.toBe(expect.stringContaining('text')) - }) - }) - - describe('Promise type assertions', () => { - const booleanPromise: Promise = Promise.resolve(true) - - it('should have expect return Matchers with a Promise', async () => { - const expectPromiseBoolean1: ExpectWebdriverIO.Matchers> & ExpectLibInverse>> & ExpectWebdriverIO.PromiseMatchers = expect(booleanPromise) - const expectPromiseBoolean2: ExpectWebdriverIO.Matchers> = expect(booleanPromise).not - }) - - it('should work with resolves & rejects correctly', async () => { - expectPromiseVoid = expect(booleanPromise).resolves.toBe(true) - expectPromiseVoid = expect(booleanPromise).rejects.toBe(true) - expectPromiseVoid = expect(booleanPromise).rejects.not.toBe(true) - expectPromiseVoid = expect(booleanPromise).resolves.not.toBe(true) - - //@ts-expect-error - expectVoid = expect(booleanPromise).resolves.toBe(true) - //@ts-expect-error - expectVoid = expect(booleanPromise).rejects.toBe(true) - - //@ts-expect-error - expect(true).resolves.toBe(true) - //@ts-expect-error - expect(true).rejects.toBe(true) - }) - - it('should not support chainable and expect PromiseVoid with toBe', async () => { - //@ts-expect-error - expectPromiseVoid = expect(chainableElement).toBe(true) - //@ts-expect-error - expectPromiseVoid = expect(chainableElement).not.toBe(true) - }) - }) - - describe('Network Matchers', () => { - const promiseNetworkMock = Promise.resolve(networkMock) - - it('should not have ts errors when typing to Promise', async () => { - expectPromiseVoid = expect(promiseNetworkMock).toBeRequested() - expectPromiseVoid = expect(promiseNetworkMock).toBeRequestedTimes(2) - expectPromiseVoid = expect(promiseNetworkMock).toBeRequestedTimes({ gte: 5, lte: 10 }) - - expectPromiseVoid = expect(promiseNetworkMock).not.toBeRequested() - expectPromiseVoid = expect(promiseNetworkMock).not.toBeRequestedTimes(2) - expectPromiseVoid = expect(promiseNetworkMock).not.toBeRequestedTimes({ gte: 5, lte: 10 }) - - expectPromiseVoid = expect(promiseNetworkMock).toBeRequestedWith({ - url: 'http://localhost:8080/api', - method: 'POST', - statusCode: 200, - requestHeaders: { Authorization: 'foo' }, - responseHeaders: { Authorization: 'bar' }, - postData: { title: 'foo', description: 'bar' }, - response: { success: true }, - }) - - expectPromiseVoid = expect(promiseNetworkMock).toBeRequestedWith({ - url: expect.stringContaining('test'), - method: 'POST', - statusCode: 200, - requestHeaders: expect.objectContaining({ Authorization: 'foo' }), - responseHeaders: expect.objectContaining({ Authorization: 'bar' }), - postData: expect.objectContaining({ title: 'foo', description: 'bar' }), - response: expect.objectContaining({ success: true }), - }) - - expectPromiseVoid = expect(promiseNetworkMock).toBeRequestedWith({ - url: expect.stringMatching(/.*\/api\/.*/i), - method: ['POST', 'PUT'], - statusCode: [401, 403], - requestHeaders: headers => headers.Authorization.startsWith('Bearer '), - postData: expect.objectContaining({ released: true, title: expect.stringContaining('foobar') }), - response: (r: { data: { items: unknown[] } }) => Array.isArray(r) && r.data.items.length === 20 - }) - }) - - it('should have ts errors when typing to void', async () => { - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).toBeRequested() - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).toBeRequestedTimes(2) // await expect(mock).toBeRequestedTimes({ eq: 2 }) - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).toBeRequestedTimes({ gte: 5, lte: 10 }) // request called at least 5 times but less than 11 - - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).not.toBeRequested() - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).not.toBeRequestedTimes(2) // await expect(mock).toBeRequestedTimes({ eq: 2 }) - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).not.toBeRequestedTimes({ gte: 5, lte: 10 }) // request called at least 5 times but less than 11 - - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).toBeRequestedWith({ - url: 'http://localhost:8080/api', - method: 'POST', - statusCode: 200, - requestHeaders: { Authorization: 'foo' }, - responseHeaders: { Authorization: 'bar' }, - postData: { title: 'foo', description: 'bar' }, - response: { success: true }, - }) - - // @ts-expect-error - expectVoid = expect(promiseNetworkMock).toBeRequestedWith(expect.objectContaining({ - response: { success: true }, - })) - }) - }) - - describe('Expect', () => { - it('should have ts errors when using a non existing expect.function', async () => { - // @ts-expect-error - expect.unimplementedFunction() - }) - - it('should support stringContaining, anything and more', async () => { - expect.stringContaining('WebdriverIO') - expect.stringMatching(/WebdriverIO/) - expect.arrayContaining(['WebdriverIO', 'Test']) - expect.objectContaining({ name: 'WebdriverIO' }) - // Was not there but works! - expect.closeTo(5, 10) - expect.arrayContaining(['WebdriverIO', 'Test']) - // New from jest 30!! - expect.arrayOf(expect.stringContaining('WebdriverIO')) - - expect.anything() - expect.any(Function) - expect.any(Number) - expect.any(Boolean) - expect.any(String) - expect.any(Symbol) - expect.any(Date) - expect.any(Error) - - expect.not.stringContaining('WebdriverIO') - expect.not.stringMatching(/WebdriverIO/) - expect.not.arrayContaining(['WebdriverIO', 'Test']) - expect.not.objectContaining({ name: 'WebdriverIO' }) - expect.not.closeTo(5, 10) - expect.not.arrayContaining(['WebdriverIO', 'Test']) - expect.not.arrayOf(expect.stringContaining('WebdriverIO')) - }) - - describe('Soft Assertions', async () => { - const actualString: string = 'Test Page' - const actualPromiseString: Promise = Promise.resolve('Test Page') - - describe('expect.soft', () => { - it('should not need to be awaited/be a promise if actual is non-promise type', async () => { - const expectWdioMatcher1: WdioCustomMatchers = expect.soft(actualString) - expectVoid = expect.soft(actualString).toBe('Test Page') - expectVoid = expect.soft(actualString).not.toBe('Test Page') - expectVoid = expect.soft(actualString).not.toBe(expect.stringContaining('Test Page')) - - // @ts-expect-error - expectPromiseVoid = expect.soft(actualString).toBe('Test Page') - // @ts-expect-error - expectPromiseVoid = expect.soft(actualString).not.toBe('Test Page') - // @ts-expect-error - expectPromiseVoid = expect.soft(actualString).not.toBe(expect.stringContaining('Test Page')) - }) - - it('should need to be awaited/be a promise if actual is promise type', async () => { - const expectWdioMatcher1: ExpectWebdriverIO.MatchersAndInverse, Promise> = expect.soft(actualPromiseString) - expectPromiseVoid = expect.soft(actualPromiseString).toBe('Test Page') - expectPromiseVoid = expect.soft(actualPromiseString).not.toBe('Test Page') - expectPromiseVoid = expect.soft(actualPromiseString).not.toBe(expect.stringContaining('Test Page')) - - // @ts-expect-error - expectVoid = expect.soft(actualPromiseString).toBe('Test Page') - // @ts-expect-error - expectVoid = expect.soft(actualPromiseString).not.toBe('Test Page') - // @ts-expect-error - expectVoid = expect.soft(actualPromiseString).not.toBe(expect.stringContaining('Test Page')) - }) - - it('should support chainable element', async () => { - const expectElement: ExpectWebdriverIO.MatchersAndInverse = expect.soft(element) - const expectElementChainable: ExpectWebdriverIO.MatchersAndInverse = expect.soft(chainableElement) - - // @ts-expect-error - const expectElement2: ExpectWebdriverIO.MatchersAndInverse, WebdriverIO.Element> = expect.soft(element) - // @ts-expect-error - const expectElementChainable2: ExpectWebdriverIO.MatchersAndInverse, typeof chainableElement> = expect.soft(chainableElement) - }) - - it('should support chainable element with wdio Matchers', async () => { - expectPromiseVoid = expect.soft(element).toBeDisplayed() - expectPromiseVoid = expect.soft(chainableElement).toBeDisplayed() - expectPromiseVoid = expect.soft(chainableArray).toBeDisplayed() - await expect.soft(element).toBeDisplayed() - await expect.soft(chainableElement).toBeDisplayed() - await expect.soft(chainableArray).toBeDisplayed() - - expectPromiseVoid = expect.soft(element).not.toBeDisplayed() - expectPromiseVoid = expect.soft(chainableElement).not.toBeDisplayed() - expectPromiseVoid = expect.soft(chainableArray).not.toBeDisplayed() - await expect.soft(element).not.toBeDisplayed() - await expect.soft(chainableElement).not.toBeDisplayed() - await expect.soft(chainableArray).not.toBeDisplayed() - - // @ts-expect-error - expectVoid = expect.soft(element).toBeDisplayed() - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeDisplayed() - // @ts-expect-error - expectVoid = expect.soft(chainableArray).toBeDisplayed() - - // @ts-expect-error - expectVoid = expect.soft(element).not.toBeDisplayed() - // @ts-expect-error - expectVoid = expect.soft(chainableElement).not.toBeDisplayed() - // @ts-expect-error - expectVoid = expect.soft(chainableArray).not.toBeDisplayed() - }) - - it('should work with custom matcher and custom asymmetric matchers from `expect` module', async () => { - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty('text') - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty(expect.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).not.toHaveCustomProperty(expect.not.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty( - expect.toHaveCustomProperty(chainableElement) - ) - - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty('text') - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty(expect.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).not.toHaveCustomProperty(expect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty( - expect.toHaveCustomProperty(chainableElement) - ) - - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty('text') - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty(expect.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).not.toHaveCustomProperty(expect.not.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).toHaveCustomProperty( - expect.toHaveCustomProperty(chainableElement) - ) - - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty('text') - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty(expect.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).not.toHaveCustomProperty(expect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toHaveCustomProperty( - expect.toHaveCustomProperty(chainableElement) - ) - }) - - it('should work with custom matcher and custom asymmetric matchers from `ExpectWebDriverIO` namespace', async () => { - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise('text') - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise(expect.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).not.toBeCustomPromise(expect.not.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise( - expect.toBeCustomPromise(chainableElement) - ) - - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise('text') - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise(expect.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).not.toBeCustomPromise(expect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise( - expect.toBeCustomPromise(chainableElement) - ) - - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise('text') - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise(expect.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).not.toBeCustomPromise(expect.not.stringContaining('text')) - expectPromiseVoid = expect.soft(chainableElement).toBeCustomPromise( - expect.toBeCustomPromise(chainableElement) - ) - - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise('text') - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise(expect.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).not.toBeCustomPromise(expect.not.stringContaining('text')) - // @ts-expect-error - expectVoid = expect.soft(chainableElement).toBeCustomPromise( - expect.toBeCustomPromise(chainableElement) - ) - }) - }) - - describe('expect.getSoftFailures', () => { - it('should be of type `SoftFailure`', async () => { - const expectSoftFailure1: ExpectWebdriverIO.SoftFailure[] = expect.getSoftFailures() - - // @ts-expect-error - expectVoid = expect.getSoftFailures() - }) - }) - - describe('expect.assertSoftFailures', () => { - it('should be of type void', async () => { - expectVoid = expect.assertSoftFailures() - - // @ts-expect-error - expectPromiseVoid = expect.assertSoftFailures() - }) - }) - - describe('expect.clearSoftFailures', () => { - it('should be of type void', async () => { - expectVoid = expect.clearSoftFailures() - - // @ts-expect-error - expectPromiseVoid = expect.clearSoftFailures() - }) - }) - }) - }) - - describe('Asymmetric matchers', () => { - const string: string = 'WebdriverIO is a test framework' - const array: string[] = ['WebdriverIO', 'Test'] - const object: { name: string } = { name: 'WebdriverIO' } - const number: number = 1 - - it('should have no ts error using asymmetric matchers', async () => { - expect(string).toEqual(expect.stringContaining('WebdriverIO')) - expect(array).toEqual(expect.arrayContaining(['WebdriverIO', 'Test'])) - expect(object).toEqual(expect.objectContaining({ name: 'WebdriverIO' })) - // This one is tested and is working correctly, surprisingly! - expect(number).toEqual(expect.closeTo(1.0001, 0.0001)) - // New from jest 30, should work! - expect(['apple', 'banana', 'cherry']).toEqual(expect.arrayOf(expect.any(String))) - }) - }) -}) diff --git a/test/index.test.ts b/test/index.test.ts index d430ef85d..d46d50d45 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,9 +1,10 @@ import { test, expect } from 'vitest' -import { setOptions, expect as expectExport, matchers, utils } from '../src/index.js' +import { setOptions, expect as expectExport, matchers, utils, wdioCustomMatchers } from '../src/index.js' test('index', () => { expect(setOptions.name).toBe('setDefaultOptions') expect(expectExport).toBeDefined() expect(utils.compareText).toBeDefined() + expect(Object.keys(wdioCustomMatchers).length).toEqual(42) expect(matchers.size).toEqual(42) }) diff --git a/test/matchers.test.ts b/test/matchers.test.ts index 0a610356e..6baf7daec 100644 --- a/test/matchers.test.ts +++ b/test/matchers.test.ts @@ -1,5 +1,5 @@ import { test, expect, vi, describe } from 'vitest' -import { matchers, expect as expectLib } from '../src/index.js' +import { matchers, wdioCustomMatchers, expect as expectLib } from '../src/index.js' import { $ } from '@wdio/globals' vi.mock('@wdio/globals') @@ -60,6 +60,7 @@ const ALL_MATCHERS = [ test('matchers', () => { expect([...matchers.keys()]).toEqual(ALL_MATCHERS) + expect(Object.keys(wdioCustomMatchers).length).toEqual(ALL_MATCHERS.length) }) test('allows to add matcher', () => { @@ -69,6 +70,7 @@ test('allows to add matcher', () => { // @ts-expect-error not in types expectLib('foo').toBeCustom('foo') expect(matchers.keys()).toContain('toBeCustom') + expect(wdioCustomMatchers).toHaveProperty('toBeCustom') }) test('Generic asymmetric matchers from Expect library should work', () => { diff --git a/test/utils.test.ts b/test/utils.test.ts index 377628621..72dc918e0 100644 --- a/test/utils.test.ts +++ b/test/utils.test.ts @@ -1,8 +1,29 @@ import { describe, test, expect, vi } from 'vitest' -import { compareNumbers, compareObject, compareText, compareTextWithArray, waitUntil } from '../src/utils' +import { compareNumbers, compareObject, compareText, compareTextWithArray, getAsymmetricMatcherValue, isAsymmetricMatcher, isStrictlyStringContainingMatcher, isStringContainingMatcherLike, waitUntil } from '../src/utils' describe('utils', () => { - describe('compareText', () => { + + // Jasmine's StringContaining mimic (from https://github.com/jasmine/jasmine/blob/main/src/core/asymmetric_equality/StringContaining.js) + class StringContaining { + expected: string + constructor(expected: string) { + if (typeof expected !== 'string') { + throw new Error('Expected is not a string') + } + this.expected = expected + } + asymmetricMatch(actual: unknown) { + return typeof actual === 'string' && actual.indexOf(this.expected) !== -1 + } + jasmineToString() { + return '' + } + getExpectedType() { + return 'string' + } + } + + describe(compareText, () => { test('should pass when strings match', () => { expect(compareText('foo', 'foo', {}).result).toBe(true) }) @@ -40,6 +61,12 @@ describe('utils', () => { expect(compareText(' Foo ', expect.not.stringContaining('FOO'), { ignoreCase: true }).result).toBe(false) expect(compareText(' foo ', expect.stringContaining('foo'), { ignoreCase: true }).result).toBe(true) }) + + test('should support jasmine.asymmetric matchers and using ignoreCase', () => { + expect(compareText(' FOO ', new StringContaining('foo') as unknown as WdioAsymmetricMatcher, { ignoreCase: true }).result).toBe(true) + expect(compareText(' Foo ', new StringContaining('FOO') as unknown as WdioAsymmetricMatcher, { ignoreCase: true }).result).toBe(true) + expect(compareText(' foo ', new StringContaining('foo') as unknown as WdioAsymmetricMatcher, { ignoreCase: true }).result).toBe(true) + }) }) describe('compareTextWithArray', () => { @@ -345,4 +372,82 @@ describe('utils', () => { }) }) }) + + describe(isAsymmetricMatcher, () => { + + describe('StringContaining (Jasmine mimic)', () => { + test('matches when substring is present', () => { + const matcher = new StringContaining('foo') + expect(matcher.asymmetricMatch('foobar')).toBe(true) + expect(matcher.asymmetricMatch('barfoo')).toBe(true) + expect(matcher.asymmetricMatch('barbaz')).toBe(false) + }) + test('throws if expected is not a string', () => { + // @ts-expect-error + expect(() => new StringContaining(123)).toThrow('Expected is not a string') + }) + test('jasmineToString and getExpectedType', () => { + const matcher = new StringContaining('foo') + expect(matcher.jasmineToString()).toBe('') + expect(matcher.getExpectedType()).toBe('string') + }) + }) + + test.for([ + expect.stringContaining('foo'), + new StringContaining('foo') + ])('should work with %s matcher', async (asymmetricMatcher) => { + const isAsymmetric = isAsymmetricMatcher(asymmetricMatcher) + + expect(isAsymmetric).toBe(true) + }) + }) + + describe(isStringContainingMatcherLike, () => { + test.for([ + expect.stringContaining('foo'), + expect.not.stringContaining('foo'), + new StringContaining('foo') + ])('should work with %s matcher', async (asymmetricMatcher) => { + const isStringContaining = isStringContainingMatcherLike(asymmetricMatcher) + + expect(isStringContaining).toBe(true) + }) + }) + + describe(isStrictlyStringContainingMatcher, () => { + test.for([ + // expect.stringContaining('foo'), + new StringContaining('foo') + ])('should work with %s matcher', async (asymmetricMatcher) => { + const isStrictlyStringContaining = isStrictlyStringContainingMatcher(asymmetricMatcher) + + expect(isStrictlyStringContaining).toBe(true) + }) + + test('should work with %s matcher', async () => { + const asymmetricMatcher = expect.not.stringContaining('foo') + + const isStrictlyStringContaining = isStrictlyStringContainingMatcher(asymmetricMatcher) + + expect(isStrictlyStringContaining).toBe(false) + }) + }) + + describe(getAsymmetricMatcherValue, () => { + test.for([ + expect.stringContaining('foo'), + expect.not.stringContaining('foo'), + new StringContaining('foo'), + ])('should return expected value of matcher', (asymmetricMatcher) => { + + const value = getAsymmetricMatcherValue(asymmetricMatcher) + + expect(value).toBe('foo') + }) + + test('should throw when unknown matcher', () => { + expect(() => getAsymmetricMatcherValue({} as any)).toThrow('Could not extract value from asymmetric matcher: [object Object]') + }) + }) }) diff --git a/types/expect-global.d.ts b/types/expect-global.d.ts index b546de019..03de50fed 100644 --- a/types/expect-global.d.ts +++ b/types/expect-global.d.ts @@ -5,11 +5,12 @@ * Required when used in standalone mode (mocha) or to override the one of Jasmine */ -//// @ts-expect-error: IDE might flags this one but just does be concerned by it. This way the `tsc:root-types` can pass! +// @ts-expect-error: IDE might flags this one but just does be concerned by it. This way the `tsc:root-types` can pass! declare const expect: ExpectWebdriverIO.Expect declare namespace NodeJS { interface Global { + // @ts-expect-error: Both wdio & Jasmine augmentation declare different global expect explaining why TS is complaining here expect: ExpectWebdriverIO.Expect } -} \ No newline at end of file +} diff --git a/types/expect-webdriverio.d.ts b/types/expect-webdriverio.d.ts index e0f9dd4bf..8d3af7e69 100644 --- a/types/expect-webdriverio.d.ts +++ b/types/expect-webdriverio.d.ts @@ -31,6 +31,7 @@ type RawMatcherFn = PromiseLike | ChainablePromiseElement | ChainablePromiseArray +type WdioElementOrPromiseLike = WdioPromiseLike | WebdriverIO.Element type ElementPromise = Promise type ElementArrayPromise = Promise @@ -118,7 +119,7 @@ interface WdioNetworkMatchers<_R, ActualT> { /** * Check that `WebdriverIO.Mock` was called with the specific parameters */ - toBeRequestedWith: FnWhenMock Promise> + toBeRequestedWith: FnWhenMock, options?: ExpectWebdriverIO.CommandOptions) => Promise> } /** @@ -201,7 +202,7 @@ interface WdioElementOrArrayMatchers<_R, ActualT = unknown> { ActualT, ( property: string, - value?: string | RegExp | WdioAsymmetricMatcher | null, + value?: string | RegExp | ExpectWebdriverIO.PartialMatcher | null, options?: ExpectWebdriverIO.StringOptions, ) => Promise > @@ -396,18 +397,18 @@ interface WdioElementArrayOnlyMatchers<_R, ActualT = unknown> { * Therefore, they also need to be redefined in the jest.d.ts file so correctly overload the matchers from the Jest namespace. * @see jest.d.ts */ -interface WdioJestOverloadedMatchers<_R, ActualT> { +interface WdioJestOverloadedMatchers { /** * snapshot matcher * @param label optional snapshot label */ - toMatchSnapshot(label?: string): ActualT extends WdioPromiseLike ? Promise : void; + toMatchSnapshot(label?: string): ActualT extends WdioElementOrPromiseLike ? Promise : R /** * inline snapshot matcher * @param snapshot snapshot string (autogenerated if not specified) * @param label optional snapshot label */ - toMatchInlineSnapshot(snapshot?: string, label?: string): ActualT extends WdioPromiseLike ? Promise : void; + toMatchInlineSnapshot(snapshot?: string, label?: string): ActualT extends WdioElementOrPromiseLike ? Promise : R } /** @@ -468,6 +469,12 @@ type WdioAsymmetricMatcher = ExpectWebdriverIO.PartialMatcher & { sample: R; } +type JasmineAsymmetricMatcher = { + jasmineToString(): string; + expected: R; + asymmetricMatch(other: unknown): boolean; +} + declare namespace ExpectWebdriverIO { /** * When importing expect from 'expect-webdriverio', instead of using globals this is the one used. @@ -510,7 +517,13 @@ declare namespace ExpectWebdriverIO { (actual: T): T extends PromiseLike ? ExpectWebdriverIO.MatchersAndInverse & ExpectWebdriverIO.PromiseMatchers : ExpectWebdriverIO.MatchersAndInverse; } - interface Matchers, T> extends WdioMatchers {} + /** + * Matchers defining the custom wdio matchers. + * Matchers is documented as the interface to augment to add other custom matchers. + * + * We MUST NOT have Jest's expect Lib matchers here, so that we can use it with Jasmine augmentation as well. + */ + interface Matchers, T> extends WdioCustomMatchers {} interface AsymmetricMatchers extends WdioAsymmetricMatchers {} @@ -520,7 +533,7 @@ declare namespace ExpectWebdriverIO { * End of block overloading types from the expect library. */ - type MatchersAndInverse, ActualT> = ExpectWebdriverIO.Matchers & ExpectLibInverse> + type MatchersAndInverse, ActualT> = (ExpectWebdriverIO.Matchers & ExpectLibMatchers) & ExpectLibInverse & ExpectLibMatchers> /** * Take from expect library @@ -582,18 +595,26 @@ declare namespace ExpectWebdriverIO { interface AssertionResult extends ExpectLibSyncExpectationResult {} type AsyncAssertionResult = ExpectLibAsyncExpectationResult + /** + * @deprecated use `wdioCustomMatchers` instead + */ + const matchers: Map + /** * Used by the wdio main project to configure the matchers in the runner when using Jasmine or Jest. + * Contains only the custom matchers from wdio, and not the ones from the expect library, to avoid any conflict with the matchers from the expect library when using Jasmine or Jest. + * Map to src/index.ts#wdioCustomMatchers + * * Equivalent as `MatchersObject` from the expect library. * @see https://github.com/jestjs/jest/blob/fd3d6cf9fe416b549a74b6577e5e1ea1130e3659/packages/expect/src/types.ts#L43C13-L43C27 */ - const matchers: Map + const wdioCustomMatchers: Record interface AssertionHookParams { /** * name of the matcher, e.g. `toHaveText` or `toBeClickable` */ - matcherName: keyof Matchers, + matcherName: keyof Matchers /** * Value that the user has passed in *