@testsmith/testblocks 0.6.0 → 0.8.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.
Files changed (71) hide show
  1. package/dist/cli/executor.d.ts +4 -1
  2. package/dist/cli/executor.js +101 -5
  3. package/dist/cli/index.js +148 -4
  4. package/dist/cli/reporters/ConsoleReporter.d.ts +12 -0
  5. package/dist/cli/reporters/ConsoleReporter.js +39 -0
  6. package/dist/cli/reporters/HTMLReporter.d.ts +19 -0
  7. package/dist/cli/reporters/HTMLReporter.js +506 -0
  8. package/dist/cli/reporters/JSONReporter.d.ts +15 -0
  9. package/dist/cli/reporters/JSONReporter.js +80 -0
  10. package/dist/cli/reporters/JUnitReporter.d.ts +19 -0
  11. package/dist/cli/reporters/JUnitReporter.js +105 -0
  12. package/dist/cli/reporters/index.d.ts +17 -0
  13. package/dist/cli/reporters/index.js +31 -0
  14. package/dist/cli/reporters/types.d.ts +28 -0
  15. package/dist/cli/reporters/types.js +2 -0
  16. package/dist/cli/reporters/utils.d.ts +31 -0
  17. package/dist/cli/reporters/utils.js +136 -0
  18. package/dist/cli/reporters.d.ts +13 -62
  19. package/dist/cli/reporters.js +16 -719
  20. package/dist/client/assets/index-Boo8ZrY_.js +2195 -0
  21. package/dist/client/assets/{index-dXniUrbi.js.map → index-Boo8ZrY_.js.map} +1 -1
  22. package/dist/client/assets/index-OxNH9dW-.css +1 -0
  23. package/dist/client/index.html +2 -2
  24. package/dist/core/blocks/api.js +3 -6
  25. package/dist/core/blocks/assertions.d.ts +31 -0
  26. package/dist/core/blocks/assertions.js +72 -0
  27. package/dist/core/blocks/index.d.ts +1 -0
  28. package/dist/core/blocks/index.js +6 -1
  29. package/dist/core/blocks/lifecycle.js +5 -3
  30. package/dist/core/blocks/logic.js +2 -3
  31. package/dist/core/blocks/playwright/assertions.d.ts +5 -0
  32. package/dist/core/blocks/playwright/assertions.js +321 -0
  33. package/dist/core/blocks/playwright/index.d.ts +17 -0
  34. package/dist/core/blocks/playwright/index.js +49 -0
  35. package/dist/core/blocks/playwright/interactions.d.ts +5 -0
  36. package/dist/core/blocks/playwright/interactions.js +191 -0
  37. package/dist/core/blocks/playwright/navigation.d.ts +5 -0
  38. package/dist/core/blocks/playwright/navigation.js +133 -0
  39. package/dist/core/blocks/playwright/retrieval.d.ts +5 -0
  40. package/dist/core/blocks/playwright/retrieval.js +144 -0
  41. package/dist/core/blocks/playwright/types.d.ts +65 -0
  42. package/dist/core/blocks/playwright/types.js +5 -0
  43. package/dist/core/blocks/playwright/utils.d.ts +26 -0
  44. package/dist/core/blocks/playwright/utils.js +137 -0
  45. package/dist/core/blocks/playwright.d.ts +13 -2
  46. package/dist/core/blocks/playwright.js +14 -761
  47. package/dist/core/executor/BaseTestExecutor.d.ts +60 -0
  48. package/dist/core/executor/BaseTestExecutor.js +297 -0
  49. package/dist/core/executor/index.d.ts +1 -0
  50. package/dist/core/executor/index.js +5 -0
  51. package/dist/core/index.d.ts +1 -0
  52. package/dist/core/index.js +4 -0
  53. package/dist/core/types.d.ts +12 -0
  54. package/dist/core/utils/blocklyParser.d.ts +18 -0
  55. package/dist/core/utils/blocklyParser.js +84 -0
  56. package/dist/core/utils/dataLoader.d.ts +9 -0
  57. package/dist/core/utils/dataLoader.js +117 -0
  58. package/dist/core/utils/index.d.ts +2 -0
  59. package/dist/core/utils/index.js +12 -0
  60. package/dist/core/utils/logger.d.ts +14 -0
  61. package/dist/core/utils/logger.js +48 -0
  62. package/dist/core/utils/variableResolver.d.ts +24 -0
  63. package/dist/core/utils/variableResolver.js +92 -0
  64. package/dist/server/executor.d.ts +6 -0
  65. package/dist/server/executor.js +207 -47
  66. package/dist/server/globals.d.ts +6 -1
  67. package/dist/server/globals.js +7 -0
  68. package/dist/server/startServer.js +15 -0
  69. package/package.json +1 -1
  70. package/dist/client/assets/index-dXniUrbi.js +0 -2193
  71. package/dist/client/assets/index-oTTttNKd.css +0 -1
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.JUnitReporter = void 0;
37
+ exports.generateJUnitXML = generateJUnitXML;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const utils_1 = require("./utils");
41
+ /**
42
+ * JUnit XML reporter - outputs results in JUnit XML format
43
+ */
44
+ class JUnitReporter {
45
+ constructor(outputDir) {
46
+ this.allResults = [];
47
+ this.outputDir = outputDir;
48
+ }
49
+ onTestFileComplete(file, testFile, results) {
50
+ this.allResults.push({ file, testFile, results });
51
+ const passed = results.filter(r => r.status === 'passed').length;
52
+ const failed = results.filter(r => r.status !== 'passed').length;
53
+ console.log(` ${passed} passed, ${failed} failed\n`);
54
+ }
55
+ onComplete(allResults) {
56
+ if (!fs.existsSync(this.outputDir)) {
57
+ fs.mkdirSync(this.outputDir, { recursive: true });
58
+ }
59
+ const timestamp = (0, utils_1.getTimestamp)();
60
+ const outputPath = path.join(this.outputDir, `junit-${timestamp}.xml`);
61
+ const xml = generateJUnitXML({
62
+ timestamp: new Date().toISOString(),
63
+ summary: {
64
+ totalTests: allResults.reduce((sum, r) => sum + r.results.length, 0),
65
+ passed: allResults.reduce((sum, r) => sum + r.results.filter(t => t.status === 'passed').length, 0),
66
+ failed: allResults.reduce((sum, r) => sum + r.results.filter(t => t.status !== 'passed').length, 0),
67
+ duration: allResults.reduce((sum, r) => sum + r.results.reduce((s, t) => s + t.duration, 0), 0),
68
+ },
69
+ testFiles: this.allResults,
70
+ });
71
+ fs.writeFileSync(outputPath, xml);
72
+ console.log(`JUnit report saved to: ${outputPath}`);
73
+ }
74
+ }
75
+ exports.JUnitReporter = JUnitReporter;
76
+ /**
77
+ * Generate JUnit XML from report data
78
+ */
79
+ function generateJUnitXML(data) {
80
+ const { testFiles } = data;
81
+ const totalTests = testFiles.reduce((sum, f) => sum + f.results.length, 0);
82
+ const failures = testFiles.reduce((sum, f) => sum + f.results.filter(t => t.status !== 'passed').length, 0);
83
+ const totalTime = testFiles.reduce((sum, f) => sum + f.results.reduce((s, t) => s + t.duration, 0), 0) / 1000;
84
+ let xml = '<?xml version="1.0" encoding="UTF-8"?>\n';
85
+ xml += `<testsuites tests="${totalTests}" failures="${failures}" time="${totalTime.toFixed(3)}">\n`;
86
+ for (const { file, testFile, results } of testFiles) {
87
+ const suiteTests = results.length;
88
+ const suiteFailures = results.filter(r => r.status !== 'passed').length;
89
+ const suiteTime = results.reduce((s, t) => s + t.duration, 0) / 1000;
90
+ xml += ` <testsuite name="${(0, utils_1.escapeXml)(testFile.name)}" tests="${suiteTests}" failures="${suiteFailures}" time="${suiteTime.toFixed(3)}" file="${(0, utils_1.escapeXml)(file)}">\n`;
91
+ for (const result of results) {
92
+ const testTime = result.duration / 1000;
93
+ xml += ` <testcase name="${(0, utils_1.escapeXml)(result.testName)}" classname="${(0, utils_1.escapeXml)(testFile.name)}" time="${testTime.toFixed(3)}">\n`;
94
+ if (result.status !== 'passed' && result.error) {
95
+ xml += ` <failure message="${(0, utils_1.escapeXml)(result.error.message)}">\n`;
96
+ xml += `${(0, utils_1.escapeXml)(result.error.stack || result.error.message)}\n`;
97
+ xml += ` </failure>\n`;
98
+ }
99
+ xml += ` </testcase>\n`;
100
+ }
101
+ xml += ` </testsuite>\n`;
102
+ }
103
+ xml += '</testsuites>\n';
104
+ return xml;
105
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Reporters module - modular organization
3
+ *
4
+ * Reporters are organized into separate files:
5
+ * - ConsoleReporter.ts - Terminal output
6
+ * - JSONReporter.ts - JSON file output
7
+ * - JUnitReporter.ts - JUnit XML output
8
+ * - HTMLReporter.ts - Styled HTML report
9
+ * - types.ts - Shared interfaces
10
+ * - utils.ts - Utility functions
11
+ */
12
+ export { Reporter, ReportData } from './types';
13
+ export { getTimestamp, escapeXml, escapeHtml, formatStepType } from './utils';
14
+ export { ConsoleReporter } from './ConsoleReporter';
15
+ export { JSONReporter } from './JSONReporter';
16
+ export { JUnitReporter, generateJUnitXML } from './JUnitReporter';
17
+ export { HTMLReporter, generateHTMLReport } from './HTMLReporter';
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ /**
3
+ * Reporters module - modular organization
4
+ *
5
+ * Reporters are organized into separate files:
6
+ * - ConsoleReporter.ts - Terminal output
7
+ * - JSONReporter.ts - JSON file output
8
+ * - JUnitReporter.ts - JUnit XML output
9
+ * - HTMLReporter.ts - Styled HTML report
10
+ * - types.ts - Shared interfaces
11
+ * - utils.ts - Utility functions
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.generateHTMLReport = exports.HTMLReporter = exports.generateJUnitXML = exports.JUnitReporter = exports.JSONReporter = exports.ConsoleReporter = exports.formatStepType = exports.escapeHtml = exports.escapeXml = exports.getTimestamp = void 0;
15
+ // Utilities
16
+ var utils_1 = require("./utils");
17
+ Object.defineProperty(exports, "getTimestamp", { enumerable: true, get: function () { return utils_1.getTimestamp; } });
18
+ Object.defineProperty(exports, "escapeXml", { enumerable: true, get: function () { return utils_1.escapeXml; } });
19
+ Object.defineProperty(exports, "escapeHtml", { enumerable: true, get: function () { return utils_1.escapeHtml; } });
20
+ Object.defineProperty(exports, "formatStepType", { enumerable: true, get: function () { return utils_1.formatStepType; } });
21
+ // Reporters
22
+ var ConsoleReporter_1 = require("./ConsoleReporter");
23
+ Object.defineProperty(exports, "ConsoleReporter", { enumerable: true, get: function () { return ConsoleReporter_1.ConsoleReporter; } });
24
+ var JSONReporter_1 = require("./JSONReporter");
25
+ Object.defineProperty(exports, "JSONReporter", { enumerable: true, get: function () { return JSONReporter_1.JSONReporter; } });
26
+ var JUnitReporter_1 = require("./JUnitReporter");
27
+ Object.defineProperty(exports, "JUnitReporter", { enumerable: true, get: function () { return JUnitReporter_1.JUnitReporter; } });
28
+ Object.defineProperty(exports, "generateJUnitXML", { enumerable: true, get: function () { return JUnitReporter_1.generateJUnitXML; } });
29
+ var HTMLReporter_1 = require("./HTMLReporter");
30
+ Object.defineProperty(exports, "HTMLReporter", { enumerable: true, get: function () { return HTMLReporter_1.HTMLReporter; } });
31
+ Object.defineProperty(exports, "generateHTMLReport", { enumerable: true, get: function () { return HTMLReporter_1.generateHTMLReport; } });
@@ -0,0 +1,28 @@
1
+ import { TestFile, TestResult } from '../../core';
2
+ /**
3
+ * Reporter interface - all reporters must implement this
4
+ */
5
+ export interface Reporter {
6
+ onTestFileComplete(file: string, testFile: TestFile, results: TestResult[]): void;
7
+ onComplete(allResults: {
8
+ file: string;
9
+ results: TestResult[];
10
+ }[]): void;
11
+ }
12
+ /**
13
+ * Report data structure for HTML/JSON reports
14
+ */
15
+ export interface ReportData {
16
+ timestamp: string;
17
+ summary: {
18
+ totalTests: number;
19
+ passed: number;
20
+ failed: number;
21
+ duration: number;
22
+ };
23
+ testFiles: {
24
+ file: string;
25
+ testFile: TestFile;
26
+ results: TestResult[];
27
+ }[];
28
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Utility functions for reporters
3
+ */
4
+ /**
5
+ * Generate timestamp string for filenames (e.g., 2024-01-15T14-30-45)
6
+ */
7
+ export declare function getTimestamp(): string;
8
+ /**
9
+ * Escape XML special characters
10
+ */
11
+ export declare function escapeXml(str: string): string;
12
+ /**
13
+ * Escape HTML special characters
14
+ */
15
+ export declare function escapeHtml(str: string): string;
16
+ /**
17
+ * Format step type for display (same as StepResultItem.tsx)
18
+ */
19
+ export declare function formatStepType(type: string): string;
20
+ /**
21
+ * Get step summary from output
22
+ */
23
+ export declare function getStepSummary(stepType: string, output: unknown): string | null;
24
+ /**
25
+ * Check if step is an API request
26
+ */
27
+ export declare function isApiRequestStep(stepType: string): boolean;
28
+ /**
29
+ * Format step output for display
30
+ */
31
+ export declare function formatStepOutput(output: unknown, stepType: string): string;
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ /**
3
+ * Utility functions for reporters
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getTimestamp = getTimestamp;
7
+ exports.escapeXml = escapeXml;
8
+ exports.escapeHtml = escapeHtml;
9
+ exports.formatStepType = formatStepType;
10
+ exports.getStepSummary = getStepSummary;
11
+ exports.isApiRequestStep = isApiRequestStep;
12
+ exports.formatStepOutput = formatStepOutput;
13
+ /**
14
+ * Generate timestamp string for filenames (e.g., 2024-01-15T14-30-45)
15
+ */
16
+ function getTimestamp() {
17
+ return new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
18
+ }
19
+ /**
20
+ * Escape XML special characters
21
+ */
22
+ function escapeXml(str) {
23
+ return str
24
+ .replace(/&/g, '&amp;')
25
+ .replace(/</g, '&lt;')
26
+ .replace(/>/g, '&gt;')
27
+ .replace(/"/g, '&quot;')
28
+ .replace(/'/g, '&apos;');
29
+ }
30
+ /**
31
+ * Escape HTML special characters
32
+ */
33
+ function escapeHtml(str) {
34
+ return str
35
+ .replace(/&/g, '&amp;')
36
+ .replace(/</g, '&lt;')
37
+ .replace(/>/g, '&gt;')
38
+ .replace(/"/g, '&quot;');
39
+ }
40
+ /**
41
+ * Format step type for display (same as StepResultItem.tsx)
42
+ */
43
+ function formatStepType(type) {
44
+ const displayNames = {
45
+ 'logic_log': 'Log',
46
+ 'logic_set_variable': 'Set Variable',
47
+ 'logic_get_variable': 'Get Variable',
48
+ 'api_set_header': 'Set Header',
49
+ 'api_set_headers': 'Set Headers',
50
+ 'api_clear_headers': 'Clear Headers',
51
+ 'api_assert_status': 'Assert Status',
52
+ 'api_assert_body_contains': 'Assert Body',
53
+ 'api_extract': 'Extract',
54
+ 'api_extract_jsonpath': 'Extract (JSONPath)',
55
+ 'api_extract_xpath': 'Extract (XPath)',
56
+ 'web_navigate': 'Navigate',
57
+ 'web_click': 'Click',
58
+ 'web_fill': 'Fill',
59
+ 'web_type': 'Type',
60
+ 'web_press_key': 'Press Key',
61
+ 'web_select': 'Select',
62
+ 'web_checkbox': 'Checkbox',
63
+ 'web_hover': 'Hover',
64
+ 'web_wait_for_element': 'Wait for Element',
65
+ 'web_wait_for_url': 'Wait for URL',
66
+ 'web_wait': 'Wait',
67
+ 'web_screenshot': 'Screenshot',
68
+ 'web_get_text': 'Get Text',
69
+ 'web_get_attribute': 'Get Attribute',
70
+ 'web_get_input_value': 'Get Input Value',
71
+ 'web_get_title': 'Get Title',
72
+ 'web_get_url': 'Get URL',
73
+ 'web_assert_visible': 'Assert Visible',
74
+ 'web_assert_not_visible': 'Assert Not Visible',
75
+ 'web_assert_text_contains': 'Assert Text Contains',
76
+ 'web_assert_text_equals': 'Assert Text Equals',
77
+ 'web_assert_url_contains': 'Assert URL Contains',
78
+ 'web_assert_title_contains': 'Assert Title Contains',
79
+ 'web_assert_enabled': 'Assert Enabled',
80
+ 'web_assert_checked': 'Assert Checked',
81
+ 'totp_generate': 'Generate TOTP',
82
+ 'totp_generate_from_numeric': 'Generate TOTP (Numeric)',
83
+ 'totp_setup': 'Setup TOTP',
84
+ 'totp_code': 'TOTP Code',
85
+ 'totp_time_remaining': 'TOTP Time Remaining',
86
+ 'totp_wait_for_new_code': 'Wait for New TOTP',
87
+ };
88
+ if (displayNames[type]) {
89
+ return displayNames[type];
90
+ }
91
+ return type
92
+ .split('_')
93
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
94
+ .join(' ');
95
+ }
96
+ /**
97
+ * Get step summary from output
98
+ */
99
+ function getStepSummary(stepType, output) {
100
+ if (!output || typeof output !== 'object')
101
+ return null;
102
+ const out = output;
103
+ return out._summary || null;
104
+ }
105
+ /**
106
+ * Check if step is an API request
107
+ */
108
+ function isApiRequestStep(stepType) {
109
+ return ['api_get', 'api_post', 'api_put', 'api_patch', 'api_delete'].includes(stepType);
110
+ }
111
+ /**
112
+ * Format step output for display
113
+ */
114
+ function formatStepOutput(output, stepType) {
115
+ if (output === undefined || output === null)
116
+ return '';
117
+ if (stepType === 'logic_log' && typeof output === 'object' && output !== null) {
118
+ const logOutput = output;
119
+ if (logOutput._message) {
120
+ return String(logOutput._message);
121
+ }
122
+ }
123
+ if (typeof output === 'string')
124
+ return output;
125
+ if (typeof output === 'number' || typeof output === 'boolean')
126
+ return String(output);
127
+ if (typeof output === 'object') {
128
+ const filtered = Object.fromEntries(Object.entries(output)
129
+ .filter(([key]) => !key.startsWith('_')));
130
+ if (Object.keys(filtered).length === 0) {
131
+ return '';
132
+ }
133
+ return JSON.stringify(filtered, null, 2);
134
+ }
135
+ return JSON.stringify(output, null, 2);
136
+ }
@@ -1,62 +1,13 @@
1
- import { TestFile, TestResult } from '../core';
2
- export interface Reporter {
3
- onTestFileComplete(file: string, testFile: TestFile, results: TestResult[]): void;
4
- onComplete(allResults: {
5
- file: string;
6
- results: TestResult[];
7
- }[]): void;
8
- }
9
- export declare function getTimestamp(): string;
10
- export declare class ConsoleReporter implements Reporter {
11
- onTestFileComplete(file: string, testFile: TestFile, results: TestResult[]): void;
12
- onComplete(allResults: {
13
- file: string;
14
- results: TestResult[];
15
- }[]): void;
16
- }
17
- export declare class JSONReporter implements Reporter {
18
- private outputDir;
19
- private allResults;
20
- constructor(outputDir: string);
21
- onTestFileComplete(file: string, testFile: TestFile, results: TestResult[]): void;
22
- onComplete(allResults: {
23
- file: string;
24
- results: TestResult[];
25
- }[]): void;
26
- }
27
- export declare class JUnitReporter implements Reporter {
28
- private outputDir;
29
- private allResults;
30
- constructor(outputDir: string);
31
- onTestFileComplete(file: string, testFile: TestFile, results: TestResult[]): void;
32
- onComplete(allResults: {
33
- file: string;
34
- results: TestResult[];
35
- }[]): void;
36
- }
37
- export declare class HTMLReporter implements Reporter {
38
- private outputDir;
39
- private allResults;
40
- constructor(outputDir: string);
41
- onTestFileComplete(file: string, testFile: TestFile, results: TestResult[]): void;
42
- onComplete(allResults: {
43
- file: string;
44
- results: TestResult[];
45
- }[]): void;
46
- }
47
- export interface ReportData {
48
- timestamp: string;
49
- summary: {
50
- totalTests: number;
51
- passed: number;
52
- failed: number;
53
- duration: number;
54
- };
55
- testFiles: {
56
- file: string;
57
- testFile: TestFile;
58
- results: TestResult[];
59
- }[];
60
- }
61
- export declare function generateHTMLReport(data: ReportData): string;
62
- export declare function generateJUnitXML(data: ReportData): string;
1
+ /**
2
+ * Reporters - Re-export from modular structure
3
+ *
4
+ * This file re-exports all reporters from the reporters/ directory
5
+ * for backwards compatibility. The reporters are now organized in:
6
+ * - reporters/ConsoleReporter.ts - Terminal output
7
+ * - reporters/JSONReporter.ts - JSON file output
8
+ * - reporters/JUnitReporter.ts - JUnit XML output
9
+ * - reporters/HTMLReporter.ts - Styled HTML report
10
+ * - reporters/types.ts - Shared interfaces
11
+ * - reporters/utils.ts - Utility functions
12
+ */
13
+ export * from './reporters/index';