From f0cd59a7b9909887f0df2f9906af1b1065f979fe Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Tue, 1 Sep 2026 11:53:43 +0200 Subject: [PATCH] chore(lint): let the linter see tests/ and scripts/ `npm run lint` was `eslint src`, so two whole trees were never linted. Across the fleet that hid roughly 3,900 errors, none of which any CI leg had shown. Most of it was the config, not the code, and the same two defects were in every app. **scripts/ had no config block at all.** These are CommonJS Node CLI checkers, and flat config defaults every `.js` to ESM with browser-ish globals, so eslint read the CommonJS wrapper itself as undefined identifiers: `require`, `process`, `__dirname`, `__filename`, `module`. A `scripts/**` block now declares the environment. Declaring beats suppressing here: `no-undef` is the rule that catches a genuinely misspelled identifier, and dozens of fake findings would bury a real one. A second block covers `scripts/**/*.mjs`, which is ESM and needs Node's globals without the CommonJS wrapper. **The tests block applied a non-TypeScript-aware rule to TypeScript.** It named `tests/**/*.ts` while setting the CORE `no-unused-vars`, which v9 deliberately turns off for `.ts` in favour of the `@typescript-eslint` version. The core rule reads the parameter names inside a function TYPE as bindings, so t?: (app: string, key: string) => string reports `app` and `key` as unused variables, and every unused `catch (e)` in a `.ts` spec reports twice. The block is split now: `.js`/`.mjs` on the core rule, `.ts`/`.tsx` on the TypeScript one, same patterns on both. Also: stale `eslint-disable` comments naming plugins eslint 10 no longer registers, which are themselves errors ("Definition for rule ... was not found"), and a rule that must not parse shell scripts. The genuinely real findings were the useful part: dead locals, unused imports, dead helper functions, unused `catch` bindings, extensionless relative imports, and a handful of `== null` comparisons spelled out so they still match null AND undefined. Verified per app: `npm run lint` 0 errors over src + tests + scripts, `prettier --check` clean, and the unit suite still green. --- eslint.config.mjs | 141 +++++++++++++++++- package.json | 2 +- scripts/build-l10n-js.js | 3 + scripts/check-schema-l10n.js | 3 + scripts/generate-manifest-shell.js | 4 +- tests/check-manifest-budget.js | 4 - tests/e2e/AccountantPortalDashboard.spec.js | 2 +- tests/e2e/DeadlineCalendarSettings.spec.js | 2 +- tests/e2e/NavSixClusters.spec.js | 2 +- tests/e2e/ar-invoice-einvoice.spec.ts | 4 +- tests/e2e/bank-statement-wizard.spec.ts | 4 +- tests/e2e/base-url.ts | 1 - tests/e2e/bbv-compliance.spec.ts | 4 +- tests/e2e/bill-import-modal.spec.ts | 4 +- tests/e2e/bookings-calendar.spec.ts | 2 +- .../bookings-notification-triggers.spec.ts | 2 +- tests/e2e/bookings-resource-calendar.spec.ts | 4 +- tests/e2e/bookings-screenshots.spec.ts | 6 +- tests/e2e/bookings-widget-embed.spec.ts | 2 +- tests/e2e/bookkeeping-foundation.spec.ts | 2 +- tests/e2e/bookkeeping-ifrs15-revenue.spec.ts | 2 +- tests/e2e/bookkeeping-period-close.spec.ts | 2 +- .../bookkeeping-tenderned-integratie.spec.ts | 8 +- .../e2e/bookkeeping-vpb-corporate-tax.spec.ts | 8 +- .../bookkeeping-vpb-quarterly-report.spec.ts | 8 +- tests/e2e/budget-line-commitments.spec.ts | 4 +- tests/e2e/cashflow-13wk.spec.ts | 2 +- tests/e2e/cbs-submissions.spec.ts | 5 +- tests/e2e/chart-of-accounts.spec.ts | 2 +- tests/e2e/contracts-single-home.spec.ts | 4 +- tests/e2e/docs-screenshots.spec.ts | 6 +- tests/e2e/external-adapters.spec.ts | 4 +- tests/e2e/financial-dashboard.spec.ts | 2 +- tests/e2e/global-setup.ts | 15 +- tests/e2e/icp-opgaaf.spec.ts | 2 +- tests/e2e/innovatiebox-administratie.spec.ts | 2 +- tests/e2e/inventory-mobile-scanner.spec.ts | 2 +- tests/e2e/invoice-quick-draft.spec.ts | 2 +- tests/e2e/l10n-browser-catalogue.spec.ts | 3 +- tests/e2e/list-views-cndatatable.spec.ts | 2 +- tests/e2e/order-primitive.spec.ts | 8 +- tests/e2e/oss-btw-eu.spec.ts | 2 +- tests/e2e/pipelinq-customer-bridge.spec.ts | 2 +- tests/e2e/playwright.config.ts | 3 +- tests/e2e/provincies-bbv-routes-smoke.spec.ts | 4 +- tests/e2e/provincies-bbv-variant.spec.ts | 4 +- tests/e2e/receipt-extraction-consume.spec.ts | 4 +- tests/e2e/recurring-invoicing.spec.ts | 2 +- tests/e2e/retire-cost-project.spec.ts | 2 +- tests/e2e/setup-wizard-english.spec.ts | 9 +- tests/e2e/spec-coverage/_helpers.ts | 4 +- tests/e2e/spec-coverage/belastingen.spec.ts | 4 +- tests/e2e/spec-coverage/bookkeeping.spec.ts | 4 +- .../spec-coverage/cashflow-pension.spec.ts | 4 +- .../spec-coverage/dashboard-settings.spec.ts | 8 +- .../demo-data-setup-step.spec.ts | 8 +- tests/e2e/spec-coverage/dimensions.spec.ts | 6 +- tests/e2e/spec-coverage/inkoop.spec.ts | 2 +- tests/e2e/spec-coverage/inventory.spec.ts | 4 +- .../spec-coverage/overheid-compliance.spec.ts | 4 +- tests/e2e/spec-coverage/projecten.spec.ts | 4 +- tests/e2e/standards-policy-editor.spec.ts | 2 +- tests/e2e/trial-balance.spec.ts | 2 +- tests/e2e/visual/_visual-helpers.ts | 4 +- .../visual/external-adapters.visual.spec.ts | 10 +- tests/e2e/visual/shillinq.visual.spec.ts | 2 +- .../waterschappen-bbv-routes-smoke.spec.ts | 2 +- tests/e2e/waterschappen-bbv-variant.spec.ts | 5 +- tests/e2e/workflows/_fixtures.ts | 10 +- .../workflows/external-adapters-admin.spec.ts | 4 +- tests/e2e/workflows/fin-account-crud.spec.ts | 8 +- .../workflows/fin-lease-amortization.spec.ts | 8 +- tests/e2e/workflows/fin-oss-vat-rate.spec.ts | 8 +- tests/e2e/workflows/fin-trial-balance.spec.ts | 8 +- tests/l10n/check-l10n-parity.js | 6 +- tests/l10n/check-l10n.js | 4 +- .../customer-bridge-profile-helpers.test.mjs | 79 ++++++---- .../inventory-mobile-scanner-helpers.test.mjs | 27 +++- tests/validate-fragment-required.js | 4 +- tests/validate-semantic-markers.js | 4 +- tests/vitest/accountantPortalRouting.spec.js | 2 +- tests/vitest/arEInvoiceActions.spec.js | 6 +- tests/vitest/bankStatementWizard.spec.js | 8 +- tests/vitest/bbvLinkerFilterBar.spec.js | 2 +- tests/vitest/billImportModal.spec.js | 24 +-- tests/vitest/bookingsCalendarView.spec.js | 2 +- .../budgetLineCommitmentsHelpers.spec.js | 6 +- tests/vitest/deadlineCalendarSettings.spec.js | 2 +- tests/vitest/externalAdapters.spec.js | 2 +- tests/vitest/financialSeries.spec.js | 22 +-- tests/vitest/generateManifestShell.spec.js | 3 +- tests/vitest/invoiceQuickDraft.spec.js | 10 +- tests/vitest/listViewsCnDataTable.spec.js | 8 +- .../vitest/mergeFragmentIntoManifest.spec.js | 4 +- tests/vitest/receiptCapture.spec.js | 6 +- tests/vitest/recurringInvoiceProfile.spec.js | 4 +- tests/vitest/settingsStore.spec.js | 2 +- tests/vitest/spendAnalyticsPanel.spec.js | 2 +- 98 files changed, 444 insertions(+), 243 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 9bad6e2d4..6d6c921b5 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,116 @@ 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 952e3f9bf..f4a9f9737 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "postdev": "[ -d ../openregister/custom_apps/shillinq/js ] && cp -r js/. ../openregister/custom_apps/shillinq/js/ || true", "prewatch": "node scripts/generate-manifest-shell.js", "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", "test:l10n": "node tests/l10n/check-l10n.js", "test:l10n-parity": "L10N_REQUIRED_LOCALES=nl node tests/l10n/check-l10n-parity.js", 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-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/generate-manifest-shell.js b/scripts/generate-manifest-shell.js index 87f091b71..94d42408b 100644 --- a/scripts/generate-manifest-shell.js +++ b/scripts/generate-manifest-shell.js @@ -62,7 +62,7 @@ function slimPages(pages, fragment) { return pages.map((page) => { const slim = { _fragment: fragment } for (const key of SHELL_PAGE_KEYS) { - if (page && Object.prototype.hasOwnProperty.call(page, key)) { + if (page && Object.hasOwn(page, key)) { slim[key] = page[key] } } @@ -135,7 +135,7 @@ function generateShellDocument(dir = MANIFEST_D_DIR) { function main() { const shell = generateShellDocument() fs.writeFileSync(SHELL_OUTPUT_PATH, JSON.stringify(shell, null, '\t') + '\n') - // eslint-disable-next-line no-console + console.log( `[generate-manifest-shell] wrote ${SHELL_OUTPUT_PATH} ` + `(${shell.fragments.length} fragments, ` diff --git a/tests/check-manifest-budget.js b/tests/check-manifest-budget.js index 5a3d8d0f9..b845e1065 100644 --- a/tests/check-manifest-budget.js +++ b/tests/check-manifest-budget.js @@ -173,7 +173,6 @@ function main() { manifestSize = fs.statSync(MANIFEST_PATH).size fragmentsSize = sumJsonFileSizes(MANIFEST_D_DIR) } catch (err) { - // eslint-disable-next-line no-console console.error( `[check-manifest-budget] could not read manifest files: ${err.message}`, ) @@ -183,14 +182,12 @@ function main() { const total = manifestSize + fragmentsSize - // eslint-disable-next-line no-console console.log( `[check-manifest-budget] manifest.json=${manifestSize}B manifest.d/=${fragmentsSize}B ` + `total=${total}B budget=${budget}B`, ) if (total > budget) { - // eslint-disable-next-line no-console console.error( `[check-manifest-budget] FAIL: combined manifest JSON (${total}B) exceeds the ` + `${budget}B budget shipped in the main webpack chunk (REQ-MBP-001). Either trim ` @@ -201,7 +198,6 @@ function main() { return } - // eslint-disable-next-line no-console console.log('[check-manifest-budget] PASS') } diff --git a/tests/e2e/AccountantPortalDashboard.spec.js b/tests/e2e/AccountantPortalDashboard.spec.js index 9a368b609..903631a46 100644 --- a/tests/e2e/AccountantPortalDashboard.spec.js +++ b/tests/e2e/AccountantPortalDashboard.spec.js @@ -29,7 +29,7 @@ * @spec openspec/changes/accountant-portal/specs/accountant-portal/spec.md#req-acp-002 */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' import { becomesVisible } from './becomes-visible.js' const APP = '/apps/shillinq' diff --git a/tests/e2e/DeadlineCalendarSettings.spec.js b/tests/e2e/DeadlineCalendarSettings.spec.js index 47a501cf4..d1c1af103 100644 --- a/tests/e2e/DeadlineCalendarSettings.spec.js +++ b/tests/e2e/DeadlineCalendarSettings.spec.js @@ -30,7 +30,7 @@ * @spec openspec/changes/compliance-deadline-calendar/specs/compliance-deadline-calendar/spec.md#req-cdc-006 */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' import { becomesVisible } from './becomes-visible.js' const APP = '/apps/shillinq' diff --git a/tests/e2e/NavSixClusters.spec.js b/tests/e2e/NavSixClusters.spec.js index ad12d1279..049ef39e4 100644 --- a/tests/e2e/NavSixClusters.spec.js +++ b/tests/e2e/NavSixClusters.spec.js @@ -35,7 +35,7 @@ * @spec openspec/changes/nav-six-clusters/specs/nav-clusters/spec.md#req-navc-009 */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' import { becomesVisible } from './becomes-visible.js' const APP = '/apps/shillinq' diff --git a/tests/e2e/ar-invoice-einvoice.spec.ts b/tests/e2e/ar-invoice-einvoice.spec.ts index eff4413a0..d913c3d31 100644 --- a/tests/e2e/ar-invoice-einvoice.spec.ts +++ b/tests/e2e/ar-invoice-einvoice.spec.ts @@ -24,7 +24,9 @@ * @spec openspec/changes/add-invoice-pdf-export-with-ubl-peppol-support/specs/bookkeeping-einvoicing-ubl-peppol/spec.md#req-einv-007 */ -import { test, expect, type Page } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' const ROUTE_AR = '/bookkeeping/accounts-receivable' diff --git a/tests/e2e/bank-statement-wizard.spec.ts b/tests/e2e/bank-statement-wizard.spec.ts index 9865d6d64..c9dc474e8 100644 --- a/tests/e2e/bank-statement-wizard.spec.ts +++ b/tests/e2e/bank-statement-wizard.spec.ts @@ -26,7 +26,9 @@ * @spec openspec/specs/shillinq-bank-statement-wizard/spec.md */ -import { test, expect, type Page } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' import { becomesVisible } from './becomes-visible.js' const APP = '/apps/shillinq' diff --git a/tests/e2e/base-url.ts b/tests/e2e/base-url.ts index 4184c025c..d3aeeb1f0 100644 --- a/tests/e2e/base-url.ts +++ b/tests/e2e/base-url.ts @@ -60,7 +60,6 @@ export function resolveBaseURL(): string { } if (process.env.GITHUB_ACTIONS === 'true' || process.env.CI) { - // eslint-disable-next-line no-console console.warn( `[shillinq e2e] none of ${BASE_URL_ENV_NAMES.join(' / ')} is set; ` + `falling back to the CI-local ${CI_DEFAULT_BASE_URL}.`, diff --git a/tests/e2e/bbv-compliance.spec.ts b/tests/e2e/bbv-compliance.spec.ts index a0ddda74e..98ecb4a88 100644 --- a/tests/e2e/bbv-compliance.spec.ts +++ b/tests/e2e/bbv-compliance.spec.ts @@ -21,7 +21,9 @@ * @spec openspec/changes/bookkeeping-bbv-compliance/tasks.md (Tasks 5.13-5.19) */ -import { test, expect, type Page } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' const ROUTE_IV3_AANLEVERING = '/overheid/iv3-aanlevering' diff --git a/tests/e2e/bill-import-modal.spec.ts b/tests/e2e/bill-import-modal.spec.ts index d429f0bd2..7ba42e9dd 100644 --- a/tests/e2e/bill-import-modal.spec.ts +++ b/tests/e2e/bill-import-modal.spec.ts @@ -22,7 +22,9 @@ * @spec openspec/specs/shillinq-bill-import-modal/spec.md */ -import { test, expect, type Page } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' const ROUTE_FINANCIAL = '/financial' diff --git a/tests/e2e/bookings-calendar.spec.ts b/tests/e2e/bookings-calendar.spec.ts index be793e247..1d2e99f48 100644 --- a/tests/e2e/bookings-calendar.spec.ts +++ b/tests/e2e/bookings-calendar.spec.ts @@ -22,7 +22,7 @@ * scenario against the bookings-resource-calendar spec. */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/bookings-notification-triggers.spec.ts b/tests/e2e/bookings-notification-triggers.spec.ts index 95adf9de8..50d66d675 100644 --- a/tests/e2e/bookings-notification-triggers.spec.ts +++ b/tests/e2e/bookings-notification-triggers.spec.ts @@ -17,7 +17,7 @@ * @spec openspec/changes/bookings-notification-triggers/tasks.md#task-17 */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' const NOTIFICATION_TRIGGERS_ROUTE = '/communication/notification-triggers' diff --git a/tests/e2e/bookings-resource-calendar.spec.ts b/tests/e2e/bookings-resource-calendar.spec.ts index 7271cd9ec..df4bc81e7 100644 --- a/tests/e2e/bookings-resource-calendar.spec.ts +++ b/tests/e2e/bookings-resource-calendar.spec.ts @@ -35,7 +35,9 @@ * @spec openspec/changes/bookings-resource-calendar/tasks.md#task-11 */ -import { test, expect, type Page } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/bookings-screenshots.spec.ts b/tests/e2e/bookings-screenshots.spec.ts index 74bab86a7..e71313869 100644 --- a/tests/e2e/bookings-screenshots.spec.ts +++ b/tests/e2e/bookings-screenshots.spec.ts @@ -26,9 +26,11 @@ * automatically (URL is unchanged from the docs). */ -import { test, expect, type Page } from '@playwright/test' -import * as path from 'path' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' import * as fs from 'fs' +import * as path from 'path' const SHOT_ROOT = path.resolve( __dirname, diff --git a/tests/e2e/bookings-widget-embed.spec.ts b/tests/e2e/bookings-widget-embed.spec.ts index b76ceac42..9c353a1de 100644 --- a/tests/e2e/bookings-widget-embed.spec.ts +++ b/tests/e2e/bookings-widget-embed.spec.ts @@ -30,7 +30,7 @@ * @spec openspec/changes/bookings-self-service-widget/tasks.md#task-21 */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' const SERVICES_API = APP + '/api/widget/services' diff --git a/tests/e2e/bookkeeping-foundation.spec.ts b/tests/e2e/bookkeeping-foundation.spec.ts index 595c0d962..33dbefeaa 100644 --- a/tests/e2e/bookkeeping-foundation.spec.ts +++ b/tests/e2e/bookkeeping-foundation.spec.ts @@ -30,7 +30,7 @@ * "page mounted on the correct route", not "list has N rows". */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/bookkeeping-ifrs15-revenue.spec.ts b/tests/e2e/bookkeeping-ifrs15-revenue.spec.ts index 07a81cfbf..9ebdbaa10 100644 --- a/tests/e2e/bookkeeping-ifrs15-revenue.spec.ts +++ b/tests/e2e/bookkeeping-ifrs15-revenue.spec.ts @@ -26,7 +26,7 @@ * @spec openspec/changes/bookkeeping-ifrs15-revenue/tasks.md#browser-tests */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/bookkeeping-period-close.spec.ts b/tests/e2e/bookkeeping-period-close.spec.ts index 2e0a7a62f..663cc357a 100644 --- a/tests/e2e/bookkeeping-period-close.spec.ts +++ b/tests/e2e/bookkeeping-period-close.spec.ts @@ -27,7 +27,7 @@ * @spec openspec/changes/bookkeeping-period-close/tasks.md#task-16 */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' const INDEX_PATH = '/bookkeeping/period-close' diff --git a/tests/e2e/bookkeeping-tenderned-integratie.spec.ts b/tests/e2e/bookkeeping-tenderned-integratie.spec.ts index 3bb758964..133c8ca04 100644 --- a/tests/e2e/bookkeeping-tenderned-integratie.spec.ts +++ b/tests/e2e/bookkeeping-tenderned-integratie.spec.ts @@ -22,13 +22,13 @@ * @spec openspec/specs/bookkeeping-tenderned-integratie/spec.md#req-001 */ -import { test, expect } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' -const dismissWizard = async ( - page: import('@playwright/test').Page, -): Promise => { +async function dismissWizard(page: Page): Promise { const wizard = page.locator('#firstrunwizard') if (await wizard.isVisible().catch(() => false)) { await page.keyboard.press('Escape').catch(() => {}) diff --git a/tests/e2e/bookkeeping-vpb-corporate-tax.spec.ts b/tests/e2e/bookkeeping-vpb-corporate-tax.spec.ts index f669f0961..b0b6eec19 100644 --- a/tests/e2e/bookkeeping-vpb-corporate-tax.spec.ts +++ b/tests/e2e/bookkeeping-vpb-corporate-tax.spec.ts @@ -36,13 +36,13 @@ * @spec openspec/changes/bookkeeping-vpb-corporate-tax/tasks.md#task-42 */ -import { test, expect } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' -const dismissWizard = async ( - page: import('@playwright/test').Page, -): Promise => { +async function dismissWizard(page: Page): Promise { const wizard = page.locator('#firstrunwizard') if (await wizard.isVisible().catch(() => false)) { await page.keyboard.press('Escape').catch(() => {}) diff --git a/tests/e2e/bookkeeping-vpb-quarterly-report.spec.ts b/tests/e2e/bookkeeping-vpb-quarterly-report.spec.ts index a6149ddad..1d0a4a528 100644 --- a/tests/e2e/bookkeeping-vpb-quarterly-report.spec.ts +++ b/tests/e2e/bookkeeping-vpb-quarterly-report.spec.ts @@ -34,13 +34,13 @@ * @spec openspec/changes/bookkeeping-vpb-corporate-tax/tasks.md#task-43 */ -import { test, expect } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' -const dismissWizard = async ( - page: import('@playwright/test').Page, -): Promise => { +async function dismissWizard(page: Page): Promise { const wizard = page.locator('#firstrunwizard') if (await wizard.isVisible().catch(() => false)) { await page.keyboard.press('Escape').catch(() => {}) diff --git a/tests/e2e/budget-line-commitments.spec.ts b/tests/e2e/budget-line-commitments.spec.ts index eb324bb48..a9b141b82 100644 --- a/tests/e2e/budget-line-commitments.spec.ts +++ b/tests/e2e/budget-line-commitments.spec.ts @@ -31,7 +31,9 @@ * @spec openspec/changes/verplichtingen-commitment-accounting/specs/bookkeeping-verplichtingenadministratie/spec.md#req-vpl-011 */ -import { test, expect, type Page } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' import { becomesVisible } from './becomes-visible.js' const APP = '/apps/shillinq' diff --git a/tests/e2e/cashflow-13wk.spec.ts b/tests/e2e/cashflow-13wk.spec.ts index 66dac4a8e..5ac51654f 100644 --- a/tests/e2e/cashflow-13wk.spec.ts +++ b/tests/e2e/cashflow-13wk.spec.ts @@ -13,7 +13,7 @@ * @spec openspec/changes/zzp-cashflow-13wk/tasks.md#task-30 */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/cbs-submissions.spec.ts b/tests/e2e/cbs-submissions.spec.ts index a7d23bb7a..08b61c85a 100644 --- a/tests/e2e/cbs-submissions.spec.ts +++ b/tests/e2e/cbs-submissions.spec.ts @@ -42,7 +42,9 @@ * @e2e security-endpoint-guards/req-001/cbs-submissions-delete-own-draft */ -import { test, expect, type Page, type APIRequestContext } from '@playwright/test' +import type { APIRequestContext, Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' const LIST_ROUTE = '/bookkeeping/cbs-submissions' @@ -113,7 +115,6 @@ async function cleanupViaOpenRegister( headers: { 'OCS-APIRequest': 'true' }, }) if (deleted.ok() === false && deleted.status() !== 404) { - // eslint-disable-next-line no-console console.warn( `[cbs-submissions] failed to clean up seeded submission ${id}: HTTP ${deleted.status()}`, ) diff --git a/tests/e2e/chart-of-accounts.spec.ts b/tests/e2e/chart-of-accounts.spec.ts index 68ee66a67..b75723607 100644 --- a/tests/e2e/chart-of-accounts.spec.ts +++ b/tests/e2e/chart-of-accounts.spec.ts @@ -10,7 +10,7 @@ * scenario tags are emitted. */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/contracts-single-home.spec.ts b/tests/e2e/contracts-single-home.spec.ts index 8f8f8770c..d9e3d6cbf 100644 --- a/tests/e2e/contracts-single-home.spec.ts +++ b/tests/e2e/contracts-single-home.spec.ts @@ -35,7 +35,9 @@ * @spec openspec/changes/contracts-single-home/specs/contracts-single-home/spec.md */ -import { test, expect, Page } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/docs-screenshots.spec.ts b/tests/e2e/docs-screenshots.spec.ts index df6389715..2520f4ada 100644 --- a/tests/e2e/docs-screenshots.spec.ts +++ b/tests/e2e/docs-screenshots.spec.ts @@ -38,9 +38,11 @@ * Pattern reference: ADR-030 (hydra/openspec/architecture/). */ -import { test, expect, type Page } from '@playwright/test' -import * as path from 'path' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' import * as fs from 'fs' +import * as path from 'path' const SHOT_ROOT = path.resolve( __dirname, diff --git a/tests/e2e/external-adapters.spec.ts b/tests/e2e/external-adapters.spec.ts index bbc8bbc5b..5f94a25a8 100644 --- a/tests/e2e/external-adapters.spec.ts +++ b/tests/e2e/external-adapters.spec.ts @@ -1,3 +1,5 @@ +import type { ConsoleMessage, Page } from '@playwright/test' + /* * SPDX-FileCopyrightText: 2026 Conduction B.V. * SPDX-License-Identifier: EUPL-1.2 @@ -33,7 +35,7 @@ * * @spec openspec/changes/integration-config-to-openconnector/specs/integration-config-to-openconnector/spec.md */ -import { test, expect, type Page, type ConsoleMessage } from '@playwright/test' +import { expect, test } from '@playwright/test' import { readdirSync, readFileSync, statSync } from 'node:fs' import { join } from 'node:path' diff --git a/tests/e2e/financial-dashboard.spec.ts b/tests/e2e/financial-dashboard.spec.ts index d870f816d..be3c34395 100644 --- a/tests/e2e/financial-dashboard.spec.ts +++ b/tests/e2e/financial-dashboard.spec.ts @@ -57,7 +57,7 @@ * @e2e apphost-adoption::app-ui-is-unaffected-by-the-generic-controllers */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/global-setup.ts b/tests/e2e/global-setup.ts index 45577b60a..b5abe578e 100644 --- a/tests/e2e/global-setup.ts +++ b/tests/e2e/global-setup.ts @@ -20,11 +20,13 @@ * adopter). */ -import { chromium, request, type FullConfig, type Page } from '@playwright/test' -import { resolveBaseURL } from './base-url' +import type { FullConfig, Page } from '@playwright/test' + +import { chromium, request } from '@playwright/test' import { execSync } from 'child_process' -import * as path from 'path' import * as fs from 'fs' +import * as path from 'path' +import { resolveBaseURL } from './base-url.ts' const AUTH_DIR = path.resolve(__dirname, '.auth') const STORAGE_STATE = path.join(AUTH_DIR, 'admin.json') @@ -72,13 +74,12 @@ function ensureBundleBuilt(): void { return } if (fs.existsSync(BUNDLE_PATH)) { - // eslint-disable-next-line no-console console.log( `[playwright globalSetup] bundle at ${BUNDLE_PATH} is only ` + `${fs.statSync(BUNDLE_PATH).size} bytes (floor ${MIN_BUNDLE_BYTES}); rebuilding.`, ) } - // eslint-disable-next-line no-console + console.log( `[playwright globalSetup] bundle missing at ${BUNDLE_PATH}; running 'npm run build' once…`, ) @@ -170,7 +171,7 @@ async function markWalkthroughSeen(page: Page): Promise { + 'The walkthrough overlay would intercept pointer events for the whole run.', ) } - // eslint-disable-next-line no-console + console.log( `[playwright globalSetup] ${WALKTHROUGH_SEEN_KEY} = ${version} (walkthrough will not auto-start)`, ) @@ -212,7 +213,7 @@ async function markSetupWizardDismissed(page: Page): Promise { + 'The setup wizard would render over the shell and intercept pointer events for the whole run.', ) } - // eslint-disable-next-line no-console + console.log( '[playwright globalSetup] cn-setup-wizard-dismissed:shillinq:0..20 = 1 (setup wizard will not auto-open)', ) diff --git a/tests/e2e/icp-opgaaf.spec.ts b/tests/e2e/icp-opgaaf.spec.ts index 4883eade6..01481a716 100644 --- a/tests/e2e/icp-opgaaf.spec.ts +++ b/tests/e2e/icp-opgaaf.spec.ts @@ -27,7 +27,7 @@ * @spec openspec/changes/bookkeeping-icp-opgaaf/tasks.md */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/innovatiebox-administratie.spec.ts b/tests/e2e/innovatiebox-administratie.spec.ts index 8607ac6f3..e1404c590 100644 --- a/tests/e2e/innovatiebox-administratie.spec.ts +++ b/tests/e2e/innovatiebox-administratie.spec.ts @@ -20,7 +20,7 @@ * register fragment is imported into a running instance. */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/inventory-mobile-scanner.spec.ts b/tests/e2e/inventory-mobile-scanner.spec.ts index 5251d4b1d..3c44788a7 100644 --- a/tests/e2e/inventory-mobile-scanner.spec.ts +++ b/tests/e2e/inventory-mobile-scanner.spec.ts @@ -12,7 +12,7 @@ * @spec openspec/changes/inventory-mobile-scanner/tasks.md */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/invoice-quick-draft.spec.ts b/tests/e2e/invoice-quick-draft.spec.ts index d9ae455ef..56f322f79 100644 --- a/tests/e2e/invoice-quick-draft.spec.ts +++ b/tests/e2e/invoice-quick-draft.spec.ts @@ -31,7 +31,7 @@ * @spec openspec/changes/shillinq-invoice-quick-draft/specs/shillinq-invoice-quick-draft/spec.md */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/l10n-browser-catalogue.spec.ts b/tests/e2e/l10n-browser-catalogue.spec.ts index 047d6072c..1197e6aab 100644 --- a/tests/e2e/l10n-browser-catalogue.spec.ts +++ b/tests/e2e/l10n-browser-catalogue.spec.ts @@ -39,11 +39,10 @@ * nothing about apps whose translations differ. */ +import { expect, test } from '@playwright/test' import { readFileSync } from 'node:fs' import path from 'node:path' -import { expect, test } from '@playwright/test' - /** * The app id this repo declares. Resolved from the repo root by walking up * from this file, so it does not depend on the working directory playwright diff --git a/tests/e2e/list-views-cndatatable.spec.ts b/tests/e2e/list-views-cndatatable.spec.ts index 0ba6e75d4..33d9d8ec0 100644 --- a/tests/e2e/list-views-cndatatable.spec.ts +++ b/tests/e2e/list-views-cndatatable.spec.ts @@ -24,7 +24,7 @@ * @spec openspec/changes/migrate-list-views-to-cndatatable/specs/list-views-cndatatable/spec.md */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/order-primitive.spec.ts b/tests/e2e/order-primitive.spec.ts index c8fede7e4..53db47f92 100644 --- a/tests/e2e/order-primitive.spec.ts +++ b/tests/e2e/order-primitive.spec.ts @@ -33,8 +33,10 @@ * @e2e order-primitive::a-transition-never-crosses-ordertype-boundaries */ -import { test, expect, request as pwRequest } from '@playwright/test' -import { OrFixtures, UNIQUE_PREFIX } from './workflows/_fixtures' +import type { APIRequestContext } from '@playwright/test' + +import { expect, request as pwRequest, test } from '@playwright/test' +import { OrFixtures, UNIQUE_PREFIX } from './workflows/_fixtures.ts' const SCHEMA = 'OrderPrimitive' const ADMIN_ID = 'ADM-001' @@ -76,7 +78,7 @@ test.describe('order-primitive β€” Order fold + orderType-gated lifecycle (#503) // can manufacture green in CI. let fx: OrFixtures - let api: import('@playwright/test').APIRequestContext + let api: APIRequestContext test.beforeAll(async ({ baseURL }) => { api = await pwRequest.newContext({ diff --git a/tests/e2e/oss-btw-eu.spec.ts b/tests/e2e/oss-btw-eu.spec.ts index b2fcb2f43..24b4334d6 100644 --- a/tests/e2e/oss-btw-eu.spec.ts +++ b/tests/e2e/oss-btw-eu.spec.ts @@ -17,7 +17,7 @@ * emitted by this smoke. */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/pipelinq-customer-bridge.spec.ts b/tests/e2e/pipelinq-customer-bridge.spec.ts index bf2f12138..ee340f13d 100644 --- a/tests/e2e/pipelinq-customer-bridge.spec.ts +++ b/tests/e2e/pipelinq-customer-bridge.spec.ts @@ -31,7 +31,7 @@ * @spec openspec/changes/bookings-pipelinq-customer-bridge-10-integration-e2e-tests/tasks.md */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const SHILLINQ_ADMIN_SETTINGS = '/settings/admin/shillinq' diff --git a/tests/e2e/playwright.config.ts b/tests/e2e/playwright.config.ts index 1e8fbe516..3fe9fe21e 100644 --- a/tests/e2e/playwright.config.ts +++ b/tests/e2e/playwright.config.ts @@ -99,8 +99,7 @@ import { defineConfig, devices } from '@playwright/test' import * as path from 'path' - -import { resolveBaseURL } from './base-url' +import { resolveBaseURL } from './base-url.ts' /** * Everything under `tests/e2e` that is NOT part of the CI regression suite. diff --git a/tests/e2e/provincies-bbv-routes-smoke.spec.ts b/tests/e2e/provincies-bbv-routes-smoke.spec.ts index 748178a8b..afa64969c 100644 --- a/tests/e2e/provincies-bbv-routes-smoke.spec.ts +++ b/tests/e2e/provincies-bbv-routes-smoke.spec.ts @@ -49,7 +49,9 @@ * @spec openspec/changes/bookkeeping-provincies-bbv-variant/tasks.md#task-26 */ -import { test, expect, type APIRequestContext } from '@playwright/test' +import type { APIRequestContext } from '@playwright/test' + +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' const DASHBOARD_ROUTE = APP + '/bbv-provincie/compliance-dashboard' diff --git a/tests/e2e/provincies-bbv-variant.spec.ts b/tests/e2e/provincies-bbv-variant.spec.ts index 12c41a9da..edbd46d85 100644 --- a/tests/e2e/provincies-bbv-variant.spec.ts +++ b/tests/e2e/provincies-bbv-variant.spec.ts @@ -36,7 +36,9 @@ * @spec openspec/changes/bookkeeping-provincies-bbv-variant/tasks.md */ -import { test, expect, type Page } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' const DASHBOARD_ROUTE = '/bbv-provincie/compliance-dashboard' diff --git a/tests/e2e/receipt-extraction-consume.spec.ts b/tests/e2e/receipt-extraction-consume.spec.ts index cd6a155bd..d8d3cc703 100644 --- a/tests/e2e/receipt-extraction-consume.spec.ts +++ b/tests/e2e/receipt-extraction-consume.spec.ts @@ -26,7 +26,9 @@ * @spec openspec/changes/receipt-extraction-consume/specs/receipt-extraction-consume/spec.md#req-rxc-006 */ -import { test, expect, type Page } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/recurring-invoicing.spec.ts b/tests/e2e/recurring-invoicing.spec.ts index ba50eef56..62438730e 100644 --- a/tests/e2e/recurring-invoicing.spec.ts +++ b/tests/e2e/recurring-invoicing.spec.ts @@ -28,7 +28,7 @@ * @e2e recurring-invoicing::dutch-ui-renders-translated-strings-from-english-keys */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/retire-cost-project.spec.ts b/tests/e2e/retire-cost-project.spec.ts index 4e68794b5..1f10c4119 100644 --- a/tests/e2e/retire-cost-project.spec.ts +++ b/tests/e2e/retire-cost-project.spec.ts @@ -25,7 +25,7 @@ * @spec openspec/changes/retire-cost-project/specs/retire-cost-project/spec.md (REQ-RCP-004/REQ-RCP-006) */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/setup-wizard-english.spec.ts b/tests/e2e/setup-wizard-english.spec.ts index 4f46036f2..317a7cd75 100644 --- a/tests/e2e/setup-wizard-english.spec.ts +++ b/tests/e2e/setup-wizard-english.spec.ts @@ -43,12 +43,13 @@ * @spec openspec/changes/setup-wizard-english/specs/setup-wizard-english/spec.md */ -import { test, expect, request, type Page } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect, request, test } from '@playwright/test' import { execSync } from 'child_process' import * as fs from 'fs' import * as path from 'path' - -import { resolveBaseURL } from './base-url' +import { resolveBaseURL } from './base-url.ts' const APP = '/apps/shillinq' const APP_ROOT = path.resolve(__dirname, '..', '..') @@ -180,7 +181,6 @@ async function restoreCiSeedBaseline(baseURL: string): Promise { const status = await ctx.get('/index.php/apps/shillinq/api/setup/status') const body = await status.json().catch(() => ({})) if (body?.completed !== true) { - // eslint-disable-next-line no-console console.warn( '[setup-wizard-english] afterAll restore did not report completed:true β€” ' + `sibling specs may see a blocking setup dialog. status: ${JSON.stringify(body)}`, @@ -414,7 +414,6 @@ test.describe('Setup wizard β€” English source text (REQ-SWE-005)', () => { .getByRole('button', { name: /finish|complete|done|close/i }) .last() await finishButton.click({ timeout: 10_000 }).catch(() => { - // eslint-disable-next-line no-console console.warn( '[setup-wizard-english] no explicit finish button matched; the wizard may auto-close on `completed: true`.', ) diff --git a/tests/e2e/spec-coverage/_helpers.ts b/tests/e2e/spec-coverage/_helpers.ts index c55751161..569bf4054 100644 --- a/tests/e2e/spec-coverage/_helpers.ts +++ b/tests/e2e/spec-coverage/_helpers.ts @@ -59,7 +59,9 @@ * relaxed and no failing test can become passing. */ -import { expect, type Page } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect } from '@playwright/test' export const APP = '/apps/shillinq' diff --git a/tests/e2e/spec-coverage/belastingen.spec.ts b/tests/e2e/spec-coverage/belastingen.spec.ts index b14640f1d..e21bf6799 100644 --- a/tests/e2e/spec-coverage/belastingen.spec.ts +++ b/tests/e2e/spec-coverage/belastingen.spec.ts @@ -15,11 +15,11 @@ import { test } from '@playwright/test' import { - gotoPage, assertIndexSurface, assertNoShillinqFailures, + gotoPage, recordShillinqErrors, -} from './_helpers' +} from './_helpers.ts' const PAGES: Array<{ route: string; title: string; titleRe?: RegExp }> = [ { route: '/belastingen/kor', title: 'KOR', titleRe: /KOR/i }, diff --git a/tests/e2e/spec-coverage/bookkeeping.spec.ts b/tests/e2e/spec-coverage/bookkeeping.spec.ts index f026292ee..d157b7a43 100644 --- a/tests/e2e/spec-coverage/bookkeeping.spec.ts +++ b/tests/e2e/spec-coverage/bookkeeping.spec.ts @@ -14,11 +14,11 @@ import { test } from '@playwright/test' import { - gotoPage, assertIndexSurface, assertNoShillinqFailures, + gotoPage, recordShillinqErrors, -} from './_helpers' +} from './_helpers.ts' const PAGES: Array<{ route: string; title: string; titleRe?: RegExp }> = [ { route: '/chart-of-accounts', title: 'Chart of Accounts' }, diff --git a/tests/e2e/spec-coverage/cashflow-pension.spec.ts b/tests/e2e/spec-coverage/cashflow-pension.spec.ts index bf1c7ed6e..9007160f3 100644 --- a/tests/e2e/spec-coverage/cashflow-pension.spec.ts +++ b/tests/e2e/spec-coverage/cashflow-pension.spec.ts @@ -9,11 +9,11 @@ import { test } from '@playwright/test' import { - gotoPage, assertIndexSurface, assertNoShillinqFailures, + gotoPage, recordShillinqErrors, -} from './_helpers' +} from './_helpers.ts' const PAGES: Array<{ route: string; title: string; titleRe?: RegExp }> = [ { diff --git a/tests/e2e/spec-coverage/dashboard-settings.spec.ts b/tests/e2e/spec-coverage/dashboard-settings.spec.ts index 88f9cbb2b..f8e09d2c1 100644 --- a/tests/e2e/spec-coverage/dashboard-settings.spec.ts +++ b/tests/e2e/spec-coverage/dashboard-settings.spec.ts @@ -8,14 +8,14 @@ * Data-independent. */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' import { APP, - gotoPage, - dismissOverlays, assertNoShillinqFailures, + dismissOverlays, + gotoPage, recordShillinqErrors, -} from './_helpers' +} from './_helpers.ts' test.describe('shillinq spec-coverage β€” Dashboard & Settings', () => { // No `mode: 'serial'` β€” see the header of ./_helpers.ts. The Dashboard 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 16b774837..5dc1767e1 100644 --- a/tests/e2e/spec-coverage/demo-data-setup-step.spec.ts +++ b/tests/e2e/spec-coverage/demo-data-setup-step.spec.ts @@ -28,7 +28,9 @@ * (`setup-demo-data-first`) checks it statically on every change. Claiming to * prove it here would be asserting something this vantage point cannot see. */ -import { test, expect, Page } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' const BASE = '/apps/shillinq' @@ -44,12 +46,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/dimensions.spec.ts b/tests/e2e/spec-coverage/dimensions.spec.ts index ddccfff24..a24fc8aa7 100644 --- a/tests/e2e/spec-coverage/dimensions.spec.ts +++ b/tests/e2e/spec-coverage/dimensions.spec.ts @@ -16,13 +16,13 @@ * page's own "Analytical dimensions", not the old per-route titles. */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' import { - gotoPage, assertIndexSurface, assertNoShillinqFailures, + gotoPage, recordShillinqErrors, -} from './_helpers' +} from './_helpers.ts' const PAGES: Array<{ route: string; title: string; titleRe?: RegExp }> = [ { diff --git a/tests/e2e/spec-coverage/inkoop.spec.ts b/tests/e2e/spec-coverage/inkoop.spec.ts index af51a6d26..7d4ecef9b 100644 --- a/tests/e2e/spec-coverage/inkoop.spec.ts +++ b/tests/e2e/spec-coverage/inkoop.spec.ts @@ -15,7 +15,7 @@ import { assertNoShillinqFailures, gotoPage, recordShillinqErrors, -} from './_helpers' +} from './_helpers.ts' const PAGES: Array<{ route: string; title: string; titleRe?: RegExp }> = [ { route: '/inkoop/purchase-orders', title: 'Purchase Orders' }, diff --git a/tests/e2e/spec-coverage/inventory.spec.ts b/tests/e2e/spec-coverage/inventory.spec.ts index 64866f3ea..00db7b2d1 100644 --- a/tests/e2e/spec-coverage/inventory.spec.ts +++ b/tests/e2e/spec-coverage/inventory.spec.ts @@ -10,11 +10,11 @@ import { test } from '@playwright/test' import { - gotoPage, assertIndexSurface, assertNoShillinqFailures, + gotoPage, recordShillinqErrors, -} from './_helpers' +} from './_helpers.ts' const PAGES: Array<{ route: string; title: string; titleRe?: RegExp }> = [ // ⚠️ These two currently FAIL, and that is the spec working β€” see #860. diff --git a/tests/e2e/spec-coverage/overheid-compliance.spec.ts b/tests/e2e/spec-coverage/overheid-compliance.spec.ts index 460f22567..f61114767 100644 --- a/tests/e2e/spec-coverage/overheid-compliance.spec.ts +++ b/tests/e2e/spec-coverage/overheid-compliance.spec.ts @@ -10,11 +10,11 @@ import { test } from '@playwright/test' import { - gotoPage, assertIndexSurface, assertNoShillinqFailures, + gotoPage, recordShillinqErrors, -} from './_helpers' +} from './_helpers.ts' const PAGES: Array<{ route: string; title: string; titleRe?: RegExp }> = [ // Overheid diff --git a/tests/e2e/spec-coverage/projecten.spec.ts b/tests/e2e/spec-coverage/projecten.spec.ts index f2be092ca..3fbdbd243 100644 --- a/tests/e2e/spec-coverage/projecten.spec.ts +++ b/tests/e2e/spec-coverage/projecten.spec.ts @@ -15,11 +15,11 @@ import { test } from '@playwright/test' import { - gotoPage, assertIndexSurface, assertNoShillinqFailures, + gotoPage, recordShillinqErrors, -} from './_helpers' +} from './_helpers.ts' const PAGES: Array<{ route: string; title: string; titleRe?: RegExp }> = [ { diff --git a/tests/e2e/standards-policy-editor.spec.ts b/tests/e2e/standards-policy-editor.spec.ts index a77d0d93e..64b8dca7a 100644 --- a/tests/e2e/standards-policy-editor.spec.ts +++ b/tests/e2e/standards-policy-editor.spec.ts @@ -38,7 +38,7 @@ * @spec openspec/specs/accounting-standards-policy/spec.md#REQ-ASP-002 */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' const ROUTE = '/settings/accounting-standards' diff --git a/tests/e2e/trial-balance.spec.ts b/tests/e2e/trial-balance.spec.ts index 036ed0bac..1e62270ef 100644 --- a/tests/e2e/trial-balance.spec.ts +++ b/tests/e2e/trial-balance.spec.ts @@ -19,7 +19,7 @@ * running instance. */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' 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/external-adapters.visual.spec.ts b/tests/e2e/visual/external-adapters.visual.spec.ts index f4cab172d..53202c5e1 100644 --- a/tests/e2e/visual/external-adapters.visual.spec.ts +++ b/tests/e2e/visual/external-adapters.visual.spec.ts @@ -1,3 +1,5 @@ +import type { Page } from '@playwright/test' + /* * SPDX-License-Identifier: EUPL-1.2 * @@ -30,14 +32,14 @@ * See _visual-helpers.ts for the platform-rendering caveat + the shared * freeze / dismiss / mask determinism guarantees. */ -import { test, expect, type Page } from '@playwright/test' +import { expect, test } from '@playwright/test' import { dismissSupportDialog, - waitForContentReady, + dynamicMasks, freezePage, SHOT_OPTIONS, - dynamicMasks, -} from './_visual-helpers' + waitForContentReady, +} from './_visual-helpers.ts' // Use the SPA's history-mode base (no /index.php/ prefix) so the deep-link // matches the vue-router base and does not get reset to the dashboard. diff --git a/tests/e2e/visual/shillinq.visual.spec.ts b/tests/e2e/visual/shillinq.visual.spec.ts index 0dd78a603..a72bdb1a6 100644 --- a/tests/e2e/visual/shillinq.visual.spec.ts +++ b/tests/e2e/visual/shillinq.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/shillinq' diff --git a/tests/e2e/waterschappen-bbv-routes-smoke.spec.ts b/tests/e2e/waterschappen-bbv-routes-smoke.spec.ts index 0ad1c4069..3f243a41b 100644 --- a/tests/e2e/waterschappen-bbv-routes-smoke.spec.ts +++ b/tests/e2e/waterschappen-bbv-routes-smoke.spec.ts @@ -30,7 +30,7 @@ * @spec openspec/changes/bookkeeping-waterschappen-bbv-variant-11-testing/tasks.md#smoke-tests */ -import { test, expect } from '@playwright/test' +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' diff --git a/tests/e2e/waterschappen-bbv-variant.spec.ts b/tests/e2e/waterschappen-bbv-variant.spec.ts index 320cc94fe..8d451b940 100644 --- a/tests/e2e/waterschappen-bbv-variant.spec.ts +++ b/tests/e2e/waterschappen-bbv-variant.spec.ts @@ -41,7 +41,9 @@ * @spec openspec/changes/bookkeeping-waterschappen-bbv-variant-11-testing/tasks.md */ -import { test, expect, type Page } from '@playwright/test' +import type { Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' const DASHBOARD_ROUTE = '/bbv-dashboard' @@ -445,7 +447,6 @@ test.describe('BBV mapping detail β€” edit flow', () => { { headers: { 'OCS-APIRequest': 'true' } }, ) if (deleted.ok() === false) { - // eslint-disable-next-line no-console console.warn( `[bbv] failed to clean up seeded mapping ${id}: HTTP ${deleted.status()}`, ) diff --git a/tests/e2e/workflows/_fixtures.ts b/tests/e2e/workflows/_fixtures.ts index 343dcee33..f092f35dc 100644 --- a/tests/e2e/workflows/_fixtures.ts +++ b/tests/e2e/workflows/_fixtures.ts @@ -35,7 +35,10 @@ * specs run for real the moment the register imports. */ -import { APIRequestContext, expect } from '@playwright/test' +import type { APIResponse } from '@playwright/test' +import type { APIRequestContext } from '@playwright/test' + +import { expect } from '@playwright/test' /** OpenRegister generic object API base. */ const OR = '/index.php/apps/openregister/api' @@ -210,10 +213,7 @@ export class OrFixtures { * @param id The object id (uuid). * @param action The lifecycle action name (e.g. 'verleen', 'approve'). */ - async transition( - id: string, - action: string, - ): Promise { + async transition(id: string, action: string): Promise { return this.api.post(`${OR}/objects/${id}/transition`, { headers: await this.headers(), data: { action }, diff --git a/tests/e2e/workflows/external-adapters-admin.spec.ts b/tests/e2e/workflows/external-adapters-admin.spec.ts index 2e736fc92..4b3e28648 100644 --- a/tests/e2e/workflows/external-adapters-admin.spec.ts +++ b/tests/e2e/workflows/external-adapters-admin.spec.ts @@ -25,7 +25,9 @@ * @spec openspec/changes/integration-config-to-openconnector/specs/integration-config-to-openconnector/spec.md */ -import { test, expect, type Page, type ConsoleMessage } from '@playwright/test' +import type { ConsoleMessage, Page } from '@playwright/test' + +import { expect, test } from '@playwright/test' const APP = '/apps/shillinq' const STATUS_ROUTE = `${APP}/external-adapters` diff --git a/tests/e2e/workflows/fin-account-crud.spec.ts b/tests/e2e/workflows/fin-account-crud.spec.ts index eede57660..6033652d4 100644 --- a/tests/e2e/workflows/fin-account-crud.spec.ts +++ b/tests/e2e/workflows/fin-account-crud.spec.ts @@ -21,8 +21,10 @@ * @spec openspec/changes/bookkeeping-trial-balance/tasks.md */ -import { test, expect, request as pwRequest } from '@playwright/test' -import { UNIQUE_PREFIX, OrFixtures, REGISTER_SLUG } from './_fixtures' +import type { APIRequestContext } from '@playwright/test' + +import { expect, request as pwRequest, test } from '@playwright/test' +import { OrFixtures, REGISTER_SLUG, UNIQUE_PREFIX } from './_fixtures.ts' const APP = '/apps/shillinq' const ADMIN_ID = `${UNIQUE_PREFIX}-adm` @@ -30,7 +32,7 @@ const NEEDED = ['Account'] test.describe('shillinq finance β€” ledger Account full CRUD with persistence', () => { let fx: OrFixtures - let api: import('@playwright/test').APIRequestContext + let api: APIRequestContext test.beforeAll(async ({ baseURL }) => { api = await pwRequest.newContext({ diff --git a/tests/e2e/workflows/fin-lease-amortization.spec.ts b/tests/e2e/workflows/fin-lease-amortization.spec.ts index 650591e30..9a4605b5a 100644 --- a/tests/e2e/workflows/fin-lease-amortization.spec.ts +++ b/tests/e2e/workflows/fin-lease-amortization.spec.ts @@ -30,8 +30,10 @@ * @spec openspec/changes/bookkeeping-ifrs-16-lease/specs/bookkeeping-lease-accounting/spec.md */ -import { test, expect, request as pwRequest } from '@playwright/test' -import { OrFixtures, REGISTER_SLUG, UNIQUE_PREFIX, money } from './_fixtures' +import type { APIRequestContext } from '@playwright/test' + +import { expect, request as pwRequest, test } from '@playwright/test' +import { money, OrFixtures, UNIQUE_PREFIX } from './_fixtures.ts' const APP = '/apps/shillinq' const ADMIN_ID = `${UNIQUE_PREFIX}-adm` @@ -51,7 +53,7 @@ interface ScheduleRow { test.describe('shillinq finance β€” IFRS 16 lease amortization (computed numbers)', () => { let fx: OrFixtures - let api: import('@playwright/test').APIRequestContext + let api: APIRequestContext test.beforeAll(async ({ baseURL }) => { api = await pwRequest.newContext({ diff --git a/tests/e2e/workflows/fin-oss-vat-rate.spec.ts b/tests/e2e/workflows/fin-oss-vat-rate.spec.ts index 171c7d7e8..cc337ba08 100644 --- a/tests/e2e/workflows/fin-oss-vat-rate.spec.ts +++ b/tests/e2e/workflows/fin-oss-vat-rate.spec.ts @@ -32,8 +32,10 @@ * @spec openspec/specs/bookkeeping-btw-oss-eu/spec.md#REQ-OSS-001 */ -import { test, expect, request as pwRequest } from '@playwright/test' -import { UNIQUE_PREFIX, OrFixtures, money } from './_fixtures' +import type { APIRequestContext } from '@playwright/test' + +import { expect, request as pwRequest, test } from '@playwright/test' +import { money, OrFixtures, UNIQUE_PREFIX } from './_fixtures.ts' const APP = '/apps/shillinq' const ADMIN_ID = `${UNIQUE_PREFIX}-adm` @@ -41,7 +43,7 @@ const NEEDED = ['EuVatRate'] test.describe('shillinq finance β€” OSS/BTW VAT rate resolution (computed numbers)', () => { let fx: OrFixtures - let api: import('@playwright/test').APIRequestContext + let api: APIRequestContext test.beforeAll(async ({ baseURL }) => { api = await pwRequest.newContext({ diff --git a/tests/e2e/workflows/fin-trial-balance.spec.ts b/tests/e2e/workflows/fin-trial-balance.spec.ts index ca24f744a..bce9d9d75 100644 --- a/tests/e2e/workflows/fin-trial-balance.spec.ts +++ b/tests/e2e/workflows/fin-trial-balance.spec.ts @@ -39,8 +39,10 @@ * @e2e openspec/specs/bookkeeping-trial-balance/spec.md#balanced-trial-balance-returns-no-invariant-error */ -import { test, expect, request as pwRequest } from '@playwright/test' -import { UNIQUE_PREFIX, OrFixtures, money } from './_fixtures' +import type { APIRequestContext } from '@playwright/test' + +import { expect, request as pwRequest, test } from '@playwright/test' +import { money, OrFixtures, UNIQUE_PREFIX } from './_fixtures.ts' const APP = '/apps/shillinq' const ADMIN_ID = `${UNIQUE_PREFIX}-adm` @@ -55,7 +57,7 @@ interface TbRow { test.describe('shillinq finance β€” trial balance balances (debits == credits)', () => { let fx: OrFixtures - let api: import('@playwright/test').APIRequestContext + let api: APIRequestContext test.beforeAll(async ({ baseURL }) => { api = await pwRequest.newContext({ diff --git a/tests/l10n/check-l10n-parity.js b/tests/l10n/check-l10n-parity.js index 70e99a9a9..460ccf467 100644 --- a/tests/l10n/check-l10n-parity.js +++ b/tests/l10n/check-l10n-parity.js @@ -89,7 +89,7 @@ function loadJsonSet (file) { /** True when a translation value is empty (string) or has an empty plural. */ function isEmpty (v) { - if (v == null) { + if ((v === null || v === undefined)) { return true } if (Array.isArray(v)) { @@ -135,8 +135,8 @@ for (const set of sets) { failures.push({ set: set.kind, loc, kind: 'UNPARSEABLE', detail: e.message }) continue } - const missing = enKeys.filter((k) => !Object.prototype.hasOwnProperty.call(locObj, k)) - const empty = enKeys.filter((k) => Object.prototype.hasOwnProperty.call(locObj, k) && isEmpty(locObj[k])) + const missing = enKeys.filter((k) => !Object.hasOwn(locObj, k)) + const empty = enKeys.filter((k) => Object.hasOwn(locObj, k) && isEmpty(locObj[k])) if (missing.length || empty.length) { failures.push({ set: set.kind, loc, kind: 'INCOMPLETE', missing, empty, total: enKeys.length }) } 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/customer-bridge-profile-helpers.test.mjs b/tests/unit/customer-bridge-profile-helpers.test.mjs index 0de542887..2eb139009 100644 --- a/tests/unit/customer-bridge-profile-helpers.test.mjs +++ b/tests/unit/customer-bridge-profile-helpers.test.mjs @@ -20,18 +20,17 @@ * @spec openspec/changes/bookings-pipelinq-customer-bridge-06-profile-card-ui/tasks.md */ -import { test } from 'node:test' import assert from 'node:assert/strict' - +import { test } from 'node:test' import { - classifyContact, + buildPipelinqLink, buildProfileFields, - selectProfileState, - selectHistoryState, + classifyContact, formatTransactionAmount, formatTransactionDate, nextPageParams, - buildPipelinqLink, + selectHistoryState, + selectProfileState, } from '../../src/composables/usePipelinqProfile.js' // --------------------------------------------------------------------------- @@ -97,7 +96,10 @@ test('buildProfileFields omits missing optional fields entirely (no empty labels found: true, } const fields = buildProfileFields(contact) - assert.deepEqual(fields.map((f) => f.key), ['legalName']) + assert.deepEqual( + fields.map((f) => f.key), + ['legalName'], + ) }) test('buildProfileFields returns empty list for not-found contact', () => { @@ -173,13 +175,15 @@ test('selectProfileState returns error for a missing payload', () => { // selectHistoryState β€” history rendering with up to 5 entries + load-more // --------------------------------------------------------------------------- -const okPayload = (klantbeeld) => ({ - booking: { appointmentId: 'apt-1', pipelinqContactId: 'cnt-1' }, - contact: { externalId: 'cnt-1', legalName: 'Acme', found: true }, - contactError: null, - notLinkedToPipelinq: false, - klantbeeld, -}) +function okPayload(klantbeeld) { + return { + booking: { appointmentId: 'apt-1', pipelinqContactId: 'cnt-1' }, + contact: { externalId: 'cnt-1', legalName: 'Acme', found: true }, + contactError: null, + notLinkedToPipelinq: false, + klantbeeld, + } +} test('selectHistoryState returns ok with up to 5 transactions', () => { const klantbeeld = { @@ -199,7 +203,13 @@ test('selectHistoryState returns ok with up to 5 transactions', () => { }) test('selectHistoryState returns empty when envelope reports empty', () => { - const klantbeeld = { transactions: [], limit: 5, offset: 0, unavailable: false, empty: true } + const klantbeeld = { + transactions: [], + limit: 5, + offset: 0, + unavailable: false, + empty: true, + } assert.equal(selectHistoryState(okPayload(klantbeeld)), 'empty') }) @@ -233,14 +243,14 @@ test('selectHistoryState returns hidden when klantbeeld envelope is missing', () // --------------------------------------------------------------------------- test('nextPageParams advances offset by limit', () => { - assert.deepEqual( - nextPageParams({ limit: 5, offset: 0 }), - { limit: 5, offset: 5 }, - ) - assert.deepEqual( - nextPageParams({ limit: 5, offset: 5 }), - { limit: 5, offset: 10 }, - ) + assert.deepEqual(nextPageParams({ limit: 5, offset: 0 }), { + limit: 5, + offset: 5, + }) + assert.deepEqual(nextPageParams({ limit: 5, offset: 5 }), { + limit: 5, + offset: 10, + }) }) test('nextPageParams falls back to defaults when envelope is missing fields', () => { @@ -250,10 +260,10 @@ test('nextPageParams falls back to defaults when envelope is missing fields', () }) test('nextPageParams clamps limit to >= 1', () => { - assert.deepEqual( - nextPageParams({ limit: 0, offset: 0 }), - { limit: 1, offset: 1 }, - ) + assert.deepEqual(nextPageParams({ limit: 0, offset: 0 }), { + limit: 1, + offset: 1, + }) }) // --------------------------------------------------------------------------- @@ -261,8 +271,14 @@ test('nextPageParams clamps limit to >= 1', () => { // --------------------------------------------------------------------------- test('formatTransactionAmount renders the row currency with 2 decimals', () => { - assert.equal(formatTransactionAmount({ amount: 100, currency: 'EUR' }), 'EUR 100.00') - assert.equal(formatTransactionAmount({ amount: 12.5, currency: 'USD' }), 'USD 12.50') + assert.equal( + formatTransactionAmount({ amount: 100, currency: 'EUR' }), + 'EUR 100.00', + ) + assert.equal( + formatTransactionAmount({ amount: 12.5, currency: 'USD' }), + 'USD 12.50', + ) }) test('formatTransactionAmount falls back to EUR when currency is missing', () => { @@ -270,7 +286,10 @@ test('formatTransactionAmount falls back to EUR when currency is missing', () => }) test('formatTransactionAmount renders 0.00 when the amount is non-numeric', () => { - assert.equal(formatTransactionAmount({ amount: 'bogus', currency: 'EUR' }), 'EUR 0.00') + assert.equal( + formatTransactionAmount({ amount: 'bogus', currency: 'EUR' }), + 'EUR 0.00', + ) assert.equal(formatTransactionAmount({}), 'EUR 0.00') }) diff --git a/tests/unit/inventory-mobile-scanner-helpers.test.mjs b/tests/unit/inventory-mobile-scanner-helpers.test.mjs index 30ca15470..48b7297f3 100644 --- a/tests/unit/inventory-mobile-scanner-helpers.test.mjs +++ b/tests/unit/inventory-mobile-scanner-helpers.test.mjs @@ -15,9 +15,8 @@ * @spec openspec/changes/inventory-mobile-scanner/tasks.md */ -import { test } from 'node:test' import assert from 'node:assert/strict' - +import { test } from 'node:test' // Import the source modules directly. These are plain ESM so node --test // can load them without a bundler. useInventorySync.js depends on // @nextcloud/axios at the top level; we replicate its newTransactionId() @@ -45,9 +44,9 @@ function newTransactionId() { } else if (i === 14) { out += '4' } else if (i === 19) { - out += hex[(Math.random() * 4 | 0) + 8] + out += hex[((Math.random() * 4) | 0) + 8] } else { - out += hex[Math.random() * 16 | 0] + out += hex[(Math.random() * 16) | 0] } } return out @@ -60,9 +59,18 @@ test('composeStockKey produces a stable sku|location composite', () => { }) test('isStrictlyLater returns true only when a is strictly later than b', () => { - assert.equal(isStrictlyLater('2026-05-21T14:23:00Z', '2026-05-21T14:22:59Z'), true) - assert.equal(isStrictlyLater('2026-05-21T14:22:59Z', '2026-05-21T14:23:00Z'), false) - assert.equal(isStrictlyLater('2026-05-21T14:23:00Z', '2026-05-21T14:23:00Z'), false) + assert.equal( + isStrictlyLater('2026-05-21T14:23:00Z', '2026-05-21T14:22:59Z'), + true, + ) + assert.equal( + isStrictlyLater('2026-05-21T14:22:59Z', '2026-05-21T14:23:00Z'), + false, + ) + assert.equal( + isStrictlyLater('2026-05-21T14:23:00Z', '2026-05-21T14:23:00Z'), + false, + ) }) test('isStrictlyLater is defensive against missing or unparseable timestamps', () => { @@ -74,7 +82,10 @@ test('isStrictlyLater is defensive against missing or unparseable timestamps', ( test('newTransactionId returns a UUID-shaped string usable as a dedup key', () => { const id = newTransactionId() assert.equal(typeof id, 'string') - assert.match(id, /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/) + assert.match( + id, + /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/, + ) const id2 = newTransactionId() assert.notEqual(id, id2, 'consecutive ids must differ') }) diff --git a/tests/validate-fragment-required.js b/tests/validate-fragment-required.js index 95b3afc3c..7a42c4408 100644 --- a/tests/validate-fragment-required.js +++ b/tests/validate-fragment-required.js @@ -64,7 +64,7 @@ const FRAGMENT_DIR = path.join(SETTINGS_DIR, 'register.d') // only ever be LOWERED β€” no new conflicting declaration can land. const BASELINE = 44 -const loadJson = (file) => { +function loadJson(file) { try { return JSON.parse(fs.readFileSync(file, 'utf8')) } catch (err) { @@ -92,7 +92,7 @@ function registerFiles() { return files } -const sameSet = (a, b) => { +function sameSet(a, b) { const sa = [...new Set(a)].sort() const sb = [...new Set(b)].sort() return sa.length === sb.length && sa.every((v, i) => v === sb[i]) diff --git a/tests/validate-semantic-markers.js b/tests/validate-semantic-markers.js index 5c8789528..e88f116d7 100644 --- a/tests/validate-semantic-markers.js +++ b/tests/validate-semantic-markers.js @@ -69,7 +69,7 @@ function walk(node, file, offenders, contextName) { } if (!node || typeof node !== 'object') return const name = node.slug || node.title || contextName - if (Object.prototype.hasOwnProperty.call(node, 'x-schema-org')) { + if (Object.hasOwn(node, 'x-schema-org')) { const marker = node['x-schema-org'] if (typeof marker !== 'string' || !CURIE_RE.test(marker)) { offenders.push({ file, name, marker }) @@ -127,7 +127,7 @@ function countMarkers(node, box) { return } if (!node || typeof node !== 'object') return - if (Object.prototype.hasOwnProperty.call(node, 'x-schema-org')) box.n += 1 + if (Object.hasOwn(node, 'x-schema-org')) box.n += 1 for (const value of Object.values(node)) countMarkers(value, box) } diff --git a/tests/vitest/accountantPortalRouting.spec.js b/tests/vitest/accountantPortalRouting.spec.js index bb0741964..720e7b787 100644 --- a/tests/vitest/accountantPortalRouting.spec.js +++ b/tests/vitest/accountantPortalRouting.spec.js @@ -25,9 +25,9 @@ * @spec openspec/specs/accountant-portal/spec.md */ -import { describe, it, expect } from 'vitest' import fs from 'fs' import path from 'path' +import { describe, expect, it } from 'vitest' const repoRoot = path.resolve(__dirname, '..', '..') const routesSource = fs.readFileSync( diff --git a/tests/vitest/arEInvoiceActions.spec.js b/tests/vitest/arEInvoiceActions.spec.js index e978b2669..2b2441d3a 100644 --- a/tests/vitest/arEInvoiceActions.spec.js +++ b/tests/vitest/arEInvoiceActions.spec.js @@ -11,13 +11,13 @@ * @spec openspec/changes/add-invoice-pdf-export-with-ubl-peppol-support/specs/bookkeeping-einvoicing-ubl-peppol/spec.md#req-einv-007 */ -import { describe, it, expect } from 'vitest' +import { describe, expect, it } from 'vitest' import { canSendEInvoice, + extractSendErrorMessage, + mapSendResult, resolveDeliveryStatus, sendEInvoiceEndpoint, - mapSendResult, - extractSendErrorMessage, } from '../../src/components/ar-invoice/arEInvoiceActions.js' // The translate stub returns the source string β€” keys are English (house rule). diff --git a/tests/vitest/bankStatementWizard.spec.js b/tests/vitest/bankStatementWizard.spec.js index 275ddac7a..7bd41cc1c 100644 --- a/tests/vitest/bankStatementWizard.spec.js +++ b/tests/vitest/bankStatementWizard.spec.js @@ -16,15 +16,15 @@ * runs the import" β€” is driven by loadIbanMapping() asserted here. */ -import { describe, it, expect, beforeEach } from 'vitest' +import { beforeEach, describe, expect, it } from 'vitest' import { + BREADCRUMB_FLAG, + buildImportPayload, formatOptions, - normalizeIban, loadIbanMapping, + normalizeIban, saveIbanMapping, - buildImportPayload, setReturnBreadcrumb, - BREADCRUMB_FLAG, } from '../../src/modals/bankStatementWizard.js' const IBAN_MAP_KEY = 'shillinq:bank-iban-map' diff --git a/tests/vitest/bbvLinkerFilterBar.spec.js b/tests/vitest/bbvLinkerFilterBar.spec.js index e24be406a..4439f45d3 100644 --- a/tests/vitest/bbvLinkerFilterBar.spec.js +++ b/tests/vitest/bbvLinkerFilterBar.spec.js @@ -26,7 +26,7 @@ * @spec openspec/specs/bookkeeping-provincies-bbv-variant/spec.md */ -import { describe, it, expect, beforeEach, vi } from 'vitest' +import { beforeEach, describe, expect, it, vi } from 'vitest' import BbvLinkerFilterBar from '../../src/components/bbv-provincie/BbvLinkerFilterBar.vue' /** The page's declared facets, verbatim from the manifest fragment. */ diff --git a/tests/vitest/billImportModal.spec.js b/tests/vitest/billImportModal.spec.js index df941cf91..496328881 100644 --- a/tests/vitest/billImportModal.spec.js +++ b/tests/vitest/billImportModal.spec.js @@ -13,26 +13,26 @@ * invoiceQuickDraft.js pattern). */ -import { describe, it, expect } from 'vitest' +import { describe, expect, it } from 'vitest' import { - detectFormat, - isDeferredPdf, buildImportFormData, - reviewFormFromRecord, canSaveReview, - importErrorMessage, - refreshEventPayload, + confidenceForField, CREDITORS_WIDGET, - PDF_DEFERRAL_MESSAGE, + detectFormat, + glAccountSuggestionSummary, + hasKnownExtractionId, + importErrorMessage, + isDeferredPdf, isExtractionDraft, - confidenceForField, isFieldCorrected, - requiresExplicitReview, + ONE_CLICK_CONFIDENCE_GATE, + PDF_DEFERRAL_MESSAGE, pendingDraftSummary, + refreshEventPayload, + requiresExplicitReview, REVIEW_THRESHOLD, - ONE_CLICK_CONFIDENCE_GATE, - hasKnownExtractionId, - glAccountSuggestionSummary, + reviewFormFromRecord, } from '../../src/modals/billImportModal.js' describe('billImportModal β€” format detection', () => { diff --git a/tests/vitest/bookingsCalendarView.spec.js b/tests/vitest/bookingsCalendarView.spec.js index 5ed8356ff..83dafcc97 100644 --- a/tests/vitest/bookingsCalendarView.spec.js +++ b/tests/vitest/bookingsCalendarView.spec.js @@ -24,7 +24,7 @@ * @spec openspec/changes/bookings-resource-calendar/tasks.md#task-5 */ -import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import CalendarView from '../../src/views/bookings/CalendarView.vue' const { fetchBookings, bookingId, isConflict } = CalendarView.methods diff --git a/tests/vitest/budgetLineCommitmentsHelpers.spec.js b/tests/vitest/budgetLineCommitmentsHelpers.spec.js index 826de3abb..d5cff705e 100644 --- a/tests/vitest/budgetLineCommitmentsHelpers.spec.js +++ b/tests/vitest/budgetLineCommitmentsHelpers.spec.js @@ -10,11 +10,11 @@ * @spec openspec/changes/verplichtingen-commitment-accounting/specs/bookkeeping-verplichtingenadministratie/spec.md#req-vpl-011 */ -import { describe, it, expect } from 'vitest' +import { describe, expect, it } from 'vitest' import { - normaliseBudgetLineRows, - formatAmount, drilldownFilters, + formatAmount, + normaliseBudgetLineRows, } from '../../src/views/budgetLineCommitmentsHelpers.js' describe('budgetLineCommitmentsHelpers β€” normaliseBudgetLineRows', () => { diff --git a/tests/vitest/deadlineCalendarSettings.spec.js b/tests/vitest/deadlineCalendarSettings.spec.js index 34c38bebd..c21a3c4b9 100644 --- a/tests/vitest/deadlineCalendarSettings.spec.js +++ b/tests/vitest/deadlineCalendarSettings.spec.js @@ -10,9 +10,9 @@ import { describe, expect, it } from 'vitest' import { + buildSavePayload, CATEGORY_META, normaliseSettings, - buildSavePayload, } from '../../src/views/deadlineCalendarSettingsHelpers.js' describe('CATEGORY_META', () => { diff --git a/tests/vitest/externalAdapters.spec.js b/tests/vitest/externalAdapters.spec.js index 1ac6af5b2..b905bd05a 100644 --- a/tests/vitest/externalAdapters.spec.js +++ b/tests/vitest/externalAdapters.spec.js @@ -27,8 +27,8 @@ * the global `t()` translator and `axios.get` are mocked per-test. */ -import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import axios from '@nextcloud/axios' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import StatusView from '../../src/views/external-adapters/ExternalAdaptersStatus.vue' /** Identity translator: returns the source string (or fills {placeholders}). */ diff --git a/tests/vitest/financialSeries.spec.js b/tests/vitest/financialSeries.spec.js index 2e2fed456..1db162df6 100644 --- a/tests/vitest/financialSeries.spec.js +++ b/tests/vitest/financialSeries.spec.js @@ -9,25 +9,25 @@ * mapping and the one-request-per-schema guarantee. */ -import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import axios from '@nextcloud/axios' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { - monthKey, - lastMonths, - classifyAccounts, - postedLinesByMonth, - signedAmount, - monthlyFinancialSeries, billableSeries, - forecastByMonth, - openArRows, - openApRows, + classifyAccounts, computeKpis, computeRangeKpis, + forecastByMonth, + lastMonths, + monthKey, + monthlyFinancialSeries, + openApRows, + openArRows, + postedLinesByMonth, + signedAmount, } from '../../src/components/dashboard/financial/financialSeries.js' import { - useFinancialData, resetFinancialData, + useFinancialData, } from '../../src/components/dashboard/financial/useFinancialData.js' const ACCOUNTS = [ diff --git a/tests/vitest/generateManifestShell.spec.js b/tests/vitest/generateManifestShell.spec.js index a7083f9f9..56b3f8de9 100644 --- a/tests/vitest/generateManifestShell.spec.js +++ b/tests/vitest/generateManifestShell.spec.js @@ -10,11 +10,10 @@ * @spec openspec/changes/shillinq-manifest-boot-payload-reduction/specs/manifest-boot-performance/spec.md#req-mbp-001 */ -import { describe, it, expect } from 'vitest' import fs from 'fs' import os from 'os' import path from 'path' -// eslint-disable-next-line n/no-unpublished-require +import { describe, expect, it } from 'vitest' const { generateShellDocument, buildShellFragment, diff --git a/tests/vitest/invoiceQuickDraft.spec.js b/tests/vitest/invoiceQuickDraft.spec.js index c076ebc67..bbe3a9024 100644 --- a/tests/vitest/invoiceQuickDraft.spec.js +++ b/tests/vitest/invoiceQuickDraft.spec.js @@ -8,16 +8,16 @@ * localStorage preference round-trip with TTL expiry. */ -import { describe, it, expect, beforeEach, vi } from 'vitest' +import { beforeEach, describe, expect, it } from 'vitest' import { - defaultDraftLine, + buildInvoicePayload, computeTotals, - paymentTermDays, + defaultDraftLine, dueDateFromTerms, - buildInvoicePayload, + loadQuickDraftPrefs, + paymentTermDays, periodIdFromDate, provisionalInvoiceNumber, - loadQuickDraftPrefs, saveQuickDraftPrefs, } from '../../src/modals/invoiceQuickDraft.js' diff --git a/tests/vitest/listViewsCnDataTable.spec.js b/tests/vitest/listViewsCnDataTable.spec.js index 915cb8579..ebcf90122 100644 --- a/tests/vitest/listViewsCnDataTable.spec.js +++ b/tests/vitest/listViewsCnDataTable.spec.js @@ -22,12 +22,12 @@ * @spec openspec/changes/migrate-list-views-to-cndatatable/specs/list-views-cndatatable/spec.md */ -import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' -import AdminInvoiceList from '../../src/views/invoice/AdminInvoiceList.vue' -import DocumentsView from '../../src/views/bookkeeping/DocumentsView.vue' -import TransactionsView from '../../src/views/bookkeeping/TransactionsView.vue' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import ThreeWayMatchIndex from '../../src/components/three-way-match/ThreeWayMatchIndex.vue' import VendorPerformanceIndex from '../../src/components/vendor-performance/VendorPerformanceIndex.vue' +import DocumentsView from '../../src/views/bookkeeping/DocumentsView.vue' +import TransactionsView from '../../src/views/bookkeeping/TransactionsView.vue' +import AdminInvoiceList from '../../src/views/invoice/AdminInvoiceList.vue' /** Identity translator: returns the source string (or fills {placeholders}). */ function tIdentity(app, text, vars) { diff --git a/tests/vitest/mergeFragmentIntoManifest.spec.js b/tests/vitest/mergeFragmentIntoManifest.spec.js index f62f667d6..6fb6cfb25 100644 --- a/tests/vitest/mergeFragmentIntoManifest.spec.js +++ b/tests/vitest/mergeFragmentIntoManifest.spec.js @@ -11,11 +11,11 @@ * @spec openspec/changes/shillinq-manifest-boot-payload-reduction/specs/manifest-boot-performance/spec.md#req-mbp-001 */ -import { describe, it, expect } from 'vitest' +import { describe, expect, it } from 'vitest' import { computed, reactive, toRaw } from 'vue' import { - mergeFullFragmentIntoManifest, buildPageFragmentIndex, + mergeFullFragmentIntoManifest, } from '../../src/utils/mergeFragmentIntoManifest.js' describe('mergeFullFragmentIntoManifest β€” reactivity (the load-bearing contract)', () => { diff --git a/tests/vitest/receiptCapture.spec.js b/tests/vitest/receiptCapture.spec.js index d66f6969e..ab5757f32 100644 --- a/tests/vitest/receiptCapture.spec.js +++ b/tests/vitest/receiptCapture.spec.js @@ -7,12 +7,12 @@ * save gate, and the correction-commit payload shape (REQ-RXC-003 / REQ-RXC-004). */ -import { describe, it, expect } from 'vitest' +import { describe, expect, it } from 'vitest' import { - reviewFormFromReceipt, - canSaveReceipt, buildReceiptConfirmPayload, + canSaveReceipt, receiptErrorMessage, + reviewFormFromReceipt, } from '../../src/views/receiptCapture.js' describe('receiptCapture β€” review form (REQ-RXC-003)', () => { diff --git a/tests/vitest/recurringInvoiceProfile.spec.js b/tests/vitest/recurringInvoiceProfile.spec.js index 454e925eb..c3552cc53 100644 --- a/tests/vitest/recurringInvoiceProfile.spec.js +++ b/tests/vitest/recurringInvoiceProfile.spec.js @@ -7,12 +7,12 @@ * and the profile payload shape (always status draft on create). */ -import { describe, it, expect } from 'vitest' +import { describe, expect, it } from 'vitest' import { + buildProfilePayload, defaultRecurringLine, perPeriodNet, validateProfile, - buildProfilePayload, } from '../../src/modals/recurringInvoiceProfile.js' describe('recurringInvoiceProfile β€” defaults + totals', () => { diff --git a/tests/vitest/settingsStore.spec.js b/tests/vitest/settingsStore.spec.js index 4180f4d82..70f1b0a9c 100644 --- a/tests/vitest/settingsStore.spec.js +++ b/tests/vitest/settingsStore.spec.js @@ -9,8 +9,8 @@ * is aliased to a stub. */ -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' function mockFetchOnce({ ok = true, json = {} }) { diff --git a/tests/vitest/spendAnalyticsPanel.spec.js b/tests/vitest/spendAnalyticsPanel.spec.js index 1ac909ac4..6face1ea2 100644 --- a/tests/vitest/spendAnalyticsPanel.spec.js +++ b/tests/vitest/spendAnalyticsPanel.spec.js @@ -29,8 +29,8 @@ * @spec openspec/changes/spend-analytics-ui/specs/spend-analytics/spec.md */ -import { beforeEach, describe, expect, it, vi } from 'vitest' import axios from '@nextcloud/axios' +import { beforeEach, describe, expect, it, vi } from 'vitest' import SpendAnalyticsPanel, { SPEND_DIMENSIONS, } from '../../src/components/spend-analytics/SpendAnalyticsPanel.vue'