Register
Login
Resources
Docs Blog Datasets Glossary Case Studies Tutorials & Webinars
Product
Data Engine LLMs Platform Enterprise
Pricing Explore
Connect to our Discord channel

validate-exit-codes.test.ts 5.4 KB

You have to be logged in to leave a comment. Sign In
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
150
151
152
153
154
155
156
157
158
159
160
161
  1. import { Command } from 'commander';
  2. import { doValidate, validateCommand } from '../../src/commands/validate';
  3. import logger from '../../src/logger';
  4. import { resolveConfigs } from '../../src/util/config/load';
  5. import type { UnifiedConfig } from '../../src/types';
  6. jest.mock('../../src/logger');
  7. jest.mock('../../src/util/config/load');
  8. jest.mock('../../src/telemetry', () => ({
  9. record: jest.fn(),
  10. send: jest.fn(),
  11. }));
  12. describe('Validate Command Exit Codes', () => {
  13. let program: Command;
  14. const defaultConfig = {} as UnifiedConfig;
  15. const defaultConfigPath = 'config.yaml';
  16. beforeEach(() => {
  17. program = new Command();
  18. jest.clearAllMocks();
  19. // Reset exit code before each test
  20. process.exitCode = 0;
  21. });
  22. describe('Success scenarios - should set exit code 0', () => {
  23. it('should set exit code 0 when configuration is valid', async () => {
  24. // Mock successful config resolution and validation
  25. const mockValidConfig = {
  26. prompts: ['test prompt'],
  27. providers: ['test-provider'],
  28. tests: [{ vars: { test: 'value' } }],
  29. };
  30. const mockValidTestSuite = {
  31. prompts: [{ raw: 'test prompt', label: 'test' }],
  32. providers: [{ id: () => 'test-provider' }],
  33. tests: [{ vars: { test: 'value' } }],
  34. };
  35. jest.mocked(resolveConfigs).mockResolvedValue({
  36. config: mockValidConfig as any,
  37. testSuite: mockValidTestSuite as any,
  38. basePath: '/test',
  39. });
  40. await doValidate({ config: ['test-config.yaml'] }, defaultConfig, defaultConfigPath);
  41. expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('Configuration is valid'));
  42. expect(process.exitCode).toBe(0);
  43. });
  44. it('should set exit code 0 when validating with default config path', async () => {
  45. const mockValidConfig = {
  46. prompts: ['test prompt'],
  47. providers: ['test-provider'],
  48. };
  49. const mockValidTestSuite = {
  50. prompts: [{ raw: 'test prompt', label: 'test' }],
  51. providers: [{ id: () => 'test-provider' }],
  52. };
  53. jest.mocked(resolveConfigs).mockResolvedValue({
  54. config: mockValidConfig as any,
  55. testSuite: mockValidTestSuite as any,
  56. basePath: '/test',
  57. });
  58. await doValidate({}, defaultConfig, defaultConfigPath);
  59. expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('Configuration is valid'));
  60. expect(process.exitCode).toBe(0);
  61. });
  62. });
  63. describe('Failure scenarios - should set exit code 1', () => {
  64. it('should set exit code 1 when configuration validation fails', async () => {
  65. // Mock invalid config that fails schema validation
  66. const mockInvalidConfig = {
  67. // Missing required fields to trigger validation error
  68. invalidField: 'invalid value',
  69. };
  70. const mockValidTestSuite = {
  71. prompts: [{ raw: 'test prompt', label: 'test' }],
  72. providers: [{ id: () => 'test-provider' }],
  73. };
  74. jest.mocked(resolveConfigs).mockResolvedValue({
  75. config: mockInvalidConfig as any,
  76. testSuite: mockValidTestSuite as any,
  77. basePath: '/test',
  78. });
  79. await doValidate({ config: ['invalid-config.yaml'] }, defaultConfig, defaultConfigPath);
  80. expect(logger.error).toHaveBeenCalledWith(
  81. expect.stringContaining('Configuration validation error'),
  82. );
  83. expect(process.exitCode).toBe(1);
  84. });
  85. it('should set exit code 1 when test suite validation fails', async () => {
  86. // Mock valid config but invalid test suite
  87. const mockValidConfig = {
  88. prompts: ['test prompt'],
  89. providers: ['test-provider'],
  90. };
  91. const mockInvalidTestSuite = {
  92. // Invalid test suite structure to trigger validation error
  93. prompts: 'invalid prompts format', // Should be an array
  94. providers: [{ id: () => 'test-provider' }],
  95. };
  96. jest.mocked(resolveConfigs).mockResolvedValue({
  97. config: mockValidConfig as any,
  98. testSuite: mockInvalidTestSuite as any,
  99. basePath: '/test',
  100. });
  101. await doValidate({ config: ['test-config.yaml'] }, defaultConfig, defaultConfigPath);
  102. expect(logger.error).toHaveBeenCalledWith(
  103. expect.stringContaining('Test suite validation error'),
  104. );
  105. expect(process.exitCode).toBe(1);
  106. });
  107. it('should set exit code 1 when config resolution throws an error', async () => {
  108. // Mock resolveConfigs to throw an error
  109. jest.mocked(resolveConfigs).mockRejectedValue(new Error('Failed to load configuration'));
  110. await doValidate({ config: ['non-existent-config.yaml'] }, defaultConfig, defaultConfigPath);
  111. expect(logger.error).toHaveBeenCalledWith(
  112. expect.stringContaining('Failed to validate configuration: Failed to load configuration'),
  113. );
  114. expect(process.exitCode).toBe(1);
  115. });
  116. });
  117. describe('Command registration', () => {
  118. it('should register validate command correctly', () => {
  119. validateCommand(program, defaultConfig, defaultConfigPath);
  120. const validateCmd = program.commands.find((cmd) => cmd.name() === 'validate');
  121. expect(validateCmd).toBeDefined();
  122. expect(validateCmd?.name()).toBe('validate');
  123. expect(validateCmd?.description()).toBe('Validate a promptfoo configuration file');
  124. // Check that the config option is registered
  125. const configOption = validateCmd?.options.find((opt) => opt.long === '--config');
  126. expect(configOption).toBeDefined();
  127. });
  128. });
  129. });
Tip!

Press p or to see the previous file or, n or to see the next file

Comments

Loading...