diff --git a/package-lock.json b/package-lock.json index a930d5e7..32b63e34 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "choices.js", - "version": "11.0.0-rc7", + "version": "11.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "choices.js", - "version": "11.0.0-rc7", + "version": "11.0.0", "license": "MIT", "dependencies": { "fuse.js": "^7.0.0" @@ -32,6 +32,7 @@ "autoprefixer": "^10.4.20", "bundlesize": "^0.18.2", "chai": "^5.1.1", + "cross-process-lock": "^2.1.1", "csso-cli": "^4.0.2", "eslint": "^8.57.0", "eslint-config-airbnb-base": "^15.0.0", @@ -4332,9 +4333,9 @@ } }, "node_modules/axios": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.3.tgz", - "integrity": "sha512-Ar7ND9pU99eJ9GpoGQKhKf58GpUOgnzuaB7ueNQ5BMi0p+LZ5oaEnfF999fAArcTIBwXTCHAmGcHOZJaWPq9Nw==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz", + "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==", "dev": true, "license": "MIT", "dependencies": { @@ -4958,6 +4959,20 @@ "node": ">=4" } }, + "node_modules/cross-process-lock": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cross-process-lock/-/cross-process-lock-2.1.1.tgz", + "integrity": "sha512-CV2vQQmEZaz2RmA8lhu7+pQWePJPKCVLDL+IMch3hrednzp+dsr/2XBPcAp/Fd8xY7b3GV3UkaBL97yQwte/qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -8990,9 +9005,9 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "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": { diff --git a/package.json b/package.json index 890b6cdf..62103535 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,7 @@ "autoprefixer": "^10.4.20", "bundlesize": "^0.18.2", "chai": "^5.1.1", + "cross-process-lock": "^2.1.1", "csso-cli": "^4.0.2", "eslint": "^8.57.0", "eslint-config-airbnb-base": "^15.0.0", diff --git a/test-e2e/test-suit.ts b/test-e2e/test-suit.ts index d91817fc..b3d43f46 100644 --- a/test-e2e/test-suit.ts +++ b/test-e2e/test-suit.ts @@ -1,4 +1,6 @@ import { expect, type Locator, type Page } from '@playwright/test'; +import { lock } from 'cross-process-lock'; +import { writeFileSync, existsSync } from 'fs'; export class TestSuit { readonly testId: string; @@ -176,4 +178,20 @@ export class TestSuit { async expectedItemCount(count: number): Promise { await expect(this.items).toHaveCount(count); } + + // eslint-disable-next-line class-methods-use-this + async crossProcessLock(func: () => Promise): Promise { + // playwright lacks clipboard isolation, so use a lock to ensure other tests don't modify the clipboard at the same time + // https://github.com/microsoft/playwright/issues/13097#issuecomment-1445271511 + const name = 'test-results/clipboard'; + if (!existsSync(name)) { + writeFileSync(name, '', 'utf8'); + } + const unlock = await lock(name, { waitTimeout: 30000 }); + try { + await func(); + } finally { + await unlock(); + } + } } diff --git a/test-e2e/tests/select-multiple.spec.ts b/test-e2e/tests/select-multiple.spec.ts index 99f645c5..642c1bcc 100644 --- a/test-e2e/tests/select-multiple.spec.ts +++ b/test-e2e/tests/select-multiple.spec.ts @@ -653,8 +653,10 @@ describe(`Choices - select multiple`, () => { await suite.startWithClick(); await suite.expectVisibleDropdown(); - await page.evaluate(`navigator.clipboard.writeText('${country}')`); - await suite.ctrlV(); + await suite.crossProcessLock(async () => { + await page.evaluate(`navigator.clipboard.writeText('${country}')`); + await suite.ctrlV(); + }); const choice = suite.selectableChoices.first(); await expect(choice).toHaveText(city); diff --git a/test-e2e/tests/select-one.spec.ts b/test-e2e/tests/select-one.spec.ts index ccd6bd25..dfc62365 100644 --- a/test-e2e/tests/select-one.spec.ts +++ b/test-e2e/tests/select-one.spec.ts @@ -528,8 +528,10 @@ describe(`Choices - select one`, () => { await suite.startWithClick(); await suite.expectVisibleDropdown(); - await page.evaluate(`navigator.clipboard.writeText('${country}')`); - await suite.ctrlV(); + await suite.crossProcessLock(async () => { + await page.evaluate(`navigator.clipboard.writeText('${country}')`); + await suite.ctrlV(); + }); const choice = suite.selectableChoices.first(); await expect(choice).toHaveText(city);