diff --git a/.vite/fixtures/cdp-uploader.js b/.vite/fixtures/cdp-uploader.js index cec1c2e1..49699f05 100644 --- a/.vite/fixtures/cdp-uploader.js +++ b/.vite/fixtures/cdp-uploader.js @@ -61,7 +61,7 @@ const callbackReceiverFixture = { const cdpUploaderStackFixture = { // Depends on callbackReceiver to ensure correct initialisation order cdpUploaderStack: [ - async ({ callbackReceiver }, use) => { + async ({ callbackReceiver: _ }, use) => { // Disable vitest-fetch-mock so we can make real HTTP requests to containers // The global fetch is mocked by default in .vite/setup-files.js if (globalThis.fetchMock) { diff --git a/.vite/fixtures/server-with-db.js b/.vite/fixtures/server-with-db.js index 0909a68c..2286c630 100644 --- a/.vite/fixtures/server-with-db.js +++ b/.vite/fixtures/server-with-db.js @@ -4,7 +4,6 @@ export const it = dbTest.extend({ server: [ async ({ db }, use) => { // db parameter triggers MongoDB setup (unused directly) - // eslint-disable-next-line no-unused-vars const _dbUri = db const { createServer } = await import('#server/server.js') const server = await createServer() diff --git a/eslint.config.js b/eslint.config.js index efaae014..4f836159 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -24,5 +24,17 @@ export default [ rules: { 'n/no-unpublished-import': 'off' } + }, + { + rules: { + 'no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + varsIgnorePattern: '^_' + } + ] + } } ] diff --git a/scripts/mongo-performance-test/separate-collections/create-collections.js b/scripts/mongo-performance-test/separate-collections/create-collections.js index b593985b..104d4e94 100644 --- a/scripts/mongo-performance-test/separate-collections/create-collections.js +++ b/scripts/mongo-performance-test/separate-collections/create-collections.js @@ -14,7 +14,7 @@ export async function createOrganisationCollection( try { await db.collection(collectionName).drop() console.log('Dropped existing organisation collection') - } catch (error) { + } catch (_error) { console.log('Organisation collection does not exist, creating new') } @@ -149,7 +149,7 @@ export async function createRegistrationCollection( try { await db.collection(collectionName).drop() console.log('Dropped existing registration collection') - } catch (error) { + } catch (_error) { console.log('Registration collection does not exist, creating new') } @@ -355,7 +355,7 @@ export async function createAccreditationCollection( try { await db.collection(collectionName).drop() console.log('Dropped existing accreditation collection') - } catch (error) { + } catch (_error) { console.log('Accreditation collection does not exist, creating new') } diff --git a/scripts/mongo-performance-test/single-nested-collection/create-collection.js b/scripts/mongo-performance-test/single-nested-collection/create-collection.js index f7d76d68..cdb0efaa 100644 --- a/scripts/mongo-performance-test/single-nested-collection/create-collection.js +++ b/scripts/mongo-performance-test/single-nested-collection/create-collection.js @@ -15,7 +15,7 @@ export async function createOrganisationCollection( try { await db.collection(collectionName).drop() console.log('Dropped existing collection') - } catch (error) { + } catch (_error) { console.log('Collection does not exist, creating new') } diff --git a/sonar-project.properties b/sonar-project.properties index 068bcb34..f940bba1 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -19,3 +19,8 @@ sonar.test.inclusions=src/**/*.test.js,src/**/*.contract.js sonar.javascript.lcov.reportPaths=./coverage/lcov.info sonar.coverage.exclusions=src/index.js,src/common/helpers/secure-context.js,src/domain/organisations/model.js + +# Disable S1481 - we use _ prefix for intentionally unused variables (enforced by ESLint) +sonar.issue.ignore.multicriteria=e1 +sonar.issue.ignore.multicriteria.e1.ruleKey=javascript:S1481 +sonar.issue.ignore.multicriteria.e1.resourceKey=**/* diff --git a/src/common/helpers/collections/create-update.seed-data.test.js b/src/common/helpers/collections/create-update.seed-data.test.js index 22c6eaf3..32e1a294 100644 --- a/src/common/helpers/collections/create-update.seed-data.test.js +++ b/src/common/helpers/collections/create-update.seed-data.test.js @@ -38,7 +38,7 @@ describe('createSeedData', () => { } ) - it('creates seed data when there are no documents already in epr-organisations collection', async (collectionName) => { + it('creates seed data when there are no documents already in epr-organisations collection', async () => { const { mockDb } = createMockDb({ countDocuments: async () => 0 }) diff --git a/src/common/helpers/s3/s3-client.test.js b/src/common/helpers/s3/s3-client.test.js index 73151112..e5c28403 100644 --- a/src/common/helpers/s3/s3-client.test.js +++ b/src/common/helpers/s3/s3-client.test.js @@ -14,7 +14,7 @@ describe('createS3Client', () => { beforeEach(() => { s3Client = { config: { region } } - vi.mocked(S3Client).mockImplementation(function (config) { + vi.mocked(S3Client).mockImplementation(function () { return s3Client }) }) diff --git a/src/forms-submission-data/migrate-forms-data.test.js b/src/forms-submission-data/migrate-forms-data.test.js index a36901ac..e5a97bdd 100644 --- a/src/forms-submission-data/migrate-forms-data.test.js +++ b/src/forms-submission-data/migrate-forms-data.test.js @@ -1,17 +1,17 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest' -import { migrateFormsData } from './migrate-forms-data.js' -import { logger } from '#common/helpers/logging/logger.js' -import { createFormSubmissionsRepository } from '#repositories/form-submissions/inmemory.js' -import { createInMemoryOrganisationsRepository } from '#repositories/organisations/inmemory.js' -import { readdirSync, readFileSync } from 'fs' -import { join } from 'path' import { LOGGING_EVENT_ACTIONS, LOGGING_EVENT_CATEGORIES } from '#common/enums/index.js' -import { MATERIAL } from '#domain/organisations/model.js' -import reprocessorGlassAccreditation from '#data/fixtures/ea/accreditation/reprocessor-glass.json' +import { logger } from '#common/helpers/logging/logger.js' import exporterAccreditation from '#data/fixtures/ea/accreditation/exporter.json' +import reprocessorGlassAccreditation from '#data/fixtures/ea/accreditation/reprocessor-glass.json' +import { MATERIAL } from '#domain/organisations/model.js' +import { createFormSubmissionsRepository } from '#repositories/form-submissions/inmemory.js' +import { createInMemoryOrganisationsRepository } from '#repositories/organisations/inmemory.js' +import { readdirSync, readFileSync } from 'fs' +import { join } from 'path' +import { beforeEach, describe, expect, it, vi } from 'vitest' +import { migrateFormsData } from './migrate-forms-data.js' vi.mock('#common/helpers/logging/logger.js', () => ({ logger: { diff --git a/src/repositories/organisations/contract/insert.contract.js b/src/repositories/organisations/contract/insert.contract.js index e7d59b71..6d66435f 100644 --- a/src/repositories/organisations/contract/insert.contract.js +++ b/src/repositories/organisations/contract/insert.contract.js @@ -1,4 +1,4 @@ -import { describe, beforeEach, expect } from 'vitest' +import { beforeEach, describe, expect } from 'vitest' import { buildOrganisation } from './test-data.js' export const testInsertBehaviour = (it) => { @@ -24,14 +24,14 @@ export const testInsertBehaviour = (it) => { ...orgWithoutStatusHistory, formSubmissionTime: new Date(orgData.formSubmissionTime), registrations: orgData.registrations.map((reg) => { - const { statusHistory, ...regWithoutStatusHistory } = reg + const { statusHistory: _, ...regWithoutStatusHistory } = reg return { ...regWithoutStatusHistory, formSubmissionTime: new Date(reg.formSubmissionTime) } }), accreditations: orgData.accreditations.map((acc) => { - const { statusHistory, ...accWithoutStatusHistory } = acc + const { statusHistory: _, ...accWithoutStatusHistory } = acc return { ...accWithoutStatusHistory, formSubmissionTime: new Date(acc.formSubmissionTime) diff --git a/src/repositories/organisations/contract/update.contract.js b/src/repositories/organisations/contract/update.contract.js index d8c584d7..4cf430df 100644 --- a/src/repositories/organisations/contract/update.contract.js +++ b/src/repositories/organisations/contract/update.contract.js @@ -146,7 +146,7 @@ export const testUpdateBehaviour = (it) => { ) expect(addedReg).toBeDefined() - const { statusHistory, ...expectedReg } = { + const { statusHistory: _, ...expectedReg } = { ...newRegistration, formSubmissionTime: new Date(newRegistration.formSubmissionTime) } @@ -184,7 +184,7 @@ export const testUpdateBehaviour = (it) => { ) expect(addedAcc).toBeDefined() - const { statusHistory, ...expectedAcc } = { + const { statusHistory: _, ...expectedAcc } = { ...newAccreditation, formSubmissionTime: new Date(newAccreditation.formSubmissionTime) } diff --git a/src/repositories/organisations/helpers.js b/src/repositories/organisations/helpers.js index 7b6777f0..c77e376e 100644 --- a/src/repositories/organisations/helpers.js +++ b/src/repositories/organisations/helpers.js @@ -61,7 +61,7 @@ export const mergeItemsWithUpdates = (existingItems, itemUpdates) => { })) return [...processedExisting, ...newItems].map((item) => { - const { status, ...remainingFields } = item + const { status: _, ...remainingFields } = item return remainingFields }) } @@ -93,7 +93,7 @@ const normalizeItem = (item) => { if (!item) { return item } - const { status, statusHistory, ...rest } = item + const { status: _, statusHistory: _s, ...rest } = item return rest } @@ -102,7 +102,14 @@ export const normalizeForComparison = (org) => { return org } - const { version, schemaVersion, status, statusHistory, users, ...rest } = org + const { + schemaVersion: _sv, + status: _s, + statusHistory: _sh, + users: _u, + version: _v, + ...rest + } = org const normalized = { ...rest, diff --git a/src/repositories/organisations/inmemory.js b/src/repositories/organisations/inmemory.js index 10925cb7..0fb27f5f 100644 --- a/src/repositories/organisations/inmemory.js +++ b/src/repositories/organisations/inmemory.js @@ -1,18 +1,18 @@ -import { - validateId, - validateOrganisationInsert, - validateOrganisationUpdate -} from './schema/index.js' +import Boom from '@hapi/boom' import { SCHEMA_VERSION, collateUsersOnApproval, createInitialStatusHistory, getCurrentStatus, - statusHistoryWithChanges, + hasChanges, mergeSubcollection, - hasChanges + statusHistoryWithChanges } from './helpers.js' -import Boom from '@hapi/boom' +import { + validateId, + validateOrganisationInsert, + validateOrganisationUpdate +} from './schema/index.js' // Aggressive retry settings for in-memory testing (setImmediate() is microseconds) const MAX_CONSISTENCY_RETRIES = 5 @@ -104,7 +104,7 @@ const performUpdate = ) } - const { status, ...merged } = { ...existing, ...validatedUpdates } + const { status: _, ...merged } = { ...existing, ...validatedUpdates } const registrations = mergeSubcollection( existing.registrations, @@ -146,7 +146,7 @@ const performUpsert = (storage, staleCache, pendingSyncRef, insertFn, updateFn) => async (organisation) => { const validated = validateOrganisationInsert(organisation) - const { id, version, schemaVersion, ...updateData } = validated + const { id, version: _v, schemaVersion: _s, ...updateData } = validated const existing = storage.find((o) => o.id === id) diff --git a/src/repositories/organisations/mongodb.js b/src/repositories/organisations/mongodb.js index a60e1dc3..b027151c 100644 --- a/src/repositories/organisations/mongodb.js +++ b/src/repositories/organisations/mongodb.js @@ -83,7 +83,7 @@ const performUpdate = (db) => async (id, version, updates) => { throw Boom.notFound(`Organisation with id ${validatedId} not found`) } - const { status, ...merged } = { ...existing, ...validatedUpdates } + const { status: _, ...merged } = { ...existing, ...validatedUpdates } const registrations = mergeSubcollection( existing.registrations, @@ -131,7 +131,7 @@ const performUpdate = (db) => async (id, version, updates) => { const performUpsert = (db) => async (organisation) => { const validated = validateOrganisationInsert(organisation) - const { id, version, schemaVersion, ...updateData } = validated + const { id, version: _v, schemaVersion: _s, ...updateData } = validated const existing = await db .collection(COLLECTION_NAME) @@ -173,7 +173,7 @@ const performFindById = let validatedId try { validatedId = validateId(id) - } catch (error) { + } catch (_error) { throw Boom.notFound(`Organisation with id ${id} not found`) } diff --git a/src/repositories/summary-logs/contract/test-data.js b/src/repositories/summary-logs/contract/test-data.js index bc138f9d..86dea5ab 100644 --- a/src/repositories/summary-logs/contract/test-data.js +++ b/src/repositories/summary-logs/contract/test-data.js @@ -11,7 +11,7 @@ export const buildFile = (overrides = {}) => ({ }) export const buildPendingFile = (overrides = {}) => { - const { uri, status, ...rest } = overrides + const { uri: _u, status: _s, ...rest } = overrides return { id: generateFileId(), name: 'test.xlsx', @@ -21,7 +21,7 @@ export const buildPendingFile = (overrides = {}) => { } export const buildRejectedFile = (overrides = {}) => { - const { uri, status, ...rest } = overrides + const { uri: _u, status: _s, ...rest } = overrides return { id: generateFileId(), name: 'test.xlsx', diff --git a/src/repositories/waste-records/mongodb.js b/src/repositories/waste-records/mongodb.js index f1404bc4..0a0241eb 100644 --- a/src/repositories/waste-records/mongodb.js +++ b/src/repositories/waste-records/mongodb.js @@ -10,7 +10,7 @@ const SCHEMA_VERSION = 1 * @returns {import('./port.js').WasteRecord} Domain waste record */ const mapDocumentToDomain = (doc) => { - const { _id, schemaVersion, ...domainFields } = doc + const { _id, schemaVersion: _s, ...domainFields } = doc return structuredClone(domainFields) } diff --git a/src/repositories/waste-records/validation.test.js b/src/repositories/waste-records/validation.test.js index d1a924a4..a312759c 100644 --- a/src/repositories/waste-records/validation.test.js +++ b/src/repositories/waste-records/validation.test.js @@ -80,28 +80,28 @@ describe('validation', () => { }) it('rejects record missing organisationId', () => { - const { organisationId, ...invalid } = validRecord + const { organisationId: _, ...invalid } = validRecord expect(() => validateWasteRecord(invalid)).toThrow( /organisationId is required/ ) }) it('rejects record missing registrationId', () => { - const { registrationId, ...invalid } = validRecord + const { registrationId: _, ...invalid } = validRecord expect(() => validateWasteRecord(invalid)).toThrow( /registrationId is required/ ) }) it('rejects record missing rowId', () => { - const { rowId, ...invalid } = validRecord + const { rowId: _, ...invalid } = validRecord expect(() => validateWasteRecord(invalid)).toThrow( /Invalid waste record:.*rowId.*is required/ ) }) it('rejects record missing type', () => { - const { type, ...invalid } = validRecord + const { type: _, ...invalid } = validRecord expect(() => validateWasteRecord(invalid)).toThrow( /Invalid waste record:.*type.*is required/ ) @@ -115,14 +115,14 @@ describe('validation', () => { }) it('rejects record missing data', () => { - const { data, ...invalid } = validRecord + const { data: _, ...invalid } = validRecord expect(() => validateWasteRecord(invalid)).toThrow( /Invalid waste record:.*data.*is required/ ) }) it('rejects record missing versions', () => { - const { versions, ...invalid } = validRecord + const { versions: _, ...invalid } = validRecord expect(() => validateWasteRecord(invalid)).toThrow( /Invalid waste record:.*versions.*is required/ ) diff --git a/src/routes/v1/dev/organisations/patch-by-id.js b/src/routes/v1/dev/organisations/patch-by-id.js index ab981ebd..384b30fd 100644 --- a/src/routes/v1/dev/organisations/patch-by-id.js +++ b/src/routes/v1/dev/organisations/patch-by-id.js @@ -1,10 +1,9 @@ +import { mergeSubcollection } from '#repositories/organisations/helpers.js' import Boom from '@hapi/boom' import { StatusCodes } from 'http-status-codes' import Joi from 'joi' import mergeWith from 'lodash.mergewith' -import { mergeSubcollection } from '#repositories/organisations/helpers.js' - /** @import {Organisation} from '#domain/organisations/model.js' */ /** @import {OrganisationsRepository} from '#repositories/organisations/port.js' */ diff --git a/src/routes/v1/organisations/registrations/summary-logs/submit/post.test.js b/src/routes/v1/organisations/registrations/summary-logs/submit/post.test.js index 1d2fe69f..21ac68d2 100644 --- a/src/routes/v1/organisations/registrations/summary-logs/submit/post.test.js +++ b/src/routes/v1/organisations/registrations/summary-logs/submit/post.test.js @@ -38,7 +38,7 @@ describe(`${summaryLogsSubmitPath} route`, () => { server = await createTestServer({ repositories: { - summaryLogsRepository: (logger) => summaryLogsRepository + summaryLogsRepository: (_logger) => summaryLogsRepository }, workers: { summaryLogsWorker diff --git a/src/routes/v1/organisations/registrations/summary-logs/upload-completed/post.test.js b/src/routes/v1/organisations/registrations/summary-logs/upload-completed/post.test.js index ca54f528..66dc1ceb 100644 --- a/src/routes/v1/organisations/registrations/summary-logs/upload-completed/post.test.js +++ b/src/routes/v1/organisations/registrations/summary-logs/upload-completed/post.test.js @@ -5,10 +5,10 @@ import { UPLOAD_STATUS } from '#domain/summary-logs/status.js' import { createInMemoryFeatureFlags } from '#feature-flags/feature-flags.inmemory.js' -import { createTestServer } from '#test/create-test-server.js' import { createInMemorySummaryLogsRepository } from '#repositories/summary-logs/inmemory.js' -import { setupAuthContext } from '#vite/helpers/setup-auth-mocking.js' +import { createTestServer } from '#test/create-test-server.js' import { entraIdMockAuthTokens } from '#vite/helpers/create-entra-id-test-tokens.js' +import { setupAuthContext } from '#vite/helpers/setup-auth-mocking.js' import { summaryLogsUploadCompletedPath } from './post.js' @@ -113,7 +113,7 @@ describe(`${summaryLogsUploadCompletedPath} route`, () => { server = await createTestServer({ repositories: { - summaryLogsRepository: (logger) => summaryLogsRepository + summaryLogsRepository: (_logger) => summaryLogsRepository }, workers: { summaryLogsWorker diff --git a/src/workers/summary-logs/worker/integration.test.js b/src/workers/summary-logs/worker/integration.test.js index e8ee9836..7d45984e 100644 --- a/src/workers/summary-logs/worker/integration.test.js +++ b/src/workers/summary-logs/worker/integration.test.js @@ -1,17 +1,21 @@ +/** @import {SummaryLogExtractor} from '#domain/summary-logs/extractor/port.js' */ +/** @import {MetadataEntry} from '#domain/summary-logs/extractor/port.js' */ +/** @import {WasteProcessingTypeValue} from '#domain/organisations/model.js' */ + import { randomUUID } from 'crypto' import { createInMemorySummaryLogExtractor } from '#application/summary-logs/extractor-inmemory.js' import { createSummaryLogsValidator } from '#application/summary-logs/validate.js' -import { createInMemoryWasteRecordsRepository } from '#repositories/waste-records/inmemory.js' import { logger } from '#common/helpers/logging/logger.js' import { SUMMARY_LOG_STATUS, UPLOAD_STATUS } from '#domain/summary-logs/status.js' -import { createInMemorySummaryLogsRepository } from '#repositories/summary-logs/inmemory.js' -import { waitForVersion } from '#repositories/summary-logs/contract/test-helpers.js' -import { createInMemoryOrganisationsRepository } from '#repositories/organisations/inmemory.js' import { buildOrganisation } from '#repositories/organisations/contract/test-data.js' +import { createInMemoryOrganisationsRepository } from '#repositories/organisations/inmemory.js' +import { waitForVersion } from '#repositories/summary-logs/contract/test-helpers.js' +import { createInMemorySummaryLogsRepository } from '#repositories/summary-logs/inmemory.js' +import { createInMemoryWasteRecordsRepository } from '#repositories/waste-records/inmemory.js' describe('SummaryLogsValidator integration', () => { let summaryLogsRepository @@ -77,6 +81,16 @@ describe('SummaryLogsValidator integration', () => { } } + /** + * @typedef {{ + * registrationType: WasteProcessingTypeValue; + * registrationWRN: string; + * accreditationNumber?: string; + * metadata?: Record; + * summaryLogExtractor?: SummaryLogExtractor; + * }} RunValidationParams + * @param {RunValidationParams} params + */ const runValidation = async ({ registrationType, registrationWRN, @@ -277,23 +291,16 @@ describe('SummaryLogsValidator integration', () => { { registrationType: 'reprocessor', registrationWRN: 'REG-123', - spreadsheetType: 'EXPORTER', - expectedWasteProcessingType: 'exporter' + spreadsheetType: 'EXPORTER' }, { registrationType: 'exporter', registrationWRN: 'REG-456', - spreadsheetType: 'REPROCESSOR_INPUT', - expectedWasteProcessingType: 'reprocessor' + spreadsheetType: 'REPROCESSOR_INPUT' } ])( 'when $spreadsheetType type does not match $registrationType registration', - ({ - registrationType, - registrationWRN, - spreadsheetType, - expectedWasteProcessingType - }) => { + ({ registrationType, registrationWRN, spreadsheetType }) => { it('should fail validation with mismatch error', async () => { const { updated, summaryLog } = await runValidation({ registrationType,