test: unit tests for app/ with regression coverage + PR workflow - #672
Merged
Conversation
- Add vitest.config.ts with path aliases (~/, @shared/) and NativeScript globals - Add tsconfig.test.json extending main tsconfig to include *.test.ts files - Add vitest.setup.ts with mocks for @nativescript/core and @akylas/nativescript-app-utils - Extract deduplicateFilenames() to app/utils/exportUtils.ts; use it in index.common.ts - Add app/utils/path.test.ts (dirname, basename, extname) - Fix basename() bug: use slice() instead of substring() for negative-index ext strip - Add app/utils/matrix.test.ts (concatTwoColorMatrices, concatColorMatrices) - Add app/utils/utils.common.test.ts (cleanFilename, pick, omit, sortByKey, ellipsize) - Add app/helpers/formatter.test.ts (convertTime with dayjs) - Add app/utils/exportUtils.test.ts (deduplicateFilenames + cleanFilename regex spec) - Fix app/services/sync/deletedDocuments.test.ts to match tuple return type - Add 'test' and 'test:watch' scripts to package.json - Update .github/workflows/test.yml: trigger on PRs, run yarn install + yarn test
Copilot created this pull request from a session on behalf of
farfromrefug
June 2, 2026 16:30
View session
Copilot stopped work on behalf of
farfromrefug due to an error
June 2, 2026 16:59
# Conflicts: # .github/workflows/test.yml # yarn.lock
Continues the vitest setup on this branch after merging main. Test quality: - Drop the cleanFilename suite that re-declared the export regex inline: it tested a copy, so a change to the real regex could never fail it. The real function is already covered in utils.common.test.ts. - Rename matrix.test.ts to color_matrix.test.ts (it tested color_matrix.ts) and add a real matrix.test.ts for getPageColorMatrix. Export rename regression coverage (the headline case): - Extract buildExportImageNames() so the format -> sanitise -> deduplicate chain used by exportImages() is testable end to end instead of only in pieces. - Verified by mutation: removing ':' from the forbidden-character set fails 8 tests across 2 files. New coverage against real production code: - sync folder filtering: extracted SyncWorker's two private filters into services/sync/folderFilter.ts and pinned the rules (empty list means "no filter"; unfoldered documents are excluded when a filter is active). - sync bitmasks: every SyncTypes entry owns a unique single bit in 32-bit range. - BaseSyncService: stored-settings round-trip and per-service update isolation. - pkpass: barcode formats, transit icons, display-name fallbacks, alignment. - api: queryString URL building and parameter extraction. Harness: - ApplicationSettings is now an in-memory store that resets between tests, so settings-dependent behaviour can be exercised rather than only defaults. - Mock the native plugins and mirror the webpack DefinePlugin globals and the .common.ts platform resolution, which unblocks importing pkpass/api/locale. - Pin TZ=UTC: filename formatting is timezone sensitive and would otherwise pass locally and fail on CI. CI runs on pull requests via .github/workflows/unit-tests.yml; main's unrelated test.yml is left untouched. 251 tests across 14 files. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
farfromrefug
marked this pull request as ready for review
July 27, 2026 11:03
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds Vitest unit tests for
app/, atestscript, and a pull-request workflow.Merged
main(branch was 87 commits behind) and resolved both conflicts:yarn.lock— both hunks were thetoolssubmodule hash; the submodule itself merged cleanly to main's commit, so main's hashes are the correct side..github/workflows/test.yml—mainalready has an unrelatedtest.yml, which this branch had overwritten. Main's file is restored and the unit-test CI now lives in its ownunit-tests.yml.Running the tests
yarn testyarn test:watchfor watch mode,npx vitest run <path>to isolate a file. CI runsyarn teston every pull request via.github/workflows/unit-tests.yml.Regression detection
The point of the suite is to fail when behaviour changes, so the export-rename path was checked by mutation rather than assumed: removing
:from the forbidden-character set incleanFilenamefails 8 tests across 2 files.To get there,
buildExportImageNames()was extracted so the whole chain the export screen actually runs — creation date → user filename format → forbidden-character sanitising → collision suffixes — is covered end to end, instead of only its individual pieces.The same extract-then-test approach was applied to sync folder filtering:
SyncWorker's two private filter methods moved intoapp/services/sync/folderFilter.ts(the worker delegates to it, behaviour unchanged) so the rules can be pinned — an empty folder list means "no filter", and documents in no folder are excluded once a filter is active.Fixes to tests already on this branch
exportUtils.test.tsre-declared the export regex inline and asserted against that copy. It tested a duplicate, so editing the real regex could never fail it. Removed — the realcleanFilenameis covered inutils.common.test.ts.matrix.test.tsactually testedcolor_matrix.ts. Renamed tocolor_matrix.test.ts; a realmatrix.test.tsnow coversgetPageColorMatrix(filter selection, brightness/contrast composition, NaN handling).TZis now pinned to UTC in the Vitest config — this app formats dates into filenames, so this would have been a recurring CI flake.New coverage
utils/exportUtilsutils/matrixutils/pkpassservices/apiqueryStringURL building and parameter extractionservices/sync/folderFilterservices/sync/typesservices/sync/BaseSyncServiceTest harness
ApplicationSettingsis now an in-memory store that resets between tests, so settings-dependent behaviour can be exercised instead of only default values.DefinePluginglobals plus NativeScript's.common.tsplatform resolution are mirrored in the Vitest config. This unblocks importingpkpass,apiandlocale, which previously failed at import time.251 tests across 14 files. New files typecheck against
tsconfig.test.jsonand pass ESLint.Not covered, and why
app/components/**(Svelte) — no component test setup; would need a renderer.app/models/OCRDocument.ts— transitively imports the NativeScript UI layer and cannot be imported under Vitest. Documented in.claude/CLAUDE.mdalong with the extract-the-pure-logic workaround.app/services/documents.ts— SQL-backed; needs a database fixture rather than unit tests.Two things worth a maintainer decision
.github/workflows/test.ymlonmainrunsecho "${{ toJSON(secrets) }}", which writes every repository secret into the build log. It isworkflow_dispatch-only, so triggering it needs maintainer access, but logs are readable by anyone with read access. Left untouched here as out of scope — worth deleting and rotating those secrets.app/services/trashUtils.tsis unreferenced. The shipping trash logic is SQL-backed indocuments.ts, so the existingtrash.test.tsguards code the app never runs. Left as-is: either wire the module in or drop it.