diff --git a/eslint.config.mjs b/eslint.config.mjs index 9bad6e2d4..c7c8ac1e1 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -144,11 +144,32 @@ export default [ 'no-console': 'off', 'n/no-process-exit': 'off', 'n/hashbang': 'off', - // `_` / `__` as a deliberate throwaway binding β€” `catch (_)`, a - // discarded destructuring slot. Narrow on purpose: the pattern matches - // UNDERSCORES ONLY, so a real name that happens to start with `_` is - // still reported. v9 drives plain `.js` through the CORE rule (the - // `@typescript-eslint` swap is per-file-type), so it is set here. + // Tests import devDependencies by definition; this rule is about what + // ships in the published package, which tests/ never does. + 'n/no-unpublished-import': 'off', + }, + }, + + { + // `_` / `__` as a deliberate throwaway binding β€” `catch (_)`, a discarded + // destructuring slot. Narrow on purpose: the pattern matches UNDERSCORES + // ONLY, so a real name that happens to start with `_` is still reported. + // + // πŸ”΄ `.js` / `.mjs` ONLY, NOT `.ts`. The CORE rule is not TypeScript-aware: + // applied to a `.ts` file it reads the parameter NAMES inside a function + // TYPE as bindings and reports them unused. Measured on humaniq β€” + // + // t?: (app: string, key: string) => string + // + // produced four `no-unused-vars` errors for `app` and `key`, which are + // documentation, not variables. The same mis-scoping made every unused + // `catch (e)` in a `.ts` spec report TWICE, once per rule. + // + // v9 already turns the core rule off for `.ts` and drives + // `@typescript-eslint/no-unused-vars` instead; naming `.ts` here switched + // it back on. TypeScript files are handled by the block below. + files: ['tests/**/*.js', 'tests/**/*.mjs'], + rules: { 'no-unused-vars': [ 'error', { @@ -165,12 +186,117 @@ export default [ ignoreRestSiblings: true, }, ], - // Tests import devDependencies by definition; this rule is about what - // ships in the published package, which tests/ never does. - 'n/no-unpublished-import': 'off', }, }, + { + // The TypeScript half of the block above. Same intent, same patterns, on + // the rule that actually understands the language: it knows a name inside + // a function type is not a binding, so type annotations stay quiet while a + // genuinely dead local is still reported. + files: ['tests/**/*.ts', 'tests/**/*.tsx'], + rules: { + '@typescript-eslint/no-unused-vars': [ + 'error', + { + varsIgnorePattern: '^_+$', + caughtErrors: 'all', + caughtErrorsIgnorePattern: '^_+$', + argsIgnorePattern: '^_', + ignoreRestSiblings: true, + }, + ], + }, + }, + + { + // πŸ”΄ Node-side CLI tooling under `scripts/`, which is COMMONJS. Flat + // config defaults every `.js` to ESM with browser-ish globals, so without + // this block eslint reports the CommonJS wrapper itself as undefined + // identifiers. Measured on this app: 52 of the 233 errors under + // `tests/` + `scripts/` were `no-undef`, ALL of them in `scripts/`, and + // all five names were the environment rather than a typo β€” `process` 23, + // `require` 20, `__dirname` 6, `__filename` 2, `module` 1. + // + // This is describing the environment, not relaxing a rule, and it is the + // same argument the test-globals block below makes: declaring them keeps + // `no-undef` able to do its real job, which is catching a genuinely + // misspelled identifier. Suppressing the rule instead would bury that. + // + // `no-console` is off because printing its report is what a CLI checker + // is FOR. + // + // πŸ”΄ NO `n/*` ENTRIES HERE, DELIBERATELY. `eslint-plugin-n` is NOT + // registered for these files under eslint 10 + @nextcloud/eslint-config + // 9, so `'n/no-process-exit': 'off'` would be dead config that reads as + // if it were doing something. Measured both ways on this app: 0 `n/` + // findings with the entries and 0 without. + // + // What DID report was the opposite β€” four `scripts/*.js` carried + // `/* eslint-disable n/no-process-exit */` and `/* eslint-disable + // n/shebang */` left over from the eslintrc era, and an inline disable + // naming an unregistered plugin is itself an error ("Definition for rule + // 'n/shebang' was not found"). Those 8 comments are removed; do not add + // `n/*` rules back to replace them. + // + // ⚠️ `.js` and `.cjs` ONLY. A `scripts/*.mjs` is genuinely ESM and must + // keep the default `sourceType`, or `import` stops parsing there. + files: ['scripts/**/*.js', 'scripts/**/*.cjs'], + languageOptions: { + sourceType: 'commonjs', + globals: { + require: 'readonly', + module: 'writable', + exports: 'writable', + process: 'readonly', + __dirname: 'readonly', + __filename: 'readonly', + console: 'readonly', + Buffer: 'readonly', + global: 'readonly', + URL: 'readonly', + TextEncoder: 'readonly', + TextDecoder: 'readonly', + }, + }, + rules: { + 'no-console': 'off', + }, + }, + + { + // The ESM half of the block above. A `scripts/*.mjs` is genuinely a module + // and must keep the default `sourceType`, so it gets Node's globals but + // none of the CommonJS wrapper. Measured: `process` reported undefined 2x + // in hermiq's generate-opengemeenten-icons.mjs and 4x in openregister's + // l10n/runtime-check.mjs, which the `.js`/`.cjs` block deliberately does + // not match. + files: ['scripts/**/*.mjs', 'tests/**/*.mjs'], + languageOptions: { + globals: { + process: 'readonly', + console: 'readonly', + Buffer: 'readonly', + global: 'readonly', + URL: 'readonly', + TextEncoder: 'readonly', + TextDecoder: 'readonly', + }, + }, + rules: { + 'no-console': 'off', + }, + }, + + { + // eslint must not try to PARSE a shell script. `tests/e2e/seed.test.sh` + // matches the `**/*.test.*` glob some presets use, and eslint then reads + // it as JavaScript and reports "Parsing error: Unexpected character" β€” + // a finding about a file it should never have opened. + ignores: ['**/*.sh', '**/*.bash'], + }, + + { // Test globals. Several apps keep their spec files INSIDE `src/`, which the // lint script scans, and neither `@nextcloud/eslint-config` nor the runner diff --git a/package.json b/package.json index b679f0358..ad85dbc0e 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "build": "NODE_ENV=production webpack --config webpack.config.js --progress", "dev": "NODE_ENV=development webpack --config webpack.config.js --progress", "watch": "NODE_ENV=development webpack --config webpack.config.js --progress --watch", - "lint": "eslint src", + "lint": "eslint src tests scripts", "lint-fix": "npm run lint -- --fix && npm run format:fix", "test": "jest --silent", "test-coverage": "jest --silent --coverage", diff --git a/scripts/build-l10n-js.js b/scripts/build-l10n-js.js index 176ef519c..335b08d2c 100644 --- a/scripts/build-l10n-js.js +++ b/scripts/build-l10n-js.js @@ -101,6 +101,9 @@ function renderJs(id, translations, pluralForm) { ].join('\n') } +/** + * + */ function main() { const check = process.argv.includes('--check') const id = appId() diff --git a/scripts/check-l10n.js b/scripts/check-l10n.js index e77730c40..8c134549a 100755 --- a/scripts/check-l10n.js +++ b/scripts/check-l10n.js @@ -1,8 +1,6 @@ #!/usr/bin/env node /* eslint-disable jsdoc/require-param */ -/* eslint-disable n/no-process-exit */ -/* eslint-disable no-console */ -/* eslint-disable n/shebang */ + /** * l10n/i18n consistency checker. * @@ -19,7 +17,6 @@ const fs = require('fs') const path = require('path') - const { loadJsTranslations, walk } = require('./lib/l10n.js') const ROOT = path.resolve(__dirname, '..') @@ -34,10 +31,16 @@ const DIM = '\x1b[2m' const BOLD = '\x1b[1m' const RESET = '\x1b[0m' +/** + * + */ function rel(p) { return path.relative(ROOT, p) } +/** + * + */ function escapeRegex(s) { return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') } @@ -155,6 +158,9 @@ const NON_DISPLAY_ATTRS = new Set([ 'back-route', // Vue Router route name passed to $router.push({ name }) ]) +/** + * + */ function findUnwrapped(vueFiles, keys) { const hits = [] for (const file of vueFiles) { @@ -232,12 +238,18 @@ function findUnwrapped(vueFiles, keys) { return hits } +/** + * + */ function printSection(title, color, body) { console.log(`${color}${BOLD}${title}${RESET}`) console.log(body) console.log('') } +/** + * + */ function main() { const { app, translations } = loadJsTranslations(L10N_FILE) const keys = new Set(Object.keys(translations)) diff --git a/scripts/check-schema-l10n.js b/scripts/check-schema-l10n.js index 8a860b330..3c4b2626f 100644 --- a/scripts/check-schema-l10n.js +++ b/scripts/check-schema-l10n.js @@ -113,6 +113,9 @@ function collect(node, where, sink) { for (const value of Object.values(node)) collect(value, where, sink) } +/** + * + */ function main() { const update = process.argv.includes('--update') const list = process.argv.includes('--list') diff --git a/scripts/clean-l10n.js b/scripts/clean-l10n.js index dbd399114..54478d998 100755 --- a/scripts/clean-l10n.js +++ b/scripts/clean-l10n.js @@ -1,8 +1,5 @@ #!/usr/bin/env node -/* eslint-disable jsdoc/require-param */ -/* eslint-disable n/no-process-exit */ -/* eslint-disable no-console */ -/* eslint-disable n/shebang */ + /** * l10n unused-key remover. * @@ -29,7 +26,6 @@ const fs = require('fs') const path = require('path') - const { loadJsTranslations, serializeJs, @@ -56,6 +52,9 @@ const apply = args.has('--apply') // ---------- Main ---------- +/** + * + */ function main() { if (!fs.existsSync(ENGLISH_FILE)) { console.error(`English source file not found: ${ENGLISH_FILE}`) diff --git a/scripts/find-unwrapped.js b/scripts/find-unwrapped.js index b8e6e167e..e21e743f1 100644 --- a/scripts/find-unwrapped.js +++ b/scripts/find-unwrapped.js @@ -1,8 +1,6 @@ #!/usr/bin/env node /* eslint-disable jsdoc/require-param */ -/* eslint-disable n/no-process-exit */ -/* eslint-disable no-console */ -/* eslint-disable n/shebang */ + /** * Candidate unwrapped-string detector. * @@ -28,7 +26,6 @@ const fs = require('fs') const path = require('path') - const { walk } = require('./lib/l10n.js') const ROOT = path.resolve(__dirname, '..') @@ -141,6 +138,9 @@ function isComponentAttrOptOut(tagName, attrName) { // ---------- CLI ---------- +/** + * + */ function parseFlags(argv) { const flags = {} const positionals = [] @@ -176,6 +176,9 @@ const minLength = flags['min-length'] // ---------- helpers ---------- +/** + * + */ function rel(p) { return path.relative(ROOT, p) } @@ -364,6 +367,9 @@ function computeTCallRanges(text, app) { return ranges } +/** + * + */ function isInsideRange(pos, ranges) { for (const [start, end] of ranges) { if (pos >= start && pos < end) return true @@ -510,6 +516,9 @@ function isInsideStoreCall(expr, pos) { return /Store$/.test(baseIdent) } +/** + * + */ function findStringLiteralsInExpression(expr) { const out = [] let i = 0 @@ -779,6 +788,9 @@ function scanScript(file, fullText, scriptStart, scriptEnd, tCallRanges) { // ---------- main ---------- +/** + * + */ function findVueFiles(roots) { const files = [] for (const root of roots) { @@ -792,6 +804,9 @@ function findVueFiles(roots) { return files } +/** + * + */ function detectAppName() { // Mirror l10n-ai's approach: read l10n/en.js and trust the registered name. const enFile = path.join(ROOT, 'l10n', 'en.js') @@ -801,6 +816,9 @@ function detectAppName() { return m ? m[2] : 'opencatalogi' } +/** + * + */ function main() { const roots = positionals.length ? positionals.map((p) => diff --git a/scripts/l10n-ai.js b/scripts/l10n-ai.js index 4ef0981e6..c34716ef4 100644 --- a/scripts/l10n-ai.js +++ b/scripts/l10n-ai.js @@ -1,8 +1,6 @@ #!/usr/bin/env node /* eslint-disable jsdoc/require-param */ -/* eslint-disable n/no-process-exit */ -/* eslint-disable no-console */ -/* eslint-disable n/shebang */ + /** * AI-focused l10n CRUD tool. Designed to be invoked one subcommand at a time * by Claude (or other automation) so individual operations stay cheap in @@ -31,7 +29,6 @@ const fs = require('fs') const path = require('path') - const { loadJsTranslations, serializeJs, @@ -138,6 +135,9 @@ function parsePluralPairs(pairs) { // ---------- file helpers ---------- +/** + * + */ function loadAll() { const files = listJsLocaleFiles(L10N_DIR) if (!files.length) { @@ -150,6 +150,9 @@ function loadAll() { })) } +/** + * + */ function writeAll(entries) { const written = [] for (const e of entries) { @@ -166,17 +169,26 @@ function writeAll(entries) { runEslintFix(written, { rootDir: ROOT, log: (m) => console.error(m) }) } +/** + * + */ function fail(msg, code = 1) { console.error(msg) process.exit(code) } +/** + * + */ function rel(p) { return path.relative(ROOT, p) } // ---------- subcommands ---------- +/** + * + */ function cmdHas(args) { const { positionals, flags } = parseArgs(args) const [key] = positionals @@ -206,6 +218,9 @@ function cmdHas(args) { } } +/** + * + */ function cmdGet(args) { const { positionals } = parseArgs(args) const [key] = positionals @@ -214,7 +229,7 @@ function cmdGet(args) { const entries = loadAll() let any = false for (const e of entries) { - if (Object.prototype.hasOwnProperty.call(e.translations, key)) { + if (Object.hasOwn(e.translations, key)) { any = true const v = e.translations[key] const out = Array.isArray(v) ? JSON.stringify(v) : v @@ -227,6 +242,9 @@ function cmdGet(args) { } } +/** + * + */ function cmdFind(args) { const { positionals } = parseArgs(args) const [substring] = positionals @@ -251,6 +269,9 @@ function cmdFind(args) { } } +/** + * + */ function cmdAdd(args) { const { positionals, opts, flags } = parseArgs(args, { repeatable: new Set(['value', 'plural']), @@ -336,7 +357,7 @@ function cmdAdd(args) { const existing = [] for (const e of entries) { if (!targetLocales.has(e.locale)) continue - if (Object.prototype.hasOwnProperty.call(e.translations, key)) { + if (Object.hasOwn(e.translations, key)) { existing.push(e.locale) } } @@ -363,6 +384,9 @@ function cmdAdd(args) { } } +/** + * + */ function cmdSet(args) { const { positionals, opts } = parseArgs(args, { repeatable: new Set(['plural']), @@ -380,7 +404,7 @@ function cmdSet(args) { `set: locale '${opts.locale}' has no l10n/${opts.locale}.js (known: ${entries.map((e) => e.locale).join(', ')})`, ) } - if (!Object.prototype.hasOwnProperty.call(target.translations, key)) { + if (!Object.hasOwn(target.translations, key)) { fail(`set: key '${key}' not present in ${opts.locale}.js. Use 'add' first.`) } @@ -406,15 +430,16 @@ function cmdSet(args) { ) } +/** + * + */ function cmdRm(args) { const { positionals, flags } = parseArgs(args) const [key] = positionals if (!key) fail('usage: rm [--force]') const entries = loadAll() - const present = entries.filter((e) => - Object.prototype.hasOwnProperty.call(e.translations, key), - ) + const present = entries.filter((e) => Object.hasOwn(e.translations, key)) if (!present.length) { fail(`rm: key '${key}' not found in any locale .js file`) } @@ -444,6 +469,9 @@ function cmdRm(args) { for (const e of toWrite) console.log(`${e.locale}.js\tremoved`) } +/** + * + */ function cmdRename(args) { const { positionals, flags } = parseArgs(args) const [oldKey, newKey] = positionals @@ -451,15 +479,11 @@ function cmdRename(args) { if (oldKey === newKey) fail('rename: old and new keys are identical') const entries = loadAll() - const present = entries.filter((e) => - Object.prototype.hasOwnProperty.call(e.translations, oldKey), - ) + const present = entries.filter((e) => Object.hasOwn(e.translations, oldKey)) if (!present.length) { fail(`rename: key '${oldKey}' not found in any locale .js file`) } - const collisions = entries.filter((e) => - Object.prototype.hasOwnProperty.call(e.translations, newKey), - ) + const collisions = entries.filter((e) => Object.hasOwn(e.translations, newKey)) if (collisions.length && !flags.force) { fail( `rename: target key '${newKey}' already exists in ${collisions.map((e) => e.locale + '.js').join(', ')}. Pass --force to overwrite.`, @@ -468,7 +492,7 @@ function cmdRename(args) { const toWrite = [] for (const e of entries) { - if (!Object.prototype.hasOwnProperty.call(e.translations, oldKey)) continue + if (!Object.hasOwn(e.translations, oldKey)) continue const next = { ...e.translations } next[newKey] = next[oldKey] delete next[oldKey] @@ -478,12 +502,18 @@ function cmdRename(args) { for (const e of toWrite) console.log(`${e.locale}.js\trenamed`) } +/** + * + */ function cmdListLocales() { const files = listJsLocaleFiles(L10N_DIR) if (!files.length) fail('list-locales: no l10n/*.js files found') for (const f of files) console.log(localeNameOf(f)) } +/** + * + */ function cmdHelp() { const text = [ 'Usage: node scripts/l10n-ai.js [args...]', @@ -509,6 +539,9 @@ function cmdHelp() { // ---------- main ---------- +/** + * + */ function main() { const [, , sub, ...rest] = process.argv if (!sub || sub === '--help' || sub === '-h') { diff --git a/scripts/lib/l10n.js b/scripts/lib/l10n.js index 58a77df5e..79f7a3af9 100644 --- a/scripts/lib/l10n.js +++ b/scripts/lib/l10n.js @@ -9,10 +9,10 @@ * out of sync (which is exactly the bug sync-l10n-json.js exists to prevent). */ +const { spawnSync } = require('child_process') const fs = require('fs') const path = require('path') const vm = require('vm') -const { spawnSync } = require('child_process') /** * Load a single l10n/*.js file and return its app name, translations object, @@ -238,6 +238,9 @@ function findKeyReferences(srcDir, app, key) { return hits } +/** + * + */ function escapeRegex(s) { return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') } diff --git a/scripts/sync-l10n-ellipsis.js b/scripts/sync-l10n-ellipsis.js index c94aef652..c427bfd33 100644 --- a/scripts/sync-l10n-ellipsis.js +++ b/scripts/sync-l10n-ellipsis.js @@ -18,6 +18,10 @@ const path = require('path') const ELLIPSIS_RE = /(? { } catch (err) { last = `request failed: ${(err as Error).message}` } - // eslint-disable-next-line no-await-in-loop + await new Promise((resolve) => setTimeout(resolve, 5_000)) } throw new Error( @@ -235,7 +237,7 @@ export default async function globalSetup(config: FullConfig): Promise { await page.evaluate(() => { try { window.localStorage.setItem('cn-support-dialog-shown:filinq', '1') - } catch (e) { + } catch { /* private mode / quota β€” the dismissOverlays fallback still applies */ } }) @@ -266,7 +268,7 @@ export default async function globalSetup(config: FullConfig): Promise { await page.evaluate(() => { try { window.localStorage.setItem('cn-walkthrough-seen:filinq', '999.0.0') - } catch (e) { + } catch { // localStorage unavailable β€” specs fall back to dismissing by hand. } }) diff --git a/tests/e2e/playwright.config.ts b/tests/e2e/playwright.config.ts index 6a595c666..b19bb3bf8 100644 --- a/tests/e2e/playwright.config.ts +++ b/tests/e2e/playwright.config.ts @@ -43,8 +43,7 @@ import { defineConfig, devices } from '@playwright/test' import * as path from 'path' - -import { resolveBaseUrl } from './base-url' +import { resolveBaseUrl } from './base-url.ts' const APP_ROOT = path.resolve(__dirname, '..', '..') diff --git a/tests/e2e/spec-coverage/_helpers.ts b/tests/e2e/spec-coverage/_helpers.ts index 0ce8d07c9..7111da9e2 100644 --- a/tests/e2e/spec-coverage/_helpers.ts +++ b/tests/e2e/spec-coverage/_helpers.ts @@ -15,7 +15,7 @@ * defects, and must not make a page-render assertion flap. */ -import { type Page } from '@playwright/test' +import type { Page } from '@playwright/test' const IGNORE = [ 'user_status', @@ -241,7 +241,6 @@ async function resolveAppBase(page: Page): Promise { await page.goto(APP, { waitUntil: 'domcontentloaded' }) await waitForAppReady(page) cachedAppBase = await page.evaluate(() => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any const oc = (window as any).OC return (oc?.generateUrl?.('/apps/filinq') as string) || '' }) diff --git a/tests/e2e/spec-coverage/admin-settings.spec.ts b/tests/e2e/spec-coverage/admin-settings.spec.ts index 665e9896c..62f5cfc02 100644 --- a/tests/e2e/spec-coverage/admin-settings.spec.ts +++ b/tests/e2e/spec-coverage/admin-settings.spec.ts @@ -23,8 +23,10 @@ // @e2e openspec/specs/processing-activity-export/spec.md#admin-exports-the-register-from-filinq // @e2e openspec/specs/processing-activity-export/spec.md#unconfigured-identity-prompts-not-blocks -import { test, expect, type Page } from '@playwright/test' -import { waitForNcContentReady } from './_helpers' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' +import { waitForNcContentReady } from './_helpers.ts' async function dismissOverlays(page: Page): Promise { const wizard = page.locator('#firstrunwizard') diff --git a/tests/e2e/spec-coverage/anonymiser-backend-warning.spec.ts b/tests/e2e/spec-coverage/anonymiser-backend-warning.spec.ts index 614006b2d..eba2ce1c1 100644 --- a/tests/e2e/spec-coverage/anonymiser-backend-warning.spec.ts +++ b/tests/e2e/spec-coverage/anonymiser-backend-warning.spec.ts @@ -32,8 +32,10 @@ * (see the long comment in orphaned-surface-restoration.spec.ts). */ -import { test, expect, type Page, type APIRequestContext } from '@playwright/test' -import { waitForNcContentReady, dismissOverlays, go } from './_helpers' +import type { APIRequestContext, Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' +import { dismissOverlays, go, waitForNcContentReady } from './_helpers.ts' const SETTINGS = '/index.php/settings/admin/filinq' const API_SETTINGS = '/index.php/apps/filinq/api/settings' diff --git a/tests/e2e/spec-coverage/anonymization.spec.ts b/tests/e2e/spec-coverage/anonymization.spec.ts index a90d1a480..105c09109 100644 --- a/tests/e2e/spec-coverage/anonymization.spec.ts +++ b/tests/e2e/spec-coverage/anonymization.spec.ts @@ -14,8 +14,10 @@ // @e2e openspec/specs/anonymization/spec.md#error-during-anonymization // @e2e openspec/specs/anonymization/spec.md#anonymize-another-document -import { test, expect, type Page } from '@playwright/test' -import { appUrl, waitForAppReady } from './_helpers' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' +import { appUrl, waitForAppReady } from './_helpers.ts' // The local `const APP = '/index.php/apps/filinq'` that used to live here is // gone β€” navigation now goes through `appUrl()`, which reads the base from the diff --git a/tests/e2e/spec-coverage/consent-management.spec.ts b/tests/e2e/spec-coverage/consent-management.spec.ts index 6b187847f..7c5906a4a 100644 --- a/tests/e2e/spec-coverage/consent-management.spec.ts +++ b/tests/e2e/spec-coverage/consent-management.spec.ts @@ -13,9 +13,11 @@ // @e2e openspec/specs/consent-management/spec.md#click-consent-to-view-details // @e2e openspec/specs/consent-management/spec.md#empty-consent-list -import { test, expect, type Page } from '@playwright/test' -import { appUrl, waitForAppReady } from './_helpers' -import { API } from '../workflows/_fixtures' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' +import { API } from '../workflows/_fixtures.ts' +import { appUrl, waitForAppReady } from './_helpers.ts' // `index.php`-prefixed β€” see the APP constant in ./_helpers.ts for why the // prefix is required on CI (`php -S` does not rewrite, so `/apps/...` hits diff --git a/tests/e2e/spec-coverage/custom-dictionary-detection.spec.ts b/tests/e2e/spec-coverage/custom-dictionary-detection.spec.ts index 89f30ce2b..52765cc48 100644 --- a/tests/e2e/spec-coverage/custom-dictionary-detection.spec.ts +++ b/tests/e2e/spec-coverage/custom-dictionary-detection.spec.ts @@ -42,9 +42,11 @@ * `CUSTOM_DICTIONARY` card disappears while everything else still renders. */ -import { test, expect, type APIRequestContext } from '@playwright/test' -import { go, waitForAppReady } from './_helpers' -import { harvestToken, jsonHeaders, API } from '../workflows/_fixtures' +import type { APIRequestContext } from '@playwright/test' + +import { expect, test } from '@playwright/test' +import { API, harvestToken, jsonHeaders } from '../workflows/_fixtures.ts' +import { go, waitForAppReady } from './_helpers.ts' /** Unique per run β€” the whole point of the assertion is that only WE seeded it. */ const RUN = `g19cdd-${Date.now()}` @@ -180,7 +182,6 @@ test.describe('custom-dictionary-recognition β€” a dictionary hit is detected, r }) .catch(() => null) if (res && res.status() >= 400) { - // eslint-disable-next-line no-console console.warn( `[teardown] dictionary ${dictionaryId} -> ${res.status()} (leaked)`, ) diff --git a/tests/e2e/spec-coverage/custom-dictionary-recognition.spec.ts b/tests/e2e/spec-coverage/custom-dictionary-recognition.spec.ts index 11d0bc096..022cbc8ba 100644 --- a/tests/e2e/spec-coverage/custom-dictionary-recognition.spec.ts +++ b/tests/e2e/spec-coverage/custom-dictionary-recognition.spec.ts @@ -30,9 +30,11 @@ * bottom of this file. Their anchors have been removed rather than repointed. */ -import { test, expect, type APIRequestContext, type Page } from '@playwright/test' -import { appUrl, go, waitForAppReady } from './_helpers' -import { harvestToken, jsonHeaders, API } from '../workflows/_fixtures' +import type { APIRequestContext, Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' +import { API, harvestToken, jsonHeaders } from '../workflows/_fixtures.ts' +import { appUrl, go, waitForAppReady } from './_helpers.ts' const P = `g19cdr-${Date.now()}` const SEEDED_LABEL = 'Projectnamen' // shipped by lib/Settings/filinq_register.json @@ -102,7 +104,6 @@ test.describe('custom-dictionary-recognition β€” dictionaries admin UI', () => { }) .catch(() => null) if (res && res.status() >= 400) { - // eslint-disable-next-line no-console console.warn( `[teardown] dictionary ${fixtureId} -> ${res.status()} (leaked)`, ) diff --git a/tests/e2e/spec-coverage/dashboard.spec.ts b/tests/e2e/spec-coverage/dashboard.spec.ts index ef1deb8ce..485e456c6 100644 --- a/tests/e2e/spec-coverage/dashboard.spec.ts +++ b/tests/e2e/spec-coverage/dashboard.spec.ts @@ -24,8 +24,10 @@ // @e2e openspec/specs/dashboard/spec.md#dashboard-widget-icon // @e2e openspec/specs/dashboard/spec.md#admin-settings-section-icon -import { test, expect, type Page } from '@playwright/test' -import { waitForAppReady, waitForNcContentReady } from './_helpers' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' +import { waitForAppReady, waitForNcContentReady } from './_helpers.ts' // `index.php`-prefixed β€” see the APP constant in ./_helpers.ts for why the // prefix is required on CI (`php -S` does not rewrite, so `/apps/...` hits diff --git a/tests/e2e/spec-coverage/demo-data-setup-step.spec.ts b/tests/e2e/spec-coverage/demo-data-setup-step.spec.ts index 0d537e062..f8b176b46 100644 --- a/tests/e2e/spec-coverage/demo-data-setup-step.spec.ts +++ b/tests/e2e/spec-coverage/demo-data-setup-step.spec.ts @@ -1,3 +1,5 @@ +import type { Page } from '@playwright/test' + /* * SPDX-FileCopyrightText: 2026 Conduction B.V. * SPDX-License-Identifier: EUPL-1.2 @@ -34,7 +36,7 @@ * * @spec exclude ADR-042/ADR-111 setup contract; no per-app behavioural spec. */ -import { test, expect, type Page } from '@playwright/test' +import { expect, test } from '@playwright/test' import * as path from 'path' const STORAGE_STATE = path.resolve(__dirname, '../.auth/admin.json') @@ -53,12 +55,12 @@ async function api( method, headers: { 'Content-Type': 'application/json', - // eslint-disable-next-line no-undef + requesttoken: (window as any).OC?.requestToken || '', 'OCS-APIREQUEST': 'true', }, }) - let json: any = null + let json: any try { json = await res.json() } catch { diff --git a/tests/e2e/spec-coverage/document-comparison.spec.ts b/tests/e2e/spec-coverage/document-comparison.spec.ts index b25505621..318cf3ea5 100644 --- a/tests/e2e/spec-coverage/document-comparison.spec.ts +++ b/tests/e2e/spec-coverage/document-comparison.spec.ts @@ -15,8 +15,8 @@ // @e2e openspec/specs/document-comparison/spec.md#operator-picks-two-versions // @e2e openspec/specs/document-comparison/spec.md#advisory-panel-for-unredacted-entities -import { test, expect } from '@playwright/test' -import { attachConsoleGuard, go } from './_helpers' +import { expect, test } from '@playwright/test' +import { attachConsoleGuard, go } from './_helpers.ts' test.describe('document-comparison β€” side-by-side view', () => { test('comparison view renders its heading, pickers and Compare action', async ({ diff --git a/tests/e2e/spec-coverage/document-validation-checks.spec.ts b/tests/e2e/spec-coverage/document-validation-checks.spec.ts index 027b8722b..4b272e093 100644 --- a/tests/e2e/spec-coverage/document-validation-checks.spec.ts +++ b/tests/e2e/spec-coverage/document-validation-checks.spec.ts @@ -15,8 +15,8 @@ // @e2e openspec/specs/document-validation-checks/spec.md#operator-sees-why-a-document-failed // @e2e openspec/specs/document-validation-checks/spec.md#scan-only-document-offers-the-ocr-path -import { test, expect } from '@playwright/test' -import { attachConsoleGuard, go } from './_helpers' +import { expect, test } from '@playwright/test' +import { attachConsoleGuard, go } from './_helpers.ts' test.describe('document-validation-checks β€” verdict + findings UI', () => { test('My documents exposes a Validate action that opens the findings panel', async ({ diff --git a/tests/e2e/spec-coverage/entity-publication-policies.spec.ts b/tests/e2e/spec-coverage/entity-publication-policies.spec.ts index 349434eed..351b912df 100644 --- a/tests/e2e/spec-coverage/entity-publication-policies.spec.ts +++ b/tests/e2e/spec-coverage/entity-publication-policies.spec.ts @@ -39,9 +39,11 @@ * poison the next one's negative assertions. */ -import { test, expect, type APIRequestContext, type Page } from '@playwright/test' -import { go, waitForAppReady } from './_helpers' -import { harvestToken, jsonHeaders, API } from '../workflows/_fixtures' +import type { APIRequestContext, Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' +import { API, harvestToken, jsonHeaders } from '../workflows/_fixtures.ts' +import { go, waitForAppReady } from './_helpers.ts' /** Unique per run β€” the negative assertions depend on no stale twin existing. */ const P = `g19epp-${Date.now()}` @@ -193,7 +195,6 @@ test.describe('entity-publication-policies β€” three separate admin surfaces', ( }) .catch(() => null) if (res && res.status() >= 400) { - // eslint-disable-next-line no-console console.warn( `[teardown] standing consent ${created.standing} -> ${res.status()} (leaked)`, ) diff --git a/tests/e2e/spec-coverage/features-roadmap.spec.ts b/tests/e2e/spec-coverage/features-roadmap.spec.ts index 13e8a40ac..385e5d4f0 100644 --- a/tests/e2e/spec-coverage/features-roadmap.spec.ts +++ b/tests/e2e/spec-coverage/features-roadmap.spec.ts @@ -12,8 +12,8 @@ // @e2e openspec/specs/dashboard/spec.md#navigation-items-and-icons -import { test, expect } from '@playwright/test' -import { attachConsoleGuard, go, navClick } from './_helpers' +import { expect, test } from '@playwright/test' +import { attachConsoleGuard, go, navClick } from './_helpers.ts' test.describe('dashboard β€” features & roadmap page', () => { test('Features & roadmap page renders its heading and actions', async ({ diff --git a/tests/e2e/spec-coverage/folder-analysis.spec.ts b/tests/e2e/spec-coverage/folder-analysis.spec.ts index 16c1af24d..863706ded 100644 --- a/tests/e2e/spec-coverage/folder-analysis.spec.ts +++ b/tests/e2e/spec-coverage/folder-analysis.spec.ts @@ -24,8 +24,8 @@ // @e2e openspec/specs/folder-batch-analysis/spec.md#initiate-folder-analysis-by-folder-path-existing-behavior // @e2e openspec/specs/folder-batch-analysis/spec.md#folder-path-does-not-exist -import { test, expect } from '@playwright/test' -import { attachConsoleGuard, dismissOverlays, go, navClick } from './_helpers' +import { expect, test } from '@playwright/test' +import { attachConsoleGuard, dismissOverlays, go, navClick } from './_helpers.ts' test.describe('folder-batch-analysis β€” folder analysis UI', () => { test('Folder Analysis page renders heading, path input and Analyze action', async ({ diff --git a/tests/e2e/spec-coverage/my-documents.spec.ts b/tests/e2e/spec-coverage/my-documents.spec.ts index 3f2b03320..edab63ce3 100644 --- a/tests/e2e/spec-coverage/my-documents.spec.ts +++ b/tests/e2e/spec-coverage/my-documents.spec.ts @@ -17,8 +17,8 @@ // @e2e openspec/specs/document-register/spec.md#generated-correspondence-lifecycle -import { test, expect } from '@playwright/test' -import { attachConsoleGuard, dismissOverlays, go, navClick } from './_helpers' +import { expect, test } from '@playwright/test' +import { attachConsoleGuard, dismissOverlays, go, navClick } from './_helpers.ts' test.describe('document-register β€” my documents UI', () => { test('My Documents page renders the Documents header and view toggle', async ({ diff --git a/tests/e2e/spec-coverage/orphaned-surface-restoration.spec.ts b/tests/e2e/spec-coverage/orphaned-surface-restoration.spec.ts index 5c6fc7af4..1efb9d08b 100644 --- a/tests/e2e/spec-coverage/orphaned-surface-restoration.spec.ts +++ b/tests/e2e/spec-coverage/orphaned-surface-restoration.spec.ts @@ -45,8 +45,10 @@ * on the individual `test.fixme` blocks below. */ -import { test, expect, type Page } from '@playwright/test' -import { attachConsoleGuard, dismissOverlays, go, navClick } from './_helpers' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' +import { attachConsoleGuard, dismissOverlays, go, navClick } from './_helpers.ts' // The views under test, named after the component files they cover. Routes are // unchanged β€” this makes the spec-to-component link readable in executable code diff --git a/tests/e2e/spec-coverage/page-components.spec.ts b/tests/e2e/spec-coverage/page-components.spec.ts index 8572a3299..7df0aad5b 100644 --- a/tests/e2e/spec-coverage/page-components.spec.ts +++ b/tests/e2e/spec-coverage/page-components.spec.ts @@ -33,8 +33,8 @@ * over the route-specific markup. */ -import { test, expect } from '@playwright/test' -import { go, waitForNcContentReady, dismissOverlays } from './_helpers' +import { expect, test } from '@playwright/test' +import { dismissOverlays, go, waitForNcContentReady } from './_helpers.ts' /** * A syntactically valid UUID that no Filinq object can have. diff --git a/tests/e2e/spec-coverage/print-preview.spec.ts b/tests/e2e/spec-coverage/print-preview.spec.ts index 5b6848bab..3555172a8 100644 --- a/tests/e2e/spec-coverage/print-preview.spec.ts +++ b/tests/e2e/spec-coverage/print-preview.spec.ts @@ -12,8 +12,8 @@ // @e2e openspec/specs/print-preview/spec.md#preview-with-inline-template -import { test, expect } from '@playwright/test' -import { attachConsoleGuard, go } from './_helpers' +import { expect, test } from '@playwright/test' +import { attachConsoleGuard, go } from './_helpers.ts' // The view under test, named after the component file it covers. The route // is unchanged β€” this makes the spec-to-component link readable in executable diff --git a/tests/e2e/spec-coverage/signing.spec.ts b/tests/e2e/spec-coverage/signing.spec.ts index f585c4c9c..6663491a9 100644 --- a/tests/e2e/spec-coverage/signing.spec.ts +++ b/tests/e2e/spec-coverage/signing.spec.ts @@ -14,8 +14,8 @@ // @e2e openspec/specs/document-signing/spec.md#list-all-signing-requests // @e2e openspec/specs/document-signing/spec.md#view-signing-request-status -import { test, expect } from '@playwright/test' -import { attachConsoleGuard, go, navClick } from './_helpers' +import { expect, test } from '@playwright/test' +import { attachConsoleGuard, go, navClick } from './_helpers.ts' test.describe('document-signing β€” signing requests list UI', () => { test('Signing Requests page renders heading and a list or empty-state', async ({ diff --git a/tests/e2e/spec-coverage/templates.spec.ts b/tests/e2e/spec-coverage/templates.spec.ts index 4eac60ea0..fd4d2566c 100644 --- a/tests/e2e/spec-coverage/templates.spec.ts +++ b/tests/e2e/spec-coverage/templates.spec.ts @@ -12,8 +12,8 @@ // @e2e openspec/specs/template-management/spec.md#list-templates-with-namespace-filter // @e2e openspec/specs/template-management/spec.md#create-a-template -import { test, expect } from '@playwright/test' -import { attachConsoleGuard, dismissOverlays, go, navClick } from './_helpers' +import { expect, test } from '@playwright/test' +import { attachConsoleGuard, dismissOverlays, go, navClick } from './_helpers.ts' // The view under test, named after the component file it covers. The route // is unchanged β€” this makes the spec-to-component link readable in executable diff --git a/tests/e2e/spec-coverage/versions.spec.ts b/tests/e2e/spec-coverage/versions.spec.ts index 808701dcd..71d6fb1ea 100644 --- a/tests/e2e/spec-coverage/versions.spec.ts +++ b/tests/e2e/spec-coverage/versions.spec.ts @@ -18,8 +18,8 @@ // @e2e openspec/specs/document-versions/spec.md#compare-a-version-with-the-current-document // @e2e openspec/specs/document-versions/spec.md#compare-is-not-offered-for-non-extractable-versions -import { test, expect } from '@playwright/test' -import { attachConsoleGuard, go } from './_helpers' +import { expect, test } from '@playwright/test' +import { attachConsoleGuard, go } from './_helpers.ts' // The view under test, named after the component file it covers. The route // is unchanged β€” this makes the spec-to-component link readable in executable diff --git a/tests/e2e/visual/_visual-helpers.ts b/tests/e2e/visual/_visual-helpers.ts index a96bb7b58..0d80da57c 100644 --- a/tests/e2e/visual/_visual-helpers.ts +++ b/tests/e2e/visual/_visual-helpers.ts @@ -1,3 +1,5 @@ +import type { Locator, Page } from '@playwright/test' + /* * SPDX-License-Identifier: EUPL-1.2 * @@ -24,7 +26,7 @@ * own baselines on first run, or (b) stay non-gating until baselined in the CI * environment. See tests/e2e/visual/README in-repo wiring notes. */ -import { expect, type Page, type Locator } from '@playwright/test' +import { expect } from '@playwright/test' /** Common screenshot options applied to every visual assertion. */ export const SHOT_OPTIONS = { diff --git a/tests/e2e/visual/filinq.visual.spec.ts b/tests/e2e/visual/filinq.visual.spec.ts index 440c23a01..6cfa893fa 100644 --- a/tests/e2e/visual/filinq.visual.spec.ts +++ b/tests/e2e/visual/filinq.visual.spec.ts @@ -11,7 +11,7 @@ * See _visual-helpers.ts for the platform-rendering caveat. */ import { test } from '@playwright/test' -import { shootSurface } from './_visual-helpers' +import { shootSurface } from './_visual-helpers.ts' const APP = '/index.php/apps/filinq' diff --git a/tests/e2e/workflows/_fixtures.ts b/tests/e2e/workflows/_fixtures.ts index 6fb049088..383411246 100644 --- a/tests/e2e/workflows/_fixtures.ts +++ b/tests/e2e/workflows/_fixtures.ts @@ -31,7 +31,9 @@ * concurrent runs never collide. */ -import { type APIRequestContext, type Page, expect } from '@playwright/test' +import type { APIRequestContext, Page } from '@playwright/test' + +import { expect } from '@playwright/test' /** Shared family prefix for ALL workflow-test artefacts (every run). */ export const TEST_FAMILY = 'e2eflow-' @@ -85,7 +87,6 @@ export async function harvestToken(page: Page): Promise { // naming the token, instead of failing later as a mysterious 412 on the // first write request. await page.waitForFunction( - // eslint-disable-next-line @typescript-eslint/no-explicit-any () => Boolean( (window as any).OC?.requestToken @@ -95,7 +96,6 @@ export async function harvestToken(page: Page): Promise { { timeout: 30_000 }, ) const token = await page.evaluate( - // eslint-disable-next-line @typescript-eslint/no-explicit-any () => (window as any).OC?.requestToken || document.head.dataset.requesttoken diff --git a/tests/e2e/workflows/agent-document-editing.spec.ts b/tests/e2e/workflows/agent-document-editing.spec.ts index 53d3508ce..785d94d04 100644 --- a/tests/e2e/workflows/agent-document-editing.spec.ts +++ b/tests/e2e/workflows/agent-document-editing.spec.ts @@ -31,9 +31,10 @@ * provider; it is not automatable here because it needs a live LLM credential. */ -import { test, expect, type APIRequestContext } from '@playwright/test' +import type { APIRequestContext } from '@playwright/test' -import { harvestToken, jsonHeaders, TEST_PREFIX } from './_fixtures' +import { expect, test } from '@playwright/test' +import { harvestToken, jsonHeaders, TEST_PREFIX } from './_fixtures.ts' /** OpenRegister's MCP JSON-RPC endpoint β€” the tool surface under test. */ const MCP = '/index.php/apps/openregister/api/mcp' @@ -159,7 +160,7 @@ async function callTool( ).toBeTruthy() const text = String(body.result.content?.[0]?.text ?? '') - let payload: Record = {} + let payload: Record try { payload = JSON.parse(text) } catch { diff --git a/tests/e2e/workflows/anonymization-workflow.spec.ts b/tests/e2e/workflows/anonymization-workflow.spec.ts index 4b9fd64d2..0faabc10c 100644 --- a/tests/e2e/workflows/anonymization-workflow.spec.ts +++ b/tests/e2e/workflows/anonymization-workflow.spec.ts @@ -36,22 +36,22 @@ * @spec openspec/specs/folder-batch-analysis/spec.md#requirement-folder-batch-initiation-from-existing-nextcloud-folder */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' import { APP, appUrl, dismissOverlays, waitForAppReady, -} from '../spec-coverage/_helpers' +} from '../spec-coverage/_helpers.ts' import { + API, + createDavFile, + createDavFolder, harvestToken, jsonHeaders, - API, - TEST_PREFIX, TEST_FAMILY, - createDavFolder, - createDavFile, -} from './_fixtures' + TEST_PREFIX, +} from './_fixtures.ts' test.describe.configure({ mode: 'serial' }) diff --git a/tests/e2e/workflows/consent-workflow.spec.ts b/tests/e2e/workflows/consent-workflow.spec.ts index 92c1ae269..e1f250ef4 100644 --- a/tests/e2e/workflows/consent-workflow.spec.ts +++ b/tests/e2e/workflows/consent-workflow.spec.ts @@ -29,18 +29,20 @@ * ------------------------------------------------------------------ */ -import { test, expect, type APIRequestContext } from '@playwright/test' -import { go, waitForAppReady } from '../spec-coverage/_helpers' +import type { APIRequestContext } from '@playwright/test' + +import { expect, test } from '@playwright/test' +import { go, waitForAppReady } from '../spec-coverage/_helpers.ts' import { API, - POLICY_PREFIX, createProhibition, createStandingConsent, getConsent, harvestToken, jsonHeaders, + POLICY_PREFIX, seedPolicyMatchedConsent, -} from './_fixtures' +} from './_fixtures.ts' /** Harvested once in `beforeAll`; every request helper needs it. */ let token = '' diff --git a/tests/e2e/workflows/dashboard-widget.spec.ts b/tests/e2e/workflows/dashboard-widget.spec.ts index ce3e40138..65237b786 100644 --- a/tests/e2e/workflows/dashboard-widget.spec.ts +++ b/tests/e2e/workflows/dashboard-widget.spec.ts @@ -19,8 +19,8 @@ * are all on markup that only this widget's template produces. */ -import { test, expect } from '@playwright/test' -import { harvestToken } from './_fixtures' +import { expect, test } from '@playwright/test' +import { harvestToken } from './_fixtures.ts' /** * Widget id β€” `FileEntitiesWidget::getId()` in lib/Dashboard/. diff --git a/tests/e2e/workflows/entity-relation-decision.spec.ts b/tests/e2e/workflows/entity-relation-decision.spec.ts index 1a3902026..afaccedcc 100644 --- a/tests/e2e/workflows/entity-relation-decision.spec.ts +++ b/tests/e2e/workflows/entity-relation-decision.spec.ts @@ -27,15 +27,17 @@ * @e2e consent-management::reversal-event-does-not-trigger-consent-creation */ -import { test, expect, type APIRequestContext, type Page } from '@playwright/test' +import type { APIRequestContext, Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' import { + API, + createDavFile, + createDavFolder, harvestToken, jsonHeaders, - API, TEST_PREFIX, - createDavFolder, - createDavFile, -} from './_fixtures' +} from './_fixtures.ts' const FOLDER = `${TEST_PREFIX}-reldecision` const TERM = `Beslissing Roerdomp ${TEST_PREFIX}` diff --git a/tests/e2e/workflows/entity-review.spec.ts b/tests/e2e/workflows/entity-review.spec.ts index 397a12a9f..79f3da922 100644 --- a/tests/e2e/workflows/entity-review.spec.ts +++ b/tests/e2e/workflows/entity-review.spec.ts @@ -50,17 +50,23 @@ * rather than cleaned up. */ -import { test, expect, type APIRequestContext, type Page } from '@playwright/test' -import { appUrl, dismissOverlays, waitForAppReady } from '../spec-coverage/_helpers' +import type { APIRequestContext, Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' +import { + appUrl, + dismissOverlays, + waitForAppReady, +} from '../spec-coverage/_helpers.ts' import { + API, + createDavFile, + createDavFolder, harvestToken, jsonHeaders, - API, - TEST_PREFIX, TEST_FAMILY, - createDavFolder, - createDavFile, -} from './_fixtures' + TEST_PREFIX, +} from './_fixtures.ts' test.describe.configure({ mode: 'serial' }) diff --git a/tests/e2e/workflows/file-viewer.spec.ts b/tests/e2e/workflows/file-viewer.spec.ts index f9b2eaf5f..32623c23d 100644 --- a/tests/e2e/workflows/file-viewer.spec.ts +++ b/tests/e2e/workflows/file-viewer.spec.ts @@ -16,15 +16,15 @@ * wrote β€” an assertion the SPA shell cannot satisfy by accident. */ -import { test, expect } from '@playwright/test' -import { go } from '../spec-coverage/_helpers' +import { expect, test } from '@playwright/test' +import { go } from '../spec-coverage/_helpers.ts' import { - harvestToken, - TEST_PREFIX, createDavFile, createDavFolder, deleteDavPath, -} from './_fixtures' + harvestToken, + TEST_PREFIX, +} from './_fixtures.ts' /** The folder MyDocumentsIndex lists by default (`myDocumentsStore.currentPath`). */ const DOCS_FOLDER = 'DocuDesk' diff --git a/tests/e2e/workflows/prohibition-override-audit-schema.spec.ts b/tests/e2e/workflows/prohibition-override-audit-schema.spec.ts index 272df70ce..39eda8fd6 100644 --- a/tests/e2e/workflows/prohibition-override-audit-schema.spec.ts +++ b/tests/e2e/workflows/prohibition-override-audit-schema.spec.ts @@ -33,8 +33,8 @@ * `.github#345` describes. */ -import { test, expect } from '@playwright/test' -import { harvestToken, jsonHeaders, TEST_PREFIX } from './_fixtures' +import { expect, test } from '@playwright/test' +import { harvestToken, jsonHeaders, TEST_PREFIX } from './_fixtures.ts' // `filinq`, not `consent`: the five registers were consolidated into one. const OR = '/index.php/apps/openregister/api/objects/filinq' diff --git a/tests/e2e/workflows/publication-policy-toggle.spec.ts b/tests/e2e/workflows/publication-policy-toggle.spec.ts index 3d354c449..655071446 100644 --- a/tests/e2e/workflows/publication-policy-toggle.spec.ts +++ b/tests/e2e/workflows/publication-policy-toggle.spec.ts @@ -98,8 +98,10 @@ * `TEST_PREFIX` and every assertion names only this run's strings. */ -import { test, expect, type APIRequestContext } from '@playwright/test' -import { harvestToken, jsonHeaders, API, TEST_PREFIX } from './_fixtures' +import type { APIRequestContext } from '@playwright/test' + +import { expect, test } from '@playwright/test' +import { API, harvestToken, jsonHeaders, TEST_PREFIX } from './_fixtures.ts' // Deliberately NOT `test.describe.configure({ mode: 'serial' })`, unlike most // files in this directory. The two tests below share no state β€” each seeds its diff --git a/tests/e2e/workflows/signing-workflow.spec.ts b/tests/e2e/workflows/signing-workflow.spec.ts index e16839897..1dd34de83 100644 --- a/tests/e2e/workflows/signing-workflow.spec.ts +++ b/tests/e2e/workflows/signing-workflow.spec.ts @@ -33,16 +33,16 @@ * @spec openspec/specs/document-signing/spec.md#view-signing-request-status */ -import { test, expect } from '@playwright/test' -import { go } from '../spec-coverage/_helpers' +import { expect, test } from '@playwright/test' +import { go } from '../spec-coverage/_helpers.ts' import { + API, + createDavFile, harvestToken, jsonHeaders, - API, - TEST_PREFIX, TEST_FAMILY, - createDavFile, -} from './_fixtures' + TEST_PREFIX, +} from './_fixtures.ts' // The views under test, named after the component files they cover. Routes are // unchanged β€” this makes the spec-to-component link readable in executable code diff --git a/tests/e2e/workflows/template-detail.spec.ts b/tests/e2e/workflows/template-detail.spec.ts index af484012f..e02b9440f 100644 --- a/tests/e2e/workflows/template-detail.spec.ts +++ b/tests/e2e/workflows/template-detail.spec.ts @@ -53,18 +53,24 @@ * that level. */ -import { test, expect, type APIRequestContext } from '@playwright/test' -import { appUrl, dismissOverlays, waitForAppReady } from '../spec-coverage/_helpers' +import type { APIRequestContext } from '@playwright/test' + +import { expect, test } from '@playwright/test' +import { + appUrl, + dismissOverlays, + waitForAppReady, +} from '../spec-coverage/_helpers.ts' import { - harvestToken, - jsonHeaders, API, createTemplate, - getTemplate, deleteTemplate, - TEST_PREFIX, + getTemplate, + harvestToken, + jsonHeaders, TEST_FAMILY, -} from './_fixtures' + TEST_PREFIX, +} from './_fixtures.ts' // Deliberately NOT `test.describe.configure({ mode: 'serial' })`. The two // tests seed and delete their own run-stamped templates and share no state, diff --git a/tests/e2e/workflows/templates-crud.spec.ts b/tests/e2e/workflows/templates-crud.spec.ts index 3fafd4aea..671a97e32 100644 --- a/tests/e2e/workflows/templates-crud.spec.ts +++ b/tests/e2e/workflows/templates-crud.spec.ts @@ -46,20 +46,20 @@ * @spec openspec/specs/template-management/spec.md#list-templates-with-namespace-filter */ -import { test, expect } from '@playwright/test' -import { go } from '../spec-coverage/_helpers' +import { expect, test } from '@playwright/test' +import { go } from '../spec-coverage/_helpers.ts' import { - harvestToken, - jsonHeaders, API, + cleanupTemplates, createTemplate, + deleteTemplate, getTemplate, + harvestToken, + jsonHeaders, listTemplates, - deleteTemplate, - cleanupTemplates, - TEST_PREFIX, TEST_FAMILY, -} from './_fixtures' + TEST_PREFIX, +} from './_fixtures.ts' // The views under test, named after the component files they cover. Routes are // unchanged β€” this makes the spec-to-component link readable in executable code diff --git a/tests/l10n/check-l10n.js b/tests/l10n/check-l10n.js index 70c2c26c3..922da5d31 100644 --- a/tests/l10n/check-l10n.js +++ b/tests/l10n/check-l10n.js @@ -128,7 +128,7 @@ function unescape (s) { const used = new Map() function record (key, file, idx, content) { - if (key == null) { + if ((key === null || key === undefined)) { return } const k = unescape(key) @@ -154,7 +154,7 @@ for (const file of files) { const missing = [] for (const [key, locations] of used) { - if (!Object.prototype.hasOwnProperty.call(translations, key)) { + if (!Object.hasOwn(translations, key)) { missing.push({ key, locations: [...locations] }) } } diff --git a/tests/unit/reachability.spec.js b/tests/unit/reachability.spec.js index 306d01a55..98c1a4b47 100644 --- a/tests/unit/reachability.spec.js +++ b/tests/unit/reachability.spec.js @@ -23,10 +23,10 @@ * and because this file needs zero DOM. */ -import { describe, it, expect } from 'vitest' import fs from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' +import { describe, expect, it } from 'vitest' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const REPO_ROOT = path.resolve(__dirname, '../..') diff --git a/tests/validate-manifest.js b/tests/validate-manifest.js index b3bd58612..5e2e52e59 100644 --- a/tests/validate-manifest.js +++ b/tests/validate-manifest.js @@ -93,7 +93,7 @@ function loadAjv() { // entry point. Prefer Ajv 8 (`ajv/dist/2020`) when available; otherwise // fall back to whichever ajv resolves first. let Ajv2020 = null - let addFormats = null + let addFormats const ajvCandidates = [ 'ajv/dist/2020', path.join( diff --git a/tests/vitest/anonymizationGetters.spec.js b/tests/vitest/anonymizationGetters.spec.js index b3714b043..75f3270d4 100644 --- a/tests/vitest/anonymizationGetters.spec.js +++ b/tests/vitest/anonymizationGetters.spec.js @@ -14,8 +14,8 @@ * scope. */ -import { describe, it, expect, beforeEach } from 'vitest' import { createPinia, setActivePinia } from 'pinia' +import { beforeEach, describe, expect, it } from 'vitest' import { useAnonymizationStore } from '../../src/store/modules/anonymization.js' beforeEach(() => { diff --git a/tests/vitest/comparisonService.spec.js b/tests/vitest/comparisonService.spec.js index 545302ef9..f3dc6d8a5 100644 --- a/tests/vitest/comparisonService.spec.js +++ b/tests/vitest/comparisonService.spec.js @@ -8,7 +8,7 @@ * and @nextcloud/router are mocked. */ -import { describe, it, expect, vi, beforeEach } from 'vitest' +import { beforeEach, describe, expect, it, vi } from 'vitest' const postMock = vi.fn() diff --git a/tests/vitest/fileViewerService.spec.js b/tests/vitest/fileViewerService.spec.js index 232d04b44..e7f45548a 100644 --- a/tests/vitest/fileViewerService.spec.js +++ b/tests/vitest/fileViewerService.spec.js @@ -12,7 +12,7 @@ * unauthenticated guard. @nextcloud/auth + router are stubbed. */ -import { describe, it, expect, afterEach } from 'vitest' +import { afterEach, describe, expect, it } from 'vitest' import { buildWebdavUrl } from '../../src/services/fileViewerService.js' import { __setCurrentUser } from '../../tests/vitest/stubs/nextcloud-auth.js' diff --git a/tests/vitest/registerI18n.spec.js b/tests/vitest/registerI18n.spec.js index 009468978..f89fbdcbb 100644 --- a/tests/vitest/registerI18n.spec.js +++ b/tests/vitest/registerI18n.spec.js @@ -13,7 +13,7 @@ * @spec openspec/specs/register-i18n/spec.md */ -import { describe, it, expect, vi } from 'vitest' +import { describe, expect, it, vi } from 'vitest' vi.mock('@nextcloud/l10n', () => ({ getLanguage: () => 'en', diff --git a/tests/vitest/settingsStore.spec.js b/tests/vitest/settingsStore.spec.js index 4906370e5..d7268521f 100644 --- a/tests/vitest/settingsStore.spec.js +++ b/tests/vitest/settingsStore.spec.js @@ -9,8 +9,8 @@ * global are mocked. */ -import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { createPinia, setActivePinia } from 'pinia' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { useSettingsStore } from '../../src/store/modules/settings.js' beforeEach(() => { diff --git a/tests/vitest/validationService.spec.js b/tests/vitest/validationService.spec.js index 8ddccf6f2..968e46a06 100644 --- a/tests/vitest/validationService.spec.js +++ b/tests/vitest/validationService.spec.js @@ -7,7 +7,7 @@ * @nextcloud/router are mocked. */ -import { describe, it, expect, vi, beforeEach } from 'vitest' +import { beforeEach, describe, expect, it, vi } from 'vitest' const postMock = vi.fn()