Skip to content

Commit 866037b

Browse files
committed
snapshot tests
1 parent 5f6324c commit 866037b

File tree

2 files changed

+224
-0
lines changed

2 files changed

+224
-0
lines changed
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`generate-workers-entry-content > matches snapshot for multiple workers and redis url 1`] = `
4+
"
5+
import { fileURLToPath } from 'node:url'
6+
import { resolve as resolvePath } from 'node:path'
7+
import { consola } from 'consola'
8+
import { $workers } from '#processor-utils'
9+
10+
// Initialize connection as early as possible so any imports that register
11+
// workers/queues have a valid connection available.
12+
const api = $workers()
13+
api.setConnection(new (await import("ioredis")).default("redis://localhost:6379"))
14+
15+
export async function createWorkersApp() {
16+
// Avoid EPIPE when stdout/stderr are closed by terminal (e.g., Ctrl+C piping)
17+
const handleStreamError = (err) => {
18+
try {
19+
const code = (typeof err === 'object' && err && 'code' in err) ? err.code : null
20+
if (code === 'EPIPE') return
21+
} catch (e) { console.warn?.('nuxt-processor: stream error inspection failed', e) }
22+
throw err
23+
}
24+
try { process.stdout?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stdout error handler', err) }
25+
try { process.stderr?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stderr error handler', err) }
26+
const modules = [
27+
() => import("/app/server/workers/basic.ts"),
28+
() => import("/app/server/workers/hello.ts")
29+
]
30+
for (const loader of modules) {
31+
await loader()
32+
}
33+
// Parse --workers flag (e.g. --workers=basic,hello)
34+
const workersArg = process.argv.find(a => typeof a === 'string' && a.startsWith('--workers='))
35+
const selectedWorkers = workersArg
36+
? workersArg.split('=')[1].split(',').map(s => s.trim()).filter(Boolean)
37+
: null
38+
const workersToRun = selectedWorkers
39+
? (Array.isArray(api.workers) ? api.workers.filter(w => w && selectedWorkers.includes(w.name)) : [])
40+
: (Array.isArray(api.workers) ? api.workers : [])
41+
const logger = consola.create({}).withTag('nuxt-processor')
42+
try {
43+
const workerNames = workersToRun.map(w => w && w.name).filter(Boolean)
44+
logger.info('starting workers:\\n' + workerNames.map(n => ' - ' + n).join('\\n'))
45+
for (const w of workersToRun) {
46+
w.on('error', (err) => logger.error('worker error', err))
47+
}
48+
// Explicitly start workers since autorun is disabled
49+
for (const w of workersToRun) {
50+
try {
51+
// run() returns a promise that resolves when the worker stops; do not await to avoid blocking
52+
// eslint-disable-next-line promise/catch-or-return
53+
w.run().catch((err) => logger.error('worker run error', err))
54+
}
55+
catch (err) {
56+
logger.error('failed to start worker', err)
57+
}
58+
}
59+
logger.success('workers started')
60+
} catch (err) {
61+
logger.error('failed to initialize workers', err)
62+
}
63+
const stopOnlyRunning = async () => {
64+
await Promise.allSettled(workersToRun.map(w => w.close()))
65+
await Promise.allSettled(api.queues.map(q => q.close()))
66+
}
67+
return { stop: stopOnlyRunning, workers: workersToRun }
68+
}
69+
70+
const isMain = (() => {
71+
try {
72+
if (typeof process === 'undefined' || !process.argv || !process.argv[1]) return false
73+
const argvPath = resolvePath(process.cwd?.() || '.', process.argv[1])
74+
const filePath = fileURLToPath(import.meta.url)
75+
return filePath === argvPath
76+
} catch {
77+
return false
78+
}
79+
})()
80+
if (isMain) {
81+
const logger = consola.create({}).withTag('nuxt-processor')
82+
const appPromise = createWorkersApp().catch((err) => {
83+
logger.error('failed to start workers', err)
84+
process.exit(1)
85+
})
86+
const shutdown = async () => {
87+
try { logger.info('closing workers...') } catch (err) { console.warn('nuxt-processor: failed to log shutdown start', err) }
88+
try {
89+
const app = await appPromise
90+
try {
91+
const names = (app?.workers || []).map(w => w && w.name).filter(Boolean)
92+
logger.info('closing workers:\\n' + names.map(n => ' - ' + n).join('\\n'))
93+
} catch (eL) { console.warn('nuxt-processor: failed to log workers list on shutdown', eL) }
94+
await app.stop()
95+
try { logger.success('workers closed') } catch (err2) { console.warn('nuxt-processor: failed to log shutdown complete', err2) }
96+
}
97+
finally { process.exit(0) }
98+
}
99+
;['SIGINT','SIGTERM','SIGQUIT'].forEach(sig => process.on(sig, shutdown))
100+
process.on('beforeExit', shutdown)
101+
}
102+
103+
export default { createWorkersApp }
104+
"
105+
`;
106+
107+
exports[`generate-workers-entry-content > matches snapshot for single worker and undefined redis 1`] = `
108+
"
109+
import { fileURLToPath } from 'node:url'
110+
import { resolve as resolvePath } from 'node:path'
111+
import { consola } from 'consola'
112+
import { $workers } from '#processor-utils'
113+
114+
// Initialize connection as early as possible so any imports that register
115+
// workers/queues have a valid connection available.
116+
const api = $workers()
117+
api.setConnection(undefined)
118+
119+
export async function createWorkersApp() {
120+
// Avoid EPIPE when stdout/stderr are closed by terminal (e.g., Ctrl+C piping)
121+
const handleStreamError = (err) => {
122+
try {
123+
const code = (typeof err === 'object' && err && 'code' in err) ? err.code : null
124+
if (code === 'EPIPE') return
125+
} catch (e) { console.warn?.('nuxt-processor: stream error inspection failed', e) }
126+
throw err
127+
}
128+
try { process.stdout?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stdout error handler', err) }
129+
try { process.stderr?.on?.('error', handleStreamError) } catch (err) { console.warn('nuxt-processor: failed to attach stderr error handler', err) }
130+
const modules = [
131+
() => import("/path/to/worker.mjs")
132+
]
133+
for (const loader of modules) {
134+
await loader()
135+
}
136+
// Parse --workers flag (e.g. --workers=basic,hello)
137+
const workersArg = process.argv.find(a => typeof a === 'string' && a.startsWith('--workers='))
138+
const selectedWorkers = workersArg
139+
? workersArg.split('=')[1].split(',').map(s => s.trim()).filter(Boolean)
140+
: null
141+
const workersToRun = selectedWorkers
142+
? (Array.isArray(api.workers) ? api.workers.filter(w => w && selectedWorkers.includes(w.name)) : [])
143+
: (Array.isArray(api.workers) ? api.workers : [])
144+
const logger = consola.create({}).withTag('nuxt-processor')
145+
try {
146+
const workerNames = workersToRun.map(w => w && w.name).filter(Boolean)
147+
logger.info('starting workers:\\n' + workerNames.map(n => ' - ' + n).join('\\n'))
148+
for (const w of workersToRun) {
149+
w.on('error', (err) => logger.error('worker error', err))
150+
}
151+
// Explicitly start workers since autorun is disabled
152+
for (const w of workersToRun) {
153+
try {
154+
// run() returns a promise that resolves when the worker stops; do not await to avoid blocking
155+
// eslint-disable-next-line promise/catch-or-return
156+
w.run().catch((err) => logger.error('worker run error', err))
157+
}
158+
catch (err) {
159+
logger.error('failed to start worker', err)
160+
}
161+
}
162+
logger.success('workers started')
163+
} catch (err) {
164+
logger.error('failed to initialize workers', err)
165+
}
166+
const stopOnlyRunning = async () => {
167+
await Promise.allSettled(workersToRun.map(w => w.close()))
168+
await Promise.allSettled(api.queues.map(q => q.close()))
169+
}
170+
return { stop: stopOnlyRunning, workers: workersToRun }
171+
}
172+
173+
const isMain = (() => {
174+
try {
175+
if (typeof process === 'undefined' || !process.argv || !process.argv[1]) return false
176+
const argvPath = resolvePath(process.cwd?.() || '.', process.argv[1])
177+
const filePath = fileURLToPath(import.meta.url)
178+
return filePath === argvPath
179+
} catch {
180+
return false
181+
}
182+
})()
183+
if (isMain) {
184+
const logger = consola.create({}).withTag('nuxt-processor')
185+
const appPromise = createWorkersApp().catch((err) => {
186+
logger.error('failed to start workers', err)
187+
process.exit(1)
188+
})
189+
const shutdown = async () => {
190+
try { logger.info('closing workers...') } catch (err) { console.warn('nuxt-processor: failed to log shutdown start', err) }
191+
try {
192+
const app = await appPromise
193+
try {
194+
const names = (app?.workers || []).map(w => w && w.name).filter(Boolean)
195+
logger.info('closing workers:\\n' + names.map(n => ' - ' + n).join('\\n'))
196+
} catch (eL) { console.warn('nuxt-processor: failed to log workers list on shutdown', eL) }
197+
await app.stop()
198+
try { logger.success('workers closed') } catch (err2) { console.warn('nuxt-processor: failed to log shutdown complete', err2) }
199+
}
200+
finally { process.exit(0) }
201+
}
202+
;['SIGINT','SIGTERM','SIGQUIT'].forEach(sig => process.on(sig, shutdown))
203+
process.on('beforeExit', shutdown)
204+
}
205+
206+
export default { createWorkersApp }
207+
"
208+
`;

spec/utils/generate-workers-entry-content.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,22 @@ import { describe, it, expect } from 'vitest'
22
import { generateWorkersEntryContent } from '../../src/utils/generate-workers-entry-content'
33

44
describe('generate-workers-entry-content', () => {
5+
it('matches snapshot for single worker and undefined redis', () => {
6+
const content = generateWorkersEntryContent(
7+
['/path/to/worker.mjs'],
8+
'undefined',
9+
)
10+
expect(content).toMatchSnapshot()
11+
})
12+
13+
it('matches snapshot for multiple workers and redis url', () => {
14+
const content = generateWorkersEntryContent(
15+
['/app/server/workers/basic.ts', '/app/server/workers/hello.ts'],
16+
'new (await import("ioredis")).default("redis://localhost:6379")',
17+
)
18+
expect(content).toMatchSnapshot()
19+
})
20+
521
it('generates entry that parses --workers flag from process.argv', () => {
622
const content = generateWorkersEntryContent(
723
['/path/to/worker.mjs'],

0 commit comments

Comments
 (0)