@elisra-devops/docgen-data-provider 1.138.0 → 1.139.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.
- package/bin/modules/TicketsDataProvider.d.ts +19 -0
- package/bin/modules/TicketsDataProvider.js +65 -10
- package/bin/modules/TicketsDataProvider.js.map +1 -1
- package/bin/tests/modules/ticketsDataProvider.historical.test.js +145 -0
- package/bin/tests/modules/ticketsDataProvider.historical.test.js.map +1 -1
- package/package.json +1 -1
- package/src/modules/TicketsDataProvider.ts +104 -28
- package/src/tests/modules/ticketsDataProvider.historical.test.ts +167 -0
|
@@ -202,6 +202,25 @@ export default class TicketsDataProvider {
|
|
|
202
202
|
}>;
|
|
203
203
|
private normalizeHistoricalAsOf;
|
|
204
204
|
private normalizeHistoricalCompareValue;
|
|
205
|
+
/**
|
|
206
|
+
* Stores rich-text fields (Description, Steps) with only whitespace trimmed, preserving markup
|
|
207
|
+
* so the report renderer can clean/render it faithfully. Equality between two snapshots must go
|
|
208
|
+
* through canonicalizeHistoricalRichTextForCompare instead of comparing this value directly.
|
|
209
|
+
*/
|
|
210
|
+
private rawHistoricalRichText;
|
|
211
|
+
/**
|
|
212
|
+
* Canonicalizes a rich-text field for equality comparison only. Intentionally identical to the
|
|
213
|
+
* whitespace collapse previously applied at storage time, so Changed/No-changes verdicts and
|
|
214
|
+
* summary counts are unaffected by storing the raw value for rendering.
|
|
215
|
+
*/
|
|
216
|
+
private canonicalizeHistoricalRichTextForCompare;
|
|
217
|
+
/**
|
|
218
|
+
* Parses baseline/compareTo Steps XML into per-step Action/Expected arrays for a changed test
|
|
219
|
+
* case, so the report can render readable steps instead of raw Steps XML. Best-effort: a parse
|
|
220
|
+
* failure (malformed XML, shared-step lookup error) must not fail the whole comparison, so it
|
|
221
|
+
* logs and falls back to leaving the caller with only the raw XML strings.
|
|
222
|
+
*/
|
|
223
|
+
private parseHistoricalStepsForDiff;
|
|
205
224
|
private normalizeTestPhaseValue;
|
|
206
225
|
private isTestCaseType;
|
|
207
226
|
private toHistoricalRevision;
|
|
@@ -8,6 +8,7 @@ const tfs_data_3 = require("../models/tfs-data");
|
|
|
8
8
|
const tfs_data_4 = require("../models/tfs-data");
|
|
9
9
|
const tfs_data_5 = require("../models/tfs-data");
|
|
10
10
|
const tfs_data_6 = require("../models/tfs-data");
|
|
11
|
+
const testStepParserHelper_1 = require("../utils/testStepParserHelper");
|
|
11
12
|
const logger_1 = require("../utils/logger");
|
|
12
13
|
const pLimit = require('p-limit');
|
|
13
14
|
const HISTORICAL_WIT_API_VERSIONS = ['7.1', '5.1', null];
|
|
@@ -1409,6 +1410,52 @@ class TicketsDataProvider {
|
|
|
1409
1410
|
}
|
|
1410
1411
|
return String(value).trim();
|
|
1411
1412
|
}
|
|
1413
|
+
/**
|
|
1414
|
+
* Stores rich-text fields (Description, Steps) with only whitespace trimmed, preserving markup
|
|
1415
|
+
* so the report renderer can clean/render it faithfully. Equality between two snapshots must go
|
|
1416
|
+
* through canonicalizeHistoricalRichTextForCompare instead of comparing this value directly.
|
|
1417
|
+
*/
|
|
1418
|
+
rawHistoricalRichText(value) {
|
|
1419
|
+
if (value == null) {
|
|
1420
|
+
return '';
|
|
1421
|
+
}
|
|
1422
|
+
if (typeof value === 'string') {
|
|
1423
|
+
return value.trim();
|
|
1424
|
+
}
|
|
1425
|
+
return this.normalizeHistoricalCompareValue(value);
|
|
1426
|
+
}
|
|
1427
|
+
/**
|
|
1428
|
+
* Canonicalizes a rich-text field for equality comparison only. Intentionally identical to the
|
|
1429
|
+
* whitespace collapse previously applied at storage time, so Changed/No-changes verdicts and
|
|
1430
|
+
* summary counts are unaffected by storing the raw value for rendering.
|
|
1431
|
+
*/
|
|
1432
|
+
canonicalizeHistoricalRichTextForCompare(value) {
|
|
1433
|
+
return this.normalizeHistoricalCompareValue(value);
|
|
1434
|
+
}
|
|
1435
|
+
/**
|
|
1436
|
+
* Parses baseline/compareTo Steps XML into per-step Action/Expected arrays for a changed test
|
|
1437
|
+
* case, so the report can render readable steps instead of raw Steps XML. Best-effort: a parse
|
|
1438
|
+
* failure (malformed XML, shared-step lookup error) must not fail the whole comparison, so it
|
|
1439
|
+
* logs and falls back to leaving the caller with only the raw XML strings.
|
|
1440
|
+
*/
|
|
1441
|
+
async parseHistoricalStepsForDiff(testStepParserHelper, baselineStepsXml, compareToStepsXml) {
|
|
1442
|
+
try {
|
|
1443
|
+
const emptyRevisionMap = new Map();
|
|
1444
|
+
const [baselineSteps, compareToSteps] = await Promise.all([
|
|
1445
|
+
baselineStepsXml
|
|
1446
|
+
? testStepParserHelper.parseTestSteps(baselineStepsXml, emptyRevisionMap)
|
|
1447
|
+
: Promise.resolve([]),
|
|
1448
|
+
compareToStepsXml
|
|
1449
|
+
? testStepParserHelper.parseTestSteps(compareToStepsXml, emptyRevisionMap)
|
|
1450
|
+
: Promise.resolve([]),
|
|
1451
|
+
]);
|
|
1452
|
+
return { baselineSteps, compareToSteps };
|
|
1453
|
+
}
|
|
1454
|
+
catch (err) {
|
|
1455
|
+
logger_1.default.warn(`Failed to parse historical Steps XML for diff rendering: ${(err === null || err === void 0 ? void 0 : err.message) || err}`);
|
|
1456
|
+
return null;
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1412
1459
|
normalizeTestPhaseValue(value) {
|
|
1413
1460
|
const rendered = this.normalizeHistoricalCompareValue(value);
|
|
1414
1461
|
if (!rendered) {
|
|
@@ -1780,8 +1827,8 @@ class TicketsDataProvider {
|
|
|
1780
1827
|
iterationPath: this.normalizeHistoricalCompareValue(fields['System.IterationPath']),
|
|
1781
1828
|
versionId: this.toHistoricalRevision((_d = workItem === null || workItem === void 0 ? void 0 : workItem.rev) !== null && _d !== void 0 ? _d : fields['System.Rev']),
|
|
1782
1829
|
versionTimestamp: this.normalizeHistoricalCompareValue(fields['System.ChangedDate']),
|
|
1783
|
-
description: this.
|
|
1784
|
-
steps: this.
|
|
1830
|
+
description: this.rawHistoricalRichText(fields['System.Description']),
|
|
1831
|
+
steps: this.rawHistoricalRichText(fields['Microsoft.VSTS.TCM.Steps']),
|
|
1785
1832
|
testPhase: this.normalizeTestPhaseValue(testPhaseRaw),
|
|
1786
1833
|
relatedLinkCount,
|
|
1787
1834
|
workItemUrl: `${this.orgUrl}${project}/_workitems/edit/${id}`,
|
|
@@ -1917,7 +1964,8 @@ class TicketsDataProvider {
|
|
|
1917
1964
|
...Array.from(compareTo.snapshotMap.keys()),
|
|
1918
1965
|
]);
|
|
1919
1966
|
const sortedIds = Array.from(allIds.values()).sort((a, b) => a - b);
|
|
1920
|
-
const
|
|
1967
|
+
const testStepParserHelper = new testStepParserHelper_1.default(this.orgUrl, this.token);
|
|
1968
|
+
const rows = await Promise.all(sortedIds.map(async (id) => {
|
|
1921
1969
|
const baselineRow = baseline.snapshotMap.get(id) || null;
|
|
1922
1970
|
const compareToRow = compareTo.snapshotMap.get(id) || null;
|
|
1923
1971
|
const workItemType = (compareToRow === null || compareToRow === void 0 ? void 0 : compareToRow.workItemType) || (baselineRow === null || baselineRow === void 0 ? void 0 : baselineRow.workItemType) || '';
|
|
@@ -1951,7 +1999,12 @@ class TicketsDataProvider {
|
|
|
1951
1999
|
const safeBaseline = baselineRow;
|
|
1952
2000
|
const safeCompareTo = compareToRow;
|
|
1953
2001
|
const changedFields = [];
|
|
1954
|
-
|
|
2002
|
+
const descriptionChanged = this.canonicalizeHistoricalRichTextForCompare(safeBaseline.description) !==
|
|
2003
|
+
this.canonicalizeHistoricalRichTextForCompare(safeCompareTo.description);
|
|
2004
|
+
const stepsChanged = isTestCase &&
|
|
2005
|
+
this.canonicalizeHistoricalRichTextForCompare(safeBaseline.steps) !==
|
|
2006
|
+
this.canonicalizeHistoricalRichTextForCompare(safeCompareTo.steps);
|
|
2007
|
+
if (descriptionChanged) {
|
|
1955
2008
|
changedFields.push('Description');
|
|
1956
2009
|
}
|
|
1957
2010
|
if (safeBaseline.title !== safeCompareTo.title) {
|
|
@@ -1960,7 +2013,7 @@ class TicketsDataProvider {
|
|
|
1960
2013
|
if (safeBaseline.state !== safeCompareTo.state) {
|
|
1961
2014
|
changedFields.push('State');
|
|
1962
2015
|
}
|
|
1963
|
-
if (
|
|
2016
|
+
if (stepsChanged) {
|
|
1964
2017
|
changedFields.push('Steps');
|
|
1965
2018
|
}
|
|
1966
2019
|
if (safeBaseline.testPhase !== safeCompareTo.testPhase) {
|
|
@@ -1969,7 +2022,7 @@ class TicketsDataProvider {
|
|
|
1969
2022
|
if (isTestCase && safeBaseline.relatedLinkCount !== safeCompareTo.relatedLinkCount) {
|
|
1970
2023
|
changedFields.push('Related Link Count');
|
|
1971
2024
|
}
|
|
1972
|
-
const differences = changedFields.map((field) => {
|
|
2025
|
+
const differences = await Promise.all(changedFields.map(async (field) => {
|
|
1973
2026
|
switch (field) {
|
|
1974
2027
|
case 'Description':
|
|
1975
2028
|
return { field, baseline: safeBaseline.description, compareTo: safeCompareTo.description };
|
|
@@ -1977,8 +2030,10 @@ class TicketsDataProvider {
|
|
|
1977
2030
|
return { field, baseline: safeBaseline.title, compareTo: safeCompareTo.title };
|
|
1978
2031
|
case 'State':
|
|
1979
2032
|
return { field, baseline: safeBaseline.state, compareTo: safeCompareTo.state };
|
|
1980
|
-
case 'Steps':
|
|
1981
|
-
|
|
2033
|
+
case 'Steps': {
|
|
2034
|
+
const parsed = await this.parseHistoricalStepsForDiff(testStepParserHelper, safeBaseline.steps, safeCompareTo.steps);
|
|
2035
|
+
return Object.assign({ field, baseline: safeBaseline.steps, compareTo: safeCompareTo.steps }, (parsed || {}));
|
|
2036
|
+
}
|
|
1982
2037
|
case 'Test Phase':
|
|
1983
2038
|
return { field, baseline: safeBaseline.testPhase, compareTo: safeCompareTo.testPhase };
|
|
1984
2039
|
case 'Related Link Count':
|
|
@@ -1990,7 +2045,7 @@ class TicketsDataProvider {
|
|
|
1990
2045
|
default:
|
|
1991
2046
|
return { field, baseline: '', compareTo: '' };
|
|
1992
2047
|
}
|
|
1993
|
-
});
|
|
2048
|
+
}));
|
|
1994
2049
|
return {
|
|
1995
2050
|
id,
|
|
1996
2051
|
workItemType,
|
|
@@ -2002,7 +2057,7 @@ class TicketsDataProvider {
|
|
|
2002
2057
|
differences,
|
|
2003
2058
|
workItemUrl: safeCompareTo.workItemUrl || safeBaseline.workItemUrl,
|
|
2004
2059
|
};
|
|
2005
|
-
});
|
|
2060
|
+
}));
|
|
2006
2061
|
const summary = rows.reduce((acc, row) => {
|
|
2007
2062
|
if (row.compareStatus === 'Added')
|
|
2008
2063
|
acc.addedCount += 1;
|