167 lines
5.5 KiB
TypeScript
167 lines
5.5 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { PageStateValidator } from '@core/automation/domain/services/PageStateValidator';
|
|
|
|
describe('PageStateValidator', () => {
|
|
const validator = new PageStateValidator();
|
|
|
|
describe('validateState', () => {
|
|
it('should return valid when all required selectors are present', () => {
|
|
// Arrange
|
|
const actualState = (_selector: string) => {
|
|
return ['#add-car-button', '#cars-list'].includes(selector);
|
|
};
|
|
|
|
// Act
|
|
const result = validator.validateState(actualState, {
|
|
expectedStep: 'cars',
|
|
requiredSelectors: ['#add-car-button', '#cars-list']
|
|
});
|
|
|
|
// Assert
|
|
expect(result.isOk()).toBe(true);
|
|
const value = result.unwrap();
|
|
expect(value.isValid).toBe(true);
|
|
expect(value.expectedStep).toBe('cars');
|
|
expect(value.message).toContain('Page state valid');
|
|
});
|
|
|
|
it('should return invalid when required selectors are missing', () => {
|
|
// Arrange
|
|
const actualState = (_selector: string) => {
|
|
return selector === '#add-car-button'; // Only one of two selectors present
|
|
};
|
|
|
|
// Act
|
|
const result = validator.validateState(actualState, {
|
|
expectedStep: 'cars',
|
|
requiredSelectors: ['#add-car-button', '#cars-list']
|
|
});
|
|
|
|
// Assert
|
|
expect(result.isOk()).toBe(true);
|
|
const value = result.unwrap();
|
|
expect(value.isValid).toBe(false);
|
|
expect(value.expectedStep).toBe('cars');
|
|
expect(value.missingSelectors).toEqual(['#cars-list']);
|
|
expect(value.message).toContain('missing required elements');
|
|
});
|
|
|
|
it('should return invalid when forbidden selectors are present', () => {
|
|
// Arrange
|
|
const actualState = (_selector: string) => {
|
|
return ['#add-car-button', '#set-track'].includes(selector);
|
|
};
|
|
|
|
// Act
|
|
const result = validator.validateState(actualState, {
|
|
expectedStep: 'cars',
|
|
requiredSelectors: ['#add-car-button'],
|
|
forbiddenSelectors: ['#set-track'] // Should NOT be on track page yet
|
|
});
|
|
|
|
// Assert
|
|
expect(result.isOk()).toBe(true);
|
|
const value = result.unwrap();
|
|
expect(value.isValid).toBe(false);
|
|
expect(value.expectedStep).toBe('cars');
|
|
expect(value.unexpectedSelectors).toEqual(['#set-track']);
|
|
expect(value.message).toContain('unexpected elements');
|
|
});
|
|
|
|
it('should handle empty forbidden selectors array', () => {
|
|
// Arrange
|
|
const actualState = (_selector: string) => {
|
|
return selector === '#add-car-button';
|
|
};
|
|
|
|
// Act
|
|
const result = validator.validateState(actualState, {
|
|
expectedStep: 'cars',
|
|
requiredSelectors: ['#add-car-button'],
|
|
forbiddenSelectors: []
|
|
});
|
|
|
|
// Assert
|
|
expect(result.isOk()).toBe(true);
|
|
const value = result.unwrap();
|
|
expect(value.isValid).toBe(true);
|
|
});
|
|
|
|
it('should handle undefined forbidden selectors', () => {
|
|
// Arrange
|
|
const actualState = (_selector: string) => {
|
|
return selector === '#add-car-button';
|
|
};
|
|
|
|
// Act
|
|
const result = validator.validateState(actualState, {
|
|
expectedStep: 'cars',
|
|
requiredSelectors: ['#add-car-button']
|
|
// forbiddenSelectors is undefined
|
|
});
|
|
|
|
// Assert
|
|
expect(result.isOk()).toBe(true);
|
|
const value = result.unwrap();
|
|
expect(value.isValid).toBe(true);
|
|
});
|
|
|
|
it('should return error result when actualState function throws', () => {
|
|
// Arrange
|
|
const actualState = (_selector: string) => {
|
|
throw new Error('Selector evaluation failed');
|
|
};
|
|
|
|
// Act
|
|
const result = validator.validateState(actualState, {
|
|
expectedStep: 'cars',
|
|
requiredSelectors: ['#add-car-button']
|
|
});
|
|
|
|
// Assert
|
|
expect(result.isErr()).toBe(true);
|
|
const error = result.unwrapErr();
|
|
expect(error.message).toContain('Selector evaluation failed');
|
|
});
|
|
|
|
it('should provide clear error messages for missing selectors', () => {
|
|
// Arrange
|
|
const actualState = () => false; // Nothing present
|
|
|
|
// Act
|
|
const result = validator.validateState(actualState, {
|
|
expectedStep: 'track',
|
|
requiredSelectors: ['#set-track', '#track-search']
|
|
});
|
|
|
|
// Assert
|
|
expect(result.isOk()).toBe(true);
|
|
const value = result.unwrap();
|
|
expect(value.isValid).toBe(false);
|
|
expect(value.message).toBe('Page state mismatch: Expected to be on "track" page but missing required elements');
|
|
expect(value.missingSelectors).toEqual(['#set-track', '#track-search']);
|
|
});
|
|
|
|
it('should validate complex state with both required and forbidden selectors', () => {
|
|
// Arrange - Simulate being on Cars page but Track page elements leaked through
|
|
const actualState = (_selector: string) => {
|
|
const presentSelectors = ['#add-car-button', '#cars-list', '#set-track'];
|
|
return presentSelectors.includes(selector);
|
|
};
|
|
|
|
// Act
|
|
const result = validator.validateState(actualState, {
|
|
expectedStep: 'cars',
|
|
requiredSelectors: ['#add-car-button', '#cars-list'],
|
|
forbiddenSelectors: ['#set-track', '#track-search']
|
|
});
|
|
|
|
// Assert
|
|
expect(result.isOk()).toBe(true);
|
|
const value = result.unwrap();
|
|
expect(value.isValid).toBe(false); // Invalid due to forbidden selector
|
|
expect(value.unexpectedSelectors).toEqual(['#set-track']);
|
|
expect(value.message).toContain('unexpected elements');
|
|
});
|
|
});
|
|
}); |