feat: refactor claude prisma guidelines, schemas dir, and implement b… - #618
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 Walkthrough📝 Walkthrough✨ Finishing Touches🧪 Generate unit tests (beta)
|
🎭 Playwright E2E Test Results84 tests 52 ✅ 3m 37s ⏱️ Results for commit f144944. ♻️ This comment has been updated with latest results. |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
libs/system-admin-pages/src/third-party-user/queries.test.ts (1)
178-199:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRemove incorrect
awaitusage.
getHighestSensitivityis a synchronous function that returns a string immediately. Theawaitkeyword serves no purpose here and may mislead readers into thinking the function is asynchronous.🔧 Proposed fix to remove await
it("should return unselected for empty array", async () => { - const result = await getHighestSensitivity([]); + const result = getHighestSensitivity([]); expect(result).toBe("unselected"); }); it("should return CLASSIFIED when present", async () => { const subscriptions = [{ sensitivity: "PUBLIC" }, { sensitivity: "CLASSIFIED" }, { sensitivity: "PRIVATE" }]; - const result = await getHighestSensitivity(subscriptions); + const result = getHighestSensitivity(subscriptions); expect(result).toBe("CLASSIFIED"); }); it("should return PRIVATE when CLASSIFIED is not present", async () => { const subscriptions = [{ sensitivity: "PUBLIC" }, { sensitivity: "PRIVATE" }]; - const result = await getHighestSensitivity(subscriptions); + const result = getHighestSensitivity(subscriptions); expect(result).toBe("PRIVATE"); }); it("should return PUBLIC when only PUBLIC is present", async () => { const subscriptions = [{ sensitivity: "PUBLIC" }]; - const result = await getHighestSensitivity(subscriptions); + const result = getHighestSensitivity(subscriptions); expect(result).toBe("PUBLIC"); });libs/api/src/blob-ingestion/repository/queries.ts (1)
40-48: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick winExtract duplicated mapping logic to eliminate code repetition.
Both
getIngestionLogsByDateRangeandgetRecentErrorLogscontain identical mapping logic that transforms Prisma results intoIngestionLogtypes. This violates the DRY principle and increases maintenance burden.♻️ Proposed refactor to extract common mapping logic
+function mapPrismaLogToIngestionLog(log: { + id: string; + timestamp: Date; + sourceSystem: string; + courtId: string; + status: string; + errorMessage: string | null; + artefactId: string | null; +}): IngestionLog { + return { + id: log.id, + timestamp: log.timestamp, + sourceSystem: log.sourceSystem, + courtId: log.courtId, + status: log.status as "SUCCESS" | "VALIDATION_ERROR" | "SYSTEM_ERROR", + errorMessage: log.errorMessage || undefined, + artefactId: log.artefactId || undefined + }; +} + export async function getIngestionLogsByDateRange(startDate: Date, endDate: Date): Promise<IngestionLog[]> { const logs = await prisma.ingestionLog.findMany({ where: { timestamp: { gte: startDate, lte: endDate } }, orderBy: { timestamp: "desc" }, select: { id: true, timestamp: true, sourceSystem: true, courtId: true, status: true, errorMessage: true, artefactId: true } }); - return logs.map((log) => ({ - id: log.id, - timestamp: log.timestamp, - sourceSystem: log.sourceSystem, - courtId: log.courtId, - status: log.status as "SUCCESS" | "VALIDATION_ERROR" | "SYSTEM_ERROR", - errorMessage: log.errorMessage || undefined, - artefactId: log.artefactId || undefined - })); + return logs.map(mapPrismaLogToIngestionLog); } export async function getRecentErrorLogs(limit = 10): Promise<IngestionLog[]> { const logs = await prisma.ingestionLog.findMany({ where: { status: { in: ["VALIDATION_ERROR", "SYSTEM_ERROR"] } }, orderBy: { timestamp: "desc" }, take: limit, select: { id: true, timestamp: true, sourceSystem: true, courtId: true, status: true, errorMessage: true, artefactId: true } }); - return logs.map((log) => ({ - id: log.id, - timestamp: log.timestamp, - sourceSystem: log.sourceSystem, - courtId: log.courtId, - status: log.status as "SUCCESS" | "VALIDATION_ERROR" | "SYSTEM_ERROR", - errorMessage: log.errorMessage || undefined, - artefactId: log.artefactId || undefined - })); + return logs.map(mapPrismaLogToIngestionLog); }Based on learnings: Follow DRY principle: Don't repeat yourself. Factor out code used in multiple places into reusable functions or utilities.
Also applies to: 73-81
libs/location/src/filtering/service.ts (1)
67-77:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAvoid serial awaits in the jurisdiction loop.
Line 68 runs one DB call at a time, so total latency scales with jurisdiction count. Run these calls concurrently to keep response time stable.
Proposed change
- for (const jurisdiction of allJurisdictions) { - const subJurisdictionsForJurisdiction = await getSubJurisdictionsByJurisdiction(jurisdiction.jurisdictionId); - - subJurisdictionItemsByJurisdiction[jurisdiction.jurisdictionId] = subJurisdictionsForJurisdiction - .map((sub) => ({ - value: sub.subJurisdictionId.toString(), - text: locale === "cy" ? sub.welshName : sub.name, - checked: selectedSubJurisdictions.includes(sub.subJurisdictionId) - })) - .sort((a, b) => a.text.localeCompare(b.text)); - } + const entries = await Promise.all( + allJurisdictions.map(async (jurisdiction) => { + const subJurisdictionsForJurisdiction = await getSubJurisdictionsByJurisdiction(jurisdiction.jurisdictionId); + const items = subJurisdictionsForJurisdiction + .map((sub) => ({ + value: sub.subJurisdictionId.toString(), + text: locale === "cy" ? sub.welshName : sub.name, + checked: selectedSubJurisdictions.includes(sub.subJurisdictionId) + })) + .sort((a, b) => a.text.localeCompare(b.text)); + return [jurisdiction.jurisdictionId, items] as const; + }) + ); + + for (const [jurisdictionId, items] of entries) { + subJurisdictionItemsByJurisdiction[jurisdictionId] = items; + }
🧹 Nitpick comments (7)
libs/system-admin-pages/src/third-party-user/queries.ts (1)
8-22: ⚡ Quick winExtract duplicated select structure to eliminate repetition.
The identical select configuration is repeated in both
findAllThirdPartyUsersandfindThirdPartyUserById, violating the DRY principle.♻️ Proposed refactor to extract shared select
+const THIRD_PARTY_USER_SELECT = { + id: true, + name: true, + createdDate: true, + subscriptions: { + select: { + id: true, + userId: true, + listTypeId: true, + channel: true, + sensitivity: true, + createdDate: true + } + } +} as const; + export async function findAllThirdPartyUsers() { return prisma.legacyThirdPartyUser.findMany({ orderBy: { createdDate: "desc" }, - select: { - id: true, - name: true, - createdDate: true, - subscriptions: { - select: { - id: true, - userId: true, - listTypeId: true, - channel: true, - sensitivity: true, - createdDate: true - } - } - } + select: THIRD_PARTY_USER_SELECT }); } export async function findThirdPartyUserById(id: string) { return prisma.legacyThirdPartyUser.findUnique({ where: { id }, - select: { - id: true, - name: true, - createdDate: true, - subscriptions: { - select: { - id: true, - userId: true, - listTypeId: true, - channel: true, - sensitivity: true, - createdDate: true - } - } - } + select: THIRD_PARTY_USER_SELECT }); }As per coding guidelines: "Follow DRY principle: Don't repeat yourself. Factor out code used in multiple places into reusable functions or utilities."
Also applies to: 29-43
libs/location/src/repository/queries.ts (2)
17-26: ⚡ Quick winConsider removing redundant length checks.
The
filters.regions.length > 0andfilters.subJurisdictions.length > 0checks are unnecessary. Prisma'sin: []operator naturally matches no rows when the array is empty, so the filter would have no effect. Removing these checks simplifies the logic without changing behaviour.♻️ Simplified version
- ...(filters?.regions && - filters.regions.length > 0 && { + ...(filters?.regions && { locationRegions: { some: { regionId: { in: filters.regions } } } }), - ...(filters?.subJurisdictions && - filters.subJurisdictions.length > 0 && { + ...(filters?.subJurisdictions && { locationSubJurisdictions: { some: { subJurisdictionId: { in: filters.subJurisdictions } } } })Also applies to: 27-36
66-72: ⚡ Quick winExtract duplicate mapping logic into helper function.
The logic for mapping nested
locationRegionsandlocationSubJurisdictionsto flat arrays of IDs is duplicated across four functions (getAllLocations,searchLocationsByName,getLocationById, andgetLocationsByIds). Extracting this into a helper would reduce duplication and improve maintainability.♻️ Suggested helper function
function mapLocationWithIds(loc: { locationId: number; name: string; welshName: string; locationRegions: Array<{ region: { regionId: number } }>; locationSubJurisdictions: Array<{ subJurisdiction: { subJurisdictionId: number } }>; }): Location { return { locationId: loc.locationId, name: loc.name, welshName: loc.welshName, regions: loc.locationRegions.map((lr) => lr.region.regionId), subJurisdictions: loc.locationSubJurisdictions.map((lsj) => lsj.subJurisdiction.subJurisdictionId) }; }Then replace the duplicated mapping with:
- return locations.map((loc) => ({ - locationId: loc.locationId, - name: loc.name, - welshName: loc.welshName, - regions: loc.locationRegions.map((lr) => lr.region.regionId), - subJurisdictions: loc.locationSubJurisdictions.map((lsj) => lsj.subJurisdiction.subJurisdictionId) - })); + return locations.map(mapLocationWithIds);Based on learnings: Follow DRY principle: Don't repeat yourself. Factor out code used in multiple places into reusable functions or utilities.
Also applies to: 115-121, 159-165, 201-207
libs/verified-pages/src/pages/pending-subscriptions/index.ts (1)
31-37: ⚡ Quick winExtract duplicate location-fetching logic and validate IDs.
Two issues:
- The location-fetching and mapping logic is duplicated between the GET handler and POST error path.
- Non-numeric strings in
pendingLocationIdswill produceNaNvalues when parsed, potentially causing unexpected behaviour.Consider extracting the location-enrichment logic into a helper function and adding validation to filter out invalid IDs.
♻️ Suggested refactor
async function enrichPendingLocations(pendingLocationIds: string[], locale: string) { const locationIds = pendingLocationIds .map((id: string) => Number.parseInt(id, 10)) .filter((id) => !Number.isNaN(id)); const locations = await getLocationsByIds(locationIds); return locations.map((location) => ({ locationId: location.locationId.toString(), name: locale === "cy" ? location.welshName : location.name })); }Then replace both occurrences with:
const pendingLocations = await enrichPendingLocations(pendingLocationIds, locale);Based on learnings: Follow DRY principle: Don't repeat yourself. Factor out code used in multiple places into reusable functions or utilities.
Also applies to: 110-116
libs/subscriptions/src/repository/service.ts (1)
140-142: ⚡ Quick winDe-duplicate IDs before batch location fetches.
Both call sites can pass repeated IDs to
getLocationsByIds, which adds avoidable query and mapping overhead.Proposed change
- const locationIds = subscriptions.map((sub) => Number.parseInt(sub.searchValue, 10)).filter((id) => !Number.isNaN(id)); + const locationIds = [ + ...new Set(subscriptions.map((sub) => Number.parseInt(sub.searchValue, 10)).filter((id) => !Number.isNaN(id))) + ]; const locations = await getLocationsByIds(locationIds);- const locationIds = subscriptions.map((sub) => Number.parseInt(sub.searchValue, 10)).filter((id) => !Number.isNaN(id)); + const locationIds = [ + ...new Set(subscriptions.map((sub) => Number.parseInt(sub.searchValue, 10)).filter((id) => !Number.isNaN(id))) + ]; const locations = await getLocationsByIds(locationIds);Also applies to: 176-178
libs/publication/src/repository/queries.test.ts (2)
822-822: ⚡ Quick winRemove obsolete mock.
The implementation no longer calls
prisma.listType.findManyas it now uses nested selection viaartefact.listType. This mock setup is dead code and should be removed.♻️ Suggested cleanup
vi.mocked(prisma.artefact.findMany).mockResolvedValue(mockArtefacts); - vi.mocked(prisma.listType.findMany).mockResolvedValue([]); const result = await getArtefactSummariesByLocation("123");
939-940: ⚡ Quick winRemove obsolete listType mocks.
The implementation of
getArtefactMetadatanow uses nested selection onartefact.listTypeinstead of separateprisma.listType.findUniquecalls. These mock setups are no longer needed and should be removed.♻️ Suggested cleanup
vi.mocked(prisma.artefact.findUnique).mockResolvedValue(mockArtefact); - vi.mocked(prisma.listType.findUnique).mockResolvedValue(mockListType); vi.mocked(getLocationById).mockResolvedValue(mockLocation);Also applies to: 970-971, 1004-1005, 1043-1044
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 8abff8f5-c2a8-4880-9217-26f909235bb8
📒 Files selected for processing (69)
.claude/agents/full-stack-engineer.md.claude/rules/backend.md.github/workflows/e2e.ymlCLAUDE.mdREADME.mdapps/postgres/package.jsonapps/postgres/prisma.config.tsapps/postgres/prisma/seed.tsdocs/ARCHITECTURE.mdlibs/admin-pages/src/pages/non-strategic-upload/index.test.tslibs/admin-pages/src/pages/non-strategic-upload/index.tslibs/api/src/blob-ingestion/repository/queries.test.tslibs/api/src/blob-ingestion/repository/queries.tslibs/audit-log/package.jsonlibs/audit-log/src/config.tslibs/audit-log/tsconfig.jsonlibs/list-search-config/package.jsonlibs/list-search-config/src/config.test.tslibs/list-search-config/src/config.tslibs/location/src/config.test.tslibs/location/src/config.tslibs/location/src/filtering/service.test.tslibs/location/src/filtering/service.tslibs/location/src/index.tslibs/location/src/repository/queries.test.tslibs/location/src/repository/queries.tslibs/location/src/repository/service.test.tslibs/location/src/repository/service.tslibs/notifications/package.jsonlibs/notifications/src/config.test.tslibs/notifications/src/config.tslibs/notifications/src/notification/subscription-queries.test.tslibs/notifications/src/notification/subscription-queries.tslibs/postgres-prisma/package.jsonlibs/postgres-prisma/prisma.config.tslibs/postgres-prisma/prisma/schema/audit-log.prismalibs/postgres-prisma/prisma/schema/base.prismalibs/postgres-prisma/prisma/schema/list-search-config.prismalibs/postgres-prisma/prisma/schema/location.prismalibs/postgres-prisma/prisma/schema/notification.prismalibs/postgres-prisma/prisma/schema/subscription.prismalibs/postgres-prisma/src/collate-schema.test.tslibs/postgres-prisma/src/collate-schema.tslibs/postgres-prisma/src/schema-discovery.test.tslibs/postgres-prisma/src/schema-discovery.tslibs/publication/src/repository/queries.test.tslibs/publication/src/repository/queries.tslibs/subscriptions/package.jsonlibs/subscriptions/src/config.tslibs/subscriptions/src/repository/service.test.tslibs/subscriptions/src/repository/service.tslibs/subscriptions/src/validation/validation.tslibs/system-admin-pages/src/list-type/queries.test.tslibs/system-admin-pages/src/list-type/queries.tslibs/system-admin-pages/src/pages/blob-explorer-publications/index.test.tslibs/system-admin-pages/src/pages/blob-explorer-publications/index.tslibs/system-admin-pages/src/pages/configure-list-type-enter-details/index.test.tslibs/system-admin-pages/src/pages/configure-list-type-enter-details/index.tslibs/system-admin-pages/src/pages/configure-list-type-preview/index.test.tslibs/system-admin-pages/src/pages/configure-list-type-preview/index.tslibs/system-admin-pages/src/reference-data-upload/services/download-service.tslibs/system-admin-pages/src/reference-data-upload/services/enrichment-service.tslibs/system-admin-pages/src/third-party-user/queries.test.tslibs/system-admin-pages/src/third-party-user/queries.tslibs/verified-pages/src/pages/pending-subscriptions/index.test.tslibs/verified-pages/src/pages/pending-subscriptions/index.tslibs/verified-pages/src/pages/subscription-confirmed/index.test.tslibs/verified-pages/src/pages/subscription-confirmed/index.tstsconfig.json
💤 Files with no reviewable changes (23)
- libs/audit-log/package.json
- libs/postgres-prisma/prisma/schema/list-search-config.prisma
- libs/postgres-prisma/src/schema-discovery.test.ts
- libs/postgres-prisma/src/schema-discovery.ts
- libs/audit-log/tsconfig.json
- libs/location/src/config.ts
- libs/notifications/src/config.ts
- libs/subscriptions/src/config.ts
- libs/notifications/src/config.test.ts
- tsconfig.json
- libs/audit-log/src/config.ts
- libs/notifications/package.json
- libs/list-search-config/src/config.ts
- libs/list-search-config/src/config.test.ts
- libs/subscriptions/package.json
- libs/postgres-prisma/src/collate-schema.test.ts
- libs/postgres-prisma/src/collate-schema.ts
- libs/postgres-prisma/prisma/schema/notification.prisma
- .github/workflows/e2e.yml
- libs/list-search-config/package.json
- libs/location/src/config.test.ts
- libs/postgres-prisma/prisma/schema/audit-log.prisma
- libs/postgres-prisma/prisma/schema/subscription.prisma
| const locationIds = confirmedLocationIds.map((id: string) => Number.parseInt(id, 10)); | ||
| const locations = await getLocationsByIds(locationIds); |
There was a problem hiding this comment.
Validate location IDs before parsing.
If confirmedLocationIds contains non-numeric strings, Number.parseInt(id, 10) will return NaN. Passing NaN values to getLocationsByIds could result in unexpected behaviour. Consider filtering out invalid IDs or adding validation to ensure all values are numeric.
🛡️ Suggested validation
const locationIds = confirmedLocationIds.map((id: string) => Number.parseInt(id, 10));
+ const validLocationIds = locationIds.filter((id) => !Number.isNaN(id));
+ const locations = await getLocationsByIds(validLocationIds);
- const locations = await getLocationsByIds(locationIds);
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/e2e.yml (1)
88-88:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRemove duplicate
ENABLE_CFT_IDAMdefinition.
ENABLE_CFT_IDAMis defined twice: at line 61 and line 88. Remove the duplicate at line 88.🔧 Proposed fix
CFT_INVALID_TEST_ACCOUNT_PASSWORD: ${{ secrets.CFT_INVALID_TEST_ACCOUNT_PASSWORD }} - # Crime IDAM Configuration - ENABLE_CFT_IDAM: true + # Crime IDAM Configuration CRIME_IDAM_BASE_URL: https://login.sit.cjscp.org.uk
🧹 Nitpick comments (1)
e2e-tests/global-setup.ts (1)
20-22: 💤 Low valueConsider making the initial delay configurable.
The hardcoded 5-second delay may be too long for fast environments or too short for slow ones. However, given the robust retry loop (60 attempts), this is acceptable as it primarily reduces log noise during startup.
💡 Optional: Make delay configurable
- // Add initial delay to allow services to start - console.log("Waiting 5 seconds for services to initialize..."); - await new Promise((resolve) => setTimeout(resolve, 5000)); + // Add initial delay to allow services to start + const initialDelay = Number(process.env.E2E_INITIAL_DELAY_MS) || 5000; + console.log(`Waiting ${initialDelay}ms for services to initialize...`); + await new Promise((resolve) => setTimeout(resolve, initialDelay));
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 40e2516e-3850-4a61-8fff-232a2598c5ff
📒 Files selected for processing (5)
.github/workflows/e2e.ymlapps/postgres/Dockerfileapps/postgres/package.jsone2e-tests/global-setup.tse2e-tests/playwright.config.ts
💤 Files with no reviewable changes (1)
- apps/postgres/Dockerfile
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/postgres/package.json
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
8a11758 to
a3c60dd
Compare
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
1d522d7 to
62dbbdd
Compare
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
There was a problem hiding this comment.
Actionable comments posted: 5
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f4e6c701-e715-4b3e-b2c8-518a41ce3a4b
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (71)
.claude/agents/full-stack-engineer.md.claude/rules/backend.md.github/workflows/e2e.ymlCLAUDE.mdREADME.mdapps/postgres/Dockerfileapps/postgres/package.jsonapps/postgres/prisma.config.tsapps/postgres/prisma/seed.tsdocs/ARCHITECTURE.mdlibs/admin-pages/src/pages/non-strategic-upload/index.test.tslibs/admin-pages/src/pages/non-strategic-upload/index.tslibs/api/src/blob-ingestion/repository/queries.test.tslibs/api/src/blob-ingestion/repository/queries.tslibs/audit-log/package.jsonlibs/audit-log/src/config.tslibs/audit-log/tsconfig.jsonlibs/list-search-config/package.jsonlibs/list-search-config/src/config.test.tslibs/list-search-config/src/config.tslibs/location/src/config.test.tslibs/location/src/config.tslibs/location/src/filtering/service.test.tslibs/location/src/filtering/service.tslibs/location/src/index.tslibs/location/src/repository/queries.test.tslibs/location/src/repository/queries.tslibs/location/src/repository/service.test.tslibs/location/src/repository/service.tslibs/notifications/package.jsonlibs/notifications/src/config.test.tslibs/notifications/src/config.tslibs/notifications/src/notification/subscription-queries.test.tslibs/notifications/src/notification/subscription-queries.tslibs/postgres-prisma/package.jsonlibs/postgres-prisma/prisma.config.tslibs/postgres-prisma/prisma/schema/audit-log.prismalibs/postgres-prisma/prisma/schema/base.prismalibs/postgres-prisma/prisma/schema/list-search-config.prismalibs/postgres-prisma/prisma/schema/location.prismalibs/postgres-prisma/prisma/schema/notification.prismalibs/postgres-prisma/prisma/schema/subscription.prismalibs/postgres-prisma/src/collate-schema.test.tslibs/postgres-prisma/src/collate-schema.tslibs/postgres-prisma/src/schema-discovery.test.tslibs/postgres-prisma/src/schema-discovery.tslibs/publication/src/repository/queries.test.tslibs/publication/src/repository/queries.tslibs/subscriptions/package.jsonlibs/subscriptions/src/config.tslibs/subscriptions/src/repository/service.test.tslibs/subscriptions/src/repository/service.tslibs/subscriptions/src/validation/validation.test.tslibs/subscriptions/src/validation/validation.tslibs/system-admin-pages/src/list-type/queries.test.tslibs/system-admin-pages/src/list-type/queries.tslibs/system-admin-pages/src/pages/blob-explorer-publications/index.test.tslibs/system-admin-pages/src/pages/blob-explorer-publications/index.tslibs/system-admin-pages/src/pages/configure-list-type-enter-details/index.test.tslibs/system-admin-pages/src/pages/configure-list-type-enter-details/index.tslibs/system-admin-pages/src/pages/configure-list-type-preview/index.test.tslibs/system-admin-pages/src/pages/configure-list-type-preview/index.tslibs/system-admin-pages/src/reference-data-upload/services/download-service.tslibs/system-admin-pages/src/reference-data-upload/services/enrichment-service.tslibs/system-admin-pages/src/third-party-user/queries.test.tslibs/system-admin-pages/src/third-party-user/queries.tslibs/verified-pages/src/pages/pending-subscriptions/index.test.tslibs/verified-pages/src/pages/pending-subscriptions/index.tslibs/verified-pages/src/pages/subscription-confirmed/index.test.tslibs/verified-pages/src/pages/subscription-confirmed/index.tstsconfig.json
💤 Files with no reviewable changes (24)
- libs/postgres-prisma/src/schema-discovery.test.ts
- libs/audit-log/tsconfig.json
- libs/notifications/src/config.ts
- libs/subscriptions/package.json
- libs/postgres-prisma/prisma/schema/notification.prisma
- libs/postgres-prisma/src/collate-schema.ts
- libs/notifications/package.json
- libs/postgres-prisma/prisma/schema/audit-log.prisma
- libs/postgres-prisma/prisma/schema/subscription.prisma
- libs/location/src/config.ts
- .github/workflows/e2e.yml
- libs/list-search-config/src/config.test.ts
- libs/audit-log/src/config.ts
- libs/audit-log/package.json
- libs/location/src/config.test.ts
- tsconfig.json
- libs/list-search-config/package.json
- libs/postgres-prisma/prisma/schema/list-search-config.prisma
- libs/notifications/src/config.test.ts
- libs/postgres-prisma/src/schema-discovery.ts
- libs/list-search-config/src/config.ts
- libs/postgres-prisma/src/collate-schema.test.ts
- apps/postgres/Dockerfile
- libs/subscriptions/src/config.ts
✅ Files skipped from review due to trivial changes (5)
- libs/verified-pages/src/pages/pending-subscriptions/index.test.ts
- libs/location/src/index.ts
- libs/admin-pages/src/pages/non-strategic-upload/index.test.ts
- libs/notifications/src/notification/subscription-queries.ts
- docs/ARCHITECTURE.md
🚧 Files skipped from review as they are similar to previous changes (32)
- libs/verified-pages/src/pages/subscription-confirmed/index.test.ts
- libs/postgres-prisma/prisma.config.ts
- libs/system-admin-pages/src/third-party-user/queries.ts
- libs/verified-pages/src/pages/subscription-confirmed/index.ts
- libs/api/src/blob-ingestion/repository/queries.ts
- apps/postgres/prisma.config.ts
- libs/system-admin-pages/src/pages/configure-list-type-enter-details/index.test.ts
- libs/api/src/blob-ingestion/repository/queries.test.ts
- libs/admin-pages/src/pages/non-strategic-upload/index.ts
- libs/system-admin-pages/src/pages/configure-list-type-preview/index.test.ts
- libs/system-admin-pages/src/reference-data-upload/services/enrichment-service.ts
- libs/location/src/filtering/service.test.ts
- libs/system-admin-pages/src/pages/configure-list-type-preview/index.ts
- libs/system-admin-pages/src/pages/blob-explorer-publications/index.ts
- libs/system-admin-pages/src/third-party-user/queries.test.ts
- libs/system-admin-pages/src/reference-data-upload/services/download-service.ts
- libs/verified-pages/src/pages/pending-subscriptions/index.ts
- libs/system-admin-pages/src/pages/blob-explorer-publications/index.test.ts
- libs/postgres-prisma/prisma/schema/base.prisma
- libs/publication/src/repository/queries.ts
- libs/postgres-prisma/package.json
- libs/system-admin-pages/src/list-type/queries.test.ts
- libs/location/src/repository/queries.ts
- libs/postgres-prisma/prisma/schema/location.prisma
- libs/location/src/filtering/service.ts
- libs/notifications/src/notification/subscription-queries.test.ts
- apps/postgres/prisma/seed.ts
- libs/publication/src/repository/queries.test.ts
- libs/subscriptions/src/repository/service.test.ts
- libs/subscriptions/src/validation/validation.ts
- .claude/rules/backend.md
- apps/postgres/package.json
| it("should return locations sorted alphabetically by name", async () => { | ||
| const results = await getAllLocations("en"); | ||
|
|
||
| for (let i = 0; i < results.length - 1; i++) { | ||
| expect(results[i].name.localeCompare(results[i + 1].name)).toBeLessThanOrEqual(0); | ||
| } | ||
| // Verify results are returned (database orderBy handles sorting via collation) | ||
| expect(results.length).toBeGreaterThan(0); | ||
| expect(results.every((loc) => loc.name && loc.welshName)).toBe(true); |
There was a problem hiding this comment.
Restore deterministic sort verification in these sorting tests.
Line 186 and Line 194 say the results are alphabetically sorted, but Line 189-Line 191 and Line 197-Line 199 only check presence. This will pass even if ordering breaks. Assert the DB orderBy contract instead.
Suggested test adjustment
it("should return locations sorted alphabetically by name", async () => {
const results = await getAllLocations("en");
- // Verify results are returned (database orderBy handles sorting via collation)
- expect(results.length).toBeGreaterThan(0);
- expect(results.every((loc) => loc.name && loc.welshName)).toBe(true);
+ expect(results.length).toBeGreaterThan(0);
+ expect(prisma.location.findMany).toHaveBeenCalledWith(
+ expect.objectContaining({
+ orderBy: { name: "asc" }
+ })
+ );
});
it("should return locations sorted alphabetically by Welsh name when language is cy", async () => {
const results = await getAllLocations("cy");
- // Verify results are returned (database orderBy handles sorting via collation)
- expect(results.length).toBeGreaterThan(0);
- expect(results.every((loc) => loc.name && loc.welshName)).toBe(true);
+ expect(results.length).toBeGreaterThan(0);
+ expect(prisma.location.findMany).toHaveBeenCalledWith(
+ expect.objectContaining({
+ orderBy: { welshName: "asc" }
+ })
+ );
});Also applies to: 194-199
736d5cf to
347aac2
Compare
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
5830b85 to
c2bfa47
Compare
Preview Deployment Successful 🚀Your preview environment is ready:
The environment will be automatically cleaned up when this PR is closed. |
c2bfa47 to
65b987c
Compare
65b987c to
ef9de8e
Compare
ef9de8e to
ef16b4a
Compare
…est practises feat: refactor claude prisma guidelines, schemas dir, and implement best practises Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Deduplicate yarn lockfile entries after rebase (std-env, opentelemetry packages, etc)
- Deduplicate yarn lockfile entries after rebase (std-env, opentelemetry packages, etc) - Increase Helm timeout from 5m to 15m for complex deployments - Prevents deployment timeouts when deploying 4 apps + PostgreSQL + Redis
ec71c69 to
f218fee
Compare
Restored Redis sync calls that were accidentally removed during Prisma optimization refactor. Maintains batch query performance improvement (getLocationsByIds instead of N+1 getLocationById calls). Changes: - Re-added savePendingSubscriptions/deletePendingSubscriptions calls - Re-added savePendingCaseSubscriptions/deletePendingCaseSubscriptions calls - Added 9 missing tests for full coverage (27 tests vs 22 in master) - Fixed TypeScript errors in test file - All 236 tests passing Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
The timeout fix from e362e27 was lost as collateral when f218fee reverted a merge commit. With the prisma-rules-and-refactor changes (PR #618) making deployments heavier, the 5m timeout is insufficient for deploying 4 apps + PostgreSQL + Redis. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>



…est practises
Jira link
https://tools.hmcts.net/jira/browse/VIBE-450
Change description
libs/postgres-prismaTesting done
Security Vulnerability Assessment
CVE Suppression: Are there any CVEs present in the codebase (either newly introduced or pre-existing) that are being intentionally suppressed or ignored by this commit?
Checklist
Summary by CodeRabbit
New Features
Performance Improvements
Bug Fixes
Documentation