diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..9bef7d23 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +**/dist/ +e2e/browser/test-app/ diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..1e118e1b --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,8 @@ +require("@rushstack/eslint-patch/modern-module-resolution"); + +module.exports = { + extends: ["@inrupt/eslint-config-lib"], + rules: { + "import/prefer-default-export": "off" + } +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b7eb9e84..08ef9b0c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,11 @@ on: [push] env: CI: true jobs: + lint: + uses: ./.github/workflows/reusable-lint.yml + with: + build: true + build: runs-on: ${{ matrix.os }} environment: diff --git a/.github/workflows/reusable-lint.yml b/.github/workflows/reusable-lint.yml index 412f9864..e6a5c18b 100644 --- a/.github/workflows/reusable-lint.yml +++ b/.github/workflows/reusable-lint.yml @@ -11,7 +11,7 @@ on: required: false default: false type: boolean - + jobs: lint: runs-on: ubuntu-latest diff --git a/eslint-configs/eslint-config-base/index.js b/eslint-configs/eslint-config-base/index.js index f2923d94..666dfebb 100644 --- a/eslint-configs/eslint-config-base/index.js +++ b/eslint-configs/eslint-config-base/index.js @@ -1,23 +1,23 @@ -/* -Copyright Inrupt Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the -Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ +// +// Copyright Inrupt Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// module.exports = { env: { @@ -44,6 +44,7 @@ module.exports = { }, }, jest: { + // eslint-disable-next-line global-require, @typescript-eslint/no-var-requires, import/extensions version: require("jest/package.json").version, }, }, diff --git a/eslint-configs/eslint-config-lib/index.js b/eslint-configs/eslint-config-lib/index.js index 42cea63b..e52a61aa 100644 --- a/eslint-configs/eslint-config-lib/index.js +++ b/eslint-configs/eslint-config-lib/index.js @@ -1,23 +1,23 @@ -/* -Copyright Inrupt Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the -Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ +// +// Copyright Inrupt Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// module.exports = { extends: [ @@ -73,7 +73,10 @@ module.exports = { // import type { Term } from '@rdfjs/types'; // ``` // - "@typescript-eslint/consistent-type-imports": ["error", { prefer: "type-imports" }], + "@typescript-eslint/consistent-type-imports": [ + "error", + { prefer: "type-imports" }, + ], }, }, ], diff --git a/eslint-configs/eslint-config-react/index.js b/eslint-configs/eslint-config-react/index.js index 52b70097..d4f9c5f0 100644 --- a/eslint-configs/eslint-config-react/index.js +++ b/eslint-configs/eslint-config-react/index.js @@ -1,23 +1,23 @@ -/* -Copyright Inrupt Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the -Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ +// +// Copyright Inrupt Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// module.exports = { extends: ["airbnb", "airbnb/hooks", "@inrupt/eslint-config-base"], diff --git a/package-lock.json b/package-lock.json index 8ae5d035..c27b2fb6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "packages/*" ], "dependencies": { + "@inrupt/eslint-config-lib": "^2.1.1", "lerna": "^7.1.4", "rimraf": "^5.0.1", "rollup": "^3.27.0", @@ -20,6 +21,7 @@ "typescript": "^5.1.3" }, "devDependencies": { + "@rushstack/eslint-patch": "^1.3.2", "@types/react": "^18.2.18", "next": "^13.4.12" } @@ -2319,9 +2321,9 @@ } }, "node_modules/@rushstack/eslint-patch": { - "version": "1.1.4", - "license": "MIT", - "peer": true + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.2.tgz", + "integrity": "sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==" }, "node_modules/@sigstore/bundle": { "version": "1.0.0", @@ -14609,8 +14611,9 @@ } }, "@rushstack/eslint-patch": { - "version": "1.1.4", - "peer": true + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.2.tgz", + "integrity": "sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==" }, "@sigstore/bundle": { "version": "1.0.0", diff --git a/package.json b/package.json index be2a9ed6..5113e5f3 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,12 @@ "release": "scripts/release.sh", "test": "playwright test", "e2e:test:setup": "cd ./e2e/browser/test-app && npm ci", - "prepare-release": "scripts/prepare-release.sh" + "prepare-release": "scripts/prepare-release.sh", + "lint": "npm run lint:check", + "lint:check": "npm run lint:eslint && npm run lint:prettier -- --check", + "lint:eslint": "eslint --config .eslintrc.js \"packages/\" \"e2e/\" \"eslint-configs/\"", + "lint:prettier": "prettier \"{src,e2e,examples}/**/*.{ts,tsx,js,jsx,css}\" \"**/*.{md,mdx,yml}\"", + "lint:fix": "npm run lint:eslint -- --fix && npm run lint:prettier -- --write" }, "workspaces": [ "eslint-configs/*", @@ -27,6 +32,7 @@ }, "homepage": "https://github.com/inrupt/typescript-sdk-tools#readme", "dependencies": { + "@inrupt/eslint-config-lib": "^2.1.1", "lerna": "^7.1.4", "rimraf": "^5.0.1", "rollup": "^3.27.0", @@ -34,6 +40,7 @@ "typescript": "^5.1.3" }, "devDependencies": { + "@rushstack/eslint-patch": "^1.3.2", "@types/react": "^18.2.18", "next": "^13.4.12" } diff --git a/packages/internal-playwright-helpers/README.md b/packages/internal-playwright-helpers/README.md index 8f78cd0f..3a18847b 100644 --- a/packages/internal-playwright-helpers/README.md +++ b/packages/internal-playwright-helpers/README.md @@ -19,11 +19,12 @@ Then add in calls to the functions such as `loginAndAllow` to your test files. For these helpers to work, your app should use predefined testids defined in `@@inrupt/internal-playwright-testids`. The following testids are expected in the exposed helpers: -- The OpenID provider should be specified in a text input identified with + +- The OpenID provider should be specified in a text input identified with `TESTID_OPENID_PROVIDER_INPUT`. -- The login should be initiated by clicking a button identified with +- The login should be initiated by clicking a button identified with `TESTID_LOGIN_BUTTON`. -- When the login process is complete, an element identified with +- When the login process is complete, an element identified with `TESTID_SESSION_STATUS` should appear in the DOM. - When an error occurs, an element identified with `TESTID_ERROR_MESSAGE` should appear in the DOM. diff --git a/packages/internal-playwright-helpers/src/fixtures.ts b/packages/internal-playwright-helpers/src/fixtures.ts index bf285a3e..08fd9149 100644 --- a/packages/internal-playwright-helpers/src/fixtures.ts +++ b/packages/internal-playwright-helpers/src/fixtures.ts @@ -1,3 +1,23 @@ +// +// Copyright Inrupt Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// import { test as base } from "@playwright/test"; import { getBrowserTestingEnvironment } from "@inrupt/internal-test-env"; import { AuthFlow } from "./flows/auth"; @@ -10,7 +30,7 @@ export const test = base.extend({ // Override the page fixture to start the app automatically page: async ({ page }, use) => { await page.goto("/"); - use(page); + await use(page); }, auth: async ({ page }, use) => { const { idp, clientCredentials } = getBrowserTestingEnvironment({ diff --git a/packages/internal-playwright-helpers/src/flows/auth.ts b/packages/internal-playwright-helpers/src/flows/auth.ts index 9a69206d..f907efa9 100644 --- a/packages/internal-playwright-helpers/src/flows/auth.ts +++ b/packages/internal-playwright-helpers/src/flows/auth.ts @@ -19,18 +19,26 @@ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -import { Page } from "@playwright/test"; +import type { Page } from "@playwright/test"; import { CognitoPage } from "../pages/cognito"; import { OpenIdPage } from "../pages/open-id"; import { TestPage } from "../pages/testPage"; export class AuthFlow { page: Page; + openidProvider: string; + userLogin: string; + password: string; - constructor(page: Page, openidProvider: string, userLogin: string, password: string) { + constructor( + page: Page, + openidProvider: string, + userLogin: string, + password: string + ) { this.page = page; this.openidProvider = openidProvider; this.userLogin = userLogin; @@ -51,9 +59,9 @@ export class AuthFlow { await testPage.startLogin(); await cognitoPage.login(this.userLogin, this.password); // TODO: handle allow === false - if(options.allow) { + if (options.allow) { await openIdPage.allow(); } await testPage.handleRedirect(); - }; + } } diff --git a/packages/internal-playwright-helpers/src/pages/cognito.ts b/packages/internal-playwright-helpers/src/pages/cognito.ts index 2fa520f5..50107c5c 100644 --- a/packages/internal-playwright-helpers/src/pages/cognito.ts +++ b/packages/internal-playwright-helpers/src/pages/cognito.ts @@ -19,7 +19,7 @@ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -import { Page } from "@playwright/test"; +import type { Page } from "@playwright/test"; /** * Login page exposed by Cognito, the OIDC Provider used for PodSpaces and other @@ -33,13 +33,13 @@ export class CognitoPage { } async login(username: string, password: string) { - await this.page.getByRole('textbox', { name: 'Username' }).fill(username); - await this.page.getByRole('textbox', { name: 'Password' }).fill(password); + await this.page.getByRole("textbox", { name: "Username" }).fill(username); + await this.page.getByRole("textbox", { name: "Password" }).fill(password); await Promise.all([ - // It is important to call waitForURL before click to set up waiting. - this.page.waitForURL(/.*/), - // Clicking the link will indirectly cause a navigation. - this.page.getByRole('button', { name: 'submit' }).click(), + // It is important to call waitForURL before click to set up waiting. + this.page.waitForURL(/.*/), + // Clicking the link will indirectly cause a navigation. + this.page.getByRole("button", { name: "submit" }).click(), ]); } } diff --git a/packages/internal-playwright-helpers/src/pages/open-id.ts b/packages/internal-playwright-helpers/src/pages/open-id.ts index 8304ee8a..58cdc66d 100644 --- a/packages/internal-playwright-helpers/src/pages/open-id.ts +++ b/packages/internal-playwright-helpers/src/pages/open-id.ts @@ -19,10 +19,10 @@ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -import { Page } from "@playwright/test"; +import type { Page } from "@playwright/test"; /** - * The Solid-OIDC Broker exposed by ESS wrapped around an underlying OpenID Provider + * The Solid-OIDC Broker exposed by ESS wrapped around an underlying OpenID Provider */ export class OpenIdPage { page: Page; diff --git a/packages/internal-playwright-helpers/src/pages/testPage.ts b/packages/internal-playwright-helpers/src/pages/testPage.ts index dc3e1258..b216a896 100644 --- a/packages/internal-playwright-helpers/src/pages/testPage.ts +++ b/packages/internal-playwright-helpers/src/pages/testPage.ts @@ -19,13 +19,12 @@ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -import { Page } from "@playwright/test"; -import { - TESTID_SELECTORS -} from "@inrupt/internal-playwright-testids"; +import type { Page } from "@playwright/test"; +import { TESTID_SELECTORS } from "@inrupt/internal-playwright-testids"; export class TestPage { page: Page; + openidProvider: string; constructor(page: Page, openidProvider: string) { diff --git a/packages/internal-playwright-testids/src/index.ts b/packages/internal-playwright-testids/src/index.ts index 616474cd..78344d82 100644 --- a/packages/internal-playwright-testids/src/index.ts +++ b/packages/internal-playwright-testids/src/index.ts @@ -1,3 +1,23 @@ +// +// Copyright Inrupt Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +// Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// export const TESTID_OPENID_PROVIDER_INPUT = "identityProviderInput"; export const TESTID_LOGIN_BUTTON = "loginButton"; export const TESTID_LOGOUT_BUTTON = "logoutButton"; diff --git a/packages/internal-test-env/README.md b/packages/internal-test-env/README.md index 31c5a8da..868626ac 100644 --- a/packages/internal-test-env/README.md +++ b/packages/internal-test-env/README.md @@ -16,12 +16,14 @@ import "@inrupt/internal-test-env" ## Features -This helper exposes the following: -- `getNodeTestingEnvironment` +This helper exposes the following: + +- `getNodeTestingEnvironment` - `getBrowserTestingEnvironment` These two functions will load from the environment variables as follows: -- Some variables will always be loaded and validated if applicable + +- Some variables will always be loaded and validated if applicable - `E2E_TEST_ENVIRONMENT`: name of the target environment, used for information purpose. E.g., `ESS Dev-Next` - `E2E_TEST_IDP`: IRI of the OpenID Provider where the test session will be retrieved. @@ -31,12 +33,12 @@ These two functions will load from the environment variables as follows: value. - Some variables will only be loaded and validated if explicitly requested as part of the `get*TestingEnvironment` call: - - `E2E_TEST_NOTIFICATION_GATEWAY` - - `E2E_TEST_NOTIFICATION_PROTOCOL` - - `E2E_TEST_VC_PROVIDER` - - `E2E_TEST_OWNER_CLIENT_ID` - - `E2E_TEST_OWNER_CLIENT_SECRET` - - `E2E_TEST_REQUESTOR_CLIENT_ID` - - `E2E_TEST_REQUESTOR_CLIENT_SECRET` - - `E2E_TEST_USER` - - `E2E_TEST_PASSWORD` + - `E2E_TEST_NOTIFICATION_GATEWAY` + - `E2E_TEST_NOTIFICATION_PROTOCOL` + - `E2E_TEST_VC_PROVIDER` + - `E2E_TEST_OWNER_CLIENT_ID` + - `E2E_TEST_OWNER_CLIENT_SECRET` + - `E2E_TEST_REQUESTOR_CLIENT_ID` + - `E2E_TEST_REQUESTOR_CLIENT_SECRET` + - `E2E_TEST_USER` + - `E2E_TEST_PASSWORD` diff --git a/packages/internal-test-env/index.ts b/packages/internal-test-env/index.ts index 4d0b8ad2..71370d7a 100644 --- a/packages/internal-test-env/index.ts +++ b/packages/internal-test-env/index.ts @@ -91,6 +91,7 @@ export interface TestingEnvironmentBase { } type FeatureFlags = { + // eslint-disable-next-line @typescript-eslint/no-explicit-any [key: string]: any; }; const ENV_FEATURE_PREFIX = "E2E_TEST_FEATURE_"; @@ -116,6 +117,7 @@ export function setupEnv() { }); if (!process.env.E2E_TEST_ENVIRONMENT) { + // eslint-disable-next-line no-console console.error( `We didn't find the given environment variable E2E_TEST_ENVIRONMENT, tried looking in the following directory for '.env.local': ${envPath}` ); @@ -123,72 +125,6 @@ export function setupEnv() { envLoaded = true; } -function getBaseTestingEnvironment( - libVars?: T -): T extends NodeVariables - ? TestingEnvironmentNode - : TestingEnvironmentBrowser { - setupEnv(); - - // Load and validate target environment name. - const targetEnvName = process.env.E2E_TEST_ENVIRONMENT; - if (!availableEnvironments.includes(targetEnvName as AvailableEnvironments)) { - throw new Error( - `Unknown environment: [${targetEnvName}]\n\nAvailable environments are ${availableEnvironments - .map((env) => `[${env}]`) - .join(", ")}` - ); - } - - // Load and validate target OpenID Provider. - const targetIdp = process.env.E2E_TEST_IDP; - if (typeof targetIdp !== "string" || !isValidUrl(targetIdp)) { - throw new Error( - `The environment variable E2E_TEST_IDP is not a valid URL: found ${targetIdp}.` - ); - } - - // Creating feature flag object if there are feature flags - const features = Object.keys(process.env) - .filter((envVar) => envVar.startsWith(ENV_FEATURE_PREFIX)) - .reduce((featureFlags, envVar) => { - // Trim the prefix from the environment variable name. - const flagName = envVar.substring(ENV_FEATURE_PREFIX.length); - const flagValue = process.env[envVar]; - return { ...featureFlags, [`${flagName}`]: flagValue }; - }, {}); - - const base = { - idp: targetIdp, - environment: targetEnvName, - features, - }; - - return libVars ? merge(base, validateLibVars(libVars)) : base; -} - -export function getNodeTestingEnvironment( - varsToValidate?: LibraryVariables -): TestingEnvironmentNode { - return getBaseTestingEnvironment( - merge(varsToValidate, { - // Enforce client credentials are present for the resource owner. - clientCredentials: { owner: { id: true, secret: true } }, - }) - ); -} - -export function getBrowserTestingEnvironment( - varsToValidate?: LibraryVariables -): TestingEnvironmentBrowser { - return getBaseTestingEnvironment( - merge(varsToValidate, { - // Enforce login/password are present for the resource owner. - clientCredentials: { owner: { login: true, password: true } }, - }) - ); -} - export interface LibraryVariables { notificationGateway?: boolean; notificationProtocol?: boolean; @@ -346,10 +282,76 @@ function validateLibVars(varsToValidate: LibraryVariables): object { }; } +function getBaseTestingEnvironment( + libVars?: T +): T extends NodeVariables + ? TestingEnvironmentNode + : TestingEnvironmentBrowser { + setupEnv(); + + // Load and validate target environment name. + const targetEnvName = process.env.E2E_TEST_ENVIRONMENT; + if (!availableEnvironments.includes(targetEnvName as AvailableEnvironments)) { + throw new Error( + `Unknown environment: [${targetEnvName}]\n\nAvailable environments are ${availableEnvironments + .map((env) => `[${env}]`) + .join(", ")}` + ); + } + + // Load and validate target OpenID Provider. + const targetIdp = process.env.E2E_TEST_IDP; + if (typeof targetIdp !== "string" || !isValidUrl(targetIdp)) { + throw new Error( + `The environment variable E2E_TEST_IDP is not a valid URL: found ${targetIdp}.` + ); + } + + // Creating feature flag object if there are feature flags + const features = Object.keys(process.env) + .filter((envVar) => envVar.startsWith(ENV_FEATURE_PREFIX)) + .reduce((featureFlags, envVar) => { + // Trim the prefix from the environment variable name. + const flagName = envVar.substring(ENV_FEATURE_PREFIX.length); + const flagValue = process.env[envVar]; + return { ...featureFlags, [`${flagName}`]: flagValue }; + }, {}); + + const base = { + idp: targetIdp, + environment: targetEnvName, + features, + }; + + return libVars ? merge(base, validateLibVars(libVars)) : base; +} + +export function getNodeTestingEnvironment( + varsToValidate?: LibraryVariables +): TestingEnvironmentNode { + return getBaseTestingEnvironment( + merge(varsToValidate, { + // Enforce client credentials are present for the resource owner. + clientCredentials: { owner: { id: true, secret: true } }, + }) + ); +} + +export function getBrowserTestingEnvironment( + varsToValidate?: LibraryVariables +): TestingEnvironmentBrowser { + return getBaseTestingEnvironment( + merge(varsToValidate, { + // Enforce login/password are present for the resource owner. + clientCredentials: { owner: { login: true, password: true } }, + }) + ); +} + export async function getAuthenticatedSession( authDetails: TestingEnvironmentNode ): Promise { - const owner = authDetails.clientCredentials.owner; + const { owner } = authDetails.clientCredentials; if (owner.type === "CSS Client Credentials") { return { @@ -357,7 +359,7 @@ export async function getAuthenticatedSession( isLoggedIn: true, // CSS WebIds are always minted in this format // with the configs that are currently available - webId: authDetails.idp + owner.login + "/profile/card#me", + webId: `${authDetails.idp + owner.login}/profile/card#me`, sessionId: "", }, fetch: await getAuthenticatedFetch({ @@ -394,7 +396,7 @@ export async function addCssPimStorage( authDetails: TestingEnvironmentNode ): Promise { const session = await getAuthenticatedSession(authDetails); - const webId = session.info.webId; + const { webId } = session.info; if (!webId) throw new Error("WebId cannot be found in session"); diff --git a/packages/internal-test-env/utils.ts b/packages/internal-test-env/utils.ts index cef8cbc4..0fa70951 100644 --- a/packages/internal-test-env/utils.ts +++ b/packages/internal-test-env/utils.ts @@ -22,6 +22,7 @@ export function isValidUrl(url: string): boolean { try { // Use URL constructor for validation + // eslint-disable-next-line no-new new URL(url); return true; } catch { diff --git a/packages/jest-jsdom-polyfills/index.js b/packages/jest-jsdom-polyfills/index.js index 087b7f42..39a74b70 100644 --- a/packages/jest-jsdom-polyfills/index.js +++ b/packages/jest-jsdom-polyfills/index.js @@ -30,8 +30,6 @@ if ( ) { const utils = require("util"); globalThis.TextEncoder = utils.TextEncoder; - // @ts-ignore TextDecoder from util doesn't necessarily conform to that from - // the Web APIs, but it's good enough: globalThis.TextDecoder = utils.TextDecoder; // TextEncoder references a Uint8Array constructor different than the global // one used by users in tests. The following enforces the same constructor to @@ -45,10 +43,13 @@ if ( // jsdom doesn't implement the subtle Web Crypto API typeof globalThis.crypto.subtle === "undefined" ) { - // Requires OPENSSL_CONF=/dev/null (see https://github.com/nodejs/node/discussions/43184) - const { Crypto, CryptoKey } = require("@peculiar/webcrypto"); - Object.assign(globalThis.crypto, new Crypto()); - globalThis.CryptoKey = CryptoKey; + // Requires OPENSSL_CONF=/dev/null (see https://github.com/nodejs/node/discussions/43184) + const { + Crypto: WCrypto, + CryptoKey: WCryptoKey, + } = require("@peculiar/webcrypto"); + Object.assign(globalThis.crypto, new WCrypto()); + globalThis.CryptoKey = WCryptoKey; } // Node.js doesn't support Blob or File, so we're polyfilling those with @@ -71,9 +72,9 @@ if ( typeof globalThis.Headers === "undefined" || typeof globalThis.fetch === "undefined" ) { - const { Request, Response, Headers, fetch } = require("undici"); - globalThis.Response = Response; - globalThis.Request = Request; - globalThis.Headers = Headers; - globalThis.fetch = fetch; + const undici = require("undici"); + globalThis.Response = undici.Response; + globalThis.Request = undici.Request; + globalThis.Headers = undici.Headers; + globalThis.fetch = undici.fetch; }