Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/vue_merge_request_widget/extensions')
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/issues.js3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/test_report/constants.js39
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/test_report/index.js82
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/test_report/utils.js55
4 files changed, 179 insertions, 0 deletions
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
index e52f2c2c666..6ca0ea9c4e7 100644
--- a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
@@ -48,6 +48,9 @@ export default {
{ text: 'Full report', href: this.conflictsDocsPath, target: '_blank' },
];
},
+ shouldCollapse() {
+ return true;
+ },
},
methods: {
// Fetches the collapsed data
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/constants.js b/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/constants.js
new file mode 100644
index 00000000000..cd5cfb6837c
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/constants.js
@@ -0,0 +1,39 @@
+import { __, n__, s__, sprintf } from '~/locale';
+
+const digitText = (bold = false) => (bold ? '%{strong_start}%d%{strong_end}' : '%d');
+const noText = (bold = false) => (bold ? '%{strong_start}no%{strong_end}' : 'no');
+
+export const TESTS_FAILED_STATUS = 'failed';
+export const ERROR_STATUS = 'error';
+
+export const i18n = {
+ label: s__('Reports|Test summary'),
+ loading: s__('Reports|Test summary results are loading'),
+ error: s__('Reports|Test summary failed to load results'),
+ fullReport: s__('Reports|Full report'),
+
+ noChanges: (bold) => s__(`Reports|${noText(bold)} changed test results`),
+ resultsString: (combinedString, resolvedString) =>
+ sprintf(s__('Reports|%{combinedString} and %{resolvedString}'), {
+ combinedString,
+ resolvedString,
+ }),
+
+ summaryText: (name, resultsString) =>
+ sprintf(__('%{name}: %{resultsString}'), { name, resultsString }),
+
+ failedClause: (failed, bold) =>
+ n__(`${digitText(bold)} failed`, `${digitText(bold)} failed`, failed),
+ erroredClause: (errored, bold) =>
+ n__(`${digitText(bold)} error`, `${digitText(bold)} errors`, errored),
+ resolvedClause: (resolved, bold) =>
+ n__(`${digitText(bold)} fixed test result`, `${digitText(bold)} fixed test results`, resolved),
+ totalClause: (total, bold) =>
+ n__(`${digitText(bold)} total test`, `${digitText(bold)} total tests`, total),
+
+ reportError: s__('Reports|An error occurred while loading report'),
+ reportErrorWithName: (name) =>
+ sprintf(s__('Reports|An error occurred while loading %{name} results'), { name }),
+ headReportParsingError: s__('Reports|Head report parsing error:'),
+ baseReportParsingError: s__('Reports|Base report parsing error:'),
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/index.js b/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/index.js
new file mode 100644
index 00000000000..65d9257903f
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/index.js
@@ -0,0 +1,82 @@
+import { uniqueId } from 'lodash';
+import axios from '~/lib/utils/axios_utils';
+import { EXTENSION_ICONS } from '../../constants';
+import { summaryTextBuilder, reportTextBuilder, reportSubTextBuilder } from './utils';
+import { i18n, TESTS_FAILED_STATUS, ERROR_STATUS } from './constants';
+
+export default {
+ name: 'WidgetTestSummary',
+ enablePolling: true,
+ i18n,
+ expandEvent: 'i_testing_summary_widget_total',
+ props: ['testResultsPath', 'headBlobPath', 'pipeline'],
+ computed: {
+ summary(data) {
+ if (data.parsingInProgress) {
+ return this.$options.i18n.loading;
+ }
+ if (data.hasSuiteError) {
+ return this.$options.i18n.error;
+ }
+ return summaryTextBuilder(this.$options.i18n.label, data.summary);
+ },
+ statusIcon(data) {
+ if (data.parsingInProgress) {
+ return null;
+ }
+ if (data.status === TESTS_FAILED_STATUS) {
+ return EXTENSION_ICONS.warning;
+ }
+ if (data.hasSuiteError) {
+ return EXTENSION_ICONS.failed;
+ }
+ return EXTENSION_ICONS.success;
+ },
+ tertiaryButtons() {
+ return [
+ {
+ text: this.$options.i18n.fullReport,
+ href: `${this.pipeline.path}/test_report`,
+ target: '_blank',
+ },
+ ];
+ },
+ },
+ methods: {
+ fetchCollapsedData() {
+ return axios.get(this.testResultsPath).then(({ data = {}, status }) => {
+ return {
+ data: {
+ hasSuiteError: data.suites?.some((suite) => suite.status === ERROR_STATUS),
+ parsingInProgress: status === 204,
+ ...data,
+ },
+ };
+ });
+ },
+ fetchFullData() {
+ return Promise.resolve(this.prepareReports());
+ },
+ suiteIcon(suite) {
+ if (suite.status === ERROR_STATUS) {
+ return EXTENSION_ICONS.error;
+ }
+ if (suite.status === TESTS_FAILED_STATUS) {
+ return EXTENSION_ICONS.failed;
+ }
+ return EXTENSION_ICONS.success;
+ },
+ prepareReports() {
+ return this.collapsedData.suites.map((suite) => {
+ return {
+ id: uniqueId('suite-'),
+ text: reportTextBuilder(suite),
+ subtext: reportSubTextBuilder(suite),
+ icon: {
+ name: this.suiteIcon(suite),
+ },
+ };
+ });
+ },
+ },
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/utils.js b/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/utils.js
new file mode 100644
index 00000000000..a74ed20362f
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/utils.js
@@ -0,0 +1,55 @@
+import { i18n } from './constants';
+
+const textBuilder = (results, boldNumbers = false) => {
+ const { failed, errored, resolved, total } = results;
+
+ const failedOrErrored = (failed || 0) + (errored || 0);
+ const failedString = failed ? i18n.failedClause(failed, boldNumbers) : null;
+ const erroredString = errored ? i18n.erroredClause(errored, boldNumbers) : null;
+ const combinedString =
+ failed && errored ? `${failedString}, ${erroredString}` : failedString || erroredString;
+ const resolvedString = resolved ? i18n.resolvedClause(resolved, boldNumbers) : null;
+ const totalString = total ? i18n.totalClause(total, boldNumbers) : null;
+
+ let resultsString = i18n.noChanges(boldNumbers);
+
+ if (failedOrErrored) {
+ if (resolved) {
+ resultsString = i18n.resultsString(combinedString, resolvedString);
+ } else {
+ resultsString = combinedString;
+ }
+ } else if (resolved) {
+ resultsString = resolvedString;
+ }
+
+ return `${resultsString}, ${totalString}`;
+};
+
+export const summaryTextBuilder = (name = '', results = {}) => {
+ const resultsString = textBuilder(results, true);
+ return i18n.summaryText(name, resultsString);
+};
+
+export const reportTextBuilder = ({ name = '', summary = {}, status }) => {
+ if (!name) {
+ return i18n.reportError;
+ }
+ if (status === 'error') {
+ return i18n.reportErrorWithName(name);
+ }
+
+ const resultsString = textBuilder(summary);
+ return i18n.summaryText(name, resultsString);
+};
+
+export const reportSubTextBuilder = ({ suite_errors }) => {
+ const errors = [];
+ if (suite_errors?.head) {
+ errors.push(`${i18n.headReportParsingError} ${suite_errors.head}`);
+ }
+ if (suite_errors?.base) {
+ errors.push(`${i18n.baseReportParsingError} ${suite_errors.base}`);
+ }
+ return errors.join('<br />');
+};