From 6aee85aef58ceab19625be6894da42e9728c359a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 29 Apr 2026 15:05:38 +0100 Subject: [PATCH] Fix OIDC login callback handling on Element Desktop (#33332) * Fix OIDC login callback handling on Element Desktop * Add unit tests * Iterate * Fix lcov reporter * Fix coverage paths * Fix coverage upload * Ensure `.test.ts` files don't get included in the desktop package * Fix coverage artifact name * Delint * Tidy coverage name * Improve coverage --- .github/workflows/tests.yml | 36 +++++--- apps/desktop/.eslintrc.cjs | 7 ++ apps/desktop/electron-builder.ts | 3 +- apps/desktop/package.json | 11 ++- apps/desktop/src/protocol.test.ts | 87 +++++++++++++++++ apps/desktop/src/protocol.ts | 25 ++++- apps/desktop/tsconfig.json | 3 +- apps/desktop/tsconfig.node.json | 15 +++ apps/desktop/vitest.config.ts | 64 +++++++++++++ pnpm-lock.yaml | 149 +++++++++++++++++++++++++++++- sonar-project.properties | 27 ++++-- 11 files changed, 395 insertions(+), 32 deletions(-) create mode 100644 apps/desktop/src/protocol.test.ts create mode 100644 apps/desktop/tsconfig.node.json create mode 100644 apps/desktop/vitest.config.ts diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8a237b6950..f365f39531 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -93,7 +93,7 @@ jobs: if: env.ENABLE_COVERAGE == 'true' uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: coverage-${{ matrix.runner }} + name: coverage-jest-${{ matrix.runner }} path: | apps/web/coverage !apps/web/coverage/lcov-report @@ -124,9 +124,10 @@ jobs: name: Vitest strategy: matrix: - package: - - shared-components - - module-api + path: + - apps/desktop + - packages/shared-components + - packages/module-api runs-on: ubuntu-24.04 steps: - name: Checkout code @@ -149,30 +150,39 @@ jobs: uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5 with: path: | - packages/${{ matrix.package }}/node_modules/.cache - packages/${{ matrix.package }}/node_modules/.vite/vitest - key: ${{ hashFiles('pnpm-lock.yaml') }} + ${{ matrix.path }}/node_modules/.cache + ${{ matrix.path }}/node_modules/.vite/vitest + key: ${{ matrix.path }}-${{ hashFiles('pnpm-lock.yaml') }} - name: Setup playwright uses: ./.github/actions/setup-playwright - if: matrix.package == 'shared-components' + if: matrix.path == 'packages/shared-components' with: write-cache: ${{ github.event_name != 'merge_group' }} - name: Run tests - working-directory: "packages/${{ matrix.package }}" + working-directory: ${{ matrix.path }} run: pnpm test:unit --coverage=$ENABLE_COVERAGE # Dump the disk usage on failure, because this job seems to fail with disk fills sometimes - name: df - run: df + run: df -h && df -i if: ${{ failure() }} + - name: Calculate artifact name + if: env.ENABLE_COVERAGE == 'true' + id: artifact + run: | + NAME=$(basename "$MATRIX_PATH") + echo "name=$NAME" >> $GITHUB_OUTPUT + env: + MATRIX_PATH: ${{ matrix.path }} + - name: Upload Artifact if: env.ENABLE_COVERAGE == 'true' uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: coverage-${{ matrix.package }} + name: coverage-${{ steps.artifact.outputs.name }} path: | - packages/${{ matrix.package }}/coverage - !packages/${{ matrix.package }}/coverage/lcov-report + ${{ matrix.path }}/coverage + !${{ matrix.path }}/coverage/lcov-report diff --git a/apps/desktop/.eslintrc.cjs b/apps/desktop/.eslintrc.cjs index d8f162c2f0..7a1d06729c 100644 --- a/apps/desktop/.eslintrc.cjs +++ b/apps/desktop/.eslintrc.cjs @@ -86,5 +86,12 @@ module.exports = { "@typescript-eslint/no-non-null-assertion": "off", }, }, + { + files: ["src/**/*.test.ts", "electron-builder.ts", "vitest.config.ts"], + extends: ["plugin:matrix-org/typescript"], + parserOptions: { + project: ["tsconfig.node.json"], + }, + }, ], }; diff --git a/apps/desktop/electron-builder.ts b/apps/desktop/electron-builder.ts index 967a129c1c..9bcd771a73 100644 --- a/apps/desktop/electron-builder.ts +++ b/apps/desktop/electron-builder.ts @@ -52,6 +52,7 @@ interface Variant extends Metadata { } type Writable = NonNullable< + // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type T extends Function ? T : T extends object ? { -readonly [K in keyof T]: Writable } : T >; @@ -74,7 +75,7 @@ if (process.env.VARIANT_PATH) { } for (const key in variant) { - console.log(`${key}: ${variant[key]}`); + console.log(`${key}: ${variant[key as keyof Variant]}`); } interface Configuration extends BaseConfiguration { diff --git a/apps/desktop/package.json b/apps/desktop/package.json index fdc5fb0a54..f4f065c6ce 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -32,8 +32,9 @@ "lint": "pnpm lint:types && pnpm lint:js", "lint:js": "eslint --max-warnings 0 src hak playwright scripts", "lint:js-fix": "eslint --fix --max-warnings 0 src hak playwright scripts && prettier --log-level=warn --write .", - "lint:types": "pnpm lint:types:src && pnpm lint:types:test && pnpm lint:types:scripts && pnpm lint:types:hak", + "lint:types": "pnpm lint:types:src && pnpm lint:types:node && pnpm lint:types:test && pnpm lint:types:scripts && pnpm lint:types:hak", "lint:types:src": "tsc --noEmit", + "lint:types:node": "tsc --noEmit -p tsconfig.node.json", "lint:types:test": "tsc --noEmit -p playwright/tsconfig.json", "lint:types:scripts": "tsc --noEmit -p scripts/tsconfig.json", "lint:types:hak": "tsc --noEmit -p hak/tsconfig.json", @@ -49,6 +50,7 @@ "docker:install": "scripts/in-docker.sh pnpm install", "clean": "rimraf webapp.asar dist packages deploys lib", "hak": "node scripts/hak/index.ts", + "test:unit": "vitest", "test:playwright": "nx test:playwright --", "test:playwright:open": "nx test:playwright -- --ui", "test:playwright:screenshots": "nx test:playwright:screenshots --", @@ -79,6 +81,7 @@ "@types/pacote": "^11.1.1", "@typescript-eslint/eslint-plugin": "^8.0.0", "@typescript-eslint/parser": "^8.0.0", + "@vitest/coverage-v8": "^4.1.5", "app-builder-lib": "26.9.0", "chokidar": "^5.0.0", "detect-libc": "^2.0.0", @@ -95,12 +98,16 @@ "eslint-plugin-unicorn": "^56.0.0", "glob": "^13.0.0", "matrix-web-i18n": "catalog:", + "memfs": "^4.57.2", "mkdirp": "^3.0.0", "pacote": "^21.0.0", "prettier": "^3.0.0", "rimraf": "^6.0.0", "tar": "^7.5.8", - "typescript": "6.0.3" + "typescript": "6.0.3", + "vite": "^8.0.9", + "vitest": "^4.1.5", + "vitest-sonar-reporter": "^3.0.0" }, "hakDependencies": { "matrix-seshat": "4.2.0" diff --git a/apps/desktop/src/protocol.test.ts b/apps/desktop/src/protocol.test.ts new file mode 100644 index 0000000000..396a59f065 --- /dev/null +++ b/apps/desktop/src/protocol.test.ts @@ -0,0 +1,87 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +import { expect, describe, it, beforeEach, vi } from "vitest"; +import { fs as memfs, vol } from "memfs"; + +import ProtocolHandler from "./protocol.js"; + +const TEST_PROTOCOL = "test.proto"; +const TEST_SESSION_ID = "test_session_id"; +const USER_DATA_DIR = "/Users/name/Library/Application Support/Element"; + +vi.mock("node:fs", () => ({ default: memfs })); +vi.mock("electron", () => ({ + app: { + getPath: vi.fn().mockReturnValue("/Users/name/Library/Application Support/Element"), + on: vi.fn(), + }, + ipcMain: { + handle: vi.fn(), + }, +})); + +beforeEach(() => { + // Reset the state of the in-memory fs + vol.reset(); +}); + +describe("ProtocolHandler", () => { + describe("getProfileFromDeeplink", () => { + const handler = new ProtocolHandler(TEST_PROTOCOL); + + beforeEach(() => { + vol.fromJSON( + { + "./sso-sessions.json": JSON.stringify({ [TEST_SESSION_ID]: USER_DATA_DIR }), + }, + USER_DATA_DIR, + ); + }); + + it("should handle legacy SSO URIs", () => { + expect( + handler.getProfileFromDeeplink([ + "Element.app", + `element://vector/webapp/?element-desktop-ssoid=${TEST_SESSION_ID}`, + ]), + ).toBe(USER_DATA_DIR); + }); + + it("should handle OIDC URIs with response_mode=query", () => { + expect( + handler.getProfileFromDeeplink([ + "Element.app", + `${TEST_PROTOCOL}:/vector/webapp/?no_universal_links=true&code=DEADBEEF&state=foobar:element-desktop-ssoid:${TEST_SESSION_ID}`, + ]), + ).toBe(USER_DATA_DIR); + }); + + it("should handle OIDC URIs with response_mode=fragment", () => { + expect( + handler.getProfileFromDeeplink([ + "Element.app", + `${TEST_PROTOCOL}:/vector/webapp/?no_universal_links=true#code=DEADBEEF&state=foobar:element-desktop-ssoid:${TEST_SESSION_ID}`, + ]), + ).toBe(USER_DATA_DIR); + }); + + it("should handle malformed OIDC URIs gracefully", () => { + expect( + handler.getProfileFromDeeplink([ + "Element.app", + `${TEST_PROTOCOL}:/vector/webapp/?no_universal_links=true#code=DEADBEEF:element-desktop-ssoid:${TEST_SESSION_ID}`, + ]), + ).toBeUndefined(); + }); + + it("should handle unrelated URIs gracefully", () => { + expect(handler.getProfileFromDeeplink(["Element.app", `${TEST_PROTOCOL}:/vector/webapp/`])).toBeUndefined(); + expect(handler.getProfileFromDeeplink(["Element.app", `test.unrelated:/vector/webapp/`])).toBeUndefined(); + }); + }); +}); diff --git a/apps/desktop/src/protocol.ts b/apps/desktop/src/protocol.ts index f6812b49e6..ad2558fc2a 100644 --- a/apps/desktop/src/protocol.ts +++ b/apps/desktop/src/protocol.ts @@ -97,7 +97,8 @@ export default class ProtocolHandler { const s = fs.readFileSync(storePath, { encoding: "utf8" }); const o = JSON.parse(s); return typeof o === "object" ? o : {}; - } catch { + } catch (e) { + console.warn("Unable to read protocol store, starting with empty store: ", e); return {}; } } @@ -130,10 +131,26 @@ export default class ProtocolHandler { let sessionId = parsedUrl.searchParams.get(SEARCH_PARAM); if (!sessionId) { // In OIDC, we must shuttle the value in the `state` param rather than `element-desktop-ssoid` - // We encode it as a suffix like `:element-desktop-ssoid:XXYYZZ` - sessionId = parsedUrl.searchParams.get("state")!.split(`:${SEARCH_PARAM}:`)[1]; + // We encode it as a suffix like `:element-desktop-ssoid:XXYYZZ`. + // The OIDC flow may have used response_mode=fragment or query, so we need to handle both cases. + let searchParams = parsedUrl.searchParams; + if (parsedUrl.hash.includes("=")) { + const [params] = parsedUrl.hash.substring(1).split("?", 2); + searchParams = new URLSearchParams(params); + } + + const state = searchParams.get("state"); + if (state) { + sessionId = state.split(`:${SEARCH_PARAM}:`)[1]; + } } - console.log("Forwarding to profile: ", store[sessionId]); + + if (!sessionId) { + console.warn("Unable to read session ID in deeplink url:", deeplinkUrl); + return undefined; + } + + console.log("Forwarding to profile:", store[sessionId]); return store[sessionId]; } } diff --git a/apps/desktop/tsconfig.json b/apps/desktop/tsconfig.json index e0490357fc..5993a344e6 100644 --- a/apps/desktop/tsconfig.json +++ b/apps/desktop/tsconfig.json @@ -14,5 +14,6 @@ "lib": ["es2022", "es2024.promise"], "strict": true }, - "include": ["./src/**/*.ts", "./src/**/*.cts"] + "include": ["./src/**/*.ts", "./src/**/*.cts"], + "exclude": ["./src/**/*.test.ts"] } diff --git a/apps/desktop/tsconfig.node.json b/apps/desktop/tsconfig.node.json new file mode 100644 index 0000000000..c9de5ead8d --- /dev/null +++ b/apps/desktop/tsconfig.node.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "resolveJsonModule": true, + "module": "nodenext", + "moduleResolution": "NodeNext", + "target": "es2022", + "sourceMap": false, + "typeRoots": [], + "types": [], + "skipLibCheck": true, + "noEmit": true, + "strict": true + }, + "include": ["./electron-builder.ts", "./vitest.config.ts", "./src/**/*.d.ts", "./src/**/*.test.ts"] +} diff --git a/apps/desktop/vitest.config.ts b/apps/desktop/vitest.config.ts new file mode 100644 index 0000000000..1d9e9f179c --- /dev/null +++ b/apps/desktop/vitest.config.ts @@ -0,0 +1,64 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +import { defineConfig } from "vitest/config"; +import { type UserConfig } from "vite"; +import { type Reporter } from "vitest/reporters"; +import { env } from "node:process"; + +const reporters: NonNullable["reporters"] = [["default"]]; + +const slowTestReporter: Reporter = { + onTestRunEnd(testModules, unhandledErrors, reason) { + const tests = testModules + .flatMap((m) => Array.from(m.children.allTests())) + .filter((test) => test.diagnostic()?.slow); + tests.sort((x, y) => x.diagnostic()!.duration! - y.diagnostic()!.duration!); + tests.reverse(); + + if (tests.length > 0) { + console.warn("Slowest 10 tests:"); + } + for (const t of tests.slice(0, 10)) { + console.warn(`${t.module.moduleId} > ${t.fullName}: ${t.diagnostic()?.duration.toFixed(0)}ms`); + } + }, +}; + +// if we're running under GHA, enable the GHA & Sonar reporters +if (env["GITHUB_ACTIONS"] !== undefined) { + reporters.push(["github-actions", { silent: false }]); + reporters.push([ + "vitest-sonar-reporter", + { + outputFile: "coverage/sonar-report.xml", + onWritePath: (path): string => `apps/desktop/${path}`, + }, + ]); + + // if we're running against the develop branch, also enable the slow test reporter + if (env["GITHUB_REF"] == "refs/heads/develop") { + reporters.push(slowTestReporter); + } +} + +export default defineConfig({ + test: { + coverage: { + provider: "v8", + include: ["src/**/*"], + // The coverage report currently chokes on this file as it doesn't process it as TypeScript + exclude: ["src/preload.cts"], + reporter: [["lcov", { projectRoot: "../../" }]], + }, + environment: "node", + reporters, + globals: true, + pool: "threads", + include: ["src/**/*.test.ts"], + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7ffc755483..0e54938527 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -243,6 +243,9 @@ importers: '@typescript-eslint/parser': specifier: ^8.0.0 version: 8.58.2(eslint@8.57.1)(typescript@6.0.3) + '@vitest/coverage-v8': + specifier: ^4.1.5 + version: 4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5) app-builder-lib: specifier: 26.9.0 version: 26.9.0(patch_hash=2dfb3fcdfe573cca6c248cecf63ddea5c8fa0276859695fba6c9664d0ff285d6)(dmg-builder@26.9.0)(electron-builder-squirrel-windows@26.9.0) @@ -291,6 +294,9 @@ importers: matrix-web-i18n: specifier: 'catalog:' version: 3.6.0 + memfs: + specifier: ^4.57.2 + version: 4.57.2(tslib@2.8.1) mkdirp: specifier: ^3.0.0 version: 3.0.1 @@ -309,6 +315,15 @@ importers: typescript: specifier: 6.0.3 version: 6.0.3 + vite: + specifier: ^8.0.9 + version: 8.0.9(@types/node@18.19.130)(esbuild@0.27.4)(jiti@2.6.1)(sugarss@5.0.1(postcss@8.5.10))(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3) + vitest: + specifier: ^4.1.5 + version: 4.1.5(@opentelemetry/api@1.9.1)(@types/node@18.19.130)(@vitest/browser-playwright@4.1.5)(@vitest/coverage-v8@4.1.5)(jsdom@26.1.0(patch_hash=040623e87b1c8b676c2a705513c0276c0704dd1b23fc3a1bb77cde8128b64b5f))(vite@8.0.9(@types/node@18.19.130)(esbuild@0.27.4)(jiti@2.6.1)(sugarss@5.0.1(postcss@8.5.10))(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest-sonar-reporter: + specifier: ^3.0.0 + version: 3.0.0(vitest@4.1.5) apps/web: dependencies: @@ -446,7 +461,7 @@ importers: version: 1.0.3 matrix-js-sdk: specifier: github:matrix-org/matrix-js-sdk#develop - version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/60993dd10ada731e37db81873fede2a0afa93a6b + version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/69985ee350a33ba75f1ad11f96468344f0c92a8d matrix-widget-api: specifier: ^1.17.0 version: 1.17.0 @@ -2987,48 +3002,96 @@ packages: peerDependencies: tslib: '2' + '@jsonjoy.com/fs-core@4.57.2': + resolution: {integrity: sha512-SVjwklkpIV5wrynpYtuYnfYH1QF4/nDuLBX7VXdb+3miglcAgBVZb/5y0cOsehRV/9Vb+3UqhkMq3/NR3ztdkQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + '@jsonjoy.com/fs-fsa@4.56.10': resolution: {integrity: sha512-/FVK63ysNzTPOnCCcPoPHt77TOmachdMS422txM4KhxddLdbW1fIbFMYH0AM0ow/YchCyS5gqEjKLNyv71j/5Q==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' + '@jsonjoy.com/fs-fsa@4.57.2': + resolution: {integrity: sha512-fhO8+iR2I+OCw668ISDJdn1aArc9zx033sWejIyzQ8RBeXa9bDSaUeA3ix0poYOfrj1KdOzytmYNv2/uLDfV6g==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + '@jsonjoy.com/fs-node-builtins@4.56.10': resolution: {integrity: sha512-uUnKz8R0YJyKq5jXpZtkGV9U0pJDt8hmYcLRrPjROheIfjMXsz82kXMgAA/qNg0wrZ1Kv+hrg7azqEZx6XZCVw==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' + '@jsonjoy.com/fs-node-builtins@4.57.2': + resolution: {integrity: sha512-xhiegylRmhw43Ki2HO1ZBL7DQ5ja/qpRsL29VtQ2xuUHiuDGbgf2uD4p9Qd8hJI5P6RCtGYD50IXHXVq/Ocjcg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + '@jsonjoy.com/fs-node-to-fsa@4.56.10': resolution: {integrity: sha512-oH+O6Y4lhn9NyG6aEoFwIBNKZeYy66toP5LJcDOMBgL99BKQMUf/zWJspdRhMdn/3hbzQsZ8EHHsuekbFLGUWw==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' + '@jsonjoy.com/fs-node-to-fsa@4.57.2': + resolution: {integrity: sha512-18LmWTSONhoAPW+IWRuf8w/+zRolPFGPeGwMxlAhhfY11EKzX+5XHDBPAw67dBF5dxDErHJbl40U+3IXSDRXSQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + '@jsonjoy.com/fs-node-utils@4.56.10': resolution: {integrity: sha512-8EuPBgVI2aDPwFdaNQeNpHsyqPi3rr+85tMNG/lHvQLiVjzoZsvxA//Xd8aB567LUhy4QS03ptT+unkD/DIsNg==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' + '@jsonjoy.com/fs-node-utils@4.57.2': + resolution: {integrity: sha512-rsPSJgekz43IlNbLyAM/Ab+ouYLWGp5DDBfYBNNEqDaSpsbXfthBn29Q4muFA9L0F+Z3mKo+CWlgSCXrf+mOyQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + '@jsonjoy.com/fs-node@4.56.10': resolution: {integrity: sha512-7R4Gv3tkUdW3dXfXiOkqxkElxKNVdd8BDOWC0/dbERd0pXpPY+s2s1Mino+aTvkGrFPiY+mmVxA7zhskm4Ue4Q==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' + '@jsonjoy.com/fs-node@4.57.2': + resolution: {integrity: sha512-nX2AdL6cOFwLdju9G4/nbRnYevmCJbh7N7hvR3gGm97Cs60uEjyd0rpR+YBS7cTg175zzl22pGKXR5USaQMvKg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + '@jsonjoy.com/fs-print@4.56.10': resolution: {integrity: sha512-JW4fp5mAYepzFsSGrQ48ep8FXxpg4niFWHdF78wDrFGof7F3tKDJln72QFDEn/27M1yHd4v7sKHHVPh78aWcEw==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' + '@jsonjoy.com/fs-print@4.57.2': + resolution: {integrity: sha512-wK9NSow48i4DbDl9F1CQE5TqnyZOJ04elU3WFG5aJ76p+YxO/ulyBBQvKsessPxdo381Bc2pcEoyPujMOhcRqQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + '@jsonjoy.com/fs-snapshot@4.56.10': resolution: {integrity: sha512-DkR6l5fj7+qj0+fVKm/OOXMGfDFCGXLfyHkORH3DF8hxkpDgIHbhf/DwncBMs2igu/ST7OEkexn1gIqoU6Y+9g==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' + '@jsonjoy.com/fs-snapshot@4.57.2': + resolution: {integrity: sha512-GdduDZuoP5V/QCgJkx9+BZ6SC0EZ/smXAdTS7PfMqgMTGXLlt/bH/FqMYaqB9JmLf05sJPtO0XRbAwwkEEPbVw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + '@jsonjoy.com/json-pack@1.21.0': resolution: {integrity: sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==} engines: {node: '>=10.0'} @@ -9934,8 +9997,8 @@ packages: matrix-events-sdk@0.0.1: resolution: {integrity: sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/60993dd10ada731e37db81873fede2a0afa93a6b: - resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/60993dd10ada731e37db81873fede2a0afa93a6b} + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/69985ee350a33ba75f1ad11f96468344f0c92a8d: + resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/69985ee350a33ba75f1ad11f96468344f0c92a8d} version: 41.4.0 engines: {node: '>=22.0.0'} @@ -9980,6 +10043,11 @@ packages: peerDependencies: tslib: '2' + memfs@4.57.2: + resolution: {integrity: sha512-2nWzSsJzrukurSDna4Z0WywuScK4Id3tSKejgu74u8KCdW4uNrseKRSIDg75C6Yw5ZRqBe0F0EtMNlTbUq8bAQ==} + peerDependencies: + tslib: '2' + memoize-one@5.2.1: resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} @@ -15586,6 +15654,13 @@ snapshots: thingies: 2.5.0(tslib@2.8.1) tslib: 2.8.1 + '@jsonjoy.com/fs-core@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + thingies: 2.5.0(tslib@2.8.1) + tslib: 2.8.1 + '@jsonjoy.com/fs-fsa@4.56.10(tslib@2.8.1)': dependencies: '@jsonjoy.com/fs-core': 4.56.10(tslib@2.8.1) @@ -15594,10 +15669,22 @@ snapshots: thingies: 2.5.0(tslib@2.8.1) tslib: 2.8.1 + '@jsonjoy.com/fs-fsa@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-core': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + thingies: 2.5.0(tslib@2.8.1) + tslib: 2.8.1 + '@jsonjoy.com/fs-node-builtins@4.56.10(tslib@2.8.1)': dependencies: tslib: 2.8.1 + '@jsonjoy.com/fs-node-builtins@4.57.2(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + '@jsonjoy.com/fs-node-to-fsa@4.56.10(tslib@2.8.1)': dependencies: '@jsonjoy.com/fs-fsa': 4.56.10(tslib@2.8.1) @@ -15605,11 +15692,23 @@ snapshots: '@jsonjoy.com/fs-node-utils': 4.56.10(tslib@2.8.1) tslib: 2.8.1 + '@jsonjoy.com/fs-node-to-fsa@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-fsa': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + tslib: 2.8.1 + '@jsonjoy.com/fs-node-utils@4.56.10(tslib@2.8.1)': dependencies: '@jsonjoy.com/fs-node-builtins': 4.56.10(tslib@2.8.1) tslib: 2.8.1 + '@jsonjoy.com/fs-node-utils@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + tslib: 2.8.1 + '@jsonjoy.com/fs-node@4.56.10(tslib@2.8.1)': dependencies: '@jsonjoy.com/fs-core': 4.56.10(tslib@2.8.1) @@ -15621,12 +15720,29 @@ snapshots: thingies: 2.5.0(tslib@2.8.1) tslib: 2.8.1 + '@jsonjoy.com/fs-node@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-core': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.57.2(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + thingies: 2.5.0(tslib@2.8.1) + tslib: 2.8.1 + '@jsonjoy.com/fs-print@4.56.10(tslib@2.8.1)': dependencies: '@jsonjoy.com/fs-node-utils': 4.56.10(tslib@2.8.1) tree-dump: 1.1.0(tslib@2.8.1) tslib: 2.8.1 + '@jsonjoy.com/fs-print@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + '@jsonjoy.com/fs-snapshot@4.56.10(tslib@2.8.1)': dependencies: '@jsonjoy.com/buffers': 17.65.0(tslib@2.8.1) @@ -15635,6 +15751,14 @@ snapshots: '@jsonjoy.com/util': 17.65.0(tslib@2.8.1) tslib: 2.8.1 + '@jsonjoy.com/fs-snapshot@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 17.65.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/json-pack': 17.65.0(tslib@2.8.1) + '@jsonjoy.com/util': 17.65.0(tslib@2.8.1) + tslib: 2.8.1 + '@jsonjoy.com/json-pack@1.21.0(tslib@2.8.1)': dependencies: '@jsonjoy.com/base64': 1.1.2(tslib@2.8.1) @@ -23553,7 +23677,7 @@ snapshots: matrix-events-sdk@0.0.1: {} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/60993dd10ada731e37db81873fede2a0afa93a6b: + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/69985ee350a33ba75f1ad11f96468344f0c92a8d: dependencies: '@babel/runtime': 7.29.2 '@matrix-org/matrix-sdk-crypto-wasm': 18.2.0 @@ -23633,6 +23757,23 @@ snapshots: tree-dump: 1.1.0(tslib@2.8.1) tslib: 2.8.1 + memfs@4.57.2(tslib@2.8.1): + dependencies: + '@jsonjoy.com/fs-core': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-fsa': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-to-fsa': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/json-pack': 1.21.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + thingies: 2.5.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + memoize-one@5.2.1: {} memoize-one@6.0.0: {} diff --git a/sonar-project.properties b/sonar-project.properties index d5e990eb83..7a25cf4571 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -5,8 +5,14 @@ sonar.organization=element-hq #sonar.sourceEncoding=UTF-8 sonar.sources=. -sonar.tests=apps/web/test,apps/web/playwright,apps/desktop/playwright,packages -sonar.test.inclusions=apps/web/test/*,apps/web/playwright/*,apps/desktop/playwright/*,packages/*/src/**/*.test.*,packages/*/src/test/**/* +sonar.tests=apps/web/test,apps/web/playwright,apps/desktop,packages +sonar.test.inclusions=\ + apps/web/test/*,\ + apps/web/playwright/*,\ + apps/desktop/playwright/*,\ + apps/desktop/src/**/*.test.ts,\ + packages/*/src/**/*.test.*,\ + packages/*/src/test/**/* sonar.exclusions=\ apps/web/__mocks__,\ docs,\ @@ -40,16 +46,23 @@ sonar.coverage.exclusions=\ apps/web/playwright/**/*,\ apps/web/res/**/*,\ apps/web/scripts/**/*,\ - apps/desktop/scripts/**/*,\ - apps/desktop/playwright/**/*,\ - apps/desktop/hak/**/*,\ - scripts/**/*,\ + apps/web/__mocks__/**/*,\ + apps/web/I18nWebpackPlugin.ts,\ + apps/web/recorder-worklet-loader.cjs,\ apps/web/src/components/views/dialogs/devtools/**/*,\ apps/web/src/utils/SessionLock.ts,\ apps/web/src/**/*.d.ts,\ apps/web/src/vector/mobile_guide/**/*,\ + apps/desktop/electron-builder.ts,\ + apps/desktop/scripts/**/*,\ + apps/desktop/playwright/**/*,\ + apps/desktop/hak/**/*,\ packages/shared-components/src/test/**/*,\ packages/shared-components/src/**/*.stories.tsx,\ + packages/shared-components/scripts/**/*,\ packages/playwright-common/**/*,\ - **/*.config.ts + scripts/**/*,\ + docs/**/*,\ + **/*.config.*,\ + knip.ts sonar.testExecutionReportPaths=apps/web/coverage/jest-sonar-report.xml