|
| 1 | +import { Test, TestingModule } from '@nestjs/testing'; |
1 | 2 | import { IdentitiesValidationService } from './identities.validation.service'; |
2 | | -import * as yup from 'yup'; |
3 | | -import fs from 'fs'; |
4 | | -import yaml from 'yaml'; |
| 3 | +import * as fs from 'fs'; |
| 4 | +import { ValidationConfigException, ValidationSchemaException } from '~/_common/errors/ValidationException'; |
| 5 | +import { |
| 6 | + invalidObjectClassAdditionalFieldsStub, |
| 7 | + invalidRequiredAdditionalFieldsStub, |
| 8 | + invalidTypeAdditionalFieldsStub, |
| 9 | + missingAttributeAdditionalFieldsStub, |
| 10 | + validSchemaStub, |
| 11 | + validAdditionalFieldsStub, |
| 12 | +} from './_stubs/identities.validation.stub'; |
| 13 | +import Ajv from 'ajv'; |
| 14 | +import ajvErrors from 'ajv-errors'; |
5 | 15 |
|
6 | | -jest.mock('yup'); |
| 16 | +jest.mock('fs'); |
7 | 17 |
|
8 | 18 | describe('IdentitiesValidationService', () => { |
9 | 19 | let service: IdentitiesValidationService; |
| 20 | + let mockAjv: jest.Mocked<Ajv>; |
| 21 | + let mockFs: jest.Mocked<typeof fs>; |
10 | 22 |
|
11 | | - beforeEach(() => { |
12 | | - jest.spyOn(fs, 'readFileSync').mockReturnValue('valid yml content'); |
13 | | - jest.spyOn(fs, 'existsSync').mockReturnValue(true); |
14 | | - jest.spyOn(yaml, 'parse').mockReturnValue({ attributes: [] }); |
15 | | - service = new IdentitiesValidationService(); |
| 23 | + beforeAll(() => {}); |
| 24 | + |
| 25 | + beforeEach(async () => { |
| 26 | + const module: TestingModule = await Test.createTestingModule({ |
| 27 | + providers: [IdentitiesValidationService], |
| 28 | + }).compile(); |
| 29 | + |
| 30 | + service = module.get<IdentitiesValidationService>(IdentitiesValidationService); |
| 31 | + |
| 32 | + mockAjv = new Ajv({ allErrors: true }) as jest.Mocked<Ajv>; |
| 33 | + ajvErrors(mockAjv); |
| 34 | + |
| 35 | + mockFs = fs as jest.Mocked<typeof fs>; |
| 36 | + mockFs.existsSync.mockReturnValue(true); |
| 37 | + mockFs.readFileSync.mockReturnValue(JSON.stringify(validSchemaStub)); |
| 38 | + }); |
| 39 | + |
| 40 | + afterEach(() => { |
16 | 41 | jest.clearAllMocks(); |
17 | 42 | }); |
18 | 43 |
|
19 | | - it('should reject when config file is missing', async () => { |
20 | | - jest.spyOn(fs, 'existsSync').mockReturnValue(false); |
21 | | - const data = { objectClasses: ['testClass'], attributes: { testClass: {} } }; |
22 | | - await expect(service.validate(data)).rejects.toMatchObject({ |
23 | | - message: 'Validation failed', |
| 44 | + describe('test Exceptions thrown', () => { |
| 45 | + describe('test ValidConfigException', () => { |
| 46 | + it('should throw ValidationConfigException for missing attributes', async () => { |
| 47 | + const data = missingAttributeAdditionalFieldsStub(); |
| 48 | + await expect(service.validate(data)).rejects.toThrow(ValidationConfigException); |
| 49 | + }); |
| 50 | + |
| 51 | + it('should throw ValidationConfigException when object class is not found in attributes', async () => { |
| 52 | + const data = invalidObjectClassAdditionalFieldsStub(); |
| 53 | + await expect(service.validate(data)).rejects.toThrow(ValidationConfigException); |
| 54 | + }); |
| 55 | + |
| 56 | + it('should throw ValidationConfigException for not found schema', async () => { |
| 57 | + mockFs.existsSync.mockReturnValue(false); |
| 58 | + const data = validAdditionalFieldsStub(); |
| 59 | + await expect(service.validate(data)).rejects.toThrow(ValidationConfigException); |
| 60 | + }); |
| 61 | + |
| 62 | + it('should throw ValidationConfigException for invalid schema', async () => { |
| 63 | + mockFs.readFileSync.mockReturnValue('invalid content'); |
| 64 | + const data = validAdditionalFieldsStub(); |
| 65 | + await expect(service.validate(data)).rejects.toThrow(ValidationConfigException); |
| 66 | + }); |
24 | 67 | }); |
25 | | - }); |
26 | 68 |
|
27 | | - it('should reject when object class is not found in attributes', async () => { |
28 | | - jest.spyOn(fs, 'existsSync').mockReturnValue(true); |
29 | | - jest.spyOn(yaml, 'parse').mockReturnValue({ attributes: [] }); // Mocked schema |
30 | | - const data = { objectClasses: ['testClass'], attributes: { supann: { test: 'test' } } }; |
31 | | - await expect(service.validate(data)).rejects.toMatchObject({ |
32 | | - message: 'Validation failed', |
| 69 | + describe('test ValidationSchemaException', () => { |
| 70 | + it('should throw ValidationSchemaException for invalid required attribute', async () => { |
| 71 | + const data = invalidRequiredAdditionalFieldsStub(); |
| 72 | + await expect(service.validate(data)).rejects.toThrow(ValidationSchemaException); |
| 73 | + }); |
| 74 | + |
| 75 | + it('should throw ValidationSchemaException for invalid attribute type', async () => { |
| 76 | + const data = invalidTypeAdditionalFieldsStub(); |
| 77 | + await expect(service.validate(data)).rejects.toThrow(ValidationSchemaException); |
| 78 | + }); |
33 | 79 | }); |
34 | 80 | }); |
35 | 81 |
|
36 | | - it('should reject on yup schema validation error', async () => { |
37 | | - jest.spyOn(fs, 'existsSync').mockReturnValue(true); |
38 | | - jest.spyOn(yaml, 'parse').mockReturnValue({ attributes: [] }); // Mocked schema |
39 | | - const mockYupObject = { validate: jest.fn() }; |
40 | | - const mockValidationError = new yup.ValidationError('error', {}, 'test'); |
41 | | - mockValidationError.inner = [ |
42 | | - { |
43 | | - path: 'test', |
44 | | - errors: ['error'], |
45 | | - value: 'test', |
46 | | - inner: [], |
47 | | - name: 'test', |
48 | | - message: 'test', |
49 | | - [Symbol.toStringTag]: 'test', |
50 | | - }, |
51 | | - ]; |
52 | | - mockValidationError.errors = ['error']; |
53 | | - mockYupObject.validate.mockRejectedValue(mockValidationError); |
54 | | - service.createSchema = jest.fn().mockResolvedValue(mockYupObject); |
55 | | - |
56 | | - const data = { objectClasses: ['testClass'], attributes: { testClass: {} } }; |
57 | | - await expect(service.validate(data)).rejects.toMatchObject({ |
58 | | - message: 'Validation failed', |
| 82 | + describe('validation success', () => { |
| 83 | + it('should validate additional fields successfully', async () => { |
| 84 | + const data = validAdditionalFieldsStub(); |
| 85 | + await expect(service.validate(data)).resolves.toEqual({ message: 'Validation succeeded' }); |
59 | 86 | }); |
60 | 87 | }); |
61 | 88 |
|
62 | | - it('should resolve on successful validation', async () => { |
63 | | - jest.spyOn(fs, 'existsSync').mockReturnValue(true); |
64 | | - jest.spyOn(yaml, 'parse').mockReturnValue({ attributes: [] }); // Mocked schema |
65 | | - const mockYupObject = { validate: jest.fn() }; |
66 | | - mockYupObject.validate.mockResolvedValue('validated'); |
67 | | - service.createSchema = jest.fn().mockResolvedValue(mockYupObject); |
68 | | - |
69 | | - const data = { objectClasses: ['testClass'], attributes: { testClass: {} } }; |
70 | | - await expect(service.validate(data)).resolves.toBeDefined(); |
| 89 | + describe('test validateAttribute', () => { |
| 90 | + it('should return null for a valid attribute', async () => { |
| 91 | + const key = validAdditionalFieldsStub().objectClasses[0]; |
| 92 | + const attribute = validAdditionalFieldsStub().attributes[key]; |
| 93 | + await expect(service.validateAttribute(key, attribute)).resolves.toBeNull(); |
| 94 | + }); |
71 | 95 | }); |
72 | 96 | }); |
73 | | - |
74 | | -// describe('createSchema', () => { |
75 | | -// let service: IdentitiesValidationService; |
76 | | - |
77 | | -// beforeEach(() => { |
78 | | -// service = new IdentitiesValidationService(); |
79 | | -// }); |
80 | | - |
81 | | -// it('should create a schema based on input attributes', async () => { |
82 | | -// const attributes = [{ name: 'test', type: 'string', required: true }]; |
83 | | -// const schema = await service.createSchema(attributes); |
84 | | -// expect(yup.object).toHaveBeenCalled(); |
85 | | -// expect(schema).toBeDefined(); |
86 | | -// }); |
87 | | -// }); |
|
0 commit comments