Skip to content

Commit 75942c2

Browse files
committed
test(dlx): cover dlx/packages package management
11 tests covering all 5 exports: isDlxPackageInstalled, listDlxPackages, listDlxPackagesAsync, removeDlxPackage, removeDlxPackageSync. Uses setPath() to override the cached DLX dir to a per-test tmpdir; SOCKET_DLX_DIR env override is set as a belt-and-suspenders. Filters out non-directory entries, handles missing-directory paths, removes existing packages and no-ops on missing ones.
1 parent 76680a5 commit 75942c2

1 file changed

Lines changed: 131 additions & 0 deletions

File tree

test/unit/dlx/packages.test.mts

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/**
2+
* @fileoverview Unit tests for dlx/packages — DLX package management.
3+
*
4+
* Uses a real tmpdir and overrides SOCKET_DLX_DIR via env so we can
5+
* inspect actual filesystem state. Each test isolates with its own
6+
* tmpdir.
7+
*/
8+
9+
import { existsSync, mkdirSync, mkdtempSync, rmSync } from 'node:fs'
10+
import { tmpdir } from 'node:os'
11+
import path from 'node:path'
12+
13+
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
14+
15+
import {
16+
isDlxPackageInstalled,
17+
listDlxPackages,
18+
listDlxPackagesAsync,
19+
removeDlxPackage,
20+
removeDlxPackageSync,
21+
} from '@socketsecurity/lib/dlx/packages'
22+
import { setPath } from '@socketsecurity/lib/paths/rewire'
23+
24+
let tmpDir: string
25+
let savedDlxDir: string | undefined
26+
27+
describe.sequential('dlx/packages', () => {
28+
beforeEach(() => {
29+
tmpDir = mkdtempSync(path.join(tmpdir(), 'socket-dlx-test-'))
30+
savedDlxDir = process.env['SOCKET_DLX_DIR']
31+
process.env['SOCKET_DLX_DIR'] = tmpDir
32+
// Override the cached path lookup so tests don't need a fresh process.
33+
setPath('socket-dlx-dir', tmpDir)
34+
})
35+
36+
afterEach(() => {
37+
if (savedDlxDir === undefined) {
38+
delete process.env['SOCKET_DLX_DIR']
39+
} else {
40+
process.env['SOCKET_DLX_DIR'] = savedDlxDir
41+
}
42+
setPath('socket-dlx-dir', undefined)
43+
try {
44+
rmSync(tmpDir, { recursive: true, force: true })
45+
} catch {}
46+
})
47+
48+
describe('isDlxPackageInstalled', () => {
49+
it('returns false when the package directory does not exist', () => {
50+
expect(isDlxPackageInstalled('nope')).toBe(false)
51+
})
52+
})
53+
54+
describe('listDlxPackages', () => {
55+
it('returns an empty array when DLX dir is empty', () => {
56+
const result = listDlxPackages()
57+
expect(result).toEqual([])
58+
})
59+
60+
it('returns sorted entries when DLX dir has subdirectories', () => {
61+
const dlxRoot = tmpDir
62+
mkdirSync(path.join(dlxRoot, 'zzz'), { recursive: true })
63+
mkdirSync(path.join(dlxRoot, 'aaa'), { recursive: true })
64+
mkdirSync(path.join(dlxRoot, 'mmm'), { recursive: true })
65+
const result = listDlxPackages()
66+
expect(result).toEqual(['aaa', 'mmm', 'zzz'])
67+
})
68+
69+
it('returns empty array when DLX dir does not exist', () => {
70+
// Remove the pre-created _dlx directory.
71+
rmSync(tmpDir, { recursive: true, force: true })
72+
const result = listDlxPackages()
73+
expect(result).toEqual([])
74+
})
75+
})
76+
77+
describe('listDlxPackagesAsync', () => {
78+
it('returns sorted entries when DLX dir has subdirectories', async () => {
79+
const dlxRoot = tmpDir
80+
mkdirSync(path.join(dlxRoot, 'beta'), { recursive: true })
81+
mkdirSync(path.join(dlxRoot, 'alpha'), { recursive: true })
82+
const result = await listDlxPackagesAsync()
83+
expect(result).toEqual(['alpha', 'beta'])
84+
})
85+
86+
it('filters out non-directory entries', async () => {
87+
const dlxRoot = tmpDir
88+
mkdirSync(path.join(dlxRoot, 'pkg-a'), { recursive: true })
89+
// Drop a file (not a directory) — should be filtered out.
90+
const fs = await import('node:fs')
91+
fs.writeFileSync(path.join(dlxRoot, 'not-a-package.txt'), '')
92+
const result = await listDlxPackagesAsync()
93+
expect(result).toEqual(['pkg-a'])
94+
})
95+
96+
it('returns empty array when DLX dir does not exist', async () => {
97+
rmSync(tmpDir, { recursive: true, force: true })
98+
const result = await listDlxPackagesAsync()
99+
expect(result).toEqual([])
100+
})
101+
})
102+
103+
describe('removeDlxPackage', () => {
104+
it('removes an existing package directory', async () => {
105+
const dlxRoot = tmpDir
106+
const pkgDir = path.join(dlxRoot, 'pkg-x')
107+
mkdirSync(pkgDir, { recursive: true })
108+
await removeDlxPackage('pkg-x')
109+
expect(existsSync(pkgDir)).toBe(false)
110+
})
111+
112+
it('does not throw when removing a non-existent package', async () => {
113+
// safeDelete with force:true silently no-ops on missing paths.
114+
await expect(removeDlxPackage('does-not-exist')).resolves.toBeUndefined()
115+
})
116+
})
117+
118+
describe('removeDlxPackageSync', () => {
119+
it('removes an existing package directory', () => {
120+
const dlxRoot = tmpDir
121+
const pkgDir = path.join(dlxRoot, 'pkg-y')
122+
mkdirSync(pkgDir, { recursive: true })
123+
removeDlxPackageSync('pkg-y')
124+
expect(existsSync(pkgDir)).toBe(false)
125+
})
126+
127+
it('does not throw when removing a non-existent package', () => {
128+
expect(() => removeDlxPackageSync('does-not-exist')).not.toThrow()
129+
})
130+
})
131+
})

0 commit comments

Comments
 (0)