@testomatio/reporter 2.7.8 → 2.7.9-beta.1-markdown
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/lib/bin/cli.js +1 -1
- package/lib/constants.d.ts +7 -0
- package/lib/constants.js +13 -1
- package/lib/pipe/debug.d.ts +2 -0
- package/lib/pipe/debug.js +29 -13
- package/lib/pipe/html.js +21 -108
- package/lib/pipe/index.js +2 -0
- package/lib/pipe/markdown.d.ts +25 -0
- package/lib/pipe/markdown.js +698 -0
- package/lib/replay.d.ts +2 -1
- package/lib/replay.js +20 -15
- package/lib/template/testomatio.hbs +0 -2
- package/lib/utils/debug.d.ts +12 -0
- package/lib/utils/debug.js +27 -0
- package/package.json +1 -1
- package/src/bin/cli.js +2 -2
- package/src/constants.js +10 -0
- package/src/pipe/debug.js +27 -13
- package/src/pipe/html.js +18 -108
- package/src/pipe/index.js +2 -0
- package/src/pipe/markdown.js +743 -0
- package/src/replay.js +23 -17
- package/src/template/testomatio.hbs +0 -2
- package/src/utils/debug.js +20 -0
- package/types/types.d.ts +5 -0
package/lib/bin/cli.js
CHANGED
|
@@ -310,7 +310,7 @@ program
|
|
|
310
310
|
program
|
|
311
311
|
.command('replay')
|
|
312
312
|
.description('Replay test data from debug file and re-send to Testomat.io')
|
|
313
|
-
.argument('[debug-file]',
|
|
313
|
+
.argument('[debug-file]', `Path to debug file. Defaults to ./${constants_js_1.DEBUG_FILE}.json`)
|
|
314
314
|
.option('--dry-run', 'Preview the data without sending to Testomat.io')
|
|
315
315
|
.action(async (debugFile, opts) => {
|
|
316
316
|
try {
|
package/lib/constants.d.ts
CHANGED
|
@@ -15,6 +15,12 @@ export namespace HTML_REPORT {
|
|
|
15
15
|
let REPORT_DEFAULT_NAME: string;
|
|
16
16
|
let TEMPLATE_NAME: string;
|
|
17
17
|
}
|
|
18
|
+
export namespace MARKDOWN_REPORT {
|
|
19
|
+
let FOLDER_1: string;
|
|
20
|
+
export { FOLDER_1 as FOLDER };
|
|
21
|
+
let REPORT_DEFAULT_NAME_1: string;
|
|
22
|
+
export { REPORT_DEFAULT_NAME_1 as REPORT_DEFAULT_NAME };
|
|
23
|
+
}
|
|
18
24
|
export const REQUEST_TIMEOUT: number;
|
|
19
25
|
export function getCreateRunRequestTimeout(): number;
|
|
20
26
|
export const testomatLogoURL: "https://avatars.githubusercontent.com/u/59105116?s=36&v=4";
|
|
@@ -25,3 +31,4 @@ export namespace REPORTER_REQUEST_RETRIES {
|
|
|
25
31
|
let withinTimeSeconds: number;
|
|
26
32
|
}
|
|
27
33
|
export const SCREENSHOTS_ON_STEPS: boolean;
|
|
34
|
+
export const DEBUG_FILE: "testomatio.debug";
|
package/lib/constants.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.SCREENSHOTS_ON_STEPS = exports.REPORTER_REQUEST_RETRIES = exports.testomatLogoURL = exports.REQUEST_TIMEOUT = exports.HTML_REPORT = exports.STATUS = exports.CSV_HEADERS = exports.TESTOMAT_TMP_STORAGE_DIR = exports.APP_PREFIX = void 0;
|
|
6
|
+
exports.DEBUG_FILE = exports.SCREENSHOTS_ON_STEPS = exports.REPORTER_REQUEST_RETRIES = exports.testomatLogoURL = exports.REQUEST_TIMEOUT = exports.MARKDOWN_REPORT = exports.HTML_REPORT = exports.STATUS = exports.CSV_HEADERS = exports.TESTOMAT_TMP_STORAGE_DIR = exports.APP_PREFIX = void 0;
|
|
7
7
|
exports.getCreateRunRequestTimeout = getCreateRunRequestTimeout;
|
|
8
8
|
const picocolors_1 = __importDefault(require("picocolors"));
|
|
9
9
|
const os_1 = __importDefault(require("os"));
|
|
@@ -44,6 +44,12 @@ const HTML_REPORT = {
|
|
|
44
44
|
TEMPLATE_NAME: 'testomatio.hbs',
|
|
45
45
|
};
|
|
46
46
|
exports.HTML_REPORT = HTML_REPORT;
|
|
47
|
+
// markdown pipe var
|
|
48
|
+
const MARKDOWN_REPORT = {
|
|
49
|
+
FOLDER: 'md-report',
|
|
50
|
+
REPORT_DEFAULT_NAME: 'testomatio-report.md',
|
|
51
|
+
};
|
|
52
|
+
exports.MARKDOWN_REPORT = MARKDOWN_REPORT;
|
|
47
53
|
const testomatLogoURL = 'https://avatars.githubusercontent.com/u/59105116?s=36&v=4';
|
|
48
54
|
exports.testomatLogoURL = testomatLogoURL;
|
|
49
55
|
const REPORTER_REQUEST_RETRIES = {
|
|
@@ -53,6 +59,8 @@ const REPORTER_REQUEST_RETRIES = {
|
|
|
53
59
|
withinTimeSeconds: Number(process.env.TESTOMATIO_MAX_REQUEST_RETRIES_WITHIN_TIME_SECONDS) || 60,
|
|
54
60
|
};
|
|
55
61
|
exports.REPORTER_REQUEST_RETRIES = REPORTER_REQUEST_RETRIES;
|
|
62
|
+
const DEBUG_FILE = 'testomatio.debug';
|
|
63
|
+
exports.DEBUG_FILE = DEBUG_FILE;
|
|
56
64
|
function getCreateRunRequestTimeout() {
|
|
57
65
|
return Math.max(REQUEST_TIMEOUT, 80 * 1000);
|
|
58
66
|
}
|
|
@@ -73,6 +81,10 @@ module.exports.STATUS = STATUS;
|
|
|
73
81
|
|
|
74
82
|
module.exports.HTML_REPORT = HTML_REPORT;
|
|
75
83
|
|
|
84
|
+
module.exports.MARKDOWN_REPORT = MARKDOWN_REPORT;
|
|
85
|
+
|
|
76
86
|
module.exports.testomatLogoURL = testomatLogoURL;
|
|
77
87
|
|
|
78
88
|
module.exports.REPORTER_REQUEST_RETRIES = REPORTER_REQUEST_RETRIES;
|
|
89
|
+
|
|
90
|
+
module.exports.DEBUG_FILE = DEBUG_FILE;
|
package/lib/pipe/debug.d.ts
CHANGED
package/lib/pipe/debug.js
CHANGED
|
@@ -6,10 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.DebugPipe = void 0;
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const os_1 = __importDefault(require("os"));
|
|
10
9
|
const debug_1 = __importDefault(require("debug"));
|
|
11
10
|
const pretty_ms_1 = __importDefault(require("pretty-ms"));
|
|
12
11
|
const log_js_1 = require("../utils/log.js");
|
|
12
|
+
const debug_js_1 = require("../utils/debug.js");
|
|
13
13
|
const debug = (0, debug_1.default)('@testomatio/reporter:pipe:debug');
|
|
14
14
|
class DebugPipe {
|
|
15
15
|
constructor(params, store) {
|
|
@@ -24,22 +24,34 @@ class DebugPipe {
|
|
|
24
24
|
tests: [],
|
|
25
25
|
batchIndex: 0,
|
|
26
26
|
};
|
|
27
|
-
|
|
27
|
+
const suffix = process.env.TESTOMATIO_REPLAY ? 'replay' : '';
|
|
28
|
+
const paths = (0, debug_js_1.getDebugFilePath)(suffix);
|
|
29
|
+
this.logFilePath = paths.tmp;
|
|
30
|
+
this.rootPath = paths.root;
|
|
31
|
+
this.historyDir = path_1.default.dirname(paths.tmp);
|
|
28
32
|
debug('Creating debug file:', this.logFilePath);
|
|
29
33
|
fs_1.default.writeFileSync(this.logFilePath, '');
|
|
30
|
-
// Create symlink
|
|
31
|
-
|
|
34
|
+
// Create symlink in project root pointing to the timestamped debug file.
|
|
35
|
+
// Symlinks may fail on Windows without admin / on filesystems that don't support them;
|
|
36
|
+
// fall back to printing the actual tmp path so the user-facing log isn't misleading.
|
|
32
37
|
try {
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
// Use lstatSync (not existsSync) so we also detect dangling symlinks —
|
|
39
|
+
// existsSync follows links and returns false when the target is gone,
|
|
40
|
+
// which would leave a stale symlink in place and make symlinkSync fail with EEXIST.
|
|
41
|
+
try {
|
|
42
|
+
fs_1.default.lstatSync(paths.root);
|
|
43
|
+
fs_1.default.unlinkSync(paths.root);
|
|
36
44
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
catch (e) {
|
|
46
|
+
if (e.code !== 'ENOENT')
|
|
47
|
+
throw e;
|
|
48
|
+
}
|
|
49
|
+
fs_1.default.symlinkSync(this.logFilePath, paths.root);
|
|
50
|
+
debug('Created symlink:', paths.root, '->', this.logFilePath);
|
|
40
51
|
}
|
|
41
52
|
catch (err) {
|
|
42
|
-
debug('Failed to create symlink:', err.message);
|
|
53
|
+
debug('Failed to create symlink, using tmp path directly:', err.message);
|
|
54
|
+
this.rootPath = this.logFilePath;
|
|
43
55
|
}
|
|
44
56
|
log_js_1.log.info('🪲 Debug file created');
|
|
45
57
|
this.testomatioEnvVars = Object.keys(process.env)
|
|
@@ -117,8 +129,12 @@ class DebugPipe {
|
|
|
117
129
|
await this.sync();
|
|
118
130
|
if (this.batch.intervalFunction)
|
|
119
131
|
clearInterval(this.batch.intervalFunction);
|
|
120
|
-
|
|
121
|
-
|
|
132
|
+
const logData = { action: 'finishRun', params };
|
|
133
|
+
if (this.store.runId)
|
|
134
|
+
logData.runId = this.store.runId;
|
|
135
|
+
this.logToFile(logData);
|
|
136
|
+
log_js_1.log.info(`🪲 Debug file: ${this.rootPath}`);
|
|
137
|
+
log_js_1.log.info(`History: ${this.historyDir}`);
|
|
122
138
|
}
|
|
123
139
|
async sync() {
|
|
124
140
|
if (!this.isEnabled)
|
package/lib/pipe/html.js
CHANGED
|
@@ -760,116 +760,29 @@ function dropISayEcho(lines) {
|
|
|
760
760
|
}
|
|
761
761
|
return out;
|
|
762
762
|
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
* @returns {Object} Object with TESTOMATIO_ and S3_ variables grouped
|
|
767
|
-
*/
|
|
768
|
-
function collectEnvironmentVariables() {
|
|
769
|
-
return getHardcodedEnvVars();
|
|
763
|
+
const SENSITIVE_ENV_PATTERNS = [/TOKEN/, /SECRET/, /PASSWORD/, /KEY/, /^TESTOMATIO$/];
|
|
764
|
+
function isSensitiveEnvName(name) {
|
|
765
|
+
return SENSITIVE_ENV_PATTERNS.some(re => re.test(name));
|
|
770
766
|
}
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
else {
|
|
791
|
-
if (value !== undefined) {
|
|
792
|
-
result[key] = { value, description: config.description, isSet: true };
|
|
793
|
-
}
|
|
794
|
-
else {
|
|
795
|
-
result[key] = { value: '', description: config.description, isSet: false };
|
|
796
|
-
}
|
|
797
|
-
}
|
|
767
|
+
function collectEnvironmentVariables() {
|
|
768
|
+
const groups = { testomatio: {}, s3: {} };
|
|
769
|
+
for (const [name, value] of Object.entries(process.env)) {
|
|
770
|
+
if (value === undefined)
|
|
771
|
+
continue;
|
|
772
|
+
let group = null;
|
|
773
|
+
if (name === 'TESTOMATIO' || name.startsWith('TESTOMATIO_'))
|
|
774
|
+
group = 'testomatio';
|
|
775
|
+
else if (name.startsWith('S3_'))
|
|
776
|
+
group = 's3';
|
|
777
|
+
if (!group)
|
|
778
|
+
continue;
|
|
779
|
+
const isSensitive = isSensitiveEnvName(name);
|
|
780
|
+
let displayValue = value;
|
|
781
|
+
if (isSensitive)
|
|
782
|
+
displayValue = '***';
|
|
783
|
+
groups[group][name] = { value: displayValue, isSet: true, isSensitive };
|
|
798
784
|
}
|
|
799
|
-
return
|
|
800
|
-
}
|
|
801
|
-
/**
|
|
802
|
-
* Hardcoded environment variables stored in code
|
|
803
|
-
* This is the main source of truth for env vars to avoid file system dependencies
|
|
804
|
-
* @returns {Object} Object with TESTOMATIO_ and S3_ variables
|
|
805
|
-
*/
|
|
806
|
-
function getHardcodedEnvVars() {
|
|
807
|
-
const allVars = {
|
|
808
|
-
testomatio: {
|
|
809
|
-
TESTOMATIO: { description: 'API Key for Testomat.io' },
|
|
810
|
-
TESTOMATIO_API_KEY: { description: 'API Key (alias for TESTOMATIO)' },
|
|
811
|
-
TESTOMATIO_CREATE: { description: 'Create new tests in Testomat.io' },
|
|
812
|
-
TESTOMATIO_DEBUG: { description: 'Enable debug mode' },
|
|
813
|
-
TESTOMATIO_DISABLE_BATCH_UPLOAD: { description: 'Disable batch upload' },
|
|
814
|
-
TESTOMATIO_ENV: { description: 'Environment label (e.g., "Windows, Chrome")' },
|
|
815
|
-
TESTOMATIO_EXCLUDE_FILES_FROM_REPORT_GLOB_PATTERN: { description: 'Glob pattern to exclude files' },
|
|
816
|
-
TESTOMATIO_EXCLUDE_SKIPPED: { description: 'Exclude skipped tests from report' },
|
|
817
|
-
TESTOMATIO_FILENAME: { description: 'HTML report filename' },
|
|
818
|
-
TESTOMATIO_HTML_FILENAME: { description: 'HTML report filename' },
|
|
819
|
-
TESTOMATIO_HTML_REPORT_FOLDER: { description: 'Folder for HTML report' },
|
|
820
|
-
TESTOMATIO_HTML_REPORT_SAVE: { description: 'Save HTML report' },
|
|
821
|
-
TESTOMATIO_INTERCEPT_CONSOLE_LOGS: { description: 'Intercept console logs' },
|
|
822
|
-
TESTOMATIO_MARK_DETACHED: { description: 'Mark tests as detached' },
|
|
823
|
-
TESTOMATIO_MAX_REQUEST_FAILURES: { description: 'Max request failures' },
|
|
824
|
-
TESTOMATIO_MAX_REQUEST_FAILURES_COUNT: { description: 'Max request failures count' },
|
|
825
|
-
TESTOMATIO_MAX_REQUEST_RETRIES_WITHIN_TIME_SECONDS: { description: 'Max retries within time period' },
|
|
826
|
-
TESTOMATIO_NO_STEPS: { description: 'Disable steps reporting' },
|
|
827
|
-
TESTOMATIO_NO_TIMESTAMP: { description: 'Remove timestamps from logs' },
|
|
828
|
-
TESTOMATIO_PROCEED: { description: 'Proceed even if tests fail' },
|
|
829
|
-
TESTOMATIO_PUBLISH: { description: 'Publish results to Testomat.io' },
|
|
830
|
-
TESTOMATIO_REQUEST_TIMEOUT: { description: 'Request timeout in milliseconds' },
|
|
831
|
-
TESTOMATIO_RUN: { description: 'Run ID to report tests to' },
|
|
832
|
-
TESTOMATIO_RUNGROUP_TITLE: { description: 'Title for run group' },
|
|
833
|
-
TESTOMATIO_SHARED_RUN: { description: 'Share run for parallel execution' },
|
|
834
|
-
TESTOMATIO_SHARED_RUN_TIMEOUT: { description: 'Timeout for shared run (in seconds)' },
|
|
835
|
-
TESTOMATIO_STACK_ARTIFACTS: { description: 'Stack artifacts in report' },
|
|
836
|
-
TESTOMATIO_STACK_FILTER: { description: 'Filter stack traces' },
|
|
837
|
-
TESTOMATIO_STACK_PASSED: { description: 'Report stack for passed tests' },
|
|
838
|
-
TESTOMATIO_STEPS_PASSED: { description: 'Report steps for passed tests' },
|
|
839
|
-
TESTOMATIO_SUITE: { description: 'Suite ID for new tests' },
|
|
840
|
-
TESTOMATIO_TOKEN: { description: 'API Token (alias for TESTOMATIO)' },
|
|
841
|
-
TESTOMATIO_TITLE: { description: 'Title for the test run' },
|
|
842
|
-
TESTOMATIO_URL: { description: 'Testomat.io URL (custom instance)' },
|
|
843
|
-
TESTOMATIO_WORKDIR: { description: 'Working directory for relative paths' },
|
|
844
|
-
},
|
|
845
|
-
s3: {
|
|
846
|
-
S3_ACCESS_KEY_ID: { description: 'S3 access key ID' },
|
|
847
|
-
S3_BUCKET: { description: 'S3 bucket name' },
|
|
848
|
-
S3_ENDPOINT: { description: 'S3 endpoint URL' },
|
|
849
|
-
S3_FORCE_PATH_STYLE: { description: 'S3 force path style' },
|
|
850
|
-
S3_KEY: { description: 'S3 access key' },
|
|
851
|
-
S3_PREFIX: { description: 'S3 key prefix' },
|
|
852
|
-
S3_REGION: { description: 'S3 region' },
|
|
853
|
-
S3_SECRET: { description: 'S3 secret key' },
|
|
854
|
-
S3_SECRET_ACCESS_KEY: { description: 'S3 secret access key' },
|
|
855
|
-
S3_SESSION_TOKEN: { description: 'S3 session token' },
|
|
856
|
-
},
|
|
857
|
-
};
|
|
858
|
-
const sensitiveVars = new Set([
|
|
859
|
-
'TESTOMATIO',
|
|
860
|
-
'TESTOMATIO_TOKEN',
|
|
861
|
-
'TESTOMATIO_API_KEY',
|
|
862
|
-
'S3_KEY',
|
|
863
|
-
'S3_SECRET',
|
|
864
|
-
'S3_ACCESS_KEY_ID',
|
|
865
|
-
'S3_SECRET_ACCESS_KEY',
|
|
866
|
-
'S3_SESSION_TOKEN',
|
|
867
|
-
]);
|
|
868
|
-
const envVars = {
|
|
869
|
-
testomatio: processEnvironmentVariables(allVars.testomatio, sensitiveVars),
|
|
870
|
-
s3: processEnvironmentVariables(allVars.s3, sensitiveVars),
|
|
871
|
-
};
|
|
872
|
-
return envVars;
|
|
785
|
+
return groups;
|
|
873
786
|
}
|
|
874
787
|
/**
|
|
875
788
|
* Prepares test steps for HTML report display
|
package/lib/pipe/index.js
CHANGED
|
@@ -45,6 +45,7 @@ const github_js_1 = __importDefault(require("./github.js"));
|
|
|
45
45
|
const gitlab_js_1 = __importDefault(require("./gitlab.js"));
|
|
46
46
|
const csv_js_1 = __importDefault(require("./csv.js"));
|
|
47
47
|
const html_js_1 = __importDefault(require("./html.js"));
|
|
48
|
+
const markdown_js_1 = __importDefault(require("./markdown.js"));
|
|
48
49
|
const coverage_js_1 = __importDefault(require("./coverage.js"));
|
|
49
50
|
const bitbucket_js_1 = require("./bitbucket.js");
|
|
50
51
|
const debug_js_1 = require("./debug.js");
|
|
@@ -83,6 +84,7 @@ async function pipesFactory(params, opts) {
|
|
|
83
84
|
new gitlab_js_1.default(params, opts),
|
|
84
85
|
new csv_js_1.default(params, opts),
|
|
85
86
|
new html_js_1.default(params, opts),
|
|
87
|
+
new markdown_js_1.default(params, opts),
|
|
86
88
|
new bitbucket_js_1.BitbucketPipe(params, opts),
|
|
87
89
|
new coverage_js_1.default(params, opts),
|
|
88
90
|
new debug_js_1.DebugPipe(params, opts),
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export default MarkdownPipe;
|
|
2
|
+
declare class MarkdownPipe {
|
|
3
|
+
constructor(params: any, store?: {});
|
|
4
|
+
store: {};
|
|
5
|
+
title: any;
|
|
6
|
+
apiKey: any;
|
|
7
|
+
isMarkdown: string;
|
|
8
|
+
isEnabled: boolean;
|
|
9
|
+
markdownOutputPath: string;
|
|
10
|
+
filenameMsg: string;
|
|
11
|
+
tests: any[];
|
|
12
|
+
markdownReportDir: string;
|
|
13
|
+
markdownReportName: string;
|
|
14
|
+
createRun(): Promise<void>;
|
|
15
|
+
prepareRun(): Promise<void>;
|
|
16
|
+
updateRun(): void;
|
|
17
|
+
/**
|
|
18
|
+
* @param {import('../../types/types.js').MarkdownTestData} test
|
|
19
|
+
*/
|
|
20
|
+
addTest(test: import("../../types/types.js").MarkdownTestData): void;
|
|
21
|
+
finishRun(runParams: any): Promise<void>;
|
|
22
|
+
buildReport(opts: any): void;
|
|
23
|
+
sync(): Promise<void>;
|
|
24
|
+
toString(): string;
|
|
25
|
+
}
|