dazscript-framework 1.0.29 → 1.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -0
- package/dist/scripts/cli.js +44 -0
- package/dist/scripts/init.js +329 -0
- package/dist/scripts/integration.js +304 -0
- package/dist/scripts/launchers.js +7 -1
- package/package.json +2 -1
- package/src/helpers/progress-helper.test.ts +95 -0
- package/src/helpers/progress-helper.ts +89 -29
- package/src/helpers/script-helper.ts +6 -1
- package/src/scripts/init.test.ts +131 -0
- package/src/scripts/integration.test.ts +97 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import os from 'node:os'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { afterEach, describe, expect, it } from 'vitest'
|
|
5
|
+
|
|
6
|
+
const { initIntegrationTests, initUnitTests } = require('../../dist/scripts/init')
|
|
7
|
+
|
|
8
|
+
const tempDirs: string[] = []
|
|
9
|
+
|
|
10
|
+
const makeProject = (name = 'toolbox-test'): string => {
|
|
11
|
+
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), `${name}-`))
|
|
12
|
+
tempDirs.push(projectDir)
|
|
13
|
+
fs.writeFileSync(path.join(projectDir, 'package.json'), JSON.stringify({
|
|
14
|
+
private: true,
|
|
15
|
+
scripts: {
|
|
16
|
+
test: 'vitest run',
|
|
17
|
+
},
|
|
18
|
+
}, null, 2))
|
|
19
|
+
return projectDir
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const toFixtureName = (projectDir: string): string =>
|
|
23
|
+
path.basename(projectDir)
|
|
24
|
+
.toLowerCase()
|
|
25
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
26
|
+
.replace(/^-+|-+$/g, '') || 'project'
|
|
27
|
+
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
while (tempDirs.length > 0) {
|
|
30
|
+
const dir = tempDirs.pop()
|
|
31
|
+
if (dir) fs.rmSync(dir, { recursive: true, force: true })
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
describe('init integration tests', () => {
|
|
36
|
+
it('creates the fixture, docs, env examples, npm script, and ignore entries', () => {
|
|
37
|
+
const projectDir = makeProject('toolbox-test')
|
|
38
|
+
const fixtureBaseName = toFixtureName(projectDir)
|
|
39
|
+
|
|
40
|
+
initIntegrationTests(projectDir, { force: false })
|
|
41
|
+
|
|
42
|
+
const fixturePath = path.join(projectDir, `test/integration/fixtures/${fixtureBaseName}-smoke.dsa.ts`)
|
|
43
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(projectDir, 'package.json'), 'utf8'))
|
|
44
|
+
const gitignore = fs.readFileSync(path.join(projectDir, '.gitignore'), 'utf8')
|
|
45
|
+
|
|
46
|
+
expect(fs.existsSync(fixturePath)).toBe(true)
|
|
47
|
+
expect(fs.existsSync(path.join(projectDir, 'test/integration/README.md'))).toBe(true)
|
|
48
|
+
expect(fs.existsSync(path.join(projectDir, '.env.integration.linux.example'))).toBe(true)
|
|
49
|
+
expect(fs.existsSync(path.join(projectDir, '.env.integration.windows.example'))).toBe(true)
|
|
50
|
+
expect(packageJson.scripts['test:integration']).toBe(
|
|
51
|
+
`dazscript integration --fixture ./test/integration/fixtures/${fixtureBaseName}-smoke.dsa.ts`
|
|
52
|
+
)
|
|
53
|
+
expect(gitignore).toContain('test/integration/out/')
|
|
54
|
+
expect(gitignore).toContain('.env.integration.local')
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('does not replace an existing integration script or duplicate ignore entries', () => {
|
|
58
|
+
const projectDir = makeProject('existing-test')
|
|
59
|
+
const packageJsonPath = path.join(projectDir, 'package.json')
|
|
60
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
|
|
61
|
+
packageJson.scripts['test:integration'] = 'custom command'
|
|
62
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
|
|
63
|
+
fs.writeFileSync(path.join(projectDir, '.gitignore'), 'test/integration/out/\n')
|
|
64
|
+
|
|
65
|
+
initIntegrationTests(projectDir, { force: false })
|
|
66
|
+
initIntegrationTests(projectDir, { force: false })
|
|
67
|
+
|
|
68
|
+
const updatedPackageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
|
|
69
|
+
const gitignore = fs.readFileSync(path.join(projectDir, '.gitignore'), 'utf8')
|
|
70
|
+
|
|
71
|
+
expect(updatedPackageJson.scripts['test:integration']).toBe('custom command')
|
|
72
|
+
expect(gitignore.match(/test\/integration\/out\//g)?.length).toBe(1)
|
|
73
|
+
expect(gitignore.match(/\.env\.integration\.local/g)?.length).toBe(1)
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
describe('init unit tests', () => {
|
|
78
|
+
it('creates Vitest config, sample test, docs, npm scripts, and dev dependency', () => {
|
|
79
|
+
const projectDir = makeProject('unit-test')
|
|
80
|
+
const packageJsonPath = path.join(projectDir, 'package.json')
|
|
81
|
+
const initialPackageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
|
|
82
|
+
delete initialPackageJson.scripts.test
|
|
83
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(initialPackageJson, null, 2))
|
|
84
|
+
|
|
85
|
+
initUnitTests(projectDir, { force: false })
|
|
86
|
+
|
|
87
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(projectDir, 'package.json'), 'utf8'))
|
|
88
|
+
|
|
89
|
+
expect(fs.existsSync(path.join(projectDir, 'vitest.config.ts'))).toBe(true)
|
|
90
|
+
expect(fs.existsSync(path.join(projectDir, 'tsconfig.test.json'))).toBe(true)
|
|
91
|
+
expect(fs.existsSync(path.join(projectDir, 'test/unit/smoke.test.ts'))).toBe(true)
|
|
92
|
+
expect(fs.existsSync(path.join(projectDir, 'test/unit/README.md'))).toBe(true)
|
|
93
|
+
expect(packageJson.scripts.test).toBe('vitest run')
|
|
94
|
+
expect(packageJson.scripts['test:watch']).toBe('vitest')
|
|
95
|
+
expect(packageJson.devDependencies.vitest).toBe('^3.0.0')
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('does not replace existing unit test scripts or duplicate Vitest dependency', () => {
|
|
99
|
+
const projectDir = makeProject('existing-unit-test')
|
|
100
|
+
const packageJsonPath = path.join(projectDir, 'package.json')
|
|
101
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
|
|
102
|
+
packageJson.scripts.test = 'custom test'
|
|
103
|
+
packageJson.scripts['test:watch'] = 'custom watch'
|
|
104
|
+
packageJson.devDependencies = {
|
|
105
|
+
vitest: '^4.0.0',
|
|
106
|
+
}
|
|
107
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
|
|
108
|
+
|
|
109
|
+
initUnitTests(projectDir, { force: false })
|
|
110
|
+
|
|
111
|
+
const updatedPackageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
|
|
112
|
+
|
|
113
|
+
expect(updatedPackageJson.scripts.test).toBe('custom test')
|
|
114
|
+
expect(updatedPackageJson.scripts['test:watch']).toBe('custom watch')
|
|
115
|
+
expect(updatedPackageJson.devDependencies.vitest).toBe('^4.0.0')
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it('replaces the default npm init failing test script', () => {
|
|
119
|
+
const projectDir = makeProject('npm-default-unit-test')
|
|
120
|
+
const packageJsonPath = path.join(projectDir, 'package.json')
|
|
121
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
|
|
122
|
+
packageJson.scripts.test = 'echo "Error: no test specified" && exit 1'
|
|
123
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
|
|
124
|
+
|
|
125
|
+
initUnitTests(projectDir, { force: false })
|
|
126
|
+
|
|
127
|
+
const updatedPackageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
|
|
128
|
+
|
|
129
|
+
expect(updatedPackageJson.scripts.test).toBe('vitest run')
|
|
130
|
+
})
|
|
131
|
+
})
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import os from 'node:os'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { afterEach, describe, expect, it } from 'vitest'
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
loadEnvFile,
|
|
8
|
+
readIntegrationResult,
|
|
9
|
+
resolveIntegrationOptions,
|
|
10
|
+
} = require('../../dist/scripts/integration')
|
|
11
|
+
|
|
12
|
+
const tempDirs: string[] = []
|
|
13
|
+
|
|
14
|
+
const makeProject = (): string => {
|
|
15
|
+
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'dsf-integration-'))
|
|
16
|
+
tempDirs.push(projectDir)
|
|
17
|
+
fs.mkdirSync(path.join(projectDir, 'test/integration/fixtures'), { recursive: true })
|
|
18
|
+
fs.writeFileSync(path.join(projectDir, 'test/integration/fixtures/smoke.dsa.ts'), 'action({}, function() {})\n')
|
|
19
|
+
fs.writeFileSync(path.join(projectDir, 'DAZStudio.exe'), '')
|
|
20
|
+
return projectDir
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
while (tempDirs.length > 0) {
|
|
25
|
+
const dir = tempDirs.pop()
|
|
26
|
+
if (dir) fs.rmSync(dir, { recursive: true, force: true })
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
describe('integration env loader', () => {
|
|
31
|
+
it('loads simple values without overriding existing values', () => {
|
|
32
|
+
const projectDir = makeProject()
|
|
33
|
+
const envPath = path.join(projectDir, '.env.integration.local')
|
|
34
|
+
fs.writeFileSync(envPath, [
|
|
35
|
+
'# local machine settings',
|
|
36
|
+
'DAZ_STUDIO_EXE=/from/file/DAZStudio.exe',
|
|
37
|
+
'DAZ_TEST_TIMEOUT_MS="12345"',
|
|
38
|
+
'INVALID KEY=ignored',
|
|
39
|
+
'',
|
|
40
|
+
].join('\n'))
|
|
41
|
+
|
|
42
|
+
const env: Record<string, string> = {
|
|
43
|
+
DAZ_STUDIO_EXE: '/from/shell/DAZStudio.exe',
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
expect(loadEnvFile(envPath, env)).toBe(true)
|
|
47
|
+
expect(env.DAZ_STUDIO_EXE).toBe('/from/shell/DAZStudio.exe')
|
|
48
|
+
expect(env.DAZ_TEST_TIMEOUT_MS).toBe('12345')
|
|
49
|
+
expect(env['INVALID KEY']).toBeUndefined()
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
describe('integration option resolution', () => {
|
|
54
|
+
it('uses project-relative fixture and output defaults without requiring content', () => {
|
|
55
|
+
const projectDir = makeProject()
|
|
56
|
+
const options = resolveIntegrationOptions(projectDir, {
|
|
57
|
+
fixture: './test/integration/fixtures/smoke.dsa.ts',
|
|
58
|
+
}, {
|
|
59
|
+
DAZ_STUDIO_EXE: path.join(projectDir, 'DAZStudio.exe'),
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
expect(options.fixturePath).toBe(path.join(projectDir, 'test/integration/fixtures/smoke.dsa.ts'))
|
|
63
|
+
expect(options.outDir).toBe(path.join(projectDir, 'test/integration/out'))
|
|
64
|
+
expect(options.fixtureRoot).toBe(path.join(projectDir, 'test/integration/out/fixture'))
|
|
65
|
+
expect(options.resultPath).toBe(path.join(projectDir, 'test/integration/out/fixture/result.json'))
|
|
66
|
+
expect(options.contentPath).toBe('')
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('requires content only when requested', () => {
|
|
70
|
+
const projectDir = makeProject()
|
|
71
|
+
|
|
72
|
+
expect(() => resolveIntegrationOptions(projectDir, {
|
|
73
|
+
fixture: './test/integration/fixtures/smoke.dsa.ts',
|
|
74
|
+
requireContent: true,
|
|
75
|
+
}, {
|
|
76
|
+
DAZ_STUDIO_EXE: path.join(projectDir, 'DAZStudio.exe'),
|
|
77
|
+
})).toThrow(/DAZ_TEST_CONTENT_DUF/)
|
|
78
|
+
})
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
describe('integration result reader', () => {
|
|
82
|
+
it('accepts successful result JSON', () => {
|
|
83
|
+
const projectDir = makeProject()
|
|
84
|
+
const resultPath = path.join(projectDir, 'result.json')
|
|
85
|
+
fs.writeFileSync(resultPath, JSON.stringify({ ok: true }))
|
|
86
|
+
|
|
87
|
+
expect(readIntegrationResult(resultPath)).toEqual({ ok: true })
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('reports fixture failures', () => {
|
|
91
|
+
const projectDir = makeProject()
|
|
92
|
+
const resultPath = path.join(projectDir, 'result.json')
|
|
93
|
+
fs.writeFileSync(resultPath, JSON.stringify({ ok: false, failures: ['bad frame'] }))
|
|
94
|
+
|
|
95
|
+
expect(() => readIntegrationResult(resultPath)).toThrow(/bad frame/)
|
|
96
|
+
})
|
|
97
|
+
})
|