@elisra-devops/docgen-data-provider 1.139.0 → 1.140.0

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.
@@ -1162,73 +1162,158 @@ describe('TicketsDataProvider historical queries', () => {
1162
1162
  ).toBe(true);
1163
1163
  });
1164
1164
 
1165
- it('GetHistoricalQueryResults drops only the specific field ADO names in TF51535, keeping Custom.TestPhase when only Elisra.TestPhase is undefined for this project', async () => {
1165
+ it('GetHistoricalQueryResults resolves the real Test Phase reference name from the project\'s own field list instead of guessing', async () => {
1166
1166
  const asOfIso = '2026-02-01T00:00:00.000Z';
1167
- // 205 ids -> 2 chunks (200 + 5), both dispatched with the full field list
1168
- // near-simultaneously — this proves the retry is decided per-call, not
1169
- // from the shared override flag, since both chunks fail before either
1170
- // one sets it.
1171
- const allIds = Array.from({ length: 205 }, (_, idx) => idx + 1);
1172
1167
 
1173
1168
  (TFSServices.getItemContent as jest.Mock).mockImplementation(
1174
1169
  async (url: string, _pat: string, method?: string, data?: any) => {
1175
- if (url.includes('/_apis/wit/queries/q-unknown-field') && url.includes('api-version=7.1')) {
1176
- return { name: 'Unknown Field Q', wiql: 'SELECT [System.Id] FROM WorkItems' };
1170
+ if (url.includes('/_apis/wit/queries/q-resolve-field') && url.includes('api-version=7.1')) {
1171
+ return { name: 'Resolve Field Q', wiql: 'SELECT [System.Id] FROM WorkItems' };
1177
1172
  }
1178
1173
  if (url.includes('/_apis/wit/wiql?') && method === 'post') {
1179
- return { workItems: allIds.map((id) => ({ id })) };
1174
+ return { workItems: [{ id: 501 }] };
1175
+ }
1176
+ if (url.endsWith('/_apis/wit/fields?api-version=7.1')) {
1177
+ // Neither Elisra.TestPhase nor Custom.TestPhase — a third,
1178
+ // project-specific reference name, discovered only by friendly
1179
+ // name ("Test Phase").
1180
+ return {
1181
+ value: [
1182
+ { name: 'Title', referenceName: 'System.Title' },
1183
+ { name: 'Test Phase', referenceName: 'MyCompany.QaPhase' },
1184
+ ],
1185
+ };
1180
1186
  }
1181
1187
  if (url.includes('/_apis/wit/workitemsbatch') && method === 'post') {
1182
1188
  if (data?.$expand === 'Relations') {
1183
- return {
1184
- value: (Array.isArray(data?.ids) ? data.ids : []).map((id: number) => ({ id, relations: [] })),
1185
- };
1189
+ return { value: [{ id: 501, relations: [] }] };
1186
1190
  }
1187
- if (Array.isArray(data?.fields) && data.fields.includes('Elisra.TestPhase')) {
1188
- throw {
1189
- response: {
1190
- status: 400,
1191
- data: { message: "TF51535: Cannot find field 'Elisra.TestPhase'." },
1191
+ expect(data.fields).toEqual(expect.arrayContaining(['MyCompany.QaPhase']));
1192
+ expect(data.fields).not.toEqual(
1193
+ expect.arrayContaining(['Elisra.TestPhase', 'Custom.TestPhase']),
1194
+ );
1195
+ return {
1196
+ value: [
1197
+ {
1198
+ id: 501,
1199
+ rev: 1,
1200
+ fields: {
1201
+ 'System.WorkItemType': 'Test Case',
1202
+ 'System.Title': 'Resolved',
1203
+ 'System.State': 'Active',
1204
+ 'System.ChangedDate': asOfIso,
1205
+ 'MyCompany.QaPhase': 'FAT',
1206
+ },
1192
1207
  },
1193
- };
1208
+ ],
1209
+ };
1210
+ }
1211
+ throw new Error(`unexpected URL: ${url}`);
1212
+ },
1213
+ );
1214
+
1215
+ const result = await provider.GetHistoricalQueryResults('q-resolve-field', project, asOfIso);
1216
+
1217
+ expect(result.total).toBe(1);
1218
+ const fieldsListCalls = (TFSServices.getItemContent as jest.Mock).mock.calls.filter((call) =>
1219
+ String(call[0]).endsWith('/_apis/wit/fields?api-version=7.1'),
1220
+ );
1221
+ expect(fieldsListCalls).toHaveLength(1);
1222
+ });
1223
+
1224
+ it('GetHistoricalQueryResults reuses the resolved field across baseline and compareTo without re-querying fields', async () => {
1225
+ const baselineIso = '2026-02-20T00:00:00.000Z';
1226
+ const compareIso = '2026-02-25T00:00:00.000Z';
1227
+ let fieldsListCallCount = 0;
1228
+
1229
+ (TFSServices.getItemContent as jest.Mock).mockImplementation(
1230
+ async (url: string, _pat: string, method?: string, data?: any) => {
1231
+ if (url.includes('/_apis/wit/queries/q-cache-field') && url.includes('api-version=7.1')) {
1232
+ return { name: 'Cache Field Q', wiql: 'SELECT [System.Id] FROM WorkItems' };
1233
+ }
1234
+ if (url.includes('/_apis/wit/wiql?') && method === 'post') {
1235
+ return { workItems: [{ id: 601 }] };
1236
+ }
1237
+ if (url.endsWith('/_apis/wit/fields?api-version=7.1')) {
1238
+ fieldsListCallCount += 1;
1239
+ return { value: [{ name: 'Test Phase', referenceName: 'Custom.TestPhase' }] };
1240
+ }
1241
+ if (url.includes('/_apis/wit/workitemsbatch') && method === 'post') {
1242
+ if (data?.$expand === 'Relations') {
1243
+ return { value: [{ id: 601, relations: [] }] };
1194
1244
  }
1195
- // Custom.TestPhase is the real field on this project and must
1196
- // still be requested — only the unrecognized alias should be
1197
- // dropped, not every optional field.
1198
- expect(data.fields).toEqual(expect.arrayContaining(['Custom.TestPhase']));
1199
- expect(data.fields).not.toEqual(expect.arrayContaining(['Elisra.TestPhase']));
1200
1245
  return {
1201
- value: (Array.isArray(data?.ids) ? data.ids : []).map((id: number) => ({
1202
- id,
1203
- rev: 1,
1204
- fields: {
1205
- 'System.WorkItemType': 'Test Case',
1206
- 'System.Title': `Test ${id}`,
1207
- 'System.State': 'Active',
1208
- 'System.ChangedDate': asOfIso,
1209
- 'Custom.TestPhase': 'FAT',
1246
+ value: [
1247
+ {
1248
+ id: 601,
1249
+ rev: 1,
1250
+ fields: {
1251
+ 'System.WorkItemType': 'Test Case',
1252
+ 'System.Title': 'Cached',
1253
+ 'System.State': 'Active',
1254
+ 'System.ChangedDate': data.asOf,
1255
+ },
1210
1256
  },
1211
- })),
1257
+ ],
1212
1258
  };
1213
1259
  }
1214
1260
  throw new Error(`unexpected URL: ${url}`);
1215
1261
  },
1216
1262
  );
1217
1263
 
1218
- const result = await provider.GetHistoricalQueryResults('q-unknown-field', project, asOfIso);
1264
+ await provider.CompareHistoricalQueryResults('q-cache-field', project, baselineIso, compareIso);
1219
1265
 
1220
- // Every id came back — nothing fell to the 2xN per-item fallback, which
1221
- // would have thrown on any call not covered by the handler above.
1222
- expect(result.total).toBe(205);
1223
- const fieldsCallsWithElisraAlias = (TFSServices.getItemContent as jest.Mock).mock.calls.filter(
1224
- (call) => Array.isArray(call[3]?.fields) && call[3].fields.includes('Elisra.TestPhase'),
1266
+ // Baseline and compareTo run concurrently against the same provider
1267
+ // instance — the field list is fetched once, not once per snapshot.
1268
+ expect(fieldsListCallCount).toBe(1);
1269
+ });
1270
+
1271
+ it('GetHistoricalQueryResults omits Test Phase entirely when the project defines neither known name, without failing the batch', async () => {
1272
+ const asOfIso = '2026-03-01T00:00:00.000Z';
1273
+
1274
+ (TFSServices.getItemContent as jest.Mock).mockImplementation(
1275
+ async (url: string, _pat: string, method?: string, data?: any) => {
1276
+ if (url.includes('/_apis/wit/queries/q-no-field') && url.includes('api-version=7.1')) {
1277
+ return { name: 'No Field Q', wiql: 'SELECT [System.Id] FROM WorkItems' };
1278
+ }
1279
+ if (url.includes('/_apis/wit/wiql?') && method === 'post') {
1280
+ return { workItems: [{ id: 701 }] };
1281
+ }
1282
+ if (url.endsWith('/_apis/wit/fields?api-version=7.1')) {
1283
+ return { value: [{ name: 'Title', referenceName: 'System.Title' }] };
1284
+ }
1285
+ if (url.includes('/_apis/wit/workitemsbatch') && method === 'post') {
1286
+ if (data?.$expand === 'Relations') {
1287
+ return { value: [{ id: 701, relations: [] }] };
1288
+ }
1289
+ expect(data.fields).not.toEqual(
1290
+ expect.arrayContaining(['Elisra.TestPhase', 'Custom.TestPhase']),
1291
+ );
1292
+ return {
1293
+ value: [
1294
+ {
1295
+ id: 701,
1296
+ rev: 1,
1297
+ fields: {
1298
+ 'System.WorkItemType': 'Bug',
1299
+ 'System.Title': 'No test phase field',
1300
+ 'System.State': 'Active',
1301
+ 'System.ChangedDate': asOfIso,
1302
+ },
1303
+ },
1304
+ ],
1305
+ };
1306
+ }
1307
+ throw new Error(`unexpected URL: ${url}`);
1308
+ },
1225
1309
  );
1226
- // Both chunks start with the full field list before the override is set,
1227
- // so both legitimately fail once and both must retry — not just one.
1228
- expect(fieldsCallsWithElisraAlias).toHaveLength(2);
1310
+
1311
+ const result = await provider.GetHistoricalQueryResults('q-no-field', project, asOfIso);
1312
+
1313
+ expect(result.total).toBe(1);
1229
1314
  expect(
1230
1315
  (logger.warn as jest.Mock).mock.calls.some((call) =>
1231
- String(call[0]).includes("field 'Elisra.TestPhase' not defined for this project"),
1316
+ String(call[0]).includes("no Test Phase field defined for project"),
1232
1317
  ),
1233
1318
  ).toBe(true);
1234
1319
  });