Duplicate Code Opportunity
Summary
- Pattern: Identical
let mockConfig declaration + useTempWorkDir(baseConfig, ...) callback block is copy-pasted verbatim at the top of every agent-volumes-*.test.ts file inside the outer describe('agent service', ...) wrapper
- Locations: 4 files under
src/services/
- Impact: ~18 duplicated lines across 4 files (72 lines total); any change to the
useTempWorkDir API or baseConfig shape must be updated in all four files
Evidence
All four files begin with this identical block:
import { generateDockerCompose, WrapperConfig, baseConfig, mockNetworkConfig, useTempWorkDir } from './service-test-setup.test-utils';
// Create mock functions (must remain per-file — jest.mock() is hoisted before imports)
// eslint-disable-next-line `@typescript-eslint/no-require-imports`
jest.mock('execa', () => require('../test-helpers/mock-execa.test-utils').execaMockFactory());
let mockConfig: WrapperConfig;
describe('agent service', () => {
useTempWorkDir(
baseConfig,
(config) => {
mockConfig = config;
},
() => mockConfig
);
// ... tests
});
Files with this exact block:
src/services/agent-volumes-workspace.test.ts — lines 1–19
src/services/agent-volumes-security.test.ts — lines 1–19
src/services/agent-volumes-logs.test.ts — lines 1–19
src/services/agent-volumes-mounts.test.ts — lines 1–16 (same pattern, extra imports follow)
Note: Issue #3305 addressed the older import/mock boilerplate and the shared service-test-setup.test-utils module was introduced as a fix. However, the useTempWorkDir describe-wrapper pattern is a second layer of duplication that still remains.
Suggested Refactoring
Extend service-test-setup.test-utils.ts to export a useAgentVolumesTestConfig() helper (or a higher-order describeAgentVolumes(label, fn) wrapper) that encapsulates the let mockConfig + useTempWorkDir boilerplate:
// In service-test-setup.test-utils.ts
export function useAgentVolumesTestConfig(): { getConfig: () => WrapperConfig } {
let mockConfig: WrapperConfig;
useTempWorkDir(baseConfig, (c) => { mockConfig = c; }, () => mockConfig);
return { getConfig: () => mockConfig };
}
Each agent-volumes-*.test.ts file then reduces to:
import { generateDockerCompose, mockNetworkConfig, useAgentVolumesTestConfig } from './service-test-setup.test-utils';
jest.mock('execa', () => require('../test-helpers/mock-execa.test-utils').execaMockFactory());
const { getConfig } = useAgentVolumesTestConfig();
describe('agent service', () => { /* tests using getConfig() */ });
Affected Files
src/services/agent-volumes-workspace.test.ts — lines 1–19
src/services/agent-volumes-security.test.ts — lines 1–19
src/services/agent-volumes-logs.test.ts — lines 1–19
src/services/agent-volumes-mounts.test.ts — lines 1–16
Effort Estimate
Low
Detected by Duplicate Code Detector workflow. Run date: 2026-06-02
Generated by Duplicate Code Detector · sonnet46 1.3M · ◷
Duplicate Code Opportunity
Summary
let mockConfigdeclaration +useTempWorkDir(baseConfig, ...)callback block is copy-pasted verbatim at the top of everyagent-volumes-*.test.tsfile inside the outerdescribe('agent service', ...)wrappersrc/services/useTempWorkDirAPI orbaseConfigshape must be updated in all four filesEvidence
All four files begin with this identical block:
Files with this exact block:
src/services/agent-volumes-workspace.test.ts— lines 1–19src/services/agent-volumes-security.test.ts— lines 1–19src/services/agent-volumes-logs.test.ts— lines 1–19src/services/agent-volumes-mounts.test.ts— lines 1–16 (same pattern, extra imports follow)Suggested Refactoring
Extend
service-test-setup.test-utils.tsto export auseAgentVolumesTestConfig()helper (or a higher-orderdescribeAgentVolumes(label, fn)wrapper) that encapsulates thelet mockConfig+useTempWorkDirboilerplate:Each
agent-volumes-*.test.tsfile then reduces to:Affected Files
src/services/agent-volumes-workspace.test.ts— lines 1–19src/services/agent-volumes-security.test.ts— lines 1–19src/services/agent-volumes-logs.test.ts— lines 1–19src/services/agent-volumes-mounts.test.ts— lines 1–16Effort Estimate
Low
Detected by Duplicate Code Detector workflow. Run date: 2026-06-02