mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
b1ba3a03e7
Clearing a book's progress deleted the shared row and left the KOReader device row behind, so the next pull served the deleted position straight back. Clearing that row too is not enough either: an empty response reads as "this server knows nothing about your book", which is the one reply that leaves a device certain its own sidecar is the only position there is, and it pushes that back on the next sync. Record the reset as a durable fact and answer the pull with a real start position attributed to BookOrbit. Route the position by format, because KOReader's own kosync plugin feeds it straight to GotoPage or GotoXPointer with no percentage fallback and an empty value leaves the reader where it was. Stamp each delivery as current, because both clients compare that against their last page turn and default backward syncs to disabled, so the original reset time would be dropped on any pull deferred past a page turn without ever prompting. Serving a reset proves nothing, since either client can classify it as a backward sync and drop it silently, so the marker survives delivery and a device is held until its own push reports the start. Retire it once a device that took the reset reads on: the pull carries no device identity, so a marker kept alive past its purpose is answered to every device and would send that one back to the start on every sync. The bound this leaves is deliberate. A second device that never took the reset is protected only until the first reads on, and closing that needs device_id on the pull, which is a plugin change. Judge convergence on the reported position rather than the percentage, so page 1 of a hundred page comic is not mistaken for a position no short book could ever reach. Wind Kobo bookmarks back through the same paths, since a Kobo device otherwise resumes from its own bookmark and reports it back the same way. Closes #1032
744 lines
26 KiB
JavaScript
744 lines
26 KiB
JavaScript
const TEST_RESULTS_DIR = "../test-results/server";
|
|
|
|
export const E2E_GLOBAL_CHANGE_PATHS = Object.freeze([
|
|
".github/workflows/ci.yml",
|
|
".github/workflows/e2e.yml",
|
|
".github/workflows/e2e-runner.yml",
|
|
"Dockerfile",
|
|
"docker-compose*.yml",
|
|
"docker/**",
|
|
]);
|
|
|
|
const SHARED_DB_AND_HELPER_PATHS = Object.freeze(["server/src/db/schema/**", "scripts/e2e/**", "scripts/db/**"]);
|
|
|
|
const SHARED_AUTH_TYPE_PATHS = Object.freeze(["packages/types/src/auth.ts", "packages/types/src/permissions.ts"]);
|
|
|
|
const SHARED_TYPES_PATHS = Object.freeze(["packages/types/src/**"]);
|
|
|
|
export const E2E_SUITES = Object.freeze({
|
|
"guard-mechanics": {
|
|
id: "guard-mechanics",
|
|
name: "Guard Mechanics",
|
|
timeout: 30,
|
|
lane: "smoke",
|
|
description: "Guard mechanics suite - verifies @Public/@RequirePermission wiring without a real DB",
|
|
vitestTarget: "test/guard-mechanics.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/guard-mechanics-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: false,
|
|
useDedicatedDatabase: false,
|
|
changedPaths: [
|
|
"server/src/common/guards/**",
|
|
"server/src/common/decorators/**",
|
|
"server/src/common/types/**",
|
|
"server/src/modules/auth/**",
|
|
"server/src/modules/user/**",
|
|
"server/src/modules/role/**",
|
|
"server/src/**",
|
|
"server/test/guard-mechanics.e2e-spec.ts",
|
|
"server/test/e2e/**",
|
|
...SHARED_AUTH_TYPE_PATHS,
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"scanner-scenarios": {
|
|
id: "scanner-scenarios",
|
|
name: "Scanner Scenarios",
|
|
timeout: 45,
|
|
lane: "full",
|
|
description: "Scanner scenario matrix",
|
|
vitestTarget: "test/scanner-scenarios.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/scanner-scenarios-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/scanner/**",
|
|
"server/test/scanner-scenarios.e2e-spec.ts",
|
|
"server/test/e2e/scanner/**",
|
|
".github/workflows/e2e-runner.yml",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"scanner-file-operations": {
|
|
id: "scanner-file-operations",
|
|
name: "Scanner File Operations",
|
|
timeout: 60,
|
|
lane: "full",
|
|
description: "Scanner file operation matrix",
|
|
vitestTarget: "test/scanner-file-operations.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/scanner-file-operations-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/scanner/**",
|
|
"server/test/scanner-file-operations.e2e-spec.ts",
|
|
"server/test/e2e/scanner/**",
|
|
".github/workflows/e2e-runner.yml",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"auth-session-security": {
|
|
id: "auth-session-security",
|
|
name: "Auth Session Security",
|
|
timeout: 50,
|
|
lane: "full",
|
|
description: "Auth session security suite",
|
|
vitestTarget: "test/auth-session-security.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/auth-session-security-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/auth/**",
|
|
"server/src/modules/user/**",
|
|
"server/src/modules/role/**",
|
|
"server/src/common/guards/**",
|
|
"server/src/common/decorators/**",
|
|
"server/src/common/types/**",
|
|
"server/test/auth-session-security.e2e-spec.ts",
|
|
"server/test/e2e/app-harness.ts",
|
|
".github/workflows/e2e-runner.yml",
|
|
...SHARED_AUTH_TYPE_PATHS,
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"auth-recovery-oidc-logout": {
|
|
id: "auth-recovery-oidc-logout",
|
|
name: "Auth Recovery OIDC Logout",
|
|
timeout: 50,
|
|
lane: "full",
|
|
description: "Auth recovery and OIDC logout suite",
|
|
vitestTarget: "test/auth-recovery-oidc-logout.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/auth-recovery-oidc-logout-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/auth/**",
|
|
"server/src/modules/user/**",
|
|
"server/src/modules/email/**",
|
|
"server/src/modules/metadata/**",
|
|
"server/test/auth-recovery-oidc-logout.e2e-spec.ts",
|
|
"server/test/e2e/app-harness.ts",
|
|
".github/workflows/e2e-runner.yml",
|
|
"packages/types/src/auth.ts",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"book-dock-ingest-finalize": {
|
|
id: "book-dock-ingest-finalize",
|
|
name: "Book Dock Ingest Finalize",
|
|
timeout: 45,
|
|
lane: "full",
|
|
description: "Book Dock ingest and finalize suite",
|
|
vitestTarget: "test/book-dock-ingest-finalize.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/book-dock-ingest-finalize-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/book-dock/**",
|
|
"server/src/modules/upload/**",
|
|
"server/src/modules/metadata/**",
|
|
"server/test/book-dock-ingest-finalize.e2e-spec.ts",
|
|
"server/test/e2e/book-dock/**",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"metadata-write": {
|
|
id: "metadata-write",
|
|
name: "Metadata Write",
|
|
timeout: 60,
|
|
lane: "full",
|
|
description: "Metadata write operations suite",
|
|
vitestTarget: "test/metadata-write.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/metadata-write-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/book/**",
|
|
"server/src/modules/library/**",
|
|
"server/src/modules/file-write/**",
|
|
"server/src/modules/metadata/**",
|
|
"server/src/modules/app-settings/**",
|
|
"server/test/metadata-write.e2e-spec.ts",
|
|
"server/test/e2e/metadata-write/**",
|
|
"packages/types/src/file-write.ts",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"metadata-lock": {
|
|
id: "metadata-lock",
|
|
name: "Metadata Lock",
|
|
timeout: 60,
|
|
lane: "full",
|
|
description: "Metadata lock end-to-end suite",
|
|
vitestTarget: "test/metadata-lock.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/metadata-lock-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/book/**",
|
|
"server/src/modules/book-metadata-lock/**",
|
|
"server/src/modules/book-metadata-fetch/**",
|
|
"server/src/modules/metadata-fetch/**",
|
|
"server/src/modules/metadata-preferences/**",
|
|
"server/src/modules/cover/**",
|
|
"server/src/modules/scanner/**",
|
|
"server/src/modules/library/**",
|
|
"server/src/modules/auth/**",
|
|
"server/src/modules/app-settings/**",
|
|
"server/test/metadata-lock.e2e-spec.ts",
|
|
"server/test/e2e/metadata-lock/**",
|
|
".github/workflows/e2e-runner.yml",
|
|
...SHARED_TYPES_PATHS,
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"migration-booklore": {
|
|
id: "migration-booklore",
|
|
name: "Migration Booklore",
|
|
timeout: 70,
|
|
lane: "full",
|
|
description: "Booklore migration end-to-end suite",
|
|
vitestTarget: "test/migration-booklore.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/migration-booklore-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/migration/**",
|
|
"server/test/migration-booklore.e2e-spec.ts",
|
|
"server/test/e2e/migration-booklore/**",
|
|
".github/workflows/e2e-runner.yml",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"migration-audiobookshelf": {
|
|
id: "migration-audiobookshelf",
|
|
name: "Migration Audiobookshelf",
|
|
timeout: 90,
|
|
lane: "full",
|
|
description: "Audiobookshelf live API and real-backup migration end-to-end suite",
|
|
vitestTarget: "test/migration-audiobookshelf.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/migration-audiobookshelf-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
requiresDocker: true,
|
|
changedPaths: [
|
|
"server/src/modules/migration/**",
|
|
"server/test/migration-audiobookshelf.e2e-spec.ts",
|
|
"server/test/e2e/migration-audiobookshelf/**",
|
|
".github/workflows/e2e-runner.yml",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"migration-calibre-web-automated": {
|
|
id: "migration-calibre-web-automated",
|
|
name: "Migration Calibre-Web Automated",
|
|
timeout: 120,
|
|
lane: "full",
|
|
description: "Calibre-Web Automated stopped-snapshot migration end-to-end suite",
|
|
vitestTarget: "test/migration-calibre-web-automated.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/migration-calibre-web-automated-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
requiresDocker: true,
|
|
changedPaths: [
|
|
"server/src/modules/migration/**",
|
|
"server/test/migration-calibre-web-automated.e2e-spec.ts",
|
|
"server/test/e2e/migration-calibre-web-automated/**",
|
|
".github/workflows/e2e-runner.yml",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"authorization-matrix": {
|
|
id: "authorization-matrix",
|
|
name: "Authorization Matrix",
|
|
timeout: 60,
|
|
lane: "full",
|
|
description: "Authorization matrix suite",
|
|
vitestTarget: "test/authorization-matrix.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/authorization-matrix-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/**",
|
|
"server/test/authorization-matrix.e2e-spec.ts",
|
|
"server/test/e2e/authorization-matrix/**",
|
|
".github/workflows/e2e-runner.yml",
|
|
...SHARED_TYPES_PATHS,
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"dashboard-random": {
|
|
id: "dashboard-random",
|
|
name: "Dashboard Random Scroller",
|
|
timeout: 60,
|
|
lane: "full",
|
|
description: "Dashboard random scroller repository integration suite",
|
|
vitestTarget: "test/dashboard-random.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/dashboard-random-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/dashboard/**",
|
|
"server/test/dashboard-random.e2e-spec.ts",
|
|
"server/test/e2e/authorization-matrix/**",
|
|
".github/workflows/e2e-runner.yml",
|
|
"packages/types/src/dashboard.ts",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"book-api-contract": {
|
|
id: "book-api-contract",
|
|
name: "Book API Contract",
|
|
timeout: 60,
|
|
lane: "full",
|
|
description: "Book API contract suite",
|
|
vitestTarget: "test/book-api-contract.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/book-api-contract-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/book/**",
|
|
"server/src/modules/library/**",
|
|
"server/src/modules/collection/**",
|
|
"server/src/modules/auth/**",
|
|
"server/src/modules/user/**",
|
|
"server/test/book-api-contract.e2e-spec.ts",
|
|
"server/test/e2e/book-api-contract/**",
|
|
...SHARED_TYPES_PATHS,
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"jump-buckets-invariant": {
|
|
id: "jump-buckets-invariant",
|
|
name: "Jump Buckets Invariant",
|
|
timeout: 45,
|
|
lane: "full",
|
|
description: "Asserts jump-bucket indexes match real listing offsets for every eligible sort, direction, and collapse mode",
|
|
vitestTarget: "test/jump-buckets-invariant.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/jump-buckets-invariant-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/book/**",
|
|
"server/src/modules/library/**",
|
|
"server/src/db/book-author-sort-key.ts",
|
|
"server/test/jump-buckets-invariant.e2e-spec.ts",
|
|
...SHARED_TYPES_PATHS,
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"app-settings-oidc-contract": {
|
|
id: "app-settings-oidc-contract",
|
|
name: "App Settings OIDC Contract",
|
|
timeout: 60,
|
|
lane: "full",
|
|
description: "App settings OIDC contract suite",
|
|
vitestTarget: "test/app-settings-oidc-contract.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/app-settings-oidc-contract-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/app-settings/**",
|
|
"server/src/modules/auth/**",
|
|
"server/src/modules/user/**",
|
|
"server/src/modules/metadata/**",
|
|
"server/test/app-settings-oidc-contract.e2e-spec.ts",
|
|
"server/test/e2e/app-settings/**",
|
|
...SHARED_TYPES_PATHS,
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"library-admin-workflows": {
|
|
id: "library-admin-workflows",
|
|
name: "Library Admin Workflows",
|
|
timeout: 60,
|
|
lane: "full",
|
|
description: "Library admin workflows suite",
|
|
vitestTarget: "test/library-admin-workflows.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/library-admin-workflows-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/library/**",
|
|
"server/src/modules/auth/**",
|
|
"server/src/modules/user/**",
|
|
"server/src/modules/role/**",
|
|
"server/test/library-admin-workflows.e2e-spec.ts",
|
|
"server/test/e2e/library/**",
|
|
...SHARED_TYPES_PATHS,
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"reader-format-delivery": {
|
|
id: "reader-format-delivery",
|
|
name: "Reader Format Delivery",
|
|
timeout: 60,
|
|
lane: "full",
|
|
description: "Reader format delivery suite",
|
|
vitestTarget: "test/reader-format-delivery.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/reader-format-delivery-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/book/**",
|
|
"server/src/modules/library/**",
|
|
"server/src/modules/reader-preferences/**",
|
|
"server/src/modules/annotation/**",
|
|
"server/src/modules/bookmark/**",
|
|
"server/test/reader-format-delivery.e2e-spec.ts",
|
|
"server/test/e2e/reader-format-delivery/**",
|
|
"packages/types/src/reader-settings.ts",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"opds-auth-catalog": {
|
|
id: "opds-auth-catalog",
|
|
name: "OPDS Auth Catalog",
|
|
timeout: 45,
|
|
lane: "full",
|
|
description: "OPDS auth and catalog suite",
|
|
vitestTarget: "test/opds-auth-catalog.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/opds-auth-catalog-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/opds/**",
|
|
"server/src/modules/book/**",
|
|
"server/src/modules/library/**",
|
|
"server/src/modules/collection/**",
|
|
"server/src/modules/lens/**",
|
|
"server/src/modules/user/**",
|
|
"server/src/modules/auth/**",
|
|
"server/src/modules/app-settings/**",
|
|
"server/test/opds-auth-catalog.e2e-spec.ts",
|
|
"server/test/e2e/opds/**",
|
|
"server/test/e2e/**",
|
|
".github/workflows/e2e-runner.yml",
|
|
...SHARED_TYPES_PATHS,
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"email-lifecycle": {
|
|
id: "email-lifecycle",
|
|
name: "Email Lifecycle",
|
|
timeout: 45,
|
|
lane: "full",
|
|
description: "Email lifecycle suite",
|
|
vitestTarget: "test/email-lifecycle.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/email-lifecycle-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/email/**",
|
|
"server/src/modules/book/**",
|
|
"server/src/modules/library/**",
|
|
"server/src/modules/auth/**",
|
|
"server/src/modules/cover/**",
|
|
"server/src/modules/scanner/**",
|
|
"server/src/modules/seed/**",
|
|
"server/test/email-lifecycle.e2e-spec.ts",
|
|
"server/test/e2e/email/**",
|
|
"server/test/e2e/**",
|
|
"client/src/features/email/**",
|
|
"client/src/router/index.ts",
|
|
"client/src/features/settings/SettingsHeader.vue",
|
|
"client/src/views/HomeView.vue",
|
|
"client/src/views/CollectionView.vue",
|
|
"client/src/views/LensView.vue",
|
|
"client/src/features/book/components/BookCoverCard.vue",
|
|
"client/src/features/book/components/BookListRow.vue",
|
|
...SHARED_TYPES_PATHS,
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"reader-state-isolation": {
|
|
id: "reader-state-isolation",
|
|
name: "Reader State Isolation",
|
|
timeout: 45,
|
|
lane: "full",
|
|
description: "Reader state isolation suite",
|
|
vitestTarget: "test/reader-state-isolation.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/reader-state-isolation-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/bookmark/**",
|
|
"server/src/modules/annotation/**",
|
|
"server/src/modules/reader-preferences/**",
|
|
"server/src/modules/reading-session/**",
|
|
"server/src/modules/book/**",
|
|
"server/src/modules/library/**",
|
|
"server/src/modules/scanner/**",
|
|
"server/src/modules/user-book-status/**",
|
|
"server/src/scripts/db-prepare-e2e.ts",
|
|
"server/test/reader-state-isolation.e2e-spec.ts",
|
|
"server/test/e2e/reader-state-isolation/**",
|
|
"packages/types/src/reader-settings.ts",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"koreader-annotation-exchange": {
|
|
id: "koreader-annotation-exchange",
|
|
name: "KOReader Annotation Exchange",
|
|
timeout: 45,
|
|
lane: "full",
|
|
description: "KOReader annotation exchange suite",
|
|
vitestTarget: "test/koreader-annotation-exchange.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/koreader-annotation-exchange-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/annotation/**",
|
|
"server/src/modules/koreader/**",
|
|
"server/src/modules/position-converter/**",
|
|
"server/test/koreader-annotation-exchange.e2e-spec.ts",
|
|
"server/test/e2e/reader-state-isolation/**",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"koreader-bookmark-exchange": {
|
|
id: "koreader-bookmark-exchange",
|
|
name: "KOReader Bookmark Exchange",
|
|
timeout: 45,
|
|
lane: "full",
|
|
description: "KOReader two-way bookmark (dogear) exchange suite",
|
|
vitestTarget: "test/koreader-bookmark-exchange.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/koreader-bookmark-exchange-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/bookmark/**",
|
|
"server/src/modules/koreader/**",
|
|
"server/src/modules/position-converter/**",
|
|
"server/test/koreader-bookmark-exchange.e2e-spec.ts",
|
|
"server/test/e2e/reader-state-isolation/**",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"koreader-bulk-manifest": {
|
|
id: "koreader-bulk-manifest",
|
|
name: "KOReader Bulk Manifest Scale",
|
|
timeout: 45,
|
|
lane: "full",
|
|
description: "KOReader bulk manifest pagination and index support at 25,000 books",
|
|
vitestTarget: "test/koreader-bulk-manifest.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/koreader-bulk-manifest-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/koreader/**",
|
|
"server/src/modules/opds/opds-book.service.ts",
|
|
"server/src/db/schema/books.ts",
|
|
"server/test/koreader-bulk-manifest.e2e-spec.ts",
|
|
"server/test/e2e/reader-state-isolation/**",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"koreader-page-stats": {
|
|
id: "koreader-page-stats",
|
|
name: "KOReader Page Stats Derivation",
|
|
timeout: 45,
|
|
lane: "full",
|
|
description: "KOReader incremental page-stat derivation suite",
|
|
vitestTarget: "test/koreader-page-stats.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/koreader-page-stats-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/koreader/**",
|
|
"server/src/common/utils/reading-daily-stats.utils.ts",
|
|
"server/test/koreader-page-stats.e2e-spec.ts",
|
|
"server/test/e2e/reader-state-isolation/**",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"koreader-progress-reset": {
|
|
id: "koreader-progress-reset",
|
|
name: "KOReader Progress Reset Propagation",
|
|
timeout: 45,
|
|
lane: "full",
|
|
description: "KOReader reset propagation: a cleared position survives a device replaying its old one",
|
|
vitestTarget: "test/koreader-progress-reset.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/koreader-progress-reset-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/koreader/**",
|
|
"server/src/modules/book/book.repository.ts",
|
|
"server/src/modules/reading-state/**",
|
|
"server/src/db/schema/koreader.ts",
|
|
"server/test/koreader-progress-reset.e2e-spec.ts",
|
|
"server/test/e2e/reader-state-isolation/**",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"koreader-progress-position": {
|
|
id: "koreader-progress-position",
|
|
name: "KOReader Progress Position Routing",
|
|
timeout: 45,
|
|
lane: "full",
|
|
description: "KOReader progress position routing into cfi or pageNumber per book format",
|
|
vitestTarget: "test/koreader-progress-position.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/koreader-progress-position-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/koreader/**",
|
|
"server/src/modules/book/book.service.ts",
|
|
"server/src/db/schema/reader.ts",
|
|
"server/test/koreader-progress-position.e2e-spec.ts",
|
|
"server/test/e2e/reader-state-isolation/**",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"koreader-file-naming": {
|
|
id: "koreader-file-naming",
|
|
name: "KOReader File Naming",
|
|
timeout: 30,
|
|
lane: "full",
|
|
description: "KOReader file naming persistence and authorization suite",
|
|
vitestTarget: "test/koreader-file-naming.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/koreader-file-naming-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/koreader/**",
|
|
"server/test/koreader-file-naming.e2e-spec.ts",
|
|
"packages/types/src/pattern-resolver.ts",
|
|
...SHARED_AUTH_TYPE_PATHS,
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"annotations-hub": {
|
|
id: "annotations-hub",
|
|
name: "Annotations Hub",
|
|
timeout: 45,
|
|
lane: "full",
|
|
description: "Annotations hub suite",
|
|
vitestTarget: "test/annotations-hub.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/annotations-hub-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/annotation/**",
|
|
"server/src/modules/position-converter/**",
|
|
"server/test/annotations-hub.e2e-spec.ts",
|
|
"server/test/e2e/reader-state-isolation/**",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"kobo-annotation-sync": {
|
|
id: "kobo-annotation-sync",
|
|
name: "Kobo Annotation Sync",
|
|
timeout: 60,
|
|
lane: "full",
|
|
description: "Kobo annotation three-way sync suite",
|
|
vitestTarget: "test/kobo-annotation-sync.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/kobo-annotation-sync-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/annotation/**",
|
|
"server/src/modules/kobo/**",
|
|
"server/src/modules/koreader/**",
|
|
"server/src/modules/position-converter/**",
|
|
"server/test/kobo-annotation-sync.e2e-spec.ts",
|
|
"server/test/e2e/reader-state-isolation/**",
|
|
"packages/types/src/kobo.ts",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"kobo-multi-device-sync": {
|
|
id: "kobo-multi-device-sync",
|
|
name: "Kobo Multi-Device Sync",
|
|
timeout: 60,
|
|
lane: "full",
|
|
description: "Kobo device-owned library snapshot suite",
|
|
vitestTarget: "test/kobo-multi-device-sync.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/kobo-multi-device-sync-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/kobo/**",
|
|
"server/src/modules/book/**",
|
|
"server/src/modules/file-write/**",
|
|
"server/test/kobo-multi-device-sync.e2e-spec.ts",
|
|
"server/test/e2e/reader-state-isolation/**",
|
|
"packages/types/src/book.ts",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"users-admin-lifecycle": {
|
|
id: "users-admin-lifecycle",
|
|
name: "Users Admin Lifecycle",
|
|
timeout: 50,
|
|
lane: "full",
|
|
description: "Users admin lifecycle suite",
|
|
vitestTarget: "test/users-admin-lifecycle.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/users-admin-lifecycle-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/user/**",
|
|
"server/src/modules/auth/**",
|
|
"server/src/common/guards/**",
|
|
"server/src/common/decorators/**",
|
|
"server/src/common/types/**",
|
|
"server/test/users-admin-lifecycle.e2e-spec.ts",
|
|
"server/test/e2e/users-admin-lifecycle/**",
|
|
".github/workflows/e2e-runner.yml",
|
|
...SHARED_AUTH_TYPE_PATHS,
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"file-rename": {
|
|
id: "file-rename",
|
|
name: "File Rename",
|
|
timeout: 120,
|
|
lane: "full",
|
|
description: "Bulk file rename end-to-end suite covering all library/file structure permutations",
|
|
vitestTarget: "test/file-rename.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/file-rename-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/library/**",
|
|
"server/src/modules/file-write/**",
|
|
"server/src/modules/scanner/**",
|
|
"server/src/modules/app-settings/**",
|
|
"server/test/file-rename.e2e-spec.ts",
|
|
"server/test/e2e/file-rename/**",
|
|
"packages/types/src/file-write.ts",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
"book-move": {
|
|
id: "book-move",
|
|
name: "Book Move",
|
|
timeout: 120,
|
|
lane: "full",
|
|
description: "Cross-library book move suite covering preview classification, collision policies, and file relocation",
|
|
vitestTarget: "test/book-move.e2e-spec.ts",
|
|
junitOutput: `${TEST_RESULTS_DIR}/book-move-e2e-junit.xml`,
|
|
prepareDedicatedDatabase: true,
|
|
useDedicatedDatabase: true,
|
|
changedPaths: [
|
|
"server/src/modules/book-move/**",
|
|
"server/src/modules/scanner/**",
|
|
"server/src/modules/app-settings/**",
|
|
"server/test/book-move.e2e-spec.ts",
|
|
"server/test/e2e/metadata-write/**",
|
|
"packages/types/src/book-move.ts",
|
|
"packages/types/src/book-selection.ts",
|
|
...SHARED_DB_AND_HELPER_PATHS,
|
|
],
|
|
},
|
|
});
|
|
|
|
export function listE2ESuites() {
|
|
return Object.values(E2E_SUITES);
|
|
}
|
|
|
|
export function getE2ESuite(suiteId) {
|
|
return E2E_SUITES[suiteId] ?? null;
|
|
}
|