Duplicate Code Opportunity
Summary
- Pattern: Identical 13-line import/mock setup block is copy-pasted at the top of every service test file
- Locations: All 13 test files under
src/services/*.test.ts (and some in src/)
- Impact: ~170 lines of boilerplate spread across 13+ files; any change to the mock factory signature must be applied in all files simultaneously
Evidence
Every one of the following files begins with this identical block:
import { generateDockerCompose } from '../compose-generator';
import { WrapperConfig } from '../types';
import { baseConfig, mockNetworkConfig, useTempWorkDir } from '../test-helpers/docker-test-fixtures.test-utils';
// Create mock functions (must remain per-file — jest.mock() is hoisted before imports)
// Mock execa module
// eslint-disable-next-line `@typescript-eslint/no-require-imports`
jest.mock('execa', () => require('../test-helpers/mock-execa.test-utils').execaMockFactory());
let mockConfig: WrapperConfig;
Files with this exact block (detected by jscpd and grep):
src/services/squid-service.test.ts lines 1–13
src/services/agent-environment-credentials.test.ts lines 1–13
src/services/doh-proxy-service.test.ts lines 1–13
src/services/agent-environment-proxy.test.ts lines 1–13
src/services/agent-environment-runtime.test.ts lines 1–13
src/services/cli-proxy-service.test.ts lines 1–13
src/services/agent-volumes.test.ts lines 1–13 (+ extra imports)
src/services/agent-service.test.ts lines 1–16 (+ extra imports)
src/services/agent-environment-options.test.ts lines 1–16
src/services/api-proxy-service-config.test.ts lines 1–14
src/services/api-proxy-service-key-isolation.test.ts lines 1–14
src/services/api-proxy-service-env-forwarding.test.ts lines 1–13
src/services/api-proxy-service-rate-limit.test.ts lines 1–13
Suggested Refactoring
Extract a shared test setup module, e.g. src/services/service-test-setup.test-utils.ts, that:
- Re-exports the common imports
- Calls
jest.mock(...) (or documents why each file needs its own — the existing comment says "must remain per-file" due to hoisting; if so, a single shared setup file can still export the common imports and let mockConfig initializer while leaving the jest.mock call in each file)
The jest.mock() hoisting constraint only prevents moving it into a helper function — a shared module re-exported via setupFilesAfterFramework or simply duplicated in one canonical location with a // shared: see service-test-setup.test-utils.ts comment would still reduce cognitive overhead.
Affected Files
src/services/squid-service.test.ts — lines 1–13
src/services/agent-environment-credentials.test.ts — lines 1–13
src/services/doh-proxy-service.test.ts — lines 1–13
src/services/agent-environment-proxy.test.ts — lines 1–13
src/services/agent-environment-runtime.test.ts — lines 1–13
src/services/cli-proxy-service.test.ts — lines 1–13
src/services/agent-volumes.test.ts — lines 1–13
src/services/agent-service.test.ts — lines 1–16
src/services/agent-environment-options.test.ts — lines 1–16
src/services/api-proxy-service-config.test.ts — lines 1–14
src/services/api-proxy-service-key-isolation.test.ts — lines 1–14
src/services/api-proxy-service-env-forwarding.test.ts — lines 1–13
src/services/api-proxy-service-rate-limit.test.ts — lines 1–13
Effort Estimate
Low — the imports and variable declarations can be placed in a shared util file; only the jest.mock(...) line is hoisting-constrained.
Detected by Duplicate Code Detector workflow. Run date: 2026-05-17
Generated by Duplicate Code Detector · ● 8M · ◷
Duplicate Code Opportunity
Summary
src/services/*.test.ts(and some insrc/)Evidence
Every one of the following files begins with this identical block:
Files with this exact block (detected by
jscpdandgrep):src/services/squid-service.test.tslines 1–13src/services/agent-environment-credentials.test.tslines 1–13src/services/doh-proxy-service.test.tslines 1–13src/services/agent-environment-proxy.test.tslines 1–13src/services/agent-environment-runtime.test.tslines 1–13src/services/cli-proxy-service.test.tslines 1–13src/services/agent-volumes.test.tslines 1–13 (+ extra imports)src/services/agent-service.test.tslines 1–16 (+ extra imports)src/services/agent-environment-options.test.tslines 1–16src/services/api-proxy-service-config.test.tslines 1–14src/services/api-proxy-service-key-isolation.test.tslines 1–14src/services/api-proxy-service-env-forwarding.test.tslines 1–13src/services/api-proxy-service-rate-limit.test.tslines 1–13Suggested Refactoring
Extract a shared test setup module, e.g.
src/services/service-test-setup.test-utils.ts, that:jest.mock(...)(or documents why each file needs its own — the existing comment says "must remain per-file" due to hoisting; if so, a single shared setup file can still export the common imports andlet mockConfiginitializer while leaving thejest.mockcall in each file)The
jest.mock()hoisting constraint only prevents moving it into a helper function — a shared module re-exported viasetupFilesAfterFrameworkor simply duplicated in one canonical location with a// shared: see service-test-setup.test-utils.tscomment would still reduce cognitive overhead.Affected Files
src/services/squid-service.test.ts— lines 1–13src/services/agent-environment-credentials.test.ts— lines 1–13src/services/doh-proxy-service.test.ts— lines 1–13src/services/agent-environment-proxy.test.ts— lines 1–13src/services/agent-environment-runtime.test.ts— lines 1–13src/services/cli-proxy-service.test.ts— lines 1–13src/services/agent-volumes.test.ts— lines 1–13src/services/agent-service.test.ts— lines 1–16src/services/agent-environment-options.test.ts— lines 1–16src/services/api-proxy-service-config.test.ts— lines 1–14src/services/api-proxy-service-key-isolation.test.ts— lines 1–14src/services/api-proxy-service-env-forwarding.test.ts— lines 1–13src/services/api-proxy-service-rate-limit.test.ts— lines 1–13Effort Estimate
Low — the imports and variable declarations can be placed in a shared util file; only the
jest.mock(...)line is hoisting-constrained.Detected by Duplicate Code Detector workflow. Run date: 2026-05-17