-
Notifications
You must be signed in to change notification settings - Fork 30
feat: export ServerConfigSchema from public validation module — closes #127 #187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
738f557
338f3dd
44be533
e6b627c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| import { describe, expect, it } from 'vitest'; | ||
| import { ServerConfigSchema, validateServerConfig } from '../../src/utils/validation'; | ||
|
|
||
| describe('ServerConfigSchema', () => { | ||
| it('is publicly importable from validation module', () => { | ||
| expect(ServerConfigSchema).toBeDefined(); | ||
| }); | ||
|
|
||
| it('has all expected ServerConfig fields', () => { | ||
| expect(ServerConfigSchema).toHaveProperty('host'); | ||
| expect(ServerConfigSchema).toHaveProperty('port'); | ||
| expect(ServerConfigSchema).toHaveProperty('debug'); | ||
| expect(ServerConfigSchema).toHaveProperty('interactiveDomain'); | ||
| }); | ||
|
|
||
| it('each field has required schema properties', () => { | ||
| for (const [key, field] of Object.entries(ServerConfigSchema)) { | ||
| expect(field, `${key} should have type`).toHaveProperty('type'); | ||
| expect(field, `${key} should have required`).toHaveProperty('required'); | ||
| expect(field, `${key} should have description`).toHaveProperty('description'); | ||
| expect(field, `${key} should have validate`).toHaveProperty('validate'); | ||
| expect(typeof field.validate).toBe('function'); | ||
| } | ||
| }); | ||
|
|
||
| describe('host field', () => { | ||
| it('validates a valid host string', () => { | ||
| expect(ServerConfigSchema.host.validate('0.0.0.0')).toBe(true); | ||
| expect(ServerConfigSchema.host.validate('localhost')).toBe(true); | ||
| }); | ||
| it('rejects non-string values', () => { | ||
| expect(ServerConfigSchema.host.validate(123)).toBe(false); | ||
| expect(ServerConfigSchema.host.validate('')).toBe(false); | ||
| }); | ||
| }); | ||
|
|
||
| describe('port field', () => { | ||
| it('validates valid port numbers', () => { | ||
| expect(ServerConfigSchema.port.validate(3000)).toBe(true); | ||
| expect(ServerConfigSchema.port.validate(1)).toBe(true); | ||
| expect(ServerConfigSchema.port.validate(65535)).toBe(true); | ||
| }); | ||
| it('rejects invalid port numbers', () => { | ||
| expect(ServerConfigSchema.port.validate(0)).toBe(false); | ||
| expect(ServerConfigSchema.port.validate(-1)).toBe(false); | ||
| expect(ServerConfigSchema.port.validate(65536)).toBe(false); | ||
| expect(ServerConfigSchema.port.validate(3.14)).toBe(false); | ||
| expect(ServerConfigSchema.port.validate('3000')).toBe(false); | ||
| }); | ||
| }); | ||
|
|
||
| describe('debug field', () => { | ||
| it('validates boolean values', () => { | ||
| expect(ServerConfigSchema.debug.validate(true)).toBe(true); | ||
| expect(ServerConfigSchema.debug.validate(false)).toBe(true); | ||
| }); | ||
| it('rejects non-boolean values', () => { | ||
| expect(ServerConfigSchema.debug.validate('true')).toBe(false); | ||
| expect(ServerConfigSchema.debug.validate(1)).toBe(false); | ||
| }); | ||
| }); | ||
|
|
||
| describe('interactiveDomain field', () => { | ||
| it('validates valid URLs', () => { | ||
| expect(ServerConfigSchema.interactiveDomain.validate('https://anchor.example.com')).toBe(true); | ||
| expect(ServerConfigSchema.interactiveDomain.validate('http://localhost:8080')).toBe(true); | ||
| }); | ||
| it('rejects invalid URLs', () => { | ||
| expect(ServerConfigSchema.interactiveDomain.validate('not-a-url')).toBe(false); | ||
| expect(ServerConfigSchema.interactiveDomain.validate('')).toBe(false); | ||
| expect(ServerConfigSchema.interactiveDomain.validate(123)).toBe(false); | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| describe('validateServerConfig', () => { | ||
| it('returns empty array for valid config', () => { | ||
| const errors = validateServerConfig({ | ||
| host: 'localhost', | ||
| port: 3000, | ||
| debug: false, | ||
| interactiveDomain: 'https://anchor.example.com', | ||
| }); | ||
| expect(errors).toEqual([]); | ||
| }); | ||
|
|
||
| it('returns empty array for empty config (all fields optional)', () => { | ||
| expect(validateServerConfig({})).toEqual([]); | ||
| }); | ||
|
|
||
| it('returns error for invalid port', () => { | ||
| const errors = validateServerConfig({ port: -1 }); | ||
| expect(errors).toContain('port: invalid value'); | ||
| }); | ||
|
|
||
| it('returns error for invalid interactiveDomain', () => { | ||
| const errors = validateServerConfig({ interactiveDomain: 'not-a-url' }); | ||
| expect(errors).toContain('interactiveDomain: invalid value'); | ||
| }); | ||
|
|
||
| it('returns multiple errors for multiple invalid fields', () => { | ||
| const errors = validateServerConfig({ | ||
| port: 0, | ||
| debug: 'yes' as unknown as boolean, | ||
| }); | ||
| expect(errors.length).toBeGreaterThanOrEqual(2); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The assertion expect(errors).toHaveLength(2);
expect(errors).toContain('port: invalid value');
expect(errors).toContain('debug: invalid value'); |
||
| }); | ||
| }); | ||
|
|
||
| describe('ServerConfigSchema public export', () => { | ||
| it('is exported from the utils validation module', async () => { | ||
| const mod = await import('../../src/utils/validation'); | ||
| expect(mod.ServerConfigSchema).toBeDefined(); | ||
| expect(mod.validateServerConfig).toBeDefined(); | ||
| }); | ||
|
|
||
| it('is accessible through the utils index', async () => { | ||
| const mod = await import('../../src/utils/index'); | ||
| expect(mod.ServerConfigSchema).toBeDefined(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test is incomplete. It only checks for expect(mod.ServerConfigSchema).toBeDefined();
expect(mod.validateServerConfig).toBeDefined(); |
||
| }); | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
ServerConfigSchemais incomplete. It is typed asRecord<keyof Required<ServerConfig>, SchemaField>, which requires all properties ofServerConfigto be defined in the schema. However,corsOriginsandrequestTimeoutfrom theServerConfiginterface are missing.This will likely cause a TypeScript compilation error. If not, it's a significant bug because the validation logic will not cover these properties, which could lead to invalid configuration being silently accepted.
Please add the missing properties to the schema with appropriate validation.