summaryrefslogtreecommitdiff
path: root/spec/frontend/alert_management/components/alert_management_table_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/alert_management/components/alert_management_table_spec.js')
-rw-r--r--spec/frontend/alert_management/components/alert_management_table_spec.js370
1 files changed, 74 insertions, 296 deletions
diff --git a/spec/frontend/alert_management/components/alert_management_table_spec.js b/spec/frontend/alert_management/components/alert_management_table_spec.js
index bcad415eb19..f7a629142f9 100644
--- a/spec/frontend/alert_management/components/alert_management_table_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_table_spec.js
@@ -1,26 +1,13 @@
import { mount } from '@vue/test-utils';
-import {
- GlTable,
- GlAlert,
- GlLoadingIcon,
- GlDeprecatedDropdown,
- GlDeprecatedDropdownItem,
- GlIcon,
- GlTabs,
- GlTab,
- GlBadge,
- GlPagination,
- GlSearchBoxByType,
- GlAvatar,
-} from '@gitlab/ui';
-import waitForPromises from 'helpers/wait_for_promises';
+import { GlTable, GlAlert, GlLoadingIcon, GlDropdown, GlIcon, GlAvatar } from '@gitlab/ui';
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
import { visitUrl } from '~/lib/utils/url_utility';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import AlertManagementTable from '~/alert_management/components/alert_management_table.vue';
-import { ALERTS_STATUS_TABS, trackAlertStatusUpdateOptions } from '~/alert_management/constants';
-import updateAlertStatus from '~/alert_management/graphql/mutations/update_alert_status.mutation.graphql';
+import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import mockAlerts from '../mocks/alerts.json';
-import Tracking from '~/tracking';
+import defaultProvideValues from '../mocks/alerts_provide_config.json';
jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn().mockName('visitUrlMock'),
@@ -29,26 +16,21 @@ jest.mock('~/lib/utils/url_utility', () => ({
describe('AlertManagementTable', () => {
let wrapper;
+ let mock;
const findAlertsTable = () => wrapper.find(GlTable);
const findAlerts = () => wrapper.findAll('table tbody tr');
const findAlert = () => wrapper.find(GlAlert);
const findLoader = () => wrapper.find(GlLoadingIcon);
- const findStatusDropdown = () => wrapper.find(GlDeprecatedDropdown);
- const findStatusFilterTabs = () => wrapper.findAll(GlTab);
- const findStatusTabs = () => wrapper.find(GlTabs);
- const findStatusFilterBadge = () => wrapper.findAll(GlBadge);
+ const findStatusDropdown = () => wrapper.find(GlDropdown);
const findDateFields = () => wrapper.findAll(TimeAgo);
- const findFirstStatusOption = () => findStatusDropdown().find(GlDeprecatedDropdownItem);
- const findPagination = () => wrapper.find(GlPagination);
- const findSearch = () => wrapper.find(GlSearchBoxByType);
+ const findSearch = () => wrapper.find(FilteredSearchBar);
const findSeverityColumnHeader = () =>
wrapper.find('[data-testid="alert-management-severity-sort"]');
const findFirstIDField = () => wrapper.findAll('[data-testid="idField"]').at(0);
const findAssignees = () => wrapper.findAll('[data-testid="assigneesField"]');
const findSeverityFields = () => wrapper.findAll('[data-testid="severityField"]');
const findIssueFields = () => wrapper.findAll('[data-testid="issueField"]');
- const findAlertError = () => wrapper.find('[data-testid="alert-error"]');
const alertsCount = {
open: 24,
triggered: 20,
@@ -56,26 +38,14 @@ describe('AlertManagementTable', () => {
resolved: 11,
all: 26,
};
- const selectFirstStatusOption = () => {
- findFirstStatusOption().vm.$emit('click');
- return waitForPromises();
- };
-
- function mountComponent({
- props = {
- alertManagementEnabled: false,
- userCanEnableAlertManagement: false,
- },
- data = {},
- loading = false,
- stubs = {},
- } = {}) {
+ function mountComponent({ provide = {}, data = {}, loading = false, stubs = {} } = {}) {
wrapper = mount(AlertManagementTable, {
- propsData: {
- projectPath: 'gitlab-org/gitlab',
- populatingAlertsHelpUrl: '/help/help-page.md#populating-alert-data',
- ...props,
+ provide: {
+ ...defaultProvideValues,
+ alertManagementEnabled: true,
+ userCanEnableAlertManagement: true,
+ ...provide,
},
data() {
return data;
@@ -95,41 +65,21 @@ describe('AlertManagementTable', () => {
});
}
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
afterEach(() => {
if (wrapper) {
wrapper.destroy();
wrapper = null;
}
- });
-
- describe('Status Filter Tabs', () => {
- beforeEach(() => {
- mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: mockAlerts, alertsCount },
- loading: false,
- stubs: {
- GlTab: true,
- },
- });
- });
-
- it('should display filter tabs with alerts count badge for each status', () => {
- const tabs = findStatusFilterTabs().wrappers;
- const badges = findStatusFilterBadge();
-
- tabs.forEach((tab, i) => {
- const status = ALERTS_STATUS_TABS[i].status.toLowerCase();
- expect(tab.text()).toContain(ALERTS_STATUS_TABS[i].title);
- expect(badges.at(i).text()).toContain(alertsCount[status]);
- });
- });
+ mock.restore();
});
describe('Alerts table', () => {
it('loading state', () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: {}, alertsCount: null },
loading: true,
});
@@ -144,8 +94,7 @@ describe('AlertManagementTable', () => {
it('error state', () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { errors: ['error'] }, alertsCount: null, hasError: true },
+ data: { alerts: { errors: ['error'] }, alertsCount: null, errored: true },
loading: false,
});
expect(findAlertsTable().exists()).toBe(true);
@@ -161,10 +110,17 @@ describe('AlertManagementTable', () => {
it('empty state', () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: [], pageInfo: {} }, alertsCount: { all: 0 }, hasError: false },
+ data: {
+ alerts: { list: [], pageInfo: {} },
+ alertsCount: { all: 0 },
+ errored: false,
+ isErrorAlertDismissed: false,
+ searchTerm: '',
+ assigneeUsername: '',
+ },
loading: false,
});
+
expect(findAlertsTable().exists()).toBe(true);
expect(findAlertsTable().text()).toContain('No alerts to display');
expect(findLoader().exists()).toBe(false);
@@ -178,8 +134,7 @@ describe('AlertManagementTable', () => {
it('has data state', () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
expect(findLoader().exists()).toBe(false);
@@ -194,8 +149,7 @@ describe('AlertManagementTable', () => {
it('displays the alert ID and title formatted correctly', () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
@@ -205,8 +159,7 @@ describe('AlertManagementTable', () => {
it('displays status dropdown', () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
expect(findStatusDropdown().exists()).toBe(true);
@@ -214,8 +167,7 @@ describe('AlertManagementTable', () => {
it('does not display a dropdown status header', () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
expect(
@@ -225,27 +177,25 @@ describe('AlertManagementTable', () => {
).toBe(false);
});
- it('shows correct severity icons', () => {
+ it('shows correct severity icons', async () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlTable).exists()).toBe(true);
- expect(
- findAlertsTable()
- .find(GlIcon)
- .classes('icon-critical'),
- ).toBe(true);
- });
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlTable).exists()).toBe(true);
+ expect(
+ findAlertsTable()
+ .find(GlIcon)
+ .classes('icon-critical'),
+ ).toBe(true);
});
it('renders severity text', () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
@@ -258,8 +208,7 @@ describe('AlertManagementTable', () => {
it('renders Unassigned when no assignee(s) present', () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
@@ -272,8 +221,7 @@ describe('AlertManagementTable', () => {
it('renders user avatar when assignee present', () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
@@ -290,22 +238,39 @@ describe('AlertManagementTable', () => {
it('navigates to the detail page when alert row is clicked', () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
+ expect(visitUrl).not.toHaveBeenCalled();
+
findAlerts()
.at(0)
.trigger('click');
- expect(visitUrl).toHaveBeenCalledWith('/1527542/details');
+ expect(visitUrl).toHaveBeenCalledWith('/1527542/details', false);
+ });
+
+ it('navigates to the detail page in new tab when alert row is clicked with the metaKey', () => {
+ mountComponent({
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
+ loading: false,
+ });
+
+ expect(visitUrl).not.toHaveBeenCalled();
+
+ findAlerts()
+ .at(0)
+ .trigger('click', {
+ metaKey: true,
+ });
+
+ expect(visitUrl).toHaveBeenCalledWith('/1527542/details', true);
});
describe('alert issue links', () => {
beforeEach(() => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
});
@@ -335,7 +300,6 @@ describe('AlertManagementTable', () => {
describe('handle date fields', () => {
it('should display time ago dates when values provided', () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: {
alerts: {
list: [
@@ -349,7 +313,7 @@ describe('AlertManagementTable', () => {
],
},
alertsCount,
- hasError: false,
+ errored: false,
},
loading: false,
});
@@ -358,7 +322,6 @@ describe('AlertManagementTable', () => {
it('should not display time ago dates when values not provided', () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: {
alerts: [
{
@@ -369,7 +332,7 @@ describe('AlertManagementTable', () => {
},
],
alertsCount,
- hasError: false,
+ errored: false,
},
loading: false,
});
@@ -383,8 +346,7 @@ describe('AlertManagementTable', () => {
it('should highlight the row when alert is new', () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: [newAlert] }, alertsCount, hasError: false },
+ data: { alerts: { list: [newAlert] }, alertsCount, errored: false },
loading: false,
});
@@ -397,8 +359,7 @@ describe('AlertManagementTable', () => {
it('should not highlight the row when alert is not new', () => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: [oldAlert] }, alertsCount, hasError: false },
+ data: { alerts: { list: [oldAlert] }, alertsCount, errored: false },
loading: false,
});
@@ -415,10 +376,9 @@ describe('AlertManagementTable', () => {
describe('sorting the alert list by column', () => {
beforeEach(() => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: {
alerts: { list: mockAlerts },
- hasError: false,
+ errored: false,
sort: 'STARTED_AT_DESC',
alertsCount,
},
@@ -438,184 +398,10 @@ describe('AlertManagementTable', () => {
});
});
- describe('updating the alert status', () => {
- const iid = '1527542';
- const mockUpdatedMutationResult = {
- data: {
- updateAlertStatus: {
- errors: [],
- alert: {
- iid,
- status: 'acknowledged',
- },
- },
- },
- };
-
- beforeEach(() => {
- mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
- loading: false,
- });
- });
-
- it('calls `$apollo.mutate` with `updateAlertStatus` mutation and variables containing `iid`, `status`, & `projectPath`', () => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
- findFirstStatusOption().vm.$emit('click');
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: updateAlertStatus,
- variables: {
- iid,
- status: 'TRIGGERED',
- projectPath: 'gitlab-org/gitlab',
- },
- });
- });
-
- describe('when a request fails', () => {
- beforeEach(() => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockReturnValue(Promise.reject(new Error()));
- });
-
- it('shows an error', async () => {
- await selectFirstStatusOption();
-
- expect(findAlertError().text()).toContain(
- 'There was an error while updating the status of the alert.',
- );
- });
-
- it('shows an error when triggered a second time', async () => {
- await selectFirstStatusOption();
-
- wrapper.find(GlAlert).vm.$emit('dismiss');
-
- await wrapper.vm.$nextTick();
-
- // Assert that the error has been dismissed in the setup
- expect(findAlertError().exists()).toBe(false);
-
- await selectFirstStatusOption();
-
- expect(findAlertError().exists()).toBe(true);
- });
- });
-
- it('shows an error when response includes HTML errors', async () => {
- const mockUpdatedMutationErrorResult = {
- data: {
- updateAlertStatus: {
- errors: ['<span data-testid="htmlError" />'],
- alert: {
- iid,
- status: 'acknowledged',
- },
- },
- },
- };
-
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationErrorResult);
-
- await selectFirstStatusOption();
-
- expect(findAlertError().exists()).toBe(true);
- expect(
- findAlertError()
- .find('[data-testid="htmlError"]')
- .exists(),
- ).toBe(true);
- });
- });
-
- describe('Snowplow tracking', () => {
- beforeEach(() => {
- jest.spyOn(Tracking, 'event');
- mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: mockAlerts }, alertsCount },
- loading: false,
- });
- });
-
- it('should track alert status updates', () => {
- Tracking.event.mockClear();
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({});
- findFirstStatusOption().vm.$emit('click');
- const status = findFirstStatusOption().text();
- setImmediate(() => {
- const { category, action, label } = trackAlertStatusUpdateOptions;
- expect(Tracking.event).toHaveBeenCalledWith(category, action, { label, property: status });
- });
- });
- });
-
- describe('Pagination', () => {
- beforeEach(() => {
- mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: mockAlerts, pageInfo: {} }, alertsCount, hasError: false },
- loading: false,
- });
- });
-
- it('does NOT show pagination control when list is smaller than default page size', () => {
- findStatusTabs().vm.$emit('input', 3);
- return wrapper.vm.$nextTick(() => {
- expect(findPagination().exists()).toBe(false);
- });
- });
-
- it('shows pagination control when list is larger than default page size', () => {
- findStatusTabs().vm.$emit('input', 0);
- return wrapper.vm.$nextTick(() => {
- expect(findPagination().exists()).toBe(true);
- });
- });
-
- describe('prevPage', () => {
- it('returns prevPage number', () => {
- findPagination().vm.$emit('input', 3);
-
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.prevPage).toBe(2);
- });
- });
-
- it('returns 0 when it is the first page', () => {
- findPagination().vm.$emit('input', 1);
-
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.prevPage).toBe(0);
- });
- });
- });
-
- describe('nextPage', () => {
- it('returns nextPage number', () => {
- findPagination().vm.$emit('input', 1);
-
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.nextPage).toBe(2);
- });
- });
-
- it('returns `null` when currentPage is already last page', () => {
- findStatusTabs().vm.$emit('input', 3);
- findPagination().vm.$emit('input', 1);
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.vm.nextPage).toBeNull();
- });
- });
- });
- });
-
describe('Search', () => {
beforeEach(() => {
mountComponent({
- props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
- data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
+ data: { alerts: { list: mockAlerts }, alertsCount, errored: false },
loading: false,
});
});
@@ -623,13 +409,5 @@ describe('AlertManagementTable', () => {
it('renders the search component', () => {
expect(findSearch().exists()).toBe(true);
});
-
- it('sets the `searchTerm` graphql variable', () => {
- const SEARCH_TERM = 'Simple Alert';
-
- findSearch().vm.$emit('input', SEARCH_TERM);
-
- expect(wrapper.vm.$data.searchTerm).toBe(SEARCH_TERM);
- });
});
});