haven-cypress-integration 2.0.0 → 2.0.1
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/package.json
CHANGED
|
@@ -243,6 +243,13 @@ if [ -f "${REPORT_HTML}" ]; then
|
|
|
243
243
|
cp "${REPORT_HTML}" "/shared/test-logs/report.html" || echo "Failed to copy HTML to shared volume"
|
|
244
244
|
fi
|
|
245
245
|
|
|
246
|
+
# Copy raw mochawesome reports for EC2 host to upload
|
|
247
|
+
if [ -d "${MOCHAWESOME_DIR}" ]; then
|
|
248
|
+
echo "Copying mochawesome reports to shared volume for EC2 upload..."
|
|
249
|
+
mkdir -p /shared/mochawesome-report
|
|
250
|
+
cp -r "${MOCHAWESOME_DIR}"/* /shared/mochawesome-report/ || echo "Failed to copy mochawesome reports"
|
|
251
|
+
fi
|
|
252
|
+
|
|
246
253
|
# Post results to HAVEN API
|
|
247
254
|
echo "Running syncCypressResults.js"
|
|
248
255
|
PLAN_ID="${PLAN_ID}" RUN_ID="${RUN_ID}" TEST_ENVIRONMENT="${TEST_ENVIRONMENT}" node /haven/syncCypressResults.js "${MERGED_JSON}" || echo "Result sync script finished with warnings"
|
|
@@ -7,6 +7,51 @@ const automationCasesPath = "/shared/automation-cases.json";
|
|
|
7
7
|
const postBaseUrlPath = "/shared/result-post-url.txt";
|
|
8
8
|
const triggeredByPath = "/shared/triggered-by.txt";
|
|
9
9
|
|
|
10
|
+
// Cache for spec file tag mappings
|
|
11
|
+
const specTagsCache = new Map();
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Parse a Cypress spec file to extract test title -> automation ID mappings
|
|
15
|
+
* Looks for patterns like: it('Test title', { tags: ['@TC-AUTO-xxx'] }, () => {
|
|
16
|
+
*/
|
|
17
|
+
function parseSpecFileForTags(specFilePath) {
|
|
18
|
+
if (specTagsCache.has(specFilePath)) {
|
|
19
|
+
return specTagsCache.get(specFilePath);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const titleToAutomationIds = new Map();
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const content = fs.readFileSync(specFilePath, 'utf-8');
|
|
26
|
+
|
|
27
|
+
// Match it() calls with tags - handles both single and double quotes
|
|
28
|
+
// Pattern: it('title' or it("title", { tags: [...] }
|
|
29
|
+
const itRegex = /it\s*\(\s*(['"`])([^'"`]+)\1\s*,\s*\{\s*tags\s*:\s*\[([^\]]+)\]/g;
|
|
30
|
+
|
|
31
|
+
let match;
|
|
32
|
+
while ((match = itRegex.exec(content)) !== null) {
|
|
33
|
+
const testTitle = match[2];
|
|
34
|
+
const tagsStr = match[3];
|
|
35
|
+
|
|
36
|
+
// Extract TC-AUTO tags from the tags array string
|
|
37
|
+
const automationIds = [];
|
|
38
|
+
const tagMatches = tagsStr.match(/@?TC-AUTO-[\w.-]+/g) || [];
|
|
39
|
+
tagMatches.forEach(tag => {
|
|
40
|
+
automationIds.push(tag.replace(/['"]/g, ''));
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
if (automationIds.length > 0) {
|
|
44
|
+
titleToAutomationIds.set(testTitle, automationIds);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
} catch (err) {
|
|
48
|
+
console.warn(`Could not parse spec file ${specFilePath}:`, err.message);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
specTagsCache.set(specFilePath, titleToAutomationIds);
|
|
52
|
+
return titleToAutomationIds;
|
|
53
|
+
}
|
|
54
|
+
|
|
10
55
|
const baseUrl = fs.readFileSync(postBaseUrlPath, "utf-8").trim();
|
|
11
56
|
let triggeredBy = null;
|
|
12
57
|
try {
|
|
@@ -72,13 +117,35 @@ function parseMochawesomeJson(jsonPath) {
|
|
|
72
117
|
}
|
|
73
118
|
}
|
|
74
119
|
|
|
75
|
-
function walkSuites(suite) {
|
|
76
|
-
|
|
77
|
-
|
|
120
|
+
function walkSuites(suite, specFilePath) {
|
|
121
|
+
// Get spec file path from suite or use passed-in path
|
|
122
|
+
const currentSpecPath = suite.fullFile || suite.file || specFilePath;
|
|
123
|
+
collectTests(suite.tests, currentSpecPath);
|
|
124
|
+
(suite.suites || []).forEach(s => walkSuites(s, currentSpecPath));
|
|
78
125
|
}
|
|
79
126
|
|
|
80
|
-
function collectTests(tests) {
|
|
127
|
+
function collectTests(tests, specFilePath) {
|
|
128
|
+
// Get tag mappings from spec file if available
|
|
129
|
+
let specTagMap = new Map();
|
|
130
|
+
if (specFilePath) {
|
|
131
|
+
// Try multiple possible paths for the spec file
|
|
132
|
+
const possiblePaths = [
|
|
133
|
+
specFilePath,
|
|
134
|
+
path.resolve(specFilePath),
|
|
135
|
+
path.resolve('/app', specFilePath),
|
|
136
|
+
path.resolve(process.cwd(), specFilePath)
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
for (const tryPath of possiblePaths) {
|
|
140
|
+
if (fs.existsSync(tryPath)) {
|
|
141
|
+
specTagMap = parseSpecFileForTags(tryPath);
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
81
147
|
(tests || []).forEach((test) => {
|
|
148
|
+
const testTitle = test.title;
|
|
82
149
|
const titleCombined =
|
|
83
150
|
typeof test.fullTitle === "string"
|
|
84
151
|
? test.fullTitle
|
|
@@ -86,8 +153,38 @@ function parseMochawesomeJson(jsonPath) {
|
|
|
86
153
|
? test.title.join(" ")
|
|
87
154
|
: test.title;
|
|
88
155
|
|
|
89
|
-
// Extract automation IDs from title
|
|
90
|
-
|
|
156
|
+
// Extract automation IDs from title first
|
|
157
|
+
let automationIdMatch = titleCombined.match(/@?TC-AUTO-[\w.-]+/g) || [];
|
|
158
|
+
|
|
159
|
+
// If not found in title, try looking up from spec file tags
|
|
160
|
+
if (automationIdMatch.length === 0 && specTagMap.has(testTitle)) {
|
|
161
|
+
automationIdMatch = specTagMap.get(testTitle);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Also check mochawesome context for automation IDs (added via addContext)
|
|
165
|
+
if (test.context && automationIdMatch.length === 0) {
|
|
166
|
+
const contextArray = Array.isArray(test.context) ? test.context : [test.context];
|
|
167
|
+
for (const ctx of contextArray) {
|
|
168
|
+
if (ctx && ctx.title === 'automationIds' && Array.isArray(ctx.value)) {
|
|
169
|
+
automationIdMatch = ctx.value.filter(id => id.includes('TC-AUTO'));
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
// Handle string context that might contain JSON
|
|
173
|
+
if (typeof ctx === 'string') {
|
|
174
|
+
try {
|
|
175
|
+
const parsed = JSON.parse(ctx);
|
|
176
|
+
if (parsed.title === 'automationIds' && Array.isArray(parsed.value)) {
|
|
177
|
+
automationIdMatch = parsed.value.filter(id => id.includes('TC-AUTO'));
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
} catch (e) {
|
|
181
|
+
// Not JSON, check if it's a direct automation ID
|
|
182
|
+
const match = ctx.match(/@?TC-AUTO-[\w.-]+/g);
|
|
183
|
+
if (match) automationIdMatch = match;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
91
188
|
|
|
92
189
|
const status =
|
|
93
190
|
test.state === "passed" || test.pass === true
|
|
@@ -104,7 +201,7 @@ function parseMochawesomeJson(jsonPath) {
|
|
|
104
201
|
});
|
|
105
202
|
}
|
|
106
203
|
|
|
107
|
-
(combinedResults.results || []).forEach(walkSuites);
|
|
204
|
+
(combinedResults.results || []).forEach(suite => walkSuites(suite, null));
|
|
108
205
|
return { results, foundIds };
|
|
109
206
|
}
|
|
110
207
|
|