forked from promptfoo/promptfoo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.config.main.test.ts
149 lines (120 loc) · 4.89 KB
/
util.config.main.test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import * as fs from 'fs';
import yaml from 'js-yaml';
import * as os from 'os';
import * as path from 'path';
import type { UnifiedConfig } from '../src/types';
import {
getConfigDirectoryPath,
setConfigDirectoryPath,
writePromptfooConfig,
} from '../src/util/config/manage';
jest.mock('os');
jest.mock('fs');
jest.mock('js-yaml');
describe('config', () => {
const mockHomedir = '/mock/home';
const defaultConfigPath = path.join(mockHomedir, '.promptfoo');
beforeEach(() => {
jest.resetAllMocks();
jest.mocked(os.homedir).mockReturnValue(mockHomedir);
jest.mocked(fs.existsSync).mockReturnValue(false);
delete process.env.PROMPTFOO_CONFIG_DIR;
});
describe('getConfigDirectoryPath', () => {
it('returns default path when no custom path is set', () => {
expect(getConfigDirectoryPath()).toBe(defaultConfigPath);
});
it('does not create directory when createIfNotExists is false', () => {
getConfigDirectoryPath(false);
expect(fs.mkdirSync).not.toHaveBeenCalled();
});
it('creates directory when createIfNotExists is true and directory does not exist', () => {
getConfigDirectoryPath(true);
expect(fs.mkdirSync).toHaveBeenCalledWith(defaultConfigPath, { recursive: true });
});
it('does not create directory when it already exists', () => {
jest.mocked(fs.existsSync).mockReturnValue(true);
getConfigDirectoryPath(true);
expect(fs.mkdirSync).not.toHaveBeenCalled();
});
});
describe('setConfigDirectoryPath', () => {
it('updates the config directory path', () => {
const newPath = '/new/config/path';
setConfigDirectoryPath(newPath);
expect(getConfigDirectoryPath()).toBe(newPath);
});
it('overrides the environment variable', () => {
const envPath = '/env/path';
const newPath = '/new/path';
process.env.PROMPTFOO_CONFIG_DIR = envPath;
setConfigDirectoryPath(newPath);
expect(getConfigDirectoryPath()).toBe(newPath);
});
});
});
describe('writePromptfooConfig', () => {
const mockOutputPath = '/mock/output/path.yaml';
beforeEach(() => {
jest.resetAllMocks();
});
it('writes a basic config to the specified path', () => {
const mockConfig: Partial<UnifiedConfig> = { description: 'Test config' };
const mockYaml = 'description: Test config\n';
jest.mocked(yaml.dump).mockReturnValue(mockYaml);
writePromptfooConfig(mockConfig, mockOutputPath);
expect(fs.writeFileSync).toHaveBeenCalledWith(mockOutputPath, mockYaml);
});
it('orders the keys of the config correctly', () => {
const mockConfig: Partial<UnifiedConfig> = {
tests: [{ assert: [{ type: 'equals', value: 'test assertion' }] }],
description: 'Test config',
prompts: ['prompt1'],
providers: ['provider1'],
defaultTest: { assert: [{ type: 'equals', value: 'default assertion' }] },
};
writePromptfooConfig(mockConfig, mockOutputPath);
const dumpCall = jest.mocked(yaml.dump).mock.calls[0][0];
const keys = Object.keys(dumpCall);
expect(keys).toEqual(['description', 'prompts', 'providers', 'defaultTest', 'tests']);
});
it('uses js-yaml to dump the config with skipInvalid option', () => {
const mockConfig: Partial<UnifiedConfig> = { description: 'Test config' };
writePromptfooConfig(mockConfig, mockOutputPath);
expect(yaml.dump).toHaveBeenCalledWith(expect.anything(), { skipInvalid: true });
});
it('handles empty config', () => {
const mockConfig: Partial<UnifiedConfig> = {};
writePromptfooConfig(mockConfig, mockOutputPath);
expect(fs.writeFileSync).toHaveBeenCalledWith(mockOutputPath, undefined);
expect(yaml.dump).toHaveBeenCalledWith({}, { skipInvalid: true });
});
it('preserves all fields of the UnifiedConfig', () => {
const mockConfig: Partial<UnifiedConfig> = {
description: 'Full config test',
prompts: ['prompt1', 'prompt2'],
providers: ['provider1', 'provider2'],
defaultTest: { assert: [{ type: 'equals', value: 'default assertion' }] },
tests: [
{ assert: [{ type: 'equals', value: 'test assertion 1' }] },
{ assert: [{ type: 'equals', value: 'test assertion 2' }] },
],
outputPath: './output',
};
writePromptfooConfig(mockConfig, mockOutputPath);
const dumpCall = jest.mocked(yaml.dump).mock.calls[0][0];
expect(dumpCall).toEqual(expect.objectContaining(mockConfig));
});
it('handles config with undefined values', () => {
const mockConfig: Partial<UnifiedConfig> = {
description: 'Config with undefined',
prompts: undefined,
providers: ['provider1'],
};
writePromptfooConfig(mockConfig, mockOutputPath);
const dumpCall = jest.mocked(yaml.dump).mock.calls[0][0];
expect(dumpCall).toHaveProperty('description', 'Config with undefined');
expect(dumpCall).toHaveProperty('providers', ['provider1']);
expect(dumpCall).not.toHaveProperty('prompts');
});
});