@elisra-devops/docgen-data-provider 1.136.4 → 1.136.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/modules/PipelinesDataProvider.d.ts +1 -1
- package/bin/modules/PipelinesDataProvider.js +11 -14
- package/bin/modules/PipelinesDataProvider.js.map +1 -1
- package/bin/modules/TicketsDataProvider.d.ts +2 -0
- package/bin/modules/TicketsDataProvider.js +45 -4
- package/bin/modules/TicketsDataProvider.js.map +1 -1
- package/bin/tests/modules/pipelineDataProvider.test.js +34 -10
- package/bin/tests/modules/pipelineDataProvider.test.js.map +1 -1
- package/bin/tests/modules/ticketsDataProvider.test.js +66 -0
- package/bin/tests/modules/ticketsDataProvider.test.js.map +1 -1
- package/package.json +1 -1
- package/src/modules/PipelinesDataProvider.ts +11 -14
- package/src/modules/TicketsDataProvider.ts +46 -4
- package/src/tests/modules/pipelineDataProvider.test.ts +43 -10
- package/src/tests/modules/ticketsDataProvider.test.ts +77 -0
|
@@ -951,23 +951,28 @@ describe('PipelinesDataProvider', () => {
|
|
|
951
951
|
});
|
|
952
952
|
|
|
953
953
|
describe('GetRecentReleaseArtifactInfo', () => {
|
|
954
|
-
it('should return empty array when no
|
|
954
|
+
it('should return empty array when release response has no artifacts', async () => {
|
|
955
955
|
// Arrange
|
|
956
956
|
const projectName = 'project1';
|
|
957
|
-
const
|
|
958
|
-
|
|
957
|
+
const releaseId = 123;
|
|
958
|
+
const mockReleaseResponse = { artifacts: [] };
|
|
959
|
+
(TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockReleaseResponse);
|
|
959
960
|
|
|
960
961
|
// Act
|
|
961
|
-
const result = await pipelinesDataProvider.GetRecentReleaseArtifactInfo(projectName);
|
|
962
|
+
const result = await pipelinesDataProvider.GetRecentReleaseArtifactInfo(projectName, releaseId);
|
|
962
963
|
|
|
963
964
|
// Assert
|
|
965
|
+
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
966
|
+
expect.stringContaining(`releases/${releaseId}`),
|
|
967
|
+
mockToken
|
|
968
|
+
);
|
|
964
969
|
expect(result).toEqual([]);
|
|
965
970
|
});
|
|
966
971
|
|
|
967
|
-
it('should return artifact info
|
|
972
|
+
it('should return artifact info for the specified release', async () => {
|
|
968
973
|
// Arrange
|
|
969
974
|
const projectName = 'project1';
|
|
970
|
-
const
|
|
975
|
+
const releaseId = 123;
|
|
971
976
|
const mockReleaseResponse = {
|
|
972
977
|
artifacts: [
|
|
973
978
|
{
|
|
@@ -978,16 +983,44 @@ describe('PipelinesDataProvider', () => {
|
|
|
978
983
|
},
|
|
979
984
|
],
|
|
980
985
|
};
|
|
981
|
-
(TFSServices.getItemContent as jest.Mock)
|
|
982
|
-
.mockResolvedValueOnce(mockReleasesResponse)
|
|
983
|
-
.mockResolvedValueOnce(mockReleaseResponse);
|
|
986
|
+
(TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockReleaseResponse);
|
|
984
987
|
|
|
985
988
|
// Act
|
|
986
|
-
const result = await pipelinesDataProvider.GetRecentReleaseArtifactInfo(projectName);
|
|
989
|
+
const result = await pipelinesDataProvider.GetRecentReleaseArtifactInfo(projectName, releaseId);
|
|
987
990
|
|
|
988
991
|
// Assert
|
|
989
992
|
expect(result).toEqual([{ artifactName: 'artifact1', artifactVersion: '1.0.0' }]);
|
|
990
993
|
});
|
|
994
|
+
|
|
995
|
+
it('should return empty array without calling the API when releaseId is invalid', async () => {
|
|
996
|
+
// Arrange
|
|
997
|
+
const projectName = 'project1';
|
|
998
|
+
|
|
999
|
+
// Act
|
|
1000
|
+
const resultForZero = await pipelinesDataProvider.GetRecentReleaseArtifactInfo(projectName, 0);
|
|
1001
|
+
const resultForNaN = await pipelinesDataProvider.GetRecentReleaseArtifactInfo(projectName, NaN);
|
|
1002
|
+
const resultForNegative = await pipelinesDataProvider.GetRecentReleaseArtifactInfo(projectName, -5);
|
|
1003
|
+
|
|
1004
|
+
// Assert
|
|
1005
|
+
expect(resultForZero).toEqual([]);
|
|
1006
|
+
expect(resultForNaN).toEqual([]);
|
|
1007
|
+
expect(resultForNegative).toEqual([]);
|
|
1008
|
+
expect(TFSServices.getItemContent).not.toHaveBeenCalled();
|
|
1009
|
+
});
|
|
1010
|
+
|
|
1011
|
+
it('should return empty array when release response has no artifacts field at all', async () => {
|
|
1012
|
+
// Arrange
|
|
1013
|
+
const projectName = 'project1';
|
|
1014
|
+
const releaseId = 123;
|
|
1015
|
+
const mockReleaseResponse = { id: releaseId, name: 'Release-1' };
|
|
1016
|
+
(TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockReleaseResponse);
|
|
1017
|
+
|
|
1018
|
+
// Act
|
|
1019
|
+
const result = await pipelinesDataProvider.GetRecentReleaseArtifactInfo(projectName, releaseId);
|
|
1020
|
+
|
|
1021
|
+
// Assert
|
|
1022
|
+
expect(result).toEqual([]);
|
|
1023
|
+
});
|
|
991
1024
|
});
|
|
992
1025
|
|
|
993
1026
|
describe('getPipelineResourcePipelinesFromObject', () => {
|
|
@@ -911,6 +911,44 @@ describe('TicketsDataProvider', () => {
|
|
|
911
911
|
),
|
|
912
912
|
).rejects.toThrow('Target relation is missing');
|
|
913
913
|
});
|
|
914
|
+
|
|
915
|
+
it('should order sourceTargetsMap by the query sortColumns (Node Name asc, Customer ID asc)', async () => {
|
|
916
|
+
// Root work items arrive in relation order 1, 2, 3 — sortColumns should reorder them
|
|
917
|
+
// by System.NodeName then CustomerRequirementId regardless of fetch order.
|
|
918
|
+
const rootFieldsById: Record<number, any> = {
|
|
919
|
+
1: { 'System.WorkItemType': 'Requirement', 'System.NodeName': 'B', CustomerRequirementId: 'C-20' },
|
|
920
|
+
2: { 'System.WorkItemType': 'Requirement', 'System.NodeName': 'A', CustomerRequirementId: 'C-10' },
|
|
921
|
+
3: { 'System.WorkItemType': 'Requirement', 'System.NodeName': 'A', CustomerRequirementId: 'C-5' },
|
|
922
|
+
};
|
|
923
|
+
jest
|
|
924
|
+
.spyOn(ticketsDataProvider as any, 'fetchWIForQueryResult')
|
|
925
|
+
.mockImplementation(async (...args: any[]) => {
|
|
926
|
+
const rel = args[0];
|
|
927
|
+
const id = rel?.target?.id ?? rel?.source?.id;
|
|
928
|
+
return { id, fields: rootFieldsById[id] };
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
const res = await (ticketsDataProvider as any).parseDirectLinkedQueryResultForTableFormat(
|
|
932
|
+
{
|
|
933
|
+
queryType: QueryType.OneHop,
|
|
934
|
+
columns: [],
|
|
935
|
+
sortColumns: [
|
|
936
|
+
{ field: { referenceName: 'System.NodeName' }, descending: false },
|
|
937
|
+
{ field: { referenceName: 'CustomerRequirementId' }, descending: false },
|
|
938
|
+
],
|
|
939
|
+
workItemRelations: [
|
|
940
|
+
{ source: null, target: { id: 1 } },
|
|
941
|
+
{ source: null, target: { id: 2 } },
|
|
942
|
+
{ source: null, target: { id: 3 } },
|
|
943
|
+
],
|
|
944
|
+
} as any,
|
|
945
|
+
new Map(),
|
|
946
|
+
);
|
|
947
|
+
|
|
948
|
+
const orderedIds = Array.from(res.sourceTargetsMap.keys()).map((k: any) => k.id);
|
|
949
|
+
// Expect Node Name A-group (ids 3,2 sorted by Customer ID 5 then 10) before Node Name B (id 1)
|
|
950
|
+
expect(orderedIds).toEqual([3, 2, 1]);
|
|
951
|
+
});
|
|
914
952
|
});
|
|
915
953
|
|
|
916
954
|
describe('fetchWIForQueryResult', () => {
|
|
@@ -952,6 +990,45 @@ describe('TicketsDataProvider', () => {
|
|
|
952
990
|
});
|
|
953
991
|
});
|
|
954
992
|
|
|
993
|
+
describe('parseFlatQueryResultForTableFormat', () => {
|
|
994
|
+
it('should order fetchedWorkItems by the query sortColumns (Node Name asc, Customer ID asc)', async () => {
|
|
995
|
+
const fieldsById: Record<number, any> = {
|
|
996
|
+
1: { 'System.WorkItemType': 'Requirement', 'System.NodeName': 'B', CustomerRequirementId: 'C-20' },
|
|
997
|
+
2: { 'System.WorkItemType': 'Requirement', 'System.NodeName': 'A', CustomerRequirementId: 'C-10' },
|
|
998
|
+
3: { 'System.WorkItemType': 'Requirement', 'System.NodeName': 'A', CustomerRequirementId: 'C-5' },
|
|
999
|
+
};
|
|
1000
|
+
jest
|
|
1001
|
+
.spyOn(ticketsDataProvider as any, 'fetchWIForQueryResult')
|
|
1002
|
+
.mockImplementation(async (...args: any[]) => {
|
|
1003
|
+
const wi = args[0];
|
|
1004
|
+
return { id: wi.id, fields: fieldsById[wi.id] };
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
const res = await (ticketsDataProvider as any).parseFlatQueryResultForTableFormat({
|
|
1008
|
+
queryType: QueryType.Flat,
|
|
1009
|
+
columns: [{ referenceName: 'CustomerRequirementId', name: 'CustomerRequirementId' }],
|
|
1010
|
+
sortColumns: [
|
|
1011
|
+
{ field: { referenceName: 'System.NodeName' }, descending: false },
|
|
1012
|
+
{ field: { referenceName: 'CustomerRequirementId' }, descending: false },
|
|
1013
|
+
],
|
|
1014
|
+
workItems: [{ id: 1 }, { id: 2 }, { id: 3 }],
|
|
1015
|
+
} as any);
|
|
1016
|
+
|
|
1017
|
+
const orderedIds = res.fetchedWorkItems.map((wi: any) => wi.id);
|
|
1018
|
+
expect(orderedIds).toEqual([3, 2, 1]);
|
|
1019
|
+
});
|
|
1020
|
+
|
|
1021
|
+
it('should throw when workItems is an empty array', async () => {
|
|
1022
|
+
await expect(
|
|
1023
|
+
(ticketsDataProvider as any).parseFlatQueryResultForTableFormat({
|
|
1024
|
+
queryType: QueryType.Flat,
|
|
1025
|
+
columns: [],
|
|
1026
|
+
workItems: [],
|
|
1027
|
+
} as any),
|
|
1028
|
+
).rejects.toThrow('No work items were found');
|
|
1029
|
+
});
|
|
1030
|
+
});
|
|
1031
|
+
|
|
955
1032
|
describe('isFlatQueryAllowedByTypeOrId', () => {
|
|
956
1033
|
it('should accept when allowedTypes is empty and WIQL references [System.WorkItemType]', async () => {
|
|
957
1034
|
const wiql = "SELECT * FROM WorkItems WHERE [System.WorkItemType] = 'Bug'";
|