diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-19 18:09:36 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-19 18:09:36 +0300 |
commit | 8bb837c4d180720d4d923ef2e7bd2c9a46ca97a0 (patch) | |
tree | 7dcb166661ba29fb6cd5935f0db34eee6c935388 /spec/frontend/error_tracking | |
parent | eef2437c0a359ec3437d31d1b1ea959e54c71458 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/error_tracking')
4 files changed, 190 insertions, 4 deletions
diff --git a/spec/frontend/error_tracking/components/error_details_spec.js b/spec/frontend/error_tracking/components/error_details_spec.js index 92f2e62b3a7..c9238c4b636 100644 --- a/spec/frontend/error_tracking/components/error_details_spec.js +++ b/spec/frontend/error_tracking/components/error_details_spec.js @@ -17,6 +17,7 @@ import ErrorDetailsInfo from '~/error_tracking/components/error_details_info.vue import { createAlert, VARIANT_WARNING } from '~/alert'; import { __ } from '~/locale'; import Tracking from '~/tracking'; +import TimelineChart from '~/error_tracking/components/timeline_chart.vue'; jest.mock('~/alert'); jest.mock('~/tracking'); @@ -159,6 +160,7 @@ describe('ErrorDetails', () => { mocks.$apollo.queries.error.loading = false; mountComponent(); // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details + // TODO remove setData usage https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2216 // eslint-disable-next-line no-restricted-syntax wrapper.setData({ error: { @@ -183,6 +185,7 @@ describe('ErrorDetails', () => { beforeEach(() => { store.state.details.loadingStacktrace = false; // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details + // TODO remove setData usage https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2216 // eslint-disable-next-line no-restricted-syntax wrapper.setData({ error: { @@ -204,6 +207,7 @@ describe('ErrorDetails', () => { describe('Badges', () => { it('should show language and error level badges', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details + // TODO remove setData usage https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2216 // eslint-disable-next-line no-restricted-syntax wrapper.setData({ error: { @@ -216,6 +220,7 @@ describe('ErrorDetails', () => { it('should NOT show the badge if the tag is not present', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details + // TODO remove setData usage https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2216 // eslint-disable-next-line no-restricted-syntax wrapper.setData({ error: { @@ -230,6 +235,7 @@ describe('ErrorDetails', () => { 'should set correct severity level variant for %s badge', async (level) => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details + // TODO remove setData usage https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2216 // eslint-disable-next-line no-restricted-syntax wrapper.setData({ error: { @@ -245,6 +251,7 @@ describe('ErrorDetails', () => { it('should fallback for ERROR severityLevelVariant when severityLevel is unknown', async () => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details + // TODO remove setData usage https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2216 // eslint-disable-next-line no-restricted-syntax wrapper.setData({ error: { @@ -268,6 +275,32 @@ describe('ErrorDetails', () => { }); }); + describe('timeline chart', () => { + it('should not show timeline chart if frequency data does not exist', () => { + expect(wrapper.findComponent(TimelineChart).exists()).toBe(false); + expect(wrapper.text()).not.toContain('Last 24 hours'); + }); + + it('should show timeline chart', async () => { + const mockFrequency = [ + [0, 1], + [2, 3], + ]; + // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details + // TODO remove setData usage https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2216 + // eslint-disable-next-line no-restricted-syntax + wrapper.setData({ + error: { + frequency: mockFrequency, + }, + }); + await nextTick(); + expect(wrapper.findComponent(TimelineChart).exists()).toBe(true); + expect(wrapper.findComponent(TimelineChart).props('timelineData')).toEqual(mockFrequency); + expect(wrapper.text()).toContain('Last 24 hours'); + }); + }); + describe('Stacktrace', () => { it('should show stacktrace', async () => { store.state.details.loadingStacktrace = false; @@ -402,6 +435,7 @@ describe('ErrorDetails', () => { it('should show alert with closed issueId', async () => { const closedIssueId = 123; // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details + // TODO remove setData usage https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2216 // eslint-disable-next-line no-restricted-syntax wrapper.setData({ isAlertVisible: true, @@ -424,6 +458,7 @@ describe('ErrorDetails', () => { describe('is present', () => { beforeEach(() => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details + // TODO remove setData usage https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2216 // eslint-disable-next-line no-restricted-syntax wrapper.setData({ error: { @@ -448,6 +483,7 @@ describe('ErrorDetails', () => { describe('is not present', () => { beforeEach(() => { // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details + // TODO remove setData usage https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2216 // eslint-disable-next-line no-restricted-syntax wrapper.setData({ error: { @@ -482,6 +518,7 @@ describe('ErrorDetails', () => { beforeEach(() => { mountComponent({ integratedErrorTrackingEnabled: integrated }); // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details + // TODO remove setData usage https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2216 // eslint-disable-next-line no-restricted-syntax wrapper.setData({ error: {}, diff --git a/spec/frontend/error_tracking/components/error_tracking_list_spec.js b/spec/frontend/error_tracking/components/error_tracking_list_spec.js index 5483500e1dd..49f365e8c60 100644 --- a/spec/frontend/error_tracking/components/error_tracking_list_spec.js +++ b/spec/frontend/error_tracking/components/error_tracking_list_spec.js @@ -12,6 +12,7 @@ import Vuex from 'vuex'; import stubChildren from 'helpers/stub_children'; import ErrorTrackingActions from '~/error_tracking/components/error_tracking_actions.vue'; import ErrorTrackingList from '~/error_tracking/components/error_tracking_list.vue'; +import TimelineChart from '~/error_tracking/components/timeline_chart.vue'; import Tracking from '~/tracking'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import errorsList from './list_mock.json'; @@ -158,6 +159,30 @@ describe('ErrorTrackingList', () => { }); }); + describe('timeline graph', () => { + it('should show the timeline chart', () => { + findErrorListRows().wrappers.forEach((row, index) => { + expect(row.findComponent(TimelineChart).exists()).toBe(true); + const mockFrequency = errorsList[index].frequency; + expect(row.findComponent(TimelineChart).props('timelineData')).toEqual(mockFrequency); + }); + }); + + it('should not show the timeline chart if frequency data does not exist', () => { + store.state.list.errors = errorsList.map((e) => ({ ...e, frequency: undefined })); + mountComponent({ + stubs: { + GlTable: false, + GlLink: false, + }, + }); + + findErrorListRows().wrappers.forEach((row) => { + expect(row.findComponent(TimelineChart).exists()).toBe(false); + }); + }); + }); + describe('filtering', () => { const findSearchBox = () => wrapper.findComponent(GlFormInput); diff --git a/spec/frontend/error_tracking/components/list_mock.json b/spec/frontend/error_tracking/components/list_mock.json index 54ae0a4c7cf..f8addef324e 100644 --- a/spec/frontend/error_tracking/components/list_mock.json +++ b/spec/frontend/error_tracking/components/list_mock.json @@ -7,7 +7,17 @@ "count": "52", "firstSeen": "2019-05-30T07:21:46Z", "lastSeen": "2019-11-06T03:21:39Z", - "status": "unresolved" + "status": "unresolved", + "frequency": [ + [ + 0, + 1 + ], + [ + 1, + 2 + ] + ] }, { "id": "2", @@ -17,7 +27,17 @@ "count": "12", "firstSeen": "2019-10-19T03:53:56Z", "lastSeen": "2019-11-05T03:51:54Z", - "status": "unresolved" + "status": "unresolved", + "frequency": [ + [ + 0, + 1 + ], + [ + 1, + 2 + ] + ] }, { "id": "3", @@ -27,6 +47,16 @@ "count": "275", "firstSeen": "2019-02-12T07:22:36Z", "lastSeen": "2019-10-22T03:20:48Z", - "status": "unresolved" + "status": "unresolved", + "frequency": [ + [ + 0, + 1 + ], + [ + 1, + 2 + ] + ] } -]
\ No newline at end of file +] diff --git a/spec/frontend/error_tracking/components/timeline_chart_spec.js b/spec/frontend/error_tracking/components/timeline_chart_spec.js new file mode 100644 index 00000000000..f864d11804c --- /dev/null +++ b/spec/frontend/error_tracking/components/timeline_chart_spec.js @@ -0,0 +1,94 @@ +import { GlChart } from '@gitlab/ui/dist/charts'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import TimelineChart from '~/error_tracking/components/timeline_chart.vue'; + +const MOCK_HEIGHT = 123; + +describe('TimelineChart', () => { + let wrapper; + + function mountComponent(timelineData = []) { + wrapper = shallowMountExtended(TimelineChart, { + stubs: { GlChart: true }, + propsData: { + timelineData: [...timelineData], + height: MOCK_HEIGHT, + }, + }); + } + + beforeEach(() => { + mountComponent(); + }); + + it('renders the component', () => { + expect(wrapper.exists()).toBe(true); + }); + + it('does not render a chart if timelineData is missing', () => { + wrapper = shallowMountExtended(TimelineChart, { + stubs: { GlChart: true }, + propsData: { + timelineData: undefined, + height: MOCK_HEIGHT, + }, + }); + expect(wrapper.findComponent(GlChart).exists()).toBe(false); + }); + + it('renders a gl-chart', () => { + expect(wrapper.findComponent(GlChart).exists()).toBe(true); + expect(wrapper.findComponent(GlChart).props('height')).toBe(MOCK_HEIGHT); + }); + + describe('timeline-data', () => { + describe.each([ + { + mockItems: [ + [1686218400, 1], + [1686222000, 2], + ], + expectedX: ['Jun 8, 2023 10:00am UTC', 'Jun 8, 2023 11:00am UTC'], + expectedY: [1, 2], + description: 'tuples with dates as timestamps in seconds', + }, + { + mockItems: [ + ['06-05-2023', 1], + ['06-06-2023', 2], + ], + expectedX: ['Jun 5, 2023 12:00am UTC', 'Jun 6, 2023 12:00am UTC'], + expectedY: [1, 2], + description: 'tuples with non-numeric dates', + }, + { + mockItems: [ + { time: 1686218400, count: 1 }, + { time: 1686222000, count: 2 }, + ], + expectedX: ['Jun 8, 2023 10:00am UTC', 'Jun 8, 2023 11:00am UTC'], + expectedY: [1, 2], + description: 'objects with dates as timestamps in seconds', + }, + { + mockItems: [ + { time: '06-05-2023', count: 1 }, + { time: '06-06-2023', count: 2 }, + ], + expectedX: ['Jun 5, 2023 12:00am UTC', 'Jun 6, 2023 12:00am UTC'], + expectedY: [1, 2], + description: 'objects with non-numeric dates', + }, + ])('when timeline-data items are $description', ({ mockItems, expectedX, expectedY }) => { + it(`renders the chart correctly`, () => { + mountComponent(mockItems); + + const chartOptions = wrapper.findComponent(GlChart).props('options'); + const xData = chartOptions.xAxis.data; + const yData = chartOptions.series[0].data; + expect(xData).toEqual(expectedX); + expect(yData).toEqual(expectedY); + }); + }); + }); +}); |