diff --git a/package-lock.json b/package-lock.json index 71232c865f..6c38563a66 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,8 +32,9 @@ "@types/resize-observer-browser": "^0.1.7", "@types/ws": "^8.5.3", "@types/xml2js": "^0.4.9", - "@typescript-eslint/eslint-plugin": "^6.12.0", - "@typescript-eslint/parser": "^6.12.0", + "@typescript-eslint/eslint-plugin": "^6.13.2", + "@typescript-eslint/parser": "^6.13.2", + "@typescript-eslint/utils": "^6.13.2", "@vitejs/plugin-basic-ssl": "^1.0.1", "@vitejs/plugin-react": "^3.1.0", "@zip.js/zip.js": "^2.7.29", @@ -47,7 +48,8 @@ "electron-to-chromium": "^1.4.212", "enquirer": "^2.3.6", "esbuild": "^0.18.11", - "eslint": "^8.37.0", + "eslint": "^8.55.0", + "eslint-plugin-internal-playwright": "file:utils/eslint-plugin-internal-playwright", "eslint-plugin-notice": "^0.9.10", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.3.0", @@ -927,14 +929,14 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", - "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.1", + "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -950,9 +952,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -964,34 +966,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@eslint/js": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.37.0.tgz", - "integrity": "sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", + "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" }, @@ -1013,9 +1003,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "node_modules/@jridgewell/gen-mapping": { @@ -1337,16 +1327,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", - "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz", + "integrity": "sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.12.0", - "@typescript-eslint/type-utils": "6.12.0", - "@typescript-eslint/utils": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/type-utils": "6.13.2", + "@typescript-eslint/utils": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1387,15 +1377,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz", - "integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz", + "integrity": "sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.12.0", - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/typescript-estree": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4" }, "engines": { @@ -1415,13 +1405,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", - "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", + "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0" + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1432,13 +1422,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz", - "integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz", + "integrity": "sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.12.0", - "@typescript-eslint/utils": "6.12.0", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/utils": "6.13.2", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1459,9 +1449,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", - "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", + "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1472,13 +1462,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", - "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", + "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1514,17 +1504,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", - "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", + "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.12.0", - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", "semver": "^7.5.4" }, "engines": { @@ -1554,12 +1544,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", - "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", + "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/types": "6.13.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1570,6 +1560,12 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/@vitejs/plugin-basic-ssl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.0.1.tgz", @@ -1741,9 +1737,9 @@ "license": "ISC" }, "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -3251,27 +3247,28 @@ } }, "node_modules/eslint": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.37.0.tgz", - "integrity": "sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", + "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.37.0", - "@humanwhocodes/config-array": "^0.11.8", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.55.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.4.0", - "espree": "^9.5.1", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -3279,22 +3276,19 @@ "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "bin": { @@ -3307,6 +3301,10 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-plugin-internal-playwright": { + "resolved": "utils/eslint-plugin-internal-playwright", + "link": true + }, "node_modules/eslint-plugin-notice": { "version": "0.9.10", "dev": true, @@ -3390,6 +3388,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint-visitor-keys": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", @@ -3458,19 +3472,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "dev": true, @@ -3516,27 +3517,15 @@ "node": ">=8" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/espree": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", - "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3559,8 +3548,9 @@ }, "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": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -4050,12 +4040,6 @@ "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 - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -4592,16 +4576,6 @@ "set-function-name": "^2.0.1" } }, - "node_modules/js-sdsl": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", - "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "license": "MIT" @@ -5497,9 +5471,9 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" @@ -6381,6 +6355,18 @@ "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", @@ -7314,6 +7300,10 @@ "xterm": "^5.1.0", "xterm-addon-fit": "^0.7.0" } + }, + "utils/eslint-plugin-internal-playwright": { + "version": "0.0.1", + "dev": true } }, "dependencies": { @@ -7907,14 +7897,14 @@ "dev": true }, "@eslint/eslintrc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", - "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.1", + "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -7924,35 +7914,29 @@ }, "dependencies": { "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "requires": { "type-fest": "^0.20.2" } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true } } }, "@eslint/js": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.37.0.tgz", - "integrity": "sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", + "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", "dev": true }, "@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" } @@ -7964,9 +7948,9 @@ "dev": true }, "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "@jridgewell/gen-mapping": { @@ -8324,16 +8308,16 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", - "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz", + "integrity": "sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.12.0", - "@typescript-eslint/type-utils": "6.12.0", - "@typescript-eslint/utils": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/type-utils": "6.13.2", + "@typescript-eslint/utils": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -8354,54 +8338,54 @@ } }, "@typescript-eslint/parser": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz", - "integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz", + "integrity": "sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "6.12.0", - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/typescript-estree": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", - "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", + "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", "dev": true, "requires": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0" + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2" } }, "@typescript-eslint/type-utils": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz", - "integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz", + "integrity": "sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "6.12.0", - "@typescript-eslint/utils": "6.12.0", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/utils": "6.13.2", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" } }, "@typescript-eslint/types": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", - "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", + "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", - "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", + "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", "dev": true, "requires": { - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/visitor-keys": "6.12.0", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8421,17 +8405,17 @@ } }, "@typescript-eslint/utils": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", - "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", + "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.12.0", - "@typescript-eslint/types": "6.12.0", - "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", "semver": "^7.5.4" }, "dependencies": { @@ -8447,15 +8431,21 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", - "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", + "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", "dev": true, "requires": { - "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/types": "6.13.2", "eslint-visitor-keys": "^3.4.1" } }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "@vitejs/plugin-basic-ssl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.0.1.tgz", @@ -8598,9 +8588,9 @@ "dev": true }, "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true }, "acorn-jsx": { @@ -9555,27 +9545,28 @@ "version": "1.0.5" }, "eslint": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.37.0.tgz", - "integrity": "sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", + "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.37.0", - "@humanwhocodes/config-array": "^0.11.8", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.55.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.4.0", - "espree": "^9.5.1", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -9583,22 +9574,19 @@ "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "dependencies": { @@ -9632,16 +9620,6 @@ "version": "4.0.0", "dev": true }, - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, "glob-parent": { "version": "6.0.2", "dev": true, @@ -9668,15 +9646,12 @@ "requires": { "has-flag": "^4.0.0" } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true } } }, + "eslint-plugin-internal-playwright": { + "version": "file:utils/eslint-plugin-internal-playwright" + }, "eslint-plugin-notice": { "version": "0.9.10", "dev": true, @@ -9737,6 +9712,16 @@ "dev": true, "requires": {} }, + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, "eslint-visitor-keys": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", @@ -9744,14 +9729,14 @@ "dev": true }, "espree": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", - "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "requires": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.0" + "eslint-visitor-keys": "^3.4.1" } }, "esquery": { @@ -9765,6 +9750,8 @@ }, "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, "requires": { "estraverse": "^5.2.0" @@ -10110,12 +10097,6 @@ "version": "4.2.9", "dev": true }, - "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 - }, "graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -10473,12 +10454,6 @@ "set-function-name": "^2.0.1" } }, - "js-sdsl": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", - "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", - "dev": true - }, "js-tokens": { "version": "4.0.0" }, @@ -11084,9 +11059,9 @@ } }, "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true }, "qs": { @@ -11682,6 +11657,12 @@ "prelude-ls": "^1.2.1" } }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, "typed-array-buffer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", diff --git a/package.json b/package.json index 7a969032f3..d2d08d0e16 100644 --- a/package.json +++ b/package.json @@ -70,8 +70,9 @@ "@types/resize-observer-browser": "^0.1.7", "@types/ws": "^8.5.3", "@types/xml2js": "^0.4.9", - "@typescript-eslint/eslint-plugin": "^6.12.0", - "@typescript-eslint/parser": "^6.12.0", + "@typescript-eslint/eslint-plugin": "^6.13.2", + "@typescript-eslint/parser": "^6.13.2", + "@typescript-eslint/utils": "^6.13.2", "@vitejs/plugin-basic-ssl": "^1.0.1", "@vitejs/plugin-react": "^3.1.0", "@zip.js/zip.js": "^2.7.29", @@ -85,7 +86,8 @@ "electron-to-chromium": "^1.4.212", "enquirer": "^2.3.6", "esbuild": "^0.18.11", - "eslint": "^8.37.0", + "eslint": "^8.55.0", + "eslint-plugin-internal-playwright": "file:utils/eslint-plugin-internal-playwright", "eslint-plugin-notice": "^0.9.10", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.3.0", diff --git a/packages/playwright-core/src/client/.eslintrc.js b/packages/playwright-core/src/client/.eslintrc.js new file mode 100644 index 0000000000..38d3ba3f0b --- /dev/null +++ b/packages/playwright-core/src/client/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: '../../../.eslintrc.js', + plugins: ['internal-playwright'], + rules: { + 'internal-playwright/await-promise-in-class-returns': 'error', + }, +}; diff --git a/packages/playwright-core/src/client/android.ts b/packages/playwright-core/src/client/android.ts index 651bcbe3e9..296a596977 100644 --- a/packages/playwright-core/src/client/android.ts +++ b/packages/playwright-core/src/client/android.ts @@ -60,7 +60,7 @@ export class Android extends ChannelOwner implements ap async launchServer(options: types.LaunchServerOptions = {}): Promise { if (!this._serverLauncher) throw new Error('Launching server is not supported'); - return this._serverLauncher.launchServer(options); + return await this._serverLauncher.launchServer(options); } async connect(wsEndpoint: string, options: Parameters[1] = {}): Promise { @@ -175,7 +175,7 @@ export class AndroidDevice extends ChannelOwner i const webView = [...this._webViews.values()].find(predicate); if (webView) return webView; - return this.waitForEvent('webview', { ...options, predicate }); + return await this.waitForEvent('webview', { ...options, predicate }); } async wait(selector: api.AndroidSelector, options?: { state?: 'gone' } & types.TimeoutOptions) { @@ -281,7 +281,7 @@ export class AndroidDevice extends ChannelOwner i } async waitForEvent(event: string, optionsOrPredicate: types.WaitForEventOptions = {}): Promise { - return this._wrapApiCall(async () => { + return await this._wrapApiCall(async () => { const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate); const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate; const waiter = Waiter.createForEvent(this, event); @@ -321,7 +321,7 @@ export class AndroidSocket extends ChannelOwner i async function loadFile(file: string | Buffer): Promise { if (isString(file)) - return fs.promises.readFile(file); + return await fs.promises.readFile(file); return file; } @@ -429,7 +429,7 @@ export class AndroidWebView extends EventEmitter implements api.AndroidWebView { async page(): Promise { if (!this._pagePromise) this._pagePromise = this._fetchPage(); - return this._pagePromise; + return await this._pagePromise; } private async _fetchPage(): Promise { diff --git a/packages/playwright-core/src/client/artifact.ts b/packages/playwright-core/src/client/artifact.ts index f93dd98541..c3a53c0294 100644 --- a/packages/playwright-core/src/client/artifact.ts +++ b/packages/playwright-core/src/client/artifact.ts @@ -60,7 +60,7 @@ export class Artifact extends ChannelOwner { async readIntoBuffer(): Promise { const stream = (await this.createReadStream())!; - return new Promise((resolve, reject) => { + return await new Promise((resolve, reject) => { const chunks: Buffer[] = []; stream.on('data', (chunk: Buffer) => { chunks.push(chunk); @@ -73,10 +73,10 @@ export class Artifact extends ChannelOwner { } async cancel(): Promise { - return this._channel.cancel(); + return await this._channel.cancel(); } async delete(): Promise { - return this._channel.delete(); + return await this._channel.delete(); } } diff --git a/packages/playwright-core/src/client/browserContext.ts b/packages/playwright-core/src/client/browserContext.ts index c5aa679433..c7eb89c531 100644 --- a/packages/playwright-core/src/client/browserContext.ts +++ b/packages/playwright-core/src/client/browserContext.ts @@ -360,7 +360,7 @@ export class BrowserContext extends ChannelOwner } async waitForEvent(event: string, optionsOrPredicate: WaitForEventOptions = {}): Promise { - return this._wrapApiCall(async () => { + return await this._wrapApiCall(async () => { const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate); const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate; const waiter = Waiter.createForEvent(this, event); diff --git a/packages/playwright-core/src/client/browserType.ts b/packages/playwright-core/src/client/browserType.ts index cc9b4eeaf5..eca564e69c 100644 --- a/packages/playwright-core/src/client/browserType.ts +++ b/packages/playwright-core/src/client/browserType.ts @@ -88,7 +88,7 @@ export class BrowserType extends ChannelOwner imple if (!this._serverLauncher) throw new Error('Launching server is not supported'); options = { ...this._defaultLaunchOptions, ...options }; - return this._serverLauncher.launchServer(options); + return await this._serverLauncher.launchServer(options); } async launchPersistentContext(userDataDir: string, options: LaunchPersistentContextOptions = {}): Promise { @@ -116,9 +116,9 @@ export class BrowserType extends ChannelOwner imple connect(wsEndpoint: string, options?: api.ConnectOptions): Promise; async connect(optionsOrWsEndpoint: string | (api.ConnectOptions & { wsEndpoint: string }), options?: api.ConnectOptions): Promise{ if (typeof optionsOrWsEndpoint === 'string') - return this._connect({ ...options, wsEndpoint: optionsOrWsEndpoint }); + return await this._connect({ ...options, wsEndpoint: optionsOrWsEndpoint }); assert(optionsOrWsEndpoint.wsEndpoint, 'options.wsEndpoint is required'); - return this._connect(optionsOrWsEndpoint); + return await this._connect(optionsOrWsEndpoint); } async _connect(params: ConnectOptions): Promise { @@ -193,14 +193,14 @@ export class BrowserType extends ChannelOwner imple }); } - connectOverCDP(options: api.ConnectOverCDPOptions & { wsEndpoint?: string }): Promise; - connectOverCDP(endpointURL: string, options?: api.ConnectOverCDPOptions): Promise; - connectOverCDP(endpointURLOrOptions: (api.ConnectOverCDPOptions & { wsEndpoint?: string })|string, options?: api.ConnectOverCDPOptions) { + async connectOverCDP(options: api.ConnectOverCDPOptions & { wsEndpoint?: string }): Promise; + async connectOverCDP(endpointURL: string, options?: api.ConnectOverCDPOptions): Promise; + async connectOverCDP(endpointURLOrOptions: (api.ConnectOverCDPOptions & { wsEndpoint?: string })|string, options?: api.ConnectOverCDPOptions) { if (typeof endpointURLOrOptions === 'string') - return this._connectOverCDP(endpointURLOrOptions, options); + return await this._connectOverCDP(endpointURLOrOptions, options); const endpointURL = 'endpointURL' in endpointURLOrOptions ? endpointURLOrOptions.endpointURL : endpointURLOrOptions.wsEndpoint; assert(endpointURL, 'Cannot connect over CDP without wsEndpoint.'); - return this.connectOverCDP(endpointURL, endpointURLOrOptions); + return await this.connectOverCDP(endpointURL, endpointURLOrOptions); } async _connectOverCDP(endpointURL: string, params: api.ConnectOverCDPOptions = {}): Promise { diff --git a/packages/playwright-core/src/client/cdpSession.ts b/packages/playwright-core/src/client/cdpSession.ts index 4c928793a5..68d1cb57f8 100644 --- a/packages/playwright-core/src/client/cdpSession.ts +++ b/packages/playwright-core/src/client/cdpSession.ts @@ -47,6 +47,6 @@ export class CDPSession extends ChannelOwner impleme } async detach() { - return this._channel.detach(); + return await this._channel.detach(); } } diff --git a/packages/playwright-core/src/client/channelOwner.ts b/packages/playwright-core/src/client/channelOwner.ts index 2093f6ca26..c41be351bd 100644 --- a/packages/playwright-core/src/client/channelOwner.ts +++ b/packages/playwright-core/src/client/channelOwner.ts @@ -141,13 +141,13 @@ export abstract class ChannelOwner { - return this._wrapApiCall(apiZone => { + return async (params: any) => { + return await this._wrapApiCall(async apiZone => { const { apiName, frames, csi, callCookie, wallTime } = apiZone.reported ? { apiName: undefined, csi: undefined, callCookie: undefined, frames: [], wallTime: undefined } : apiZone; apiZone.reported = true; if (csi && apiName) csi.onApiCallBegin(apiName, params, frames, wallTime, callCookie); - return this._connection.sendMessageToServer(this, prop, validator(params, '', { tChannelImpl: tChannelImplToWire, binary: this._connection.rawBuffers() ? 'buffer' : 'toBase64' }), apiName, frames, wallTime); + return await this._connection.sendMessageToServer(this, prop, validator(params, '', { tChannelImpl: tChannelImplToWire, binary: this._connection.rawBuffers() ? 'buffer' : 'toBase64' }), apiName, frames, wallTime); }); }; } @@ -164,7 +164,7 @@ export abstract class ChannelOwner('apiZone', stack); if (apiZone) - return func(apiZone); + return await func(apiZone); const stackTrace = captureLibraryStackTrace(stack); let apiName: string | undefined = stackTrace.apiName; diff --git a/packages/playwright-core/src/client/connection.ts b/packages/playwright-core/src/client/connection.ts index 6184666eed..bc124d91fa 100644 --- a/packages/playwright-core/src/client/connection.ts +++ b/packages/playwright-core/src/client/connection.ts @@ -111,7 +111,7 @@ export class Connection extends EventEmitter { return this._objects.get(guid)!; } - async setIsTracing(isTracing: boolean) { + setIsTracing(isTracing: boolean) { if (isTracing) this._tracingCount++; else diff --git a/packages/playwright-core/src/client/download.ts b/packages/playwright-core/src/client/download.ts index 22b08be657..e5cdd01aa6 100644 --- a/packages/playwright-core/src/client/download.ts +++ b/packages/playwright-core/src/client/download.ts @@ -45,26 +45,26 @@ export class Download implements api.Download { } async path(): Promise { - return this._artifact.pathAfterFinished(); + return await this._artifact.pathAfterFinished(); } async saveAs(path: string): Promise { - return this._artifact.saveAs(path); + return await this._artifact.saveAs(path); } async failure(): Promise { - return this._artifact.failure(); + return await this._artifact.failure(); } async createReadStream(): Promise { - return this._artifact.createReadStream(); + return await this._artifact.createReadStream(); } async cancel(): Promise { - return this._artifact.cancel(); + return await this._artifact.cancel(); } async delete(): Promise { - return this._artifact.delete(); + return await this._artifact.delete(); } } diff --git a/packages/playwright-core/src/client/electron.ts b/packages/playwright-core/src/client/electron.ts index 8a0b43ff1f..247a584367 100644 --- a/packages/playwright-core/src/client/electron.ts +++ b/packages/playwright-core/src/client/electron.ts @@ -101,7 +101,7 @@ export class ElectronApplication extends ChannelOwner { if (this._windows.size) return this._windows.values().next().value; - return this.waitForEvent('window', options); + return await this.waitForEvent('window', options); } context(): BrowserContext { @@ -119,7 +119,7 @@ export class ElectronApplication extends ChannelOwner { - return this._wrapApiCall(async () => { + return await this._wrapApiCall(async () => { const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate); const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate; const waiter = Waiter.createForEvent(this, event); diff --git a/packages/playwright-core/src/client/fetch.ts b/packages/playwright-core/src/client/fetch.ts index a6aec9f475..8dc3caa570 100644 --- a/packages/playwright-core/src/client/fetch.ts +++ b/packages/playwright-core/src/client/fetch.ts @@ -106,42 +106,42 @@ export class APIRequestContext extends ChannelOwner { - return this.fetch(url, { + return await this.fetch(url, { ...options, method: 'DELETE', }); } async head(url: string, options?: RequestWithBodyOptions): Promise { - return this.fetch(url, { + return await this.fetch(url, { ...options, method: 'HEAD', }); } async get(url: string, options?: RequestWithBodyOptions): Promise { - return this.fetch(url, { + return await this.fetch(url, { ...options, method: 'GET', }); } async patch(url: string, options?: RequestWithBodyOptions): Promise { - return this.fetch(url, { + return await this.fetch(url, { ...options, method: 'PATCH', }); } async post(url: string, options?: RequestWithBodyOptions): Promise { - return this.fetch(url, { + return await this.fetch(url, { ...options, method: 'POST', }); } async put(url: string, options?: RequestWithBodyOptions): Promise { - return this.fetch(url, { + return await this.fetch(url, { ...options, method: 'PUT', }); @@ -150,11 +150,11 @@ export class APIRequestContext extends ChannelOwner { const url = isString(urlOrRequest) ? urlOrRequest : undefined; const request = isString(urlOrRequest) ? undefined : urlOrRequest; - return this._innerFetch({ url, request, ...options }); + return await this._innerFetch({ url, request, ...options }); } async _innerFetch(options: FetchOptions & { url?: string, request?: api.Request } = {}): Promise { - return this._wrapApiCall(async () => { + return await this._wrapApiCall(async () => { assert(options.request || typeof options.url === 'string', 'First argument must be either URL string or Request'); assert((options.data === undefined ? 0 : 1) + (options.form === undefined ? 0 : 1) + (options.multipart === undefined ? 0 : 1) <= 1, `Only one of 'data', 'form' or 'multipart' can be specified`); assert(options.maxRedirects === undefined || options.maxRedirects >= 0, `'maxRedirects' should be greater than or equal to '0'`); diff --git a/packages/playwright-core/src/client/fileChooser.ts b/packages/playwright-core/src/client/fileChooser.ts index 28274a0e61..5e7b1113ff 100644 --- a/packages/playwright-core/src/client/fileChooser.ts +++ b/packages/playwright-core/src/client/fileChooser.ts @@ -44,6 +44,6 @@ export class FileChooser implements api.FileChooser { } async setFiles(files: string | FilePayload | string[] | FilePayload[], options?: channels.ElementHandleSetInputFilesOptions) { - return this._elementHandle.setInputFiles(files, options); + return await this._elementHandle.setInputFiles(files, options); } } diff --git a/packages/playwright-core/src/client/frame.ts b/packages/playwright-core/src/client/frame.ts index 18d36c732c..6845d8be6b 100644 --- a/packages/playwright-core/src/client/frame.ts +++ b/packages/playwright-core/src/client/frame.ts @@ -113,7 +113,7 @@ export class Frame extends ChannelOwner implements api.Fr } async waitForNavigation(options: WaitForNavigationOptions = {}): Promise { - return this._page!._wrapApiCall(async () => { + return await this._page!._wrapApiCall(async () => { const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil); const waiter = this._setupNavigationWaiter(options); @@ -149,7 +149,7 @@ export class Frame extends ChannelOwner implements api.Fr async waitForLoadState(state: LifecycleEvent = 'load', options: { timeout?: number } = {}): Promise { state = verifyLoadState('state', state); - return this._page!._wrapApiCall(async () => { + return await this._page!._wrapApiCall(async () => { const waiter = this._setupNavigationWaiter(options); if (this._loadStates.has(state)) { waiter.log(` not waiting, "${state}" event already fired`); diff --git a/packages/playwright-core/src/client/jsHandle.ts b/packages/playwright-core/src/client/jsHandle.ts index 39afd9a52e..ad03609e40 100644 --- a/packages/playwright-core/src/client/jsHandle.ts +++ b/packages/playwright-core/src/client/jsHandle.ts @@ -72,7 +72,7 @@ export class JSHandle extends ChannelOwner im } async _objectCount() { - return this._wrapApiCall(async () => { + return await this._wrapApiCall(async () => { const { count } = await this._channel.objectCount(); return count; }); diff --git a/packages/playwright-core/src/client/locator.ts b/packages/playwright-core/src/client/locator.ts index d6b47037bb..36ded11194 100644 --- a/packages/playwright-core/src/client/locator.ts +++ b/packages/playwright-core/src/client/locator.ts @@ -67,7 +67,7 @@ export class Locator implements api.Locator { timeout = this._frame.page()._timeoutSettings.timeout({ timeout }); const deadline = timeout ? monotonicTime() + timeout : 0; - return this._frame._wrapApiCall(async () => { + return await this._frame._wrapApiCall(async () => { const result = await this._frame._channel.waitForSelector({ selector: this._selector, strict: true, state: 'attached', timeout }); const handle = ElementHandle.fromNullable(result.element) as ElementHandle | null; if (!handle) @@ -85,59 +85,59 @@ export class Locator implements api.Locator { } async boundingBox(options?: TimeoutOptions): Promise { - return this._withElement(h => h.boundingBox(), options?.timeout); + return await this._withElement(h => h.boundingBox(), options?.timeout); } async check(options: channels.ElementHandleCheckOptions = {}) { - return this._frame.check(this._selector, { strict: true, ...options }); + return await this._frame.check(this._selector, { strict: true, ...options }); } async click(options: channels.ElementHandleClickOptions = {}): Promise { - return this._frame.click(this._selector, { strict: true, ...options }); + return await this._frame.click(this._selector, { strict: true, ...options }); } async dblclick(options: channels.ElementHandleDblclickOptions = {}): Promise { - return this._frame.dblclick(this._selector, { strict: true, ...options }); + return await this._frame.dblclick(this._selector, { strict: true, ...options }); } async dispatchEvent(type: string, eventInit: Object = {}, options?: TimeoutOptions) { - return this._frame.dispatchEvent(this._selector, type, eventInit, { strict: true, ...options }); + return await this._frame.dispatchEvent(this._selector, type, eventInit, { strict: true, ...options }); } async dragTo(target: Locator, options: channels.FrameDragAndDropOptions = {}) { - return this._frame.dragAndDrop(this._selector, target._selector, { + return await this._frame.dragAndDrop(this._selector, target._selector, { strict: true, ...options, }); } async evaluate(pageFunction: structs.PageFunctionOn, arg?: Arg, options?: TimeoutOptions): Promise { - return this._withElement(h => h.evaluate(pageFunction, arg), options?.timeout); + return await this._withElement(h => h.evaluate(pageFunction, arg), options?.timeout); } async evaluateAll(pageFunction: structs.PageFunctionOn, arg?: Arg): Promise { - return this._frame.$$eval(this._selector, pageFunction, arg); + return await this._frame.$$eval(this._selector, pageFunction, arg); } async evaluateHandle(pageFunction: structs.PageFunctionOn, arg?: Arg, options?: TimeoutOptions): Promise> { - return this._withElement(h => h.evaluateHandle(pageFunction, arg), options?.timeout); + return await this._withElement(h => h.evaluateHandle(pageFunction, arg), options?.timeout); } async fill(value: string, options: channels.ElementHandleFillOptions = {}): Promise { - return this._frame.fill(this._selector, value, { strict: true, ...options }); + return await this._frame.fill(this._selector, value, { strict: true, ...options }); } async clear(options: channels.ElementHandleFillOptions = {}): Promise { - return this.fill('', options); + return await this.fill('', options); } async _highlight() { // VS Code extension uses this one, keep it for now. - return this._frame._highlight(this._selector); + return await this._frame._highlight(this._selector); } async highlight() { - return this._frame._highlight(this._selector); + return await this._frame._highlight(this._selector); } locator(selectorOrLocator: string | Locator, options?: LocatorOptions): Locator { @@ -189,7 +189,7 @@ export class Locator implements api.Locator { } async elementHandles(): Promise[]> { - return this._frame.$$(this._selector); + return await this._frame.$$(this._selector); } first(): Locator { @@ -217,7 +217,7 @@ export class Locator implements api.Locator { } async focus(options?: TimeoutOptions): Promise { - return this._frame.focus(this._selector, { strict: true, ...options }); + return await this._frame.focus(this._selector, { strict: true, ...options }); } async blur(options?: TimeoutOptions): Promise { @@ -225,71 +225,71 @@ export class Locator implements api.Locator { } async count(): Promise { - return this._frame._queryCount(this._selector); + return await this._frame._queryCount(this._selector); } async getAttribute(name: string, options?: TimeoutOptions): Promise { - return this._frame.getAttribute(this._selector, name, { strict: true, ...options }); + return await this._frame.getAttribute(this._selector, name, { strict: true, ...options }); } async hover(options: channels.ElementHandleHoverOptions = {}): Promise { - return this._frame.hover(this._selector, { strict: true, ...options }); + return await this._frame.hover(this._selector, { strict: true, ...options }); } async innerHTML(options?: TimeoutOptions): Promise { - return this._frame.innerHTML(this._selector, { strict: true, ...options }); + return await this._frame.innerHTML(this._selector, { strict: true, ...options }); } async innerText(options?: TimeoutOptions): Promise { - return this._frame.innerText(this._selector, { strict: true, ...options }); + return await this._frame.innerText(this._selector, { strict: true, ...options }); } async inputValue(options?: TimeoutOptions): Promise { - return this._frame.inputValue(this._selector, { strict: true, ...options }); + return await this._frame.inputValue(this._selector, { strict: true, ...options }); } async isChecked(options?: TimeoutOptions): Promise { - return this._frame.isChecked(this._selector, { strict: true, ...options }); + return await this._frame.isChecked(this._selector, { strict: true, ...options }); } async isDisabled(options?: TimeoutOptions): Promise { - return this._frame.isDisabled(this._selector, { strict: true, ...options }); + return await this._frame.isDisabled(this._selector, { strict: true, ...options }); } async isEditable(options?: TimeoutOptions): Promise { - return this._frame.isEditable(this._selector, { strict: true, ...options }); + return await this._frame.isEditable(this._selector, { strict: true, ...options }); } async isEnabled(options?: TimeoutOptions): Promise { - return this._frame.isEnabled(this._selector, { strict: true, ...options }); + return await this._frame.isEnabled(this._selector, { strict: true, ...options }); } async isHidden(options?: TimeoutOptions): Promise { - return this._frame.isHidden(this._selector, { strict: true, ...options }); + return await this._frame.isHidden(this._selector, { strict: true, ...options }); } async isVisible(options?: TimeoutOptions): Promise { - return this._frame.isVisible(this._selector, { strict: true, ...options }); + return await this._frame.isVisible(this._selector, { strict: true, ...options }); } async press(key: string, options: channels.ElementHandlePressOptions = {}): Promise { - return this._frame.press(this._selector, key, { strict: true, ...options }); + return await this._frame.press(this._selector, key, { strict: true, ...options }); } async screenshot(options: Omit & { path?: string, mask?: Locator[] } = {}): Promise { - return this._withElement((h, timeout) => h.screenshot({ ...options, timeout }), options.timeout); + return await this._withElement((h, timeout) => h.screenshot({ ...options, timeout }), options.timeout); } async scrollIntoViewIfNeeded(options: channels.ElementHandleScrollIntoViewIfNeededOptions = {}) { - return this._withElement((h, timeout) => h.scrollIntoViewIfNeeded({ ...options, timeout }), options.timeout); + return await this._withElement((h, timeout) => h.scrollIntoViewIfNeeded({ ...options, timeout }), options.timeout); } async selectOption(values: string | api.ElementHandle | SelectOption | string[] | api.ElementHandle[] | SelectOption[] | null, options: SelectOptionOptions = {}): Promise { - return this._frame.selectOption(this._selector, values, { strict: true, ...options }); + return await this._frame.selectOption(this._selector, values, { strict: true, ...options }); } async selectText(options: channels.ElementHandleSelectTextOptions = {}): Promise { - return this._withElement((h, timeout) => h.selectText({ ...options, timeout }), options.timeout); + return await this._withElement((h, timeout) => h.selectText({ ...options, timeout }), options.timeout); } async setChecked(checked: boolean, options?: channels.ElementHandleCheckOptions) { @@ -300,27 +300,27 @@ export class Locator implements api.Locator { } async setInputFiles(files: string | FilePayload | string[] | FilePayload[], options: channels.ElementHandleSetInputFilesOptions = {}) { - return this._frame.setInputFiles(this._selector, files, { strict: true, ...options }); + return await this._frame.setInputFiles(this._selector, files, { strict: true, ...options }); } async tap(options: channels.ElementHandleTapOptions = {}): Promise { - return this._frame.tap(this._selector, { strict: true, ...options }); + return await this._frame.tap(this._selector, { strict: true, ...options }); } async textContent(options?: TimeoutOptions): Promise { - return this._frame.textContent(this._selector, { strict: true, ...options }); + return await this._frame.textContent(this._selector, { strict: true, ...options }); } async type(text: string, options: channels.ElementHandleTypeOptions = {}): Promise { - return this._frame.type(this._selector, text, { strict: true, ...options }); + return await this._frame.type(this._selector, text, { strict: true, ...options }); } async pressSequentially(text: string, options: channels.ElementHandleTypeOptions = {}): Promise { - return this.type(text, options); + return await this.type(text, options); } async uncheck(options: channels.ElementHandleUncheckOptions = {}) { - return this._frame.uncheck(this._selector, { strict: true, ...options }); + return await this._frame.uncheck(this._selector, { strict: true, ...options }); } async all(): Promise { @@ -328,11 +328,11 @@ export class Locator implements api.Locator { } async allInnerTexts(): Promise { - return this._frame.$$eval(this._selector, ee => ee.map(e => (e as HTMLElement).innerText)); + return await this._frame.$$eval(this._selector, ee => ee.map(e => (e as HTMLElement).innerText)); } async allTextContents(): Promise { - return this._frame.$$eval(this._selector, ee => ee.map(e => e.textContent || '')); + return await this._frame.$$eval(this._selector, ee => ee.map(e => e.textContent || '')); } waitFor(options: channels.FrameWaitForSelectorOptions & { state: 'attached' | 'visible' }): Promise; diff --git a/packages/playwright-core/src/client/network.ts b/packages/playwright-core/src/client/network.ts index 2d3a51943d..73a24034a3 100644 --- a/packages/playwright-core/src/client/network.ts +++ b/packages/playwright-core/src/client/network.ts @@ -159,16 +159,16 @@ export class Request extends ChannelOwner implements ap return this._provisionalHeaders.headers(); } - _actualHeaders(): Promise { + async _actualHeaders(): Promise { if (this._fallbackOverrides.headers) - return Promise.resolve(RawHeaders._fromHeadersObjectLossy(this._fallbackOverrides.headers)); + return RawHeaders._fromHeadersObjectLossy(this._fallbackOverrides.headers); if (!this._actualHeadersPromise) { this._actualHeadersPromise = this._wrapApiCall(async () => { return new RawHeaders((await this._channel.rawRequestHeaders()).headers); }); } - return this._actualHeadersPromise; + return await this._actualHeadersPromise; } async allHeaders(): Promise { @@ -188,7 +188,7 @@ export class Request extends ChannelOwner implements ap } async _internalResponse(): Promise { - return this._wrapApiCall(async () => { + return await this._wrapApiCall(async () => { return Response.fromNullable((await this._channel.response()).response); }, true); } @@ -300,16 +300,16 @@ export class Route extends ChannelOwner implements api.Ro return Request.from(this._initializer.request); } - private _raceWithTargetClose(promise: Promise): Promise { + private async _raceWithTargetClose(promise: Promise): Promise { // When page closes or crashes, we catch any potential rejects from this Route. // Note that page could be missing when routing popup's initial request that // does not have a Page initialized just yet. - return this.request()._targetClosedScope().safeRace(promise); + return await this.request()._targetClosedScope().safeRace(promise); } - _startHandling(): Promise { + async _startHandling(): Promise { this._handlingPromise = new ManualPromise(); - return this._handlingPromise; + return await this._handlingPromise; } async fallback(options: FallbackOverrides = {}) { @@ -332,7 +332,7 @@ export class Route extends ChannelOwner implements api.Ro async fetch(options: FallbackOverrides & { maxRedirects?: number, timeout?: number } = {}): Promise { return await this._wrapApiCall(async () => { - return this._context.request._innerFetch({ request: this.request(), data: options.postData, ...options }); + return await this._context.request._innerFetch({ request: this.request(), data: options.postData, ...options }); }); } @@ -522,7 +522,7 @@ export class Response extends ChannelOwner implements return new RawHeaders((await this._channel.rawResponseHeaders()).headers); })(); } - return this._actualHeadersPromise; + return await this._actualHeadersPromise; } async allHeaders(): Promise { @@ -542,7 +542,7 @@ export class Response extends ChannelOwner implements } async finished(): Promise { - return this.request()._targetClosedScope().race(this._finishedPromise); + return await this.request()._targetClosedScope().race(this._finishedPromise); } async body(): Promise { @@ -616,7 +616,7 @@ export class WebSocket extends ChannelOwner implement } async waitForEvent(event: string, optionsOrPredicate: WaitForEventOptions = {}): Promise { - return this._wrapApiCall(async () => { + return await this._wrapApiCall(async () => { const timeout = this._page._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate); const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate; const waiter = Waiter.createForEvent(this, event); diff --git a/packages/playwright-core/src/client/page.ts b/packages/playwright-core/src/client/page.ts index 0ed6c300b1..17b63636f3 100644 --- a/packages/playwright-core/src/client/page.ts +++ b/packages/playwright-core/src/client/page.ts @@ -281,44 +281,44 @@ export class Page extends ChannelOwner implements api.Page } async $(selector: string, options?: { strict?: boolean }): Promise | null> { - return this._mainFrame.$(selector, options); + return await this._mainFrame.$(selector, options); } waitForSelector(selector: string, options: channels.FrameWaitForSelectorOptions & { state: 'attached' | 'visible' }): Promise>; waitForSelector(selector: string, options?: channels.FrameWaitForSelectorOptions): Promise | null>; async waitForSelector(selector: string, options?: channels.FrameWaitForSelectorOptions): Promise | null> { - return this._mainFrame.waitForSelector(selector, options); + return await this._mainFrame.waitForSelector(selector, options); } async dispatchEvent(selector: string, type: string, eventInit?: any, options?: channels.FrameDispatchEventOptions): Promise { - return this._mainFrame.dispatchEvent(selector, type, eventInit, options); + return await this._mainFrame.dispatchEvent(selector, type, eventInit, options); } async evaluateHandle(pageFunction: structs.PageFunction, arg?: Arg): Promise> { assertMaxArguments(arguments.length, 2); - return this._mainFrame.evaluateHandle(pageFunction, arg); + return await this._mainFrame.evaluateHandle(pageFunction, arg); } async $eval(selector: string, pageFunction: structs.PageFunctionOn, arg?: Arg): Promise { assertMaxArguments(arguments.length, 3); - return this._mainFrame.$eval(selector, pageFunction, arg); + return await this._mainFrame.$eval(selector, pageFunction, arg); } async $$eval(selector: string, pageFunction: structs.PageFunctionOn, arg?: Arg): Promise { assertMaxArguments(arguments.length, 3); - return this._mainFrame.$$eval(selector, pageFunction, arg); + return await this._mainFrame.$$eval(selector, pageFunction, arg); } async $$(selector: string): Promise[]> { - return this._mainFrame.$$(selector); + return await this._mainFrame.$$(selector); } async addScriptTag(options: { url?: string; path?: string; content?: string; type?: string; } = {}): Promise { - return this._mainFrame.addScriptTag(options); + return await this._mainFrame.addScriptTag(options); } async addStyleTag(options: { url?: string; path?: string; content?: string; } = {}): Promise { - return this._mainFrame.addStyleTag(options); + return await this._mainFrame.addStyleTag(options); } async exposeFunction(name: string, callback: Function) { @@ -342,15 +342,15 @@ export class Page extends ChannelOwner implements api.Page } async content(): Promise { - return this._mainFrame.content(); + return await this._mainFrame.content(); } async setContent(html: string, options?: channels.FrameSetContentOptions): Promise { - return this._mainFrame.setContent(html, options); + return await this._mainFrame.setContent(html, options); } async goto(url: string, options?: channels.FrameGotoOptions): Promise { - return this._mainFrame.goto(url, options); + return await this._mainFrame.goto(url, options); } async reload(options: channels.PageReloadOptions = {}): Promise { @@ -359,41 +359,41 @@ export class Page extends ChannelOwner implements api.Page } async waitForLoadState(state?: LifecycleEvent, options?: { timeout?: number }): Promise { - return this._mainFrame.waitForLoadState(state, options); + return await this._mainFrame.waitForLoadState(state, options); } async waitForNavigation(options?: WaitForNavigationOptions): Promise { - return this._mainFrame.waitForNavigation(options); + return await this._mainFrame.waitForNavigation(options); } async waitForURL(url: URLMatch, options?: { waitUntil?: LifecycleEvent, timeout?: number }): Promise { - return this._mainFrame.waitForURL(url, options); + return await this._mainFrame.waitForURL(url, options); } async waitForRequest(urlOrPredicate: string | RegExp | ((r: Request) => boolean | Promise), options: { timeout?: number } = {}): Promise { - const predicate = (request: Request) => { + const predicate = async (request: Request) => { if (isString(urlOrPredicate) || isRegExp(urlOrPredicate)) return urlMatches(this._browserContext._options.baseURL, request.url(), urlOrPredicate); - return urlOrPredicate(request); + return await urlOrPredicate(request); }; const trimmedUrl = trimUrl(urlOrPredicate); const logLine = trimmedUrl ? `waiting for request ${trimmedUrl}` : undefined; - return this._waitForEvent(Events.Page.Request, { predicate, timeout: options.timeout }, logLine); + return await this._waitForEvent(Events.Page.Request, { predicate, timeout: options.timeout }, logLine); } async waitForResponse(urlOrPredicate: string | RegExp | ((r: Response) => boolean | Promise), options: { timeout?: number } = {}): Promise { - const predicate = (response: Response) => { + const predicate = async (response: Response) => { if (isString(urlOrPredicate) || isRegExp(urlOrPredicate)) return urlMatches(this._browserContext._options.baseURL, response.url(), urlOrPredicate); - return urlOrPredicate(response); + return await urlOrPredicate(response); }; const trimmedUrl = trimUrl(urlOrPredicate); const logLine = trimmedUrl ? `waiting for response ${trimmedUrl}` : undefined; - return this._waitForEvent(Events.Page.Response, { predicate, timeout: options.timeout }, logLine); + return await this._waitForEvent(Events.Page.Response, { predicate, timeout: options.timeout }, logLine); } async waitForEvent(event: string, optionsOrPredicate: WaitForEventOptions = {}): Promise { - return this._waitForEvent(event, optionsOrPredicate, `waiting for event "${event}"`); + return await this._waitForEvent(event, optionsOrPredicate, `waiting for event "${event}"`); } _closeErrorWithReason(): TargetClosedError { @@ -401,7 +401,7 @@ export class Page extends ChannelOwner implements api.Page } private async _waitForEvent(event: string, optionsOrPredicate: WaitForEventOptions, logLine?: string): Promise { - return this._wrapApiCall(async () => { + return await this._wrapApiCall(async () => { const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate); const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate; const waiter = Waiter.createForEvent(this, event); @@ -448,7 +448,7 @@ export class Page extends ChannelOwner implements api.Page async evaluate(pageFunction: structs.PageFunction, arg?: Arg): Promise { assertMaxArguments(arguments.length, 2); - return this._mainFrame.evaluate(pageFunction, arg); + return await this._mainFrame.evaluate(pageFunction, arg); } async addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any) { @@ -529,7 +529,7 @@ export class Page extends ChannelOwner implements api.Page } async title(): Promise { - return this._mainFrame.title(); + return await this._mainFrame.title(); } async bringToFront(): Promise { @@ -568,23 +568,23 @@ export class Page extends ChannelOwner implements api.Page } async click(selector: string, options?: channels.FrameClickOptions) { - return this._mainFrame.click(selector, options); + return await this._mainFrame.click(selector, options); } async dragAndDrop(source: string, target: string, options?: channels.FrameDragAndDropOptions) { - return this._mainFrame.dragAndDrop(source, target, options); + return await this._mainFrame.dragAndDrop(source, target, options); } async dblclick(selector: string, options?: channels.FrameDblclickOptions) { - return this._mainFrame.dblclick(selector, options); + return await this._mainFrame.dblclick(selector, options); } async tap(selector: string, options?: channels.FrameTapOptions) { - return this._mainFrame.tap(selector, options); + return await this._mainFrame.tap(selector, options); } async fill(selector: string, value: string, options?: channels.FrameFillOptions) { - return this._mainFrame.fill(selector, value, options); + return await this._mainFrame.fill(selector, value, options); } locator(selector: string, options?: LocatorOptions): Locator { @@ -624,91 +624,91 @@ export class Page extends ChannelOwner implements api.Page } async focus(selector: string, options?: channels.FrameFocusOptions) { - return this._mainFrame.focus(selector, options); + return await this._mainFrame.focus(selector, options); } async textContent(selector: string, options?: channels.FrameTextContentOptions): Promise { - return this._mainFrame.textContent(selector, options); + return await this._mainFrame.textContent(selector, options); } async innerText(selector: string, options?: channels.FrameInnerTextOptions): Promise { - return this._mainFrame.innerText(selector, options); + return await this._mainFrame.innerText(selector, options); } async innerHTML(selector: string, options?: channels.FrameInnerHTMLOptions): Promise { - return this._mainFrame.innerHTML(selector, options); + return await this._mainFrame.innerHTML(selector, options); } async getAttribute(selector: string, name: string, options?: channels.FrameGetAttributeOptions): Promise { - return this._mainFrame.getAttribute(selector, name, options); + return await this._mainFrame.getAttribute(selector, name, options); } async inputValue(selector: string, options?: channels.FrameInputValueOptions): Promise { - return this._mainFrame.inputValue(selector, options); + return await this._mainFrame.inputValue(selector, options); } async isChecked(selector: string, options?: channels.FrameIsCheckedOptions): Promise { - return this._mainFrame.isChecked(selector, options); + return await this._mainFrame.isChecked(selector, options); } async isDisabled(selector: string, options?: channels.FrameIsDisabledOptions): Promise { - return this._mainFrame.isDisabled(selector, options); + return await this._mainFrame.isDisabled(selector, options); } async isEditable(selector: string, options?: channels.FrameIsEditableOptions): Promise { - return this._mainFrame.isEditable(selector, options); + return await this._mainFrame.isEditable(selector, options); } async isEnabled(selector: string, options?: channels.FrameIsEnabledOptions): Promise { - return this._mainFrame.isEnabled(selector, options); + return await this._mainFrame.isEnabled(selector, options); } async isHidden(selector: string, options?: channels.FrameIsHiddenOptions): Promise { - return this._mainFrame.isHidden(selector, options); + return await this._mainFrame.isHidden(selector, options); } async isVisible(selector: string, options?: channels.FrameIsVisibleOptions): Promise { - return this._mainFrame.isVisible(selector, options); + return await this._mainFrame.isVisible(selector, options); } async hover(selector: string, options?: channels.FrameHoverOptions) { - return this._mainFrame.hover(selector, options); + return await this._mainFrame.hover(selector, options); } async selectOption(selector: string, values: string | api.ElementHandle | SelectOption | string[] | api.ElementHandle[] | SelectOption[] | null, options?: SelectOptionOptions): Promise { - return this._mainFrame.selectOption(selector, values, options); + return await this._mainFrame.selectOption(selector, values, options); } async setInputFiles(selector: string, files: string | FilePayload | string[] | FilePayload[], options?: channels.FrameSetInputFilesOptions): Promise { - return this._mainFrame.setInputFiles(selector, files, options); + return await this._mainFrame.setInputFiles(selector, files, options); } async type(selector: string, text: string, options?: channels.FrameTypeOptions) { - return this._mainFrame.type(selector, text, options); + return await this._mainFrame.type(selector, text, options); } async press(selector: string, key: string, options?: channels.FramePressOptions) { - return this._mainFrame.press(selector, key, options); + return await this._mainFrame.press(selector, key, options); } async check(selector: string, options?: channels.FrameCheckOptions) { - return this._mainFrame.check(selector, options); + return await this._mainFrame.check(selector, options); } async uncheck(selector: string, options?: channels.FrameUncheckOptions) { - return this._mainFrame.uncheck(selector, options); + return await this._mainFrame.uncheck(selector, options); } async setChecked(selector: string, checked: boolean, options?: channels.FrameCheckOptions) { - return this._mainFrame.setChecked(selector, checked, options); + return await this._mainFrame.setChecked(selector, checked, options); } async waitForTimeout(timeout: number) { - return this._mainFrame.waitForTimeout(timeout); + return await this._mainFrame.waitForTimeout(timeout); } async waitForFunction(pageFunction: structs.PageFunction, arg?: Arg, options?: WaitForFunctionOptions): Promise> { - return this._mainFrame.waitForFunction(pageFunction, arg, options); + return await this._mainFrame.waitForFunction(pageFunction, arg, options); } workers(): Worker[] { diff --git a/packages/playwright-core/src/client/video.ts b/packages/playwright-core/src/client/video.ts index 6c64a87be8..08c39d4247 100644 --- a/packages/playwright-core/src/client/video.ts +++ b/packages/playwright-core/src/client/video.ts @@ -47,7 +47,7 @@ export class Video implements api.Video { const artifact = await this._artifact; if (!artifact) throw new Error('Page did not produce any video frames'); - return artifact.saveAs(path); + return await artifact.saveAs(path); } async delete(): Promise { diff --git a/packages/playwright-core/src/client/waiter.ts b/packages/playwright-core/src/client/waiter.ts index dbdefc5888..1b3ffbe78d 100644 --- a/packages/playwright-core/src/client/waiter.ts +++ b/packages/playwright-core/src/client/waiter.ts @@ -47,7 +47,7 @@ export class Waiter { async waitForEvent(emitter: EventEmitter, event: string, predicate?: (arg: T) => boolean | Promise): Promise { const { promise, dispose } = waitForEvent(emitter, event, predicate); - return this.waitForPromise(promise, dispose); + return await this.waitForPromise(promise, dispose); } rejectOnEvent(emitter: EventEmitter, event: string, error: Error | (() => Error), predicate?: (arg: T) => boolean | Promise) { diff --git a/tests/library/tracing.spec.ts b/tests/library/tracing.spec.ts index 2c85afbd28..61331fc5fe 100644 --- a/tests/library/tracing.spec.ts +++ b/tests/library/tracing.spec.ts @@ -25,7 +25,7 @@ import { artifactsFolderName } from '../../packages/playwright/src/isomorphic/fo test.skip(({ trace }) => trace === 'on'); -test('should collect trace with resources, but no js', async ({ context, page, server }, testInfo) => { +test('should collect trace with resources, but no js', async ({ context, page, server, asset }, testInfo) => { await context.tracing.start({ screenshots: true, snapshots: true }); await page.goto(server.PREFIX + '/frames/frame.html'); await page.setContent(''); @@ -33,6 +33,8 @@ test('should collect trace with resources, but no js', async ({ context, page, s await page.mouse.move(20, 20); await page.mouse.dblclick(30, 30); await page.keyboard.insertText('abc'); + await page.goto(server.PREFIX + '/input/fileupload.html'); + await page.locator('input[type="file"]').setInputFiles(asset('file-to-upload.txt')); await page.waitForTimeout(2000); // Give it some time to produce screenshots. await page.close(); await context.tracing.stop({ path: testInfo.outputPath('trace.zip') }); @@ -46,6 +48,8 @@ test('should collect trace with resources, but no js', async ({ context, page, s 'mouse.move', 'mouse.dblclick', 'keyboard.insertText', + 'page.goto', + 'locator.setInputFiles', 'page.waitForTimeout', 'page.close', ]); diff --git a/utils/eslint-plugin-internal-playwright/index.js b/utils/eslint-plugin-internal-playwright/index.js new file mode 100644 index 0000000000..20deef8cc4 --- /dev/null +++ b/utils/eslint-plugin-internal-playwright/index.js @@ -0,0 +1,20 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +module.exports = { + rules: { + 'await-promise-in-class-returns': require('./rules/await-promise-in-class-returns'), + } +}; diff --git a/utils/eslint-plugin-internal-playwright/package.json b/utils/eslint-plugin-internal-playwright/package.json new file mode 100644 index 0000000000..c6de47abf7 --- /dev/null +++ b/utils/eslint-plugin-internal-playwright/package.json @@ -0,0 +1,5 @@ +{ + "name": "eslint-plugin-internal-playwright", + "version": "0.0.1", + "main": "index.js" +} diff --git a/utils/eslint-plugin-internal-playwright/rules/await-promise-in-class-returns.js b/utils/eslint-plugin-internal-playwright/rules/await-promise-in-class-returns.js new file mode 100644 index 0000000000..a71412c617 --- /dev/null +++ b/utils/eslint-plugin-internal-playwright/rules/await-promise-in-class-returns.js @@ -0,0 +1,54 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const { ESLintUtils } = require('@typescript-eslint/utils'); +const tsutils = require('ts-api-utils'); + +module.exports = { + meta: { + type: 'problem', + docs: { + description: 'ensure that return statements in classes await their promises so we always have the full stack trace in channel owners/tracing apiName extraction', + category: 'Best Practices', + recommended: false, + }, + schema: [], + fixable: 'code', + }, + create(context) { + const parserServices = ESLintUtils.getParserServices(context); + return { + 'ClassDeclaration MethodDefinition ReturnStatement': function (statement) { + if (statement.type === 'ReturnStatement' && statement.argument) { + if (tsutils.isThenableType( + parserServices.program.getTypeChecker(), + statement.argument, + parserServices.getTypeAtLocation(statement.argument) + )) { + context.report({ + node: statement, + message: 'Return statement in a class should await a promise so we are able to extract the whole stack trace when reporting it to e.g. Trace Viewer', + fix(fixer) { + const sourceCode = context.getSourceCode(); + const returnKeyword = sourceCode.getFirstToken(statement); + return fixer.insertTextAfter(returnKeyword, ' await'); + } + }); + } + } + }, + }; + }, +};