返回 AiToEarn
config-editor.service.spec.ts
根目录 / project / aitoearn-backend / libs / config-editor / src / config-editor.service.spec.ts
1 import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
2 import { tmpdir } from 'node:os'
3 import { join } from 'node:path'
4 import { createZodDto, ResponseCode } from '@yikart/common'
5 import { afterEach, beforeEach, describe, expect, it } from 'vitest'
6 import { z } from 'zod'
7 import { ConfigEditorConfig } from './config-editor.config'
8 import { ConfigEditorService } from './config-editor.service'
9 import { ConfigFileFormat } from './config-editor.vo'
10
11 const configSchema = z.object({
12 name: z.string(),
13 count: z.number().int(),
14 })
15
16 function createConfig(filePath: string) {
17 return {
18 meta: {
19 configPath: filePath,
20 },
21 }
22 }
23
24 describe('configEditorService', () => {
25 let workspace: string
26
27 beforeEach(async () => {
28 workspace = await mkdtemp(join(tmpdir(), 'config-editor-'))
29 })
30
31 afterEach(async () => {
32 await rm(workspace, { recursive: true, force: true })
33 })
34
35 it('读取 yaml 配置文件并返回结构化配置', async () => {
36 const filePath = join(workspace, 'config.yaml')
37 await writeFile(filePath, 'name: demo\ncount: 1\n', 'utf-8')
38
39 const service = new ConfigEditorService(new ConfigEditorConfig({
40 schema: configSchema,
41 config: createConfig(filePath),
42 }))
43
44 await expect(service.getConfig()).resolves.toEqual({
45 config: {
46 name: 'demo',
47 count: 1,
48 },
49 format: ConfigFileFormat.Yaml,
50 })
51 })
52
53 it('读取 json 配置文件并返回结构化配置', async () => {
54 const filePath = join(workspace, 'config.json')
55 await writeFile(filePath, '{ "name": "demo", "count": 1 }\n', 'utf-8')
56
57 const service = new ConfigEditorService(new ConfigEditorConfig({
58 schema: configSchema,
59 config: createConfig(filePath),
60 }))
61
62 await expect(service.getConfig()).resolves.toEqual({
63 config: {
64 name: 'demo',
65 count: 1,
66 },
67 format: ConfigFileFormat.Json,
68 })
69 })
70
71 it('保存 json 时由后端序列化结构化配置', async () => {
72 const filePath = join(workspace, 'config.json')
73 const ConfigDto = createZodDto(configSchema)
74
75 const service = new ConfigEditorService(new ConfigEditorConfig({
76 schema: ConfigDto,
77 config: createConfig(filePath),
78 }))
79
80 await service.saveConfig({
81 name: 'saved',
82 count: 2,
83 })
84
85 await expect(readFile(filePath, 'utf-8')).resolves.toBe('{\n "name": "saved",\n "count": 2\n}\n')
86 })
87
88 it('保存 yaml 时由后端序列化结构化配置', async () => {
89 const filePath = join(workspace, 'config.yaml')
90
91 const service = new ConfigEditorService(new ConfigEditorConfig({
92 schema: configSchema,
93 config: createConfig(filePath),
94 }))
95
96 await service.saveConfig({
97 name: 'saved',
98 count: 3,
99 })
100
101 await expect(readFile(filePath, 'utf-8')).resolves.toBe('name: saved\ncount: 3\n')
102 })
103
104 it('校验失败时不会写入配置文件', async () => {
105 const filePath = join(workspace, 'config.json')
106 const originalContent = '{ "name": "original", "count": 1 }\n'
107 await writeFile(filePath, originalContent, 'utf-8')
108
109 const service = new ConfigEditorService(new ConfigEditorConfig({
110 schema: configSchema,
111 config: createConfig(filePath),
112 }))
113
114 await expect(service.saveConfig({
115 name: 'bad',
116 count: 'wrong',
117 }))
118 .rejects
119 .toMatchObject({
120 code: ResponseCode.ConfigEditorValidationFailed,
121 })
122 await expect(readFile(filePath, 'utf-8')).resolves.toBe(originalContent)
123 })
124
125 it('拒绝不支持的配置文件扩展名', async () => {
126 const service = new ConfigEditorService(new ConfigEditorConfig({
127 schema: configSchema,
128 config: createConfig(join(workspace, 'config.txt')),
129 }))
130
131 await expect(service.saveConfig({
132 name: 'demo',
133 count: 1,
134 }))
135 .rejects
136 .toMatchObject({
137 code: ResponseCode.ConfigEditorUnsupportedFormat,
138 })
139 })
140 })
141
141 lines TYPESCRIPT