From 2ed6f8d92cb93570c78b602cda5f5fc3f2571fd2 Mon Sep 17 00:00:00 2001 From: Oskar Haarklou Veileborg Date: Thu, 29 Oct 2026 10:44:28 +0100 Subject: [PATCH] test(scan): share default reachability options across tests Each test spelled out every ReachabilityOptions field, so adding a reach flag meant editing about 17 literals. Tests now spread makeReachabilityOptions() and set only the fields they exercise. --- src/commands/scan/exclude-paths.test.mts | 38 +--- .../generate-uv-member-sboms.e2e.test.mts | 24 +-- .../scan/handle-create-new-scan.test.mts | 131 +------------ src/commands/scan/handle-scan-reach.test.mts | 176 +----------------- .../perform-reachability-analysis.test.mts | 28 +-- test/reachability-options.mts | 30 +++ 6 files changed, 53 insertions(+), 374 deletions(-) create mode 100644 test/reachability-options.mts diff --git a/src/commands/scan/exclude-paths.test.mts b/src/commands/scan/exclude-paths.test.mts index a29511ab6..342b2174a 100644 --- a/src/commands/scan/exclude-paths.test.mts +++ b/src/commands/scan/exclude-paths.test.mts @@ -6,40 +6,9 @@ import { excludePathToScanIgnores, projectIgnorePathsToReachExcludePaths, } from './exclude-paths.mts' +import { makeReachabilityOptions } from '../../../test/reachability-options.mts' import { InputError } from '../../utils/errors.mts' -import type { ReachabilityOptions } from './perform-reachability-analysis.mts' - -function makeReachOptions( - overrides: Partial = {}, -): ReachabilityOptions { - return { - dynamicSbomInference: false, - excludePaths: [], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, - reachExcludePaths: [], - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, - ...overrides, - } -} - describe('exclude-paths', () => { describe('assertValidExcludePaths', () => { it('allows positive patterns', () => { @@ -207,9 +176,10 @@ describe('exclude-paths', () => { it('expands exclude-paths into SCA ignores and re-anchored Coana excludes', () => { const result = applyFullExcludePaths({ cwd: '/repo', - reachabilityOptions: makeReachOptions({ + reachabilityOptions: { + ...makeReachabilityOptions(), excludePaths: ['tests'], - }), + }, target: '/repo', }) diff --git a/src/commands/scan/generate-uv-member-sboms.e2e.test.mts b/src/commands/scan/generate-uv-member-sboms.e2e.test.mts index e1e844112..d0680314f 100644 --- a/src/commands/scan/generate-uv-member-sboms.e2e.test.mts +++ b/src/commands/scan/generate-uv-member-sboms.e2e.test.mts @@ -7,6 +7,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { generateUvMemberSboms } from './generate-uv-member-sboms.mts' import { handleCreateNewScan } from './handle-create-new-scan.mts' +import { makeReachabilityOptions } from '../../../test/reachability-options.mts' import type { HandleCreateNewScanConfig } from './handle-create-new-scan.mts' @@ -230,29 +231,8 @@ describe('uv member scans with the real uv binary', { timeout: 30_000 }, () => { pendingHead: false, pullRequest: 0, reach: { - dynamicSbomInference: false, - excludePaths: [], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, - reachExcludePaths: [], + ...makeReachabilityOptions(), reachFallbackToRegularScan: false, - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, runReachabilityAnalysis: false, }, readOnly: false, diff --git a/src/commands/scan/handle-create-new-scan.test.mts b/src/commands/scan/handle-create-new-scan.test.mts index a14a79c53..4d2105703 100644 --- a/src/commands/scan/handle-create-new-scan.test.mts +++ b/src/commands/scan/handle-create-new-scan.test.mts @@ -15,6 +15,7 @@ import { logger } from '@socketsecurity/registry/lib/logger' import { finalizeTier1Scan } from './finalize-tier1-scan.mts' import { handleCreateNewScan } from './handle-create-new-scan.mts' import { outputCreateNewScan } from './output-create-new-scan.mts' +import { makeReachabilityOptions } from '../../../test/reachability-options.mts' import type { HandleCreateNewScanConfig } from './handle-create-new-scan.mts' @@ -103,29 +104,8 @@ function createConfig( pendingHead: false, pullRequest: 0, reach: { - dynamicSbomInference: false, - excludePaths: [], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, - reachExcludePaths: [], + ...makeReachabilityOptions(), reachFallbackToRegularScan: false, - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, runReachabilityAnalysis: false, }, readOnly: false, @@ -568,29 +548,10 @@ describe('handleCreateNewScan excludePaths', () => { pendingHead: false, pullRequest: 0, reach: { - dynamicSbomInference: false, + ...makeReachabilityOptions(), excludePaths: ['tests', 'packages/*'], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, reachExcludePaths: ['dist'], reachFallbackToRegularScan: false, - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, runReachabilityAnalysis: true, }, readOnly: false, @@ -634,29 +595,10 @@ describe('handleCreateNewScan excludePaths', () => { pendingHead: false, pullRequest: 0, reach: { - dynamicSbomInference: false, + ...makeReachabilityOptions(), excludePaths: ['apps/api/tests', '**/dist'], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, reachExcludePaths: ['node_modules'], reachFallbackToRegularScan: false, - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, runReachabilityAnalysis: true, }, readOnly: false, @@ -706,29 +648,9 @@ describe('handleCreateNewScan excludePaths', () => { pendingHead: false, pullRequest: 0, reach: { - dynamicSbomInference: false, + ...makeReachabilityOptions(), excludePaths: ['tests'], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, - reachExcludePaths: [], reachFallbackToRegularScan: false, - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, runReachabilityAnalysis: false, }, readOnly: false, @@ -768,29 +690,10 @@ describe('handleCreateNewScan excludePaths', () => { pendingHead: false, pullRequest: 0, reach: { - dynamicSbomInference: false, + ...makeReachabilityOptions(), excludePaths: ['apps/api'], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, reachExcludePaths: ['node_modules'], reachFallbackToRegularScan: false, - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, runReachabilityAnalysis: true, }, readOnly: false, @@ -830,29 +733,9 @@ describe('handleCreateNewScan excludePaths', () => { pendingHead: false, pullRequest: 0, reach: { - dynamicSbomInference: false, + ...makeReachabilityOptions(), excludePaths: ['tests'], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, - reachExcludePaths: [], reachFallbackToRegularScan: false, - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, runReachabilityAnalysis: false, }, readOnly: false, diff --git a/src/commands/scan/handle-scan-reach.test.mts b/src/commands/scan/handle-scan-reach.test.mts index 8feab61ea..487a0d7a7 100644 --- a/src/commands/scan/handle-scan-reach.test.mts +++ b/src/commands/scan/handle-scan-reach.test.mts @@ -1,6 +1,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' import { handleScanReach } from './handle-scan-reach.mts' +import { makeReachabilityOptions } from '../../../test/reachability-options.mts' const { mockCheckCommandInput, @@ -117,28 +118,9 @@ describe('handleScanReach', () => { it('applies excludePaths to manifest discovery and reachability analysis', async () => { const reachabilityOptions = { - dynamicSbomInference: false, + ...makeReachabilityOptions(), excludePaths: ['tests', 'packages/*'], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, reachExcludePaths: ['node_modules'], - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, } await handleScanReach({ @@ -171,28 +153,9 @@ describe('handleScanReach', () => { it('translates excludePaths from the scan root for nested targets', async () => { const reachabilityOptions = { - dynamicSbomInference: false, + ...makeReachabilityOptions(), excludePaths: ['apps/api/tests', '**/dist'], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, reachExcludePaths: ['node_modules'], - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, } await handleScanReach({ @@ -235,28 +198,9 @@ describe('handleScanReach', () => { checks.every(check => check.test), ) const reachabilityOptions = { - dynamicSbomInference: false, + ...makeReachabilityOptions(), excludePaths: ['apps/api'], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, reachExcludePaths: ['node_modules'], - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, } await handleScanReach({ @@ -285,28 +229,8 @@ describe('handleScanReach', () => { mockFindSocketYmlSync.mockReturnValueOnce({ ok: false }) const reachabilityOptions = { - dynamicSbomInference: false, + ...makeReachabilityOptions(), excludePaths: ['tests'], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, - reachExcludePaths: [], - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, } await handleScanReach({ @@ -339,28 +263,7 @@ describe('handleScanReach', () => { }, }) const reachabilityOptions = { - dynamicSbomInference: false, - excludePaths: [], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, - reachExcludePaths: [], - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, + ...makeReachabilityOptions(), } await handleScanReach({ @@ -378,28 +281,7 @@ describe('handleScanReach', () => { it('does not call finalize when Coana did not return a full application reachability scan id', async () => { const reachabilityOptions = { - dynamicSbomInference: false, - excludePaths: [], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, - reachExcludePaths: [], - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, + ...makeReachabilityOptions(), } await handleScanReach({ @@ -430,28 +312,7 @@ describe('handleScanReach', () => { cause: 'Socket API server error (503)', }) const reachabilityOptions = { - dynamicSbomInference: false, - excludePaths: [], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, - reachExcludePaths: [], - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, + ...makeReachabilityOptions(), } // The handler resolves normally (no throw, returns undefined) so the @@ -485,28 +346,9 @@ describe('handleScanReach', () => { }) describe('dynamic SBOM inference', () => { const baseReachabilityOptions = { + ...makeReachabilityOptions(), dynamicSbomInference: true, excludePaths: ['vendor/**'], - reachAdvisories: [], - reachAnalysisMemoryLimit: '8192', - reachAnalysisTimeout: '', - reachConcurrency: 1, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableAnalytics: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, - reachExcludePaths: [], - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, } it('generates per-build-root facts, merges them into manifest discovery, and forwards the sidecar', async () => { diff --git a/src/commands/scan/perform-reachability-analysis.test.mts b/src/commands/scan/perform-reachability-analysis.test.mts index beabe6612..60306e124 100644 --- a/src/commands/scan/perform-reachability-analysis.test.mts +++ b/src/commands/scan/perform-reachability-analysis.test.mts @@ -21,6 +21,7 @@ import path from 'node:path' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { performReachabilityAnalysis } from './perform-reachability-analysis.mts' +import { makeReachabilityOptions } from '../../../test/reachability-options.mts' import type { ReachabilityOptions } from './perform-reachability-analysis.mts' @@ -93,33 +94,6 @@ vi.mock('@socketsecurity/registry/lib/logger', () => ({ }, })) -function makeReachabilityOptions(): ReachabilityOptions { - return { - dynamicSbomInference: false, - excludePaths: [], - reachAdvisories: [], - reachAnalysisMemoryLimit: '', - reachAnalysisTimeout: '', - reachConcurrency: 0, - reachContinueOnAnalysisErrors: false, - reachContinueOnInstallErrors: false, - reachContinueOnMissingLockFiles: false, - reachContinueOnNoSourceFiles: false, - reachDebug: false, - reachDetailedAnalysisLogFile: false, - reachDisableDependencyDownloads: false, - reachDisableExternalToolChecks: false, - reachDisableAnalytics: false, - reachEcosystems: [], - reachEnableAnalysisSplitting: false, - reachExcludePaths: [], - reachRetainFactsFile: false, - reachSkipCache: false, - reachUseOnlyPregeneratedSboms: false, - reachVersion: undefined, - } -} - describe('performReachabilityAnalysis facts-file resolution', () => { let scanCwd: string diff --git a/test/reachability-options.mts b/test/reachability-options.mts new file mode 100644 index 000000000..080f62902 --- /dev/null +++ b/test/reachability-options.mts @@ -0,0 +1,30 @@ +import type { ReachabilityOptions } from '../src/commands/scan/perform-reachability-analysis.mts' + +// Mirrors the CLI flag defaults, so a test spreads this and sets only what it +// exercises. +export function makeReachabilityOptions(): ReachabilityOptions { + return { + dynamicSbomInference: false, + excludePaths: [], + reachAdvisories: [], + reachAnalysisMemoryLimit: '8192', + reachAnalysisTimeout: '', + reachConcurrency: 1, + reachContinueOnAnalysisErrors: false, + reachContinueOnInstallErrors: false, + reachContinueOnMissingLockFiles: false, + reachContinueOnNoSourceFiles: false, + reachDebug: false, + reachDetailedAnalysisLogFile: false, + reachDisableAnalytics: false, + reachDisableDependencyDownloads: false, + reachDisableExternalToolChecks: false, + reachEcosystems: [], + reachEnableAnalysisSplitting: false, + reachExcludePaths: [], + reachRetainFactsFile: false, + reachSkipCache: false, + reachUseOnlyPregeneratedSboms: false, + reachVersion: undefined, + } +}