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:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-04-21 18:21:10 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-04-21 18:21:10 +0300
commite33f87ac0fabaab468ce4b457996cc0f1b1bb648 (patch)
tree8bf0de72a9acac014cfdaddab7d463b208294af2 /app/assets/javascripts/reports
parent5baf990db20a75078684702782c24399ef9eb0fa (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/reports')
-rw-r--r--app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue13
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/actions.js47
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/index.js14
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/mutation_types.js3
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/mutations.js18
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/state.js30
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/utils.js83
-rw-r--r--app/assets/javascripts/reports/components/grouped_test_reports_app.vue15
-rw-r--r--app/assets/javascripts/reports/constants.js3
-rw-r--r--app/assets/javascripts/reports/store/mutations.js3
10 files changed, 214 insertions, 15 deletions
diff --git a/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue b/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue
index 6aae9195be1..256b0e33e79 100644
--- a/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue
+++ b/app/assets/javascripts/reports/accessibility_report/components/accessibility_issue_body.vue
@@ -26,18 +26,11 @@ export default {
* The TECHS code is the "G18", "G168", "H91", etc. from the code which is used for the documentation.
* Here we simply split the string on `.` and get the code in the 5th position
*/
- if (this.issue.code === undefined) {
- return null;
- }
-
- return this.issue.code.split('.')[4] || null;
+ return this.issue.code?.split('.')[4];
},
learnMoreUrl() {
- if (this.parsedTECHSCode === null) {
- return 'https://www.w3.org/TR/WCAG20-TECHS/Overview.html';
- }
-
- return `https://www.w3.org/TR/WCAG20-TECHS/${this.parsedTECHSCode}.html`;
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return `https://www.w3.org/TR/WCAG20-TECHS/${this.parsedTECHSCode || 'Overview'}.html`;
},
},
};
diff --git a/app/assets/javascripts/reports/accessibility_report/store/actions.js b/app/assets/javascripts/reports/accessibility_report/store/actions.js
new file mode 100644
index 00000000000..f145b352e7d
--- /dev/null
+++ b/app/assets/javascripts/reports/accessibility_report/store/actions.js
@@ -0,0 +1,47 @@
+import axios from '~/lib/utils/axios_utils';
+import * as types from './mutation_types';
+import { parseAccessibilityReport, compareAccessibilityReports } from './utils';
+import { s__ } from '~/locale';
+
+export const fetchReport = ({ state, dispatch, commit }) => {
+ commit(types.REQUEST_REPORT);
+
+ // If we don't have both endpoints, throw an error.
+ if (!state.baseEndpoint || !state.headEndpoint) {
+ commit(
+ types.RECEIVE_REPORT_ERROR,
+ s__('AccessibilityReport|Accessibility report artifact not found'),
+ );
+ return;
+ }
+
+ Promise.all([
+ axios.get(state.baseEndpoint).then(response => ({
+ ...response.data,
+ isHead: false,
+ })),
+ axios.get(state.headEndpoint).then(response => ({
+ ...response.data,
+ isHead: true,
+ })),
+ ])
+ .then(responses => dispatch('receiveReportSuccess', responses))
+ .catch(() =>
+ commit(
+ types.RECEIVE_REPORT_ERROR,
+ s__('AccessibilityReport|Failed to retrieve accessibility report'),
+ ),
+ );
+};
+
+export const receiveReportSuccess = ({ commit }, responses) => {
+ const parsedReports = responses.map(response => ({
+ isHead: response.isHead,
+ issues: parseAccessibilityReport(response),
+ }));
+ const report = compareAccessibilityReports(parsedReports);
+ commit(types.RECEIVE_REPORT_SUCCESS, report);
+};
+
+// prevent babel-plugin-rewire from generating an invalid default during karma tests
+export default () => {};
diff --git a/app/assets/javascripts/reports/accessibility_report/store/index.js b/app/assets/javascripts/reports/accessibility_report/store/index.js
new file mode 100644
index 00000000000..c1413499802
--- /dev/null
+++ b/app/assets/javascripts/reports/accessibility_report/store/index.js
@@ -0,0 +1,14 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import * as actions from './actions';
+import mutations from './mutations';
+import state from './state';
+
+Vue.use(Vuex);
+
+export default initialState =>
+ new Vuex.Store({
+ actions,
+ mutations,
+ state: state(initialState),
+ });
diff --git a/app/assets/javascripts/reports/accessibility_report/store/mutation_types.js b/app/assets/javascripts/reports/accessibility_report/store/mutation_types.js
new file mode 100644
index 00000000000..381736bbd38
--- /dev/null
+++ b/app/assets/javascripts/reports/accessibility_report/store/mutation_types.js
@@ -0,0 +1,3 @@
+export const REQUEST_REPORT = 'REQUEST_REPORT';
+export const RECEIVE_REPORT_SUCCESS = 'RECEIVE_REPORT_SUCCESS';
+export const RECEIVE_REPORT_ERROR = 'RECEIVE_REPORT_ERROR';
diff --git a/app/assets/javascripts/reports/accessibility_report/store/mutations.js b/app/assets/javascripts/reports/accessibility_report/store/mutations.js
new file mode 100644
index 00000000000..66cf9f3d69d
--- /dev/null
+++ b/app/assets/javascripts/reports/accessibility_report/store/mutations.js
@@ -0,0 +1,18 @@
+import * as types from './mutation_types';
+
+export default {
+ [types.REQUEST_REPORT](state) {
+ state.isLoading = true;
+ },
+ [types.RECEIVE_REPORT_SUCCESS](state, report) {
+ state.hasError = false;
+ state.isLoading = false;
+ state.report = report;
+ },
+ [types.RECEIVE_REPORT_ERROR](state, message) {
+ state.isLoading = false;
+ state.hasError = true;
+ state.errorMessage = message;
+ state.report = {};
+ },
+};
diff --git a/app/assets/javascripts/reports/accessibility_report/store/state.js b/app/assets/javascripts/reports/accessibility_report/store/state.js
new file mode 100644
index 00000000000..7d560a9f419
--- /dev/null
+++ b/app/assets/javascripts/reports/accessibility_report/store/state.js
@@ -0,0 +1,30 @@
+export default (initialState = {}) => ({
+ baseEndpoint: initialState.baseEndpoint || '',
+ headEndpoint: initialState.headEndpoint || '',
+
+ isLoading: initialState.isLoading || false,
+ hasError: initialState.hasError || false,
+
+ /**
+ * Report will have the following format:
+ * {
+ * status: {String},
+ * summary: {
+ * total: {Number},
+ * notes: {Number},
+ * warnings: {Number},
+ * errors: {Number},
+ * },
+ * existing_errors: {Array.<Object>},
+ * existing_notes: {Array.<Object>},
+ * existing_warnings: {Array.<Object>},
+ * new_errors: {Array.<Object>},
+ * new_notes: {Array.<Object>},
+ * new_warnings: {Array.<Object>},
+ * resolved_errors: {Array.<Object>},
+ * resolved_notes: {Array.<Object>},
+ * resolved_warnings: {Array.<Object>},
+ * }
+ */
+ report: initialState.report || {},
+});
diff --git a/app/assets/javascripts/reports/accessibility_report/store/utils.js b/app/assets/javascripts/reports/accessibility_report/store/utils.js
new file mode 100644
index 00000000000..f2de65445b0
--- /dev/null
+++ b/app/assets/javascripts/reports/accessibility_report/store/utils.js
@@ -0,0 +1,83 @@
+import { difference, intersection } from 'lodash';
+import {
+ STATUS_FAILED,
+ STATUS_SUCCESS,
+ ACCESSIBILITY_ISSUE_ERROR,
+ ACCESSIBILITY_ISSUE_WARNING,
+} from '../../constants';
+
+export const parseAccessibilityReport = data => {
+ // Combine all issues into one array
+ return Object.keys(data.results)
+ .map(key => [...data.results[key]])
+ .flat()
+ .map(issue => JSON.stringify(issue)); // stringify to help with comparisons
+};
+
+export const compareAccessibilityReports = reports => {
+ const result = {
+ status: '',
+ summary: {
+ total: 0,
+ notes: 0,
+ errors: 0,
+ warnings: 0,
+ },
+ new_errors: [],
+ new_notes: [],
+ new_warnings: [],
+ resolved_errors: [],
+ resolved_notes: [],
+ resolved_warnings: [],
+ existing_errors: [],
+ existing_notes: [],
+ existing_warnings: [],
+ };
+
+ const headReport = reports.filter(report => report.isHead)[0];
+ const baseReport = reports.filter(report => !report.isHead)[0];
+
+ // existing issues are those that exist in both the head report and the base report
+ const existingIssues = intersection(headReport.issues, baseReport.issues);
+ // new issues are those that exist in only the head report
+ const newIssues = difference(headReport.issues, baseReport.issues);
+ // resolved issues are those that exist in only the base report
+ const resolvedIssues = difference(baseReport.issues, headReport.issues);
+
+ const parseIssues = (issue, issueType, shouldCount) => {
+ const parsedIssue = JSON.parse(issue);
+ switch (parsedIssue.type) {
+ case ACCESSIBILITY_ISSUE_ERROR:
+ result[`${issueType}_errors`].push(parsedIssue);
+ if (shouldCount) {
+ result.summary.errors += 1;
+ }
+ break;
+ case ACCESSIBILITY_ISSUE_WARNING:
+ result[`${issueType}_warnings`].push(parsedIssue);
+ if (shouldCount) {
+ result.summary.warnings += 1;
+ }
+ break;
+ default:
+ result[`${issueType}_notes`].push(parsedIssue);
+ if (shouldCount) {
+ result.summary.notes += 1;
+ }
+ break;
+ }
+ };
+
+ existingIssues.forEach(issue => parseIssues(issue, 'existing', true));
+ newIssues.forEach(issue => parseIssues(issue, 'new', true));
+ resolvedIssues.forEach(issue => parseIssues(issue, 'resolved', false));
+
+ result.summary.total = result.summary.errors + result.summary.warnings + result.summary.notes;
+ const hasErrorsOrWarnings = result.summary.errors > 0 || result.summary.warnings > 0;
+ result.status = hasErrorsOrWarnings ? STATUS_FAILED : STATUS_SUCCESS;
+
+ return result;
+};
+
+// prevent babel-plugin-rewire from generating an invalid default during karma tests
+export default () => {};
diff --git a/app/assets/javascripts/reports/components/grouped_test_reports_app.vue b/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
index 88d174f96ed..0f7a0e60dc0 100644
--- a/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
+++ b/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import { s__ } from '~/locale';
+import { sprintf, s__ } from '~/locale';
import { componentNames } from './issue_body';
import ReportSection from './report_section.vue';
import SummaryRow from './summary_row.vue';
@@ -52,8 +52,17 @@ export default {
methods: {
...mapActions(['setEndpoint', 'fetchReports']),
reportText(report) {
- const summary = report.summary || {};
- return reportTextBuilder(report.name, summary);
+ const { name, summary } = report || {};
+
+ if (report.status === 'error') {
+ return sprintf(s__('Reports|An error occurred while loading %{name} results'), { name });
+ }
+
+ if (!report.name) {
+ return s__('Reports|An error occured while loading report');
+ }
+
+ return reportTextBuilder(name, summary);
},
getReportIcon(report) {
return statusIcon(report.status);
diff --git a/app/assets/javascripts/reports/constants.js b/app/assets/javascripts/reports/constants.js
index 1845b51e6b2..b3905cbfcfb 100644
--- a/app/assets/javascripts/reports/constants.js
+++ b/app/assets/javascripts/reports/constants.js
@@ -22,3 +22,6 @@ export const status = {
ERROR: 'ERROR',
SUCCESS: 'SUCCESS',
};
+
+export const ACCESSIBILITY_ISSUE_ERROR = 'error';
+export const ACCESSIBILITY_ISSUE_WARNING = 'warning';
diff --git a/app/assets/javascripts/reports/store/mutations.js b/app/assets/javascripts/reports/store/mutations.js
index 68f6de3a7ee..35ab72bf694 100644
--- a/app/assets/javascripts/reports/store/mutations.js
+++ b/app/assets/javascripts/reports/store/mutations.js
@@ -8,8 +8,7 @@ export default {
state.isLoading = true;
},
[types.RECEIVE_REPORTS_SUCCESS](state, response) {
- // Make sure to clean previous state in case it was an error
- state.hasError = false;
+ state.hasError = response.suites.some(suite => suite.status === 'error');
state.isLoading = false;