@lokalise/playwright-reporters 1.6.0 → 1.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.
- package/dist/analytics/elastic.d.ts +21 -0
- package/dist/analytics/elastic.js +21 -0
- package/dist/analytics/reporter.d.ts +10 -0
- package/dist/analytics/reporter.js +16 -0
- package/dist/analytics/transform.d.ts +17 -11
- package/dist/analytics/transform.js +15 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.js +16 -10
- package/dist/permissions/elastic.d.ts +13 -0
- package/dist/permissions/elastic.js +28 -0
- package/dist/permissions/reporter.d.ts +25 -0
- package/dist/permissions/reporter.js +58 -0
- package/dist/translation/elastic.d.ts +15 -0
- package/dist/translation/elastic.js +32 -0
- package/dist/translation/reporter.d.ts +33 -0
- package/dist/translation/reporter.js +101 -0
- package/dist/translation/tests/transform.test.d.ts +1 -0
- package/dist/translation/tests/transform.test.js +162 -0
- package/package.json +28 -17
|
@@ -17,10 +17,31 @@ export declare class Elastic {
|
|
|
17
17
|
private readonly elasticToken;
|
|
18
18
|
constructor(analyticsConfig: ElasticConfig);
|
|
19
19
|
setNativeRequestContext(): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* This method saves a flaky test data to Elasticsearch.
|
|
22
|
+
*/
|
|
20
23
|
saveFlakyData(flake: ReturnType<typeof formFlakyTestData>): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* This method saves a failed test data to Elasticsearch.
|
|
26
|
+
*/
|
|
21
27
|
saveFailedData(failure: ReturnType<typeof formFailedTestData>): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* This method saves the test run summary to Elasticsearch.
|
|
30
|
+
*/
|
|
22
31
|
saveBuildData(build: ReturnType<typeof formBuildData>): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* This method saves the browser usage data to Elasticsearch.
|
|
34
|
+
*/
|
|
23
35
|
saveBrowserUsageData(usageData: ReturnType<typeof formBrowserUsageData>): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* This method retrieves the last test run data from Elasticsearch.
|
|
38
|
+
* It is used for analytics of the main branch, where the index only contains data from the main branch.
|
|
39
|
+
*/
|
|
24
40
|
getLastRunDataByTime(): Promise<string | null>;
|
|
41
|
+
/**
|
|
42
|
+
* This method retrieves the last test run data from Elasticsearch.
|
|
43
|
+
* It is used for analytics of the feature branches, where the index contains data from all PREnv.
|
|
44
|
+
* It is therefore necessary to filter the data by the PREnv ID as well as the project name.
|
|
45
|
+
*/
|
|
25
46
|
getLastRunDataByPrenvIdAndProject(prenvId: string, projects?: string[]): Promise<string | null>;
|
|
26
47
|
}
|
|
@@ -21,6 +21,9 @@ class Elastic {
|
|
|
21
21
|
}),
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* This method saves a flaky test data to Elasticsearch.
|
|
26
|
+
*/
|
|
24
27
|
async saveFlakyData(flake) {
|
|
25
28
|
try {
|
|
26
29
|
await this.request.post(`/${this.flakyTestIndex}/_doc`, { data: flake });
|
|
@@ -29,6 +32,9 @@ class Elastic {
|
|
|
29
32
|
(0, logger_1.logger)(error);
|
|
30
33
|
}
|
|
31
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* This method saves a failed test data to Elasticsearch.
|
|
37
|
+
*/
|
|
32
38
|
async saveFailedData(failure) {
|
|
33
39
|
try {
|
|
34
40
|
await this.request.post(`/${this.failedTestIndex}/_doc`, {
|
|
@@ -39,6 +45,9 @@ class Elastic {
|
|
|
39
45
|
(0, logger_1.logger)(error);
|
|
40
46
|
}
|
|
41
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* This method saves the test run summary to Elasticsearch.
|
|
50
|
+
*/
|
|
42
51
|
async saveBuildData(build) {
|
|
43
52
|
try {
|
|
44
53
|
await this.request.post(`/${this.testRunIndex}/_doc`, { data: build });
|
|
@@ -47,6 +56,9 @@ class Elastic {
|
|
|
47
56
|
(0, logger_1.logger)(error);
|
|
48
57
|
}
|
|
49
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* This method saves the browser usage data to Elasticsearch.
|
|
61
|
+
*/
|
|
50
62
|
async saveBrowserUsageData(usageData) {
|
|
51
63
|
try {
|
|
52
64
|
await this.request.post(`/${this.browserUsageIndex}/_doc`, {
|
|
@@ -57,6 +69,10 @@ class Elastic {
|
|
|
57
69
|
(0, logger_1.logger)(error);
|
|
58
70
|
}
|
|
59
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* This method retrieves the last test run data from Elasticsearch.
|
|
74
|
+
* It is used for analytics of the main branch, where the index only contains data from the main branch.
|
|
75
|
+
*/
|
|
60
76
|
async getLastRunDataByTime() {
|
|
61
77
|
try {
|
|
62
78
|
const response = await this.request.post(`/${this.testRunIndex}/_search`, {
|
|
@@ -79,6 +95,11 @@ class Elastic {
|
|
|
79
95
|
return null;
|
|
80
96
|
}
|
|
81
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* This method retrieves the last test run data from Elasticsearch.
|
|
100
|
+
* It is used for analytics of the feature branches, where the index contains data from all PREnv.
|
|
101
|
+
* It is therefore necessary to filter the data by the PREnv ID as well as the project name.
|
|
102
|
+
*/
|
|
82
103
|
async getLastRunDataByPrenvIdAndProject(prenvId, projects) {
|
|
83
104
|
try {
|
|
84
105
|
const response = await this.request.post(`/${this.testRunIndex}/_search`, {
|
|
@@ -16,11 +16,21 @@ export default class AnalyticsReporter implements Reporter {
|
|
|
16
16
|
private readonly isMainPREnv;
|
|
17
17
|
private workerCount;
|
|
18
18
|
constructor(options: ReporterOptions);
|
|
19
|
+
/**
|
|
20
|
+
* This method is used to determine if the browser data should be saved for a given test.
|
|
21
|
+
* The browser data is saved only if the following conditions are met:
|
|
22
|
+
* - The browserUsageIndex is provided in the options.
|
|
23
|
+
* - The test project name does not match any of the projects in the ignoreProjects list.
|
|
24
|
+
* @param test The TestCase for which the browser data is to be saved.
|
|
25
|
+
*/
|
|
19
26
|
private shouldSaveBrowserData;
|
|
20
27
|
onBegin(config: FullConfig, suite: Suite): Promise<this | undefined>;
|
|
21
28
|
onStepBegin(test: TestCase, result: TestResult, step: TestStep): this | undefined;
|
|
22
29
|
onStepEnd(test: TestCase, result: TestResult, step: TestStep): this | undefined;
|
|
23
30
|
onTestEnd(test: TestCase, result: TestResult): Promise<this | undefined>;
|
|
31
|
+
/**
|
|
32
|
+
* This method is used to log the analytics data in the console for debugging purposes.
|
|
33
|
+
*/
|
|
24
34
|
private onEndDebug;
|
|
25
35
|
onEnd(result: FullResult): Promise<void>;
|
|
26
36
|
}
|
|
@@ -27,6 +27,13 @@ class AnalyticsReporter {
|
|
|
27
27
|
this.isMainPREnv = (0, helpers_1.isMainPREnv)(options);
|
|
28
28
|
this.elastic = new elastic_1.Elastic(options);
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* This method is used to determine if the browser data should be saved for a given test.
|
|
32
|
+
* The browser data is saved only if the following conditions are met:
|
|
33
|
+
* - The browserUsageIndex is provided in the options.
|
|
34
|
+
* - The test project name does not match any of the projects in the ignoreProjects list.
|
|
35
|
+
* @param test The TestCase for which the browser data is to be saved.
|
|
36
|
+
*/
|
|
30
37
|
shouldSaveBrowserData(test) {
|
|
31
38
|
const testProjectName = test?.parent?.project()?.name;
|
|
32
39
|
const isIgnoredProject = this.options.ignoreProjects?.some((project) => testProjectName?.includes(project));
|
|
@@ -126,6 +133,9 @@ class AnalyticsReporter {
|
|
|
126
133
|
console.error("Could not perform 'onTestEnd' analytics step", error);
|
|
127
134
|
}
|
|
128
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* This method is used to log the analytics data in the console for debugging purposes.
|
|
138
|
+
*/
|
|
129
139
|
onEndDebug(buildData, browserUsageData) {
|
|
130
140
|
(0, transform_1.calculateRuntime)(this.runStartTime);
|
|
131
141
|
(0, transform_1.calculateRetriedTests)(this.listOfFlakyTests);
|
|
@@ -148,6 +158,12 @@ class AnalyticsReporter {
|
|
|
148
158
|
}
|
|
149
159
|
return projectData;
|
|
150
160
|
})();
|
|
161
|
+
/**
|
|
162
|
+
* This function is used to get the last stored build data.
|
|
163
|
+
*
|
|
164
|
+
* - If the prenvId is provided, it will return the last build data for the given prenvId.
|
|
165
|
+
* - If the prenvId is not provided, it will return the last build data by time.
|
|
166
|
+
*/
|
|
151
167
|
const getLastBuildData = async () => {
|
|
152
168
|
if (this.options.prenvId) {
|
|
153
169
|
const listOfProjectNames = Object.entries(projectData)
|
|
@@ -2,11 +2,11 @@ import { type FullResult, type TestCase, type TestResult, type TestStep } from '
|
|
|
2
2
|
import type { TestAnalyticsData, BrowserUsageData } from './report.types';
|
|
3
3
|
import type AnalyticsReporter from './reporter';
|
|
4
4
|
export declare const calculateRuntime: (startTime: number) => void;
|
|
5
|
-
export declare const calculateRetriedTests: (listOfNonPassingTests: AnalyticsReporter[
|
|
6
|
-
export declare const calculateHooksDuration: (steps: TestStep[], hook:
|
|
5
|
+
export declare const calculateRetriedTests: (listOfNonPassingTests: AnalyticsReporter["listOfNonPassingTests"]) => void;
|
|
6
|
+
export declare const calculateHooksDuration: (steps: TestStep[], hook: "before" | "after") => number;
|
|
7
7
|
export declare const getTeamNames: (test: TestCase) => {
|
|
8
8
|
type: string;
|
|
9
|
-
description?: string
|
|
9
|
+
description?: string;
|
|
10
10
|
}[];
|
|
11
11
|
export declare const formFailedTestData: (test: TestCase, result: TestResult, testRunId: string, prenvId?: string) => {
|
|
12
12
|
prenvId?: string | undefined;
|
|
@@ -15,7 +15,7 @@ export declare const formFailedTestData: (test: TestCase, result: TestResult, te
|
|
|
15
15
|
name: string;
|
|
16
16
|
team: string | null;
|
|
17
17
|
testRunId: string;
|
|
18
|
-
status:
|
|
18
|
+
status: "skipped" | "failed" | "interrupted" | "passed" | "timedOut";
|
|
19
19
|
hooksDuration: number;
|
|
20
20
|
beforeHookDuration: number;
|
|
21
21
|
afterHookDuration: number;
|
|
@@ -32,7 +32,7 @@ export declare const formFlakyTestData: (test: TestCase, result: TestResult, tes
|
|
|
32
32
|
name: string;
|
|
33
33
|
team: string | null;
|
|
34
34
|
testRunId: string;
|
|
35
|
-
status:
|
|
35
|
+
status: "skipped" | "failed" | "interrupted" | "passed" | "timedOut";
|
|
36
36
|
hooksDuration: number;
|
|
37
37
|
beforeHookDuration: number;
|
|
38
38
|
afterHookDuration: number;
|
|
@@ -43,7 +43,7 @@ export declare const formFlakyTestData: (test: TestCase, result: TestResult, tes
|
|
|
43
43
|
};
|
|
44
44
|
};
|
|
45
45
|
export declare const formBuildData: (args: {
|
|
46
|
-
result: Pick<FullResult,
|
|
46
|
+
result: Pick<FullResult, "status">;
|
|
47
47
|
startTime: number;
|
|
48
48
|
endTime: number;
|
|
49
49
|
numberOfTests: number;
|
|
@@ -71,10 +71,18 @@ export declare const formBuildData: (args: {
|
|
|
71
71
|
buildId: string;
|
|
72
72
|
prenvId: string | undefined;
|
|
73
73
|
};
|
|
74
|
-
export declare const addTeamCount: (teamStats: TeamStats, ownerTestAnnotations: TestCase[
|
|
74
|
+
export declare const addTeamCount: (teamStats: TeamStats, ownerTestAnnotations: TestCase["annotations"]) => {
|
|
75
75
|
[x: string]: number;
|
|
76
76
|
};
|
|
77
|
-
|
|
77
|
+
/**
|
|
78
|
+
* This function is used to compute the build id with prefix.
|
|
79
|
+
* The prefix is required to differentiate between different builds in case the PREnv is reset and the build id starts from 1 again.
|
|
80
|
+
* The prefix is incremented by 1 when the current build id is less than the last build id.
|
|
81
|
+
* @param previousBuildId - The last build id with prefix
|
|
82
|
+
* @param currentBuildId - The current build id without prefix
|
|
83
|
+
* @returns The new build id with prefix
|
|
84
|
+
*/
|
|
85
|
+
export declare const getBuildIdWithPrefix: (previousBuildId: string | null, currentBuildId: string) => string;
|
|
78
86
|
export declare const formBrowserUsageData: (args: {
|
|
79
87
|
startTime: number;
|
|
80
88
|
testRunId: string;
|
|
@@ -92,6 +100,4 @@ export declare const formBrowserUsageData: (args: {
|
|
|
92
100
|
browserUsageFromRequest: number;
|
|
93
101
|
browserUsageAfterCreation: number;
|
|
94
102
|
};
|
|
95
|
-
type
|
|
96
|
-
export type TeamStats = Record<TeamName, number>;
|
|
97
|
-
export {};
|
|
103
|
+
export type TeamStats = Record<string, number>;
|
|
@@ -100,8 +100,18 @@ const addTeamCount = (teamStats, ownerTestAnnotations) => {
|
|
|
100
100
|
return testOwnerCount;
|
|
101
101
|
};
|
|
102
102
|
exports.addTeamCount = addTeamCount;
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
/**
|
|
104
|
+
* This function is used to compute the build id with prefix.
|
|
105
|
+
* The prefix is required to differentiate between different builds in case the PREnv is reset and the build id starts from 1 again.
|
|
106
|
+
* The prefix is incremented by 1 when the current build id is less than the last build id.
|
|
107
|
+
* @param previousBuildId - The last build id with prefix
|
|
108
|
+
* @param currentBuildId - The current build id without prefix
|
|
109
|
+
* @returns The new build id with prefix
|
|
110
|
+
*/
|
|
111
|
+
const getBuildIdWithPrefix = (previousBuildId, currentBuildId) => {
|
|
112
|
+
// If the previous build does not exist, for instance on a new index, the default value is set.
|
|
113
|
+
const lastBuildIdWithPrefix = previousBuildId ?? '0001-00001';
|
|
114
|
+
// We are getting the prefix from the last stored build id, or setting the default value.
|
|
105
115
|
const previousPrefix = (() => {
|
|
106
116
|
const defaultPrefix = '0001';
|
|
107
117
|
if (lastBuildIdWithPrefix.includes('-')) {
|
|
@@ -109,12 +119,15 @@ const getBuildIdWithPrefix = (lastRunData, currentBuildId) => {
|
|
|
109
119
|
}
|
|
110
120
|
return defaultPrefix;
|
|
111
121
|
})();
|
|
122
|
+
// We are getting the last build id from the last stored build id.
|
|
112
123
|
const lastBuildId = (() => {
|
|
113
124
|
if (lastBuildIdWithPrefix.includes('-')) {
|
|
114
125
|
return lastBuildIdWithPrefix.split('-').at(1);
|
|
115
126
|
}
|
|
116
127
|
return lastBuildIdWithPrefix;
|
|
117
128
|
})();
|
|
129
|
+
// We are comparing the current build id with the last build id.
|
|
130
|
+
// If the current build id is less than the last build id, we are incrementing the prefix by 1, as it indicates the PREnv reset.
|
|
118
131
|
if (Number(currentBuildId) < Number(lastBuildId)) {
|
|
119
132
|
const newPrefix = String(Number(previousPrefix) + 1).padStart(4, '0');
|
|
120
133
|
return `${newPrefix}-${currentBuildId.padStart(5, '0')}`;
|
|
@@ -122,7 +135,6 @@ const getBuildIdWithPrefix = (lastRunData, currentBuildId) => {
|
|
|
122
135
|
return `${previousPrefix}-${currentBuildId.padStart(5, '0')}`;
|
|
123
136
|
};
|
|
124
137
|
exports.getBuildIdWithPrefix = getBuildIdWithPrefix;
|
|
125
|
-
// eslint-disable-next-line max-statements
|
|
126
138
|
const formBrowserUsageData = (args) => {
|
|
127
139
|
let browserUsageFromRequest = 0;
|
|
128
140
|
let browserUsageAfterCreation = 0;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import AnalyticsReporter, { defineAnalyticsReporterConfig } from './analytics/reporter';
|
|
2
|
+
import PermissionsReporter, { definePermissionsReporterConfig } from './permissions/reporter';
|
|
2
3
|
import RetryReporter, { defineRetryReporterConfig } from './retry/reporter';
|
|
3
4
|
import StepDurationReporter, { defineStepDurationReporterConfig } from './stepDuration/reporter';
|
|
4
5
|
import TimelineReporter, { defineTimelineReporterConfig } from './timeline/reporter';
|
|
5
|
-
|
|
6
|
+
import TranslationReporter, { defineTranslationReporterConfig } from './translation/reporter';
|
|
7
|
+
export { AnalyticsReporter, defineAnalyticsReporterConfig, RetryReporter, defineRetryReporterConfig, TimelineReporter, defineTimelineReporterConfig, StepDurationReporter, defineStepDurationReporterConfig, PermissionsReporter, definePermissionsReporterConfig, TranslationReporter, defineTranslationReporterConfig, };
|
package/dist/index.js
CHANGED
|
@@ -23,16 +23,22 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.defineStepDurationReporterConfig = exports.StepDurationReporter = exports.defineTimelineReporterConfig = exports.TimelineReporter = exports.defineRetryReporterConfig = exports.RetryReporter = exports.defineAnalyticsReporterConfig = exports.AnalyticsReporter = void 0;
|
|
26
|
+
exports.defineTranslationReporterConfig = exports.TranslationReporter = exports.definePermissionsReporterConfig = exports.PermissionsReporter = exports.defineStepDurationReporterConfig = exports.StepDurationReporter = exports.defineTimelineReporterConfig = exports.TimelineReporter = exports.defineRetryReporterConfig = exports.RetryReporter = exports.defineAnalyticsReporterConfig = exports.AnalyticsReporter = void 0;
|
|
27
27
|
const reporter_1 = __importStar(require("./analytics/reporter"));
|
|
28
28
|
exports.AnalyticsReporter = reporter_1.default;
|
|
29
29
|
Object.defineProperty(exports, "defineAnalyticsReporterConfig", { enumerable: true, get: function () { return reporter_1.defineAnalyticsReporterConfig; } });
|
|
30
|
-
const reporter_2 = __importStar(require("./
|
|
31
|
-
exports.
|
|
32
|
-
Object.defineProperty(exports, "
|
|
33
|
-
const reporter_3 = __importStar(require("./
|
|
34
|
-
exports.
|
|
35
|
-
Object.defineProperty(exports, "
|
|
36
|
-
const reporter_4 = __importStar(require("./
|
|
37
|
-
exports.
|
|
38
|
-
Object.defineProperty(exports, "
|
|
30
|
+
const reporter_2 = __importStar(require("./permissions/reporter"));
|
|
31
|
+
exports.PermissionsReporter = reporter_2.default;
|
|
32
|
+
Object.defineProperty(exports, "definePermissionsReporterConfig", { enumerable: true, get: function () { return reporter_2.definePermissionsReporterConfig; } });
|
|
33
|
+
const reporter_3 = __importStar(require("./retry/reporter"));
|
|
34
|
+
exports.RetryReporter = reporter_3.default;
|
|
35
|
+
Object.defineProperty(exports, "defineRetryReporterConfig", { enumerable: true, get: function () { return reporter_3.defineRetryReporterConfig; } });
|
|
36
|
+
const reporter_4 = __importStar(require("./stepDuration/reporter"));
|
|
37
|
+
exports.StepDurationReporter = reporter_4.default;
|
|
38
|
+
Object.defineProperty(exports, "defineStepDurationReporterConfig", { enumerable: true, get: function () { return reporter_4.defineStepDurationReporterConfig; } });
|
|
39
|
+
const reporter_5 = __importStar(require("./timeline/reporter"));
|
|
40
|
+
exports.TimelineReporter = reporter_5.default;
|
|
41
|
+
Object.defineProperty(exports, "defineTimelineReporterConfig", { enumerable: true, get: function () { return reporter_5.defineTimelineReporterConfig; } });
|
|
42
|
+
const reporter_6 = __importStar(require("./translation/reporter"));
|
|
43
|
+
exports.TranslationReporter = reporter_6.default;
|
|
44
|
+
Object.defineProperty(exports, "defineTranslationReporterConfig", { enumerable: true, get: function () { return reporter_6.defineTranslationReporterConfig; } });
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { PermissionsReportData } from "./reporter";
|
|
2
|
+
export type ElasticOptions = {
|
|
3
|
+
permissionsIndex: string;
|
|
4
|
+
elasticUrl: string;
|
|
5
|
+
elasticToken: string;
|
|
6
|
+
};
|
|
7
|
+
export declare class Elastic {
|
|
8
|
+
private readonly options;
|
|
9
|
+
private request;
|
|
10
|
+
constructor(options: ElasticOptions);
|
|
11
|
+
setRequestContext(): Promise<void>;
|
|
12
|
+
savePermissionsData(testData: PermissionsReportData): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Elastic = void 0;
|
|
4
|
+
const test_1 = require("@playwright/test");
|
|
5
|
+
class Elastic {
|
|
6
|
+
constructor(options) {
|
|
7
|
+
this.options = options;
|
|
8
|
+
}
|
|
9
|
+
async setRequestContext() {
|
|
10
|
+
this.request = await test_1.request.newContext({
|
|
11
|
+
baseURL: this.options.elasticUrl,
|
|
12
|
+
ignoreHTTPSErrors: true,
|
|
13
|
+
...(this.options.elasticToken && {
|
|
14
|
+
extraHTTPHeaders: { Authorization: `ApiKey ${this.options.elasticToken}` },
|
|
15
|
+
}),
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
async savePermissionsData(testData) {
|
|
19
|
+
try {
|
|
20
|
+
await this.request.post(`/${this.options.permissionsIndex}/_doc`, { data: testData });
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
console.error("Failed to save permissions data");
|
|
24
|
+
console.error(error);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.Elastic = Elastic;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { TestCase, TestResult, Reporter, TestStep } from '@playwright/test/reporter';
|
|
2
|
+
import { type ElasticOptions } from './elastic';
|
|
3
|
+
type ReporterOptions = {
|
|
4
|
+
annotationName: string;
|
|
5
|
+
stepName: string;
|
|
6
|
+
debug: boolean;
|
|
7
|
+
} & ElasticOptions;
|
|
8
|
+
export type PermissionsReportData = {
|
|
9
|
+
title: string;
|
|
10
|
+
permissions: Record<string, boolean>;
|
|
11
|
+
failedStep: string;
|
|
12
|
+
timestamp: number;
|
|
13
|
+
};
|
|
14
|
+
export default class PermissionsReporter implements Reporter {
|
|
15
|
+
private readonly options;
|
|
16
|
+
private readonly elastic;
|
|
17
|
+
private readonly debugLogging;
|
|
18
|
+
private failedTestData;
|
|
19
|
+
constructor(options: ReporterOptions);
|
|
20
|
+
onBegin(): Promise<void>;
|
|
21
|
+
onTestEnd(test: TestCase): Promise<void>;
|
|
22
|
+
onStepEnd(test: TestCase, _result: TestResult, step: TestStep): void;
|
|
23
|
+
}
|
|
24
|
+
export declare const definePermissionsReporterConfig: (options: ConstructorParameters<typeof PermissionsReporter>[0]) => ReporterOptions;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.definePermissionsReporterConfig = void 0;
|
|
4
|
+
const elastic_1 = require("./elastic");
|
|
5
|
+
// eslint-disable-next-line import/no-default-export
|
|
6
|
+
class PermissionsReporter {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.elastic = new elastic_1.Elastic(options);
|
|
9
|
+
this.options = options;
|
|
10
|
+
this.failedTestData = {};
|
|
11
|
+
this.debugLogging = options.debug ? console.info : () => { };
|
|
12
|
+
}
|
|
13
|
+
async onBegin() {
|
|
14
|
+
await this.elastic.setRequestContext();
|
|
15
|
+
}
|
|
16
|
+
async onTestEnd(test) {
|
|
17
|
+
// Omit the results if the test is passing
|
|
18
|
+
if (test.outcome() === 'expected') {
|
|
19
|
+
this.debugLogging('Not reporting test - test passed');
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
// Omit the results if the test does not contain the annotation
|
|
23
|
+
if (!test.annotations.find((annotation) => annotation.type === this.options.annotationName)) {
|
|
24
|
+
this.debugLogging('Not reporting test - no permission annotation');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
// Test Title
|
|
28
|
+
const testTitle = test.title;
|
|
29
|
+
// Permissions as object
|
|
30
|
+
const testPermissions = test.annotations.find((annotation) => annotation.type === this.options.annotationName);
|
|
31
|
+
const permissionContents = testPermissions?.description ? JSON.parse(testPermissions.description) : {};
|
|
32
|
+
// Which step failed
|
|
33
|
+
const failedStep = this.failedTestData[test.id];
|
|
34
|
+
// Send payload body
|
|
35
|
+
const reportData = {
|
|
36
|
+
title: testTitle,
|
|
37
|
+
permissions: permissionContents,
|
|
38
|
+
failedStep,
|
|
39
|
+
timestamp: Date.now()
|
|
40
|
+
};
|
|
41
|
+
await this.elastic.savePermissionsData(reportData);
|
|
42
|
+
}
|
|
43
|
+
onStepEnd(test, _result, step) {
|
|
44
|
+
if (!step.title.includes(this.options.stepName)) {
|
|
45
|
+
this.debugLogging('Not reporting step - no step annotation', step.title);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (!step.error) {
|
|
49
|
+
this.debugLogging("Not reporting step - no error");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
this.debugLogging('Captured step name with error:', step.title);
|
|
53
|
+
this.failedTestData[test.id] = step.title;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.default = PermissionsReporter;
|
|
57
|
+
const definePermissionsReporterConfig = (options) => options;
|
|
58
|
+
exports.definePermissionsReporterConfig = definePermissionsReporterConfig;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { BaseTranslationReport } from './reporter';
|
|
2
|
+
export type ElasticOptions = {
|
|
3
|
+
dryRun: boolean;
|
|
4
|
+
debug: boolean;
|
|
5
|
+
translationIndex: string;
|
|
6
|
+
elasticUrl: string;
|
|
7
|
+
elasticToken: string;
|
|
8
|
+
};
|
|
9
|
+
export declare class Elastic {
|
|
10
|
+
private readonly options;
|
|
11
|
+
private request;
|
|
12
|
+
constructor(options: ElasticOptions);
|
|
13
|
+
setRequestContext(): Promise<void>;
|
|
14
|
+
saveTranslationsData(testData: BaseTranslationReport): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Elastic = void 0;
|
|
4
|
+
const node_http2_1 = require("node:http2");
|
|
5
|
+
const test_1 = require("@playwright/test");
|
|
6
|
+
class Elastic {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.options = options;
|
|
9
|
+
}
|
|
10
|
+
async setRequestContext() {
|
|
11
|
+
this.request = await test_1.request.newContext({
|
|
12
|
+
baseURL: this.options.elasticUrl,
|
|
13
|
+
ignoreHTTPSErrors: true,
|
|
14
|
+
extraHTTPHeaders: {
|
|
15
|
+
Authorization: `ApiKey ${this.options.elasticToken}`,
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
async saveTranslationsData(testData) {
|
|
20
|
+
try {
|
|
21
|
+
const response = await this.request.post(`/${this.options.translationIndex}/_doc`, {
|
|
22
|
+
data: testData,
|
|
23
|
+
});
|
|
24
|
+
(0, test_1.expect)(response.status()).toEqual(node_http2_1.constants.HTTP_STATUS_CREATED);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
console.error('Failed to save Shopify translation data');
|
|
28
|
+
console.error(error);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.Elastic = Elastic;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Reporter, TestCase, TestResult, TestStep } from '@playwright/test/reporter';
|
|
2
|
+
import type { ElasticOptions } from './elastic';
|
|
3
|
+
export declare enum ShopifySteps {
|
|
4
|
+
importing = "Start IMPORTING content",
|
|
5
|
+
translating = "Start TRANSLATING content",
|
|
6
|
+
publishing = "Start PUBLISHING content"
|
|
7
|
+
}
|
|
8
|
+
export type BaseTranslationReport = {
|
|
9
|
+
totalImportDuration: number;
|
|
10
|
+
totalTranslationDuration: number;
|
|
11
|
+
totalPublishDuration: number;
|
|
12
|
+
totalImportSteps: number;
|
|
13
|
+
totalTranslationSteps: number;
|
|
14
|
+
totalPublishingSteps: number;
|
|
15
|
+
name: string;
|
|
16
|
+
duration: number;
|
|
17
|
+
testRunId: string;
|
|
18
|
+
result: string;
|
|
19
|
+
timestamp_: number;
|
|
20
|
+
};
|
|
21
|
+
export type TranslationsReportData = {
|
|
22
|
+
data: Record<string, BaseTranslationReport>;
|
|
23
|
+
};
|
|
24
|
+
export default class TranslationReporter implements Reporter {
|
|
25
|
+
private readonly elastic;
|
|
26
|
+
private readonly options;
|
|
27
|
+
readonly listOfTests: TranslationsReportData;
|
|
28
|
+
constructor(options: ElasticOptions);
|
|
29
|
+
onBegin(): Promise<void>;
|
|
30
|
+
onStepEnd(test: TestCase, result: TestResult, step: TestStep): void;
|
|
31
|
+
onTestEnd(test: TestCase, result: TestResult): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
export declare const defineTranslationReporterConfig: (options: ConstructorParameters<typeof TranslationReporter>[0]) => ElasticOptions;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defineTranslationReporterConfig = exports.ShopifySteps = void 0;
|
|
4
|
+
const faker_1 = require("@faker-js/faker");
|
|
5
|
+
const elastic_1 = require("./elastic");
|
|
6
|
+
var ShopifySteps;
|
|
7
|
+
(function (ShopifySteps) {
|
|
8
|
+
ShopifySteps["importing"] = "Start IMPORTING content";
|
|
9
|
+
ShopifySteps["translating"] = "Start TRANSLATING content";
|
|
10
|
+
ShopifySteps["publishing"] = "Start PUBLISHING content";
|
|
11
|
+
})(ShopifySteps || (exports.ShopifySteps = ShopifySteps = {}));
|
|
12
|
+
// eslint-disable-next-line import/no-default-export
|
|
13
|
+
class TranslationReporter {
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.options = options;
|
|
16
|
+
this.listOfTests = { data: {} };
|
|
17
|
+
this.elastic = new elastic_1.Elastic(options);
|
|
18
|
+
}
|
|
19
|
+
async onBegin() {
|
|
20
|
+
try {
|
|
21
|
+
if (!this.options.dryRun) {
|
|
22
|
+
await this.elastic.setRequestContext();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
console.error("Could not perform 'onBegin' analytics step", error);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// eslint-disable-next-line max-statements
|
|
30
|
+
onStepEnd(test, result, step) {
|
|
31
|
+
try {
|
|
32
|
+
const testProjectName = test?.parent?.project()?.name;
|
|
33
|
+
if (!testProjectName?.toLowerCase().includes('shopify')) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const stepName = step.title;
|
|
37
|
+
const testId = `${test.id}-${result.retry ?? 0}`;
|
|
38
|
+
// Ensure that the data object for this test ID exists
|
|
39
|
+
if (!this.listOfTests.data[testId]) {
|
|
40
|
+
this.listOfTests.data[testId] = {
|
|
41
|
+
totalImportDuration: 0,
|
|
42
|
+
totalPublishDuration: 0,
|
|
43
|
+
totalTranslationDuration: 0,
|
|
44
|
+
totalImportSteps: 0,
|
|
45
|
+
totalTranslationSteps: 0,
|
|
46
|
+
totalPublishingSteps: 0,
|
|
47
|
+
name: test.title,
|
|
48
|
+
duration: 0,
|
|
49
|
+
testRunId: faker_1.faker.string.uuid(),
|
|
50
|
+
result: '',
|
|
51
|
+
timestamp_: 0,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (stepName.toLowerCase().includes(ShopifySteps.importing.toLowerCase())) {
|
|
55
|
+
// Directly accumulate the duration of the importing step
|
|
56
|
+
this.listOfTests.data[testId].totalImportDuration += step.duration;
|
|
57
|
+
this.listOfTests.data[testId].totalImportSteps++;
|
|
58
|
+
}
|
|
59
|
+
if (stepName.toLowerCase().includes(ShopifySteps.translating.toLowerCase())) {
|
|
60
|
+
this.listOfTests.data[testId].totalTranslationSteps++;
|
|
61
|
+
this.listOfTests.data[testId].totalTranslationDuration += step.duration;
|
|
62
|
+
}
|
|
63
|
+
if (stepName.toLowerCase().includes(ShopifySteps.publishing.toLowerCase())) {
|
|
64
|
+
this.listOfTests.data[testId].totalPublishingSteps++;
|
|
65
|
+
this.listOfTests.data[testId].totalPublishDuration += step.duration;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
console.error("Could not perform 'onStepEnd' analytics step", error);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async onTestEnd(test, result) {
|
|
73
|
+
try {
|
|
74
|
+
const testProjectName = test?.parent?.project()?.name;
|
|
75
|
+
if (!testProjectName?.toLowerCase().includes('shopify')) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const testId = `${test.id}-${result.retry ?? 0}`;
|
|
79
|
+
// No need to calculate totalImportDuration here; it's already accumulated
|
|
80
|
+
this.listOfTests.data[testId] = {
|
|
81
|
+
...this.listOfTests.data[testId],
|
|
82
|
+
timestamp_: result.startTime.getTime(),
|
|
83
|
+
name: test.title,
|
|
84
|
+
result: result.status,
|
|
85
|
+
duration: result.duration,
|
|
86
|
+
};
|
|
87
|
+
if (this.options.debug) {
|
|
88
|
+
console.log(this.listOfTests.data[testId]);
|
|
89
|
+
}
|
|
90
|
+
if (!this.options.dryRun) {
|
|
91
|
+
await this.elastic.saveTranslationsData(this.listOfTests.data[testId]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
console.error("Could not perform 'onTestEnd' analytics step", error);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.default = TranslationReporter;
|
|
100
|
+
const defineTranslationReporterConfig = (options) => options;
|
|
101
|
+
exports.defineTranslationReporterConfig = defineTranslationReporterConfig;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,162 @@
|
|
|
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 (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
const test_1 = __importStar(require("@playwright/test"));
|
|
27
|
+
const reporter_1 = __importStar(require("../reporter"));
|
|
28
|
+
test_1.default.describe('TranslationReporter Unit Tests', () => {
|
|
29
|
+
let reporter;
|
|
30
|
+
test_1.default.beforeEach(async () => {
|
|
31
|
+
reporter = new reporter_1.default({
|
|
32
|
+
dryRun: true, // Use dryRun to prevent requests to Elastic
|
|
33
|
+
debug: false,
|
|
34
|
+
elasticToken: '',
|
|
35
|
+
elasticUrl: '',
|
|
36
|
+
translationIndex: '',
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
test_1.default.describe('onStepEnd', () => {
|
|
40
|
+
// eslint-disable-next-line max-statements
|
|
41
|
+
(0, test_1.default)('should correctly accumulate data for importing step', () => {
|
|
42
|
+
const testCase = {
|
|
43
|
+
id: 'test-id',
|
|
44
|
+
title: 'Shopify Import Test',
|
|
45
|
+
parent: {
|
|
46
|
+
project: () => ({ name: 'shopify' }),
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
const testResult = {
|
|
50
|
+
retry: 0,
|
|
51
|
+
};
|
|
52
|
+
const testStep1 = {
|
|
53
|
+
title: reporter_1.ShopifySteps.importing,
|
|
54
|
+
duration: 50,
|
|
55
|
+
};
|
|
56
|
+
const testStep2 = {
|
|
57
|
+
title: reporter_1.ShopifySteps.importing,
|
|
58
|
+
duration: 50,
|
|
59
|
+
};
|
|
60
|
+
const testStep3 = {
|
|
61
|
+
title: reporter_1.ShopifySteps.importing,
|
|
62
|
+
duration: 100,
|
|
63
|
+
};
|
|
64
|
+
const testStep4 = {
|
|
65
|
+
title: reporter_1.ShopifySteps.translating,
|
|
66
|
+
duration: 300,
|
|
67
|
+
};
|
|
68
|
+
const testStep5 = {
|
|
69
|
+
title: reporter_1.ShopifySteps.translating,
|
|
70
|
+
duration: 200,
|
|
71
|
+
};
|
|
72
|
+
const testStep6 = {
|
|
73
|
+
title: reporter_1.ShopifySteps.publishing,
|
|
74
|
+
duration: 600,
|
|
75
|
+
};
|
|
76
|
+
reporter.onStepEnd(testCase, testResult, testStep1);
|
|
77
|
+
reporter.onStepEnd(testCase, testResult, testStep2);
|
|
78
|
+
reporter.onStepEnd(testCase, testResult, testStep3);
|
|
79
|
+
reporter.onStepEnd(testCase, testResult, testStep4);
|
|
80
|
+
reporter.onStepEnd(testCase, testResult, testStep5);
|
|
81
|
+
reporter.onStepEnd(testCase, testResult, testStep6);
|
|
82
|
+
const testId = `${testCase.id}-${testResult.retry ?? 0}`;
|
|
83
|
+
const resultData = reporter.listOfTests.data[testId];
|
|
84
|
+
(0, test_1.expect)(resultData).toMatchObject({
|
|
85
|
+
totalImportDuration: 200,
|
|
86
|
+
totalTranslationDuration: 500,
|
|
87
|
+
totalPublishDuration: 600,
|
|
88
|
+
totalImportSteps: 3,
|
|
89
|
+
totalTranslationSteps: 2,
|
|
90
|
+
totalPublishingSteps: 1,
|
|
91
|
+
name: 'Shopify Import Test',
|
|
92
|
+
duration: 0,
|
|
93
|
+
testRunId: test_1.expect.any(String),
|
|
94
|
+
result: '',
|
|
95
|
+
timestamp_: 0,
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
(0, test_1.default)('should not accumulate data for non-Shopify tests', () => {
|
|
99
|
+
const testCase = {
|
|
100
|
+
id: 'test-id',
|
|
101
|
+
title: 'Non-Shopify Test',
|
|
102
|
+
parent: {
|
|
103
|
+
project: () => ({ name: 'other-project' }),
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
const testResult = {
|
|
107
|
+
retry: 0,
|
|
108
|
+
};
|
|
109
|
+
const testStep = {
|
|
110
|
+
title: 'Some Step',
|
|
111
|
+
duration: 400,
|
|
112
|
+
};
|
|
113
|
+
reporter.onStepEnd(testCase, testResult, testStep);
|
|
114
|
+
const testId = `${testCase.id}-${testResult.retry ?? 0}`;
|
|
115
|
+
const resultData = reporter.listOfTests.data[testId];
|
|
116
|
+
(0, test_1.expect)(resultData).toBeUndefined();
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
test_1.default.describe('onTestEnd', () => {
|
|
120
|
+
(0, test_1.default)('should correctly finalize and store test data', async () => {
|
|
121
|
+
const testCase = {
|
|
122
|
+
id: 'test-id',
|
|
123
|
+
title: 'Shopify Final Test',
|
|
124
|
+
parent: {
|
|
125
|
+
project: () => ({ name: 'shopify' }),
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
const testResult = {
|
|
129
|
+
retry: 0,
|
|
130
|
+
startTime: new Date(),
|
|
131
|
+
status: 'passed',
|
|
132
|
+
duration: 600,
|
|
133
|
+
};
|
|
134
|
+
await reporter.onTestEnd(testCase, testResult);
|
|
135
|
+
const testId = `${testCase.id}-${testResult.retry ?? 0}`;
|
|
136
|
+
const resultData = reporter.listOfTests.data[testId];
|
|
137
|
+
(0, test_1.expect)(resultData.name).toBe(testCase.title);
|
|
138
|
+
(0, test_1.expect)(resultData.result).toBe(testResult.status);
|
|
139
|
+
(0, test_1.expect)(resultData.duration).toBe(testResult.duration);
|
|
140
|
+
(0, test_1.expect)(resultData.timestamp_).toBe(testResult.startTime.getTime());
|
|
141
|
+
});
|
|
142
|
+
(0, test_1.default)('should not store data for non-Shopify tests', async () => {
|
|
143
|
+
const testCase = {
|
|
144
|
+
id: 'non-shopify-test-id',
|
|
145
|
+
title: 'Non-Shopify Test',
|
|
146
|
+
parent: {
|
|
147
|
+
project: () => ({ name: 'other-project' }),
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
const testResult = {
|
|
151
|
+
retry: 0,
|
|
152
|
+
startTime: new Date(),
|
|
153
|
+
status: 'passed',
|
|
154
|
+
duration: 600,
|
|
155
|
+
};
|
|
156
|
+
await reporter.onTestEnd(testCase, testResult);
|
|
157
|
+
const testId = `${testCase.id}-${testResult.retry ?? 0}`;
|
|
158
|
+
const resultData = reporter.listOfTests.data[testId];
|
|
159
|
+
(0, test_1.expect)(resultData).toBeUndefined();
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lokalise/playwright-reporters",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"lint:eslint": "eslint --cache . --ext .js,.cjs,.ts",
|
|
6
6
|
"lint:ts": "tsc --noEmit",
|
|
@@ -41,37 +41,48 @@
|
|
|
41
41
|
"./testSimilarity": {
|
|
42
42
|
"import": "./dist/testSimilarity/reporter.js",
|
|
43
43
|
"require": "./dist/testSimilarity/reporter.js"
|
|
44
|
+
},
|
|
45
|
+
"./permissions": {
|
|
46
|
+
"import": "./dist/permissions/reporter.js",
|
|
47
|
+
"require": "./dist/permissions/reporter.js"
|
|
48
|
+
},
|
|
49
|
+
"./translation": {
|
|
50
|
+
"import": "./dist/translation/reporter.js",
|
|
51
|
+
"require": "./dist/translation/reporter.js"
|
|
44
52
|
}
|
|
45
53
|
},
|
|
46
54
|
"publishConfig": {
|
|
47
55
|
"access": "public"
|
|
48
56
|
},
|
|
49
57
|
"devDependencies": {
|
|
50
|
-
"@commitlint/cli": "19.
|
|
58
|
+
"@commitlint/cli": "19.4.0",
|
|
51
59
|
"@commitlint/config-conventional": "19.2.2",
|
|
52
|
-
"@commitlint/prompt-cli": "19.
|
|
53
|
-
"@lokalise/eslint-config-frontend": "^4.6.
|
|
54
|
-
"@lokalise/prettier-config": "^1.0.
|
|
60
|
+
"@commitlint/prompt-cli": "19.4.0",
|
|
61
|
+
"@lokalise/eslint-config-frontend": "^4.6.1",
|
|
62
|
+
"@lokalise/prettier-config": "^1.0.1",
|
|
55
63
|
"@semantic-release/changelog": "6.0.3",
|
|
56
|
-
"@semantic-release/commit-analyzer": "
|
|
64
|
+
"@semantic-release/commit-analyzer": "13.0.0",
|
|
57
65
|
"@semantic-release/git": "10.0.1",
|
|
58
|
-
"@semantic-release/github": "10.
|
|
59
|
-
"@semantic-release/npm": "12.0.
|
|
60
|
-
"@semantic-release/release-notes-generator": "
|
|
61
|
-
"@types/lodash": "^4.17.
|
|
62
|
-
"@types/node": "^
|
|
66
|
+
"@semantic-release/github": "10.1.6",
|
|
67
|
+
"@semantic-release/npm": "12.0.1",
|
|
68
|
+
"@semantic-release/release-notes-generator": "14.0.1",
|
|
69
|
+
"@types/lodash": "^4.17.7",
|
|
70
|
+
"@types/node": "^22.3.0",
|
|
63
71
|
"eslint-config-prettier": "^9.1.0",
|
|
64
|
-
"eslint-plugin-prettier": "^5.1
|
|
65
|
-
"husky": "9.
|
|
66
|
-
"prettier": "^3.
|
|
67
|
-
"semantic-release": "
|
|
68
|
-
"typescript": "5.4
|
|
72
|
+
"eslint-plugin-prettier": "^5.2.1",
|
|
73
|
+
"husky": "9.1.4",
|
|
74
|
+
"prettier": "^3.3.3",
|
|
75
|
+
"semantic-release": "24.0.0",
|
|
76
|
+
"typescript": "5.5.4"
|
|
69
77
|
},
|
|
70
78
|
"dependencies": {
|
|
71
79
|
"@faker-js/faker": "^8.4.1",
|
|
72
|
-
"@playwright/test": "^1.
|
|
80
|
+
"@playwright/test": "^1.46.0",
|
|
73
81
|
"fastest-levenshtein": "^1.0.16",
|
|
74
82
|
"lodash": "^4.17.21"
|
|
75
83
|
},
|
|
84
|
+
"overrides": {
|
|
85
|
+
"conventional-changelog-conventionalcommits": ">= 8.0.0"
|
|
86
|
+
},
|
|
76
87
|
"prettier": "@lokalise/prettier-config"
|
|
77
88
|
}
|