-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add union types mapping * add unit tests
- Loading branch information
1 parent
5796fd5
commit 1fc941f
Showing
7 changed files
with
264 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/** | ||
* @import { UnionSchema, FEStatement, Union } from "../../types/types" | ||
*/ | ||
|
||
const { getDefinitionNameFromReferencePath } = require('../helpers/referenceHelper'); | ||
const { joinInlineStatements } = require('../helpers/feStatementJoinHelper'); | ||
const { getDirectivesUsageStatement } = require('./directives'); | ||
|
||
/** | ||
* Map the union member types to a string. | ||
* | ||
* @param {Object} args - The arguments | ||
* @param {UnionMemberType[]} unionMemberTypes - The union member types with all properties | ||
* @return {string} | ||
*/ | ||
const getUnionMemberTypes = ({ unionMemberTypes }) => { | ||
return unionMemberTypes | ||
.map(unionMemberType => { | ||
if (unionMemberType.$ref) { | ||
return getDefinitionNameFromReferencePath({ referencePath: unionMemberType.$ref }); | ||
} | ||
}) | ||
.filter(Boolean) // Filter out empty subschemas when a user missed to add union member types | ||
.join(' | '); | ||
}; | ||
|
||
/** | ||
* Maps a union to an FEStatement. | ||
* | ||
* @param {Object} args - The arguments | ||
* @param {string} args.name - The name of the union. | ||
* @param {Union} args.union - The union object with all properties | ||
* @returns {FEStatement} | ||
*/ | ||
const mapUnion = ({ name, union }) => { | ||
const unionMemberTypes = getUnionMemberTypes({ unionMemberTypes: union.oneOf }); | ||
const unionDirectives = getDirectivesUsageStatement({ directives: union.typeDirectives }); | ||
return { | ||
statement: joinInlineStatements({ statements: ['union', name, unionDirectives, '=', unionMemberTypes] }), | ||
description: union.description, | ||
isActivated: union.isActivated, | ||
}; | ||
}; | ||
/** | ||
* Maps the union types to an array of FEStatement. | ||
* | ||
* @param {Object} args - The arguments | ||
* @param {UnionSchema} args.unions - The union types schema. | ||
* @return {FEStatement[]} | ||
*/ | ||
const getUnions = ({ unions }) => { | ||
return Object.entries(unions).map(([name, union]) => mapUnion({ name, union })); | ||
}; | ||
|
||
module.exports = { | ||
getUnionMemberTypes, | ||
mapUnion, | ||
getUnions, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
const { describe, it } = require('node:test'); | ||
const { strictEqual } = require('node:assert'); | ||
const { getDefinitionNameFromReferencePath } = require('../../../forward_engineering/helpers/referenceHelper'); | ||
|
||
describe('getDefinitionNameFromReferencePath', () => { | ||
it('should return the definition name from a reference path', () => { | ||
const referencePath = '#/model/definitions/Objects/User'; | ||
const result = getDefinitionNameFromReferencePath({ referencePath }); | ||
strictEqual(result, 'User'); | ||
}); | ||
|
||
it('should return the last element from a simple reference path', () => { | ||
const referencePath = '#/User'; | ||
const result = getDefinitionNameFromReferencePath({ referencePath }); | ||
strictEqual(result, 'User'); | ||
}); | ||
|
||
it('should return an empty string if the reference path is undefined', () => { | ||
const result = getDefinitionNameFromReferencePath({ referencePath: undefined }); | ||
strictEqual(result, ''); | ||
}); | ||
|
||
it('should return the correct name when reference path has multiple slashes', () => { | ||
const referencePath = '#/model/definitions/Objects/Account/User'; | ||
const result = getDefinitionNameFromReferencePath({ referencePath }); | ||
strictEqual(result, 'User'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
const { describe, it, mock, afterEach } = require('node:test'); | ||
const { strictEqual, deepStrictEqual } = require('node:assert'); | ||
|
||
const getDefinitionNameFromReferencePathMock = mock.fn(() => ''); | ||
const joinInlineStatementsMock = mock.fn(() => ''); | ||
const getDirectivesUsageStatementMock = mock.fn(() => ''); | ||
|
||
mock.module('../../../forward_engineering/helpers/referenceHelper', { | ||
namedExports: { | ||
getDefinitionNameFromReferencePath: getDefinitionNameFromReferencePathMock, | ||
}, | ||
}); | ||
|
||
mock.module('../../../forward_engineering/helpers/feStatementJoinHelper', { | ||
namedExports: { | ||
joinInlineStatements: joinInlineStatementsMock, | ||
}, | ||
}); | ||
|
||
mock.module('../../../forward_engineering/mappers/directives', { | ||
namedExports: { | ||
getDirectivesUsageStatement: getDirectivesUsageStatementMock, | ||
}, | ||
}); | ||
|
||
// This require should be after the mocks to ensure that the mocks are applied before the module is required | ||
const { getUnionMemberTypes, mapUnion, getUnions } = require('../../../forward_engineering/mappers/unions'); | ||
|
||
describe('getUnionMemberTypes', () => { | ||
afterEach(() => { | ||
getDefinitionNameFromReferencePathMock.mock.resetCalls(); | ||
joinInlineStatementsMock.mock.resetCalls(); | ||
getDirectivesUsageStatementMock.mock.resetCalls(); | ||
}); | ||
|
||
it('should return union member types as a string', () => { | ||
const unionMemberTypes = [{ $ref: '#/definitions/User' }, { $ref: '#/definitions/Account' }]; | ||
|
||
getDefinitionNameFromReferencePathMock.mock.mockImplementationOnce(() => 'User', 0); | ||
getDefinitionNameFromReferencePathMock.mock.mockImplementationOnce(() => 'Account', 1); | ||
|
||
const result = getUnionMemberTypes({ unionMemberTypes }); | ||
|
||
strictEqual(getDefinitionNameFromReferencePathMock.mock.calls.length, 2); | ||
strictEqual(result, 'User | Account'); | ||
}); | ||
|
||
it('should filter out empty union member types', () => { | ||
const unionMemberTypes = [{ $ref: '#/definitions/User' }, {}]; | ||
|
||
getDefinitionNameFromReferencePathMock.mock.mockImplementationOnce(() => 'User', 0); | ||
|
||
const result = getUnionMemberTypes({ unionMemberTypes }); | ||
|
||
strictEqual(getDefinitionNameFromReferencePathMock.mock.calls.length, 1); | ||
strictEqual(result, 'User'); | ||
}); | ||
}); | ||
|
||
describe('mapUnion', () => { | ||
afterEach(() => { | ||
getDefinitionNameFromReferencePathMock.mock.resetCalls(); | ||
joinInlineStatementsMock.mock.resetCalls(); | ||
getDirectivesUsageStatementMock.mock.resetCalls(); | ||
}); | ||
|
||
it('should map a union to an FEStatement', () => { | ||
const union = { | ||
oneOf: [{ $ref: '#/definitions/User' }], | ||
typeDirectives: [{ directiveFormat: 'Raw', rawDirective: '@directive' }], | ||
description: 'A union type', | ||
isActivated: true, | ||
}; | ||
|
||
getDefinitionNameFromReferencePathMock.mock.mockImplementationOnce(() => 'User'); | ||
getDirectivesUsageStatementMock.mock.mockImplementationOnce(() => '@directive'); | ||
joinInlineStatementsMock.mock.mockImplementationOnce(() => 'union UserUnion @directive = User'); | ||
|
||
const result = mapUnion({ name: 'UserUnion', union }); | ||
|
||
strictEqual(getDefinitionNameFromReferencePathMock.mock.calls.length, 1); | ||
strictEqual(getDirectivesUsageStatementMock.mock.calls.length, 1); | ||
strictEqual(joinInlineStatementsMock.mock.calls.length, 1); | ||
deepStrictEqual(result, { | ||
statement: 'union UserUnion @directive = User', | ||
description: 'A union type', | ||
isActivated: true, | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getUnions', () => { | ||
afterEach(() => { | ||
getDefinitionNameFromReferencePathMock.mock.resetCalls(); | ||
joinInlineStatementsMock.mock.resetCalls(); | ||
getDirectivesUsageStatementMock.mock.resetCalls(); | ||
}); | ||
|
||
it('should map union types to an array of FEStatement', () => { | ||
const unions = { | ||
UserUnion: { | ||
oneOf: [{ $ref: '#/definitions/User' }], | ||
typeDirectives: [{ directiveFormat: 'Raw', rawDirective: '@directive' }], | ||
description: 'A union type', | ||
isActivated: true, | ||
}, | ||
}; | ||
|
||
getDefinitionNameFromReferencePathMock.mock.mockImplementationOnce(() => 'User'); | ||
getDirectivesUsageStatementMock.mock.mockImplementationOnce(() => '@directive'); | ||
joinInlineStatementsMock.mock.mockImplementationOnce(() => 'union UserUnion @directive = User'); | ||
|
||
const result = getUnions({ unions }); | ||
deepStrictEqual(result, [ | ||
{ | ||
statement: 'union UserUnion @directive = User', | ||
description: 'A union type', | ||
isActivated: true, | ||
}, | ||
]); | ||
}); | ||
}); |