summaryrefslogtreecommitdiff
path: root/spec/frontend/ci/reports/components/report_section_spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/ci/reports/components/report_section_spec.js')
-rw-r--r--spec/frontend/ci/reports/components/report_section_spec.js285
1 files changed, 285 insertions, 0 deletions
diff --git a/spec/frontend/ci/reports/components/report_section_spec.js b/spec/frontend/ci/reports/components/report_section_spec.js
new file mode 100644
index 00000000000..f032b210184
--- /dev/null
+++ b/spec/frontend/ci/reports/components/report_section_spec.js
@@ -0,0 +1,285 @@
+import { GlButton } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import HelpPopover from '~/vue_shared/components/help_popover.vue';
+import ReportItem from '~/ci/reports/components/report_item.vue';
+import ReportSection from '~/ci/reports/components/report_section.vue';
+
+describe('ReportSection component', () => {
+ let wrapper;
+
+ const findExpandButton = () => wrapper.findComponent(GlButton);
+ const findPopover = () => wrapper.findComponent(HelpPopover);
+ const findReportSection = () => wrapper.find('.js-report-section-container');
+ const expectExpandButtonOpen = () =>
+ expect(findExpandButton().props('icon')).toBe('chevron-lg-up');
+ const expectExpandButtonClosed = () =>
+ expect(findExpandButton().props('icon')).toBe('chevron-lg-down');
+
+ const resolvedIssues = [
+ {
+ name: 'Insecure Dependency',
+ fingerprint: 'ca2e59451e98ae60ba2f54e3857c50e5',
+ path: 'Gemfile.lock',
+ line: 12,
+ urlPath: 'foo/Gemfile.lock',
+ },
+ ];
+
+ const defaultProps = {
+ component: '',
+ status: 'SUCCESS',
+ loadingText: 'Loading Code Quality report',
+ errorText: 'foo',
+ successText: 'Code quality improved on 1 point and degraded on 1 point',
+ resolvedIssues,
+ hasIssues: false,
+ alwaysOpen: false,
+ };
+
+ const createComponent = ({ props = {}, data = {}, slots = {} } = {}) => {
+ wrapper = mountExtended(ReportSection, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ data() {
+ return data;
+ },
+ slots,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('computed', () => {
+ describe('isCollapsible', () => {
+ const testMatrix = [
+ { hasIssues: false, alwaysOpen: false, isCollapsible: false },
+ { hasIssues: false, alwaysOpen: true, isCollapsible: false },
+ { hasIssues: true, alwaysOpen: false, isCollapsible: true },
+ { hasIssues: true, alwaysOpen: true, isCollapsible: false },
+ ];
+
+ testMatrix.forEach(({ hasIssues, alwaysOpen, isCollapsible }) => {
+ const issues = hasIssues ? 'has issues' : 'has no issues';
+ const open = alwaysOpen ? 'is always open' : 'is not always open';
+
+ it(`is ${isCollapsible}, if the report ${issues} and ${open}`, () => {
+ createComponent({ props: { hasIssues, alwaysOpen } });
+
+ expect(wrapper.vm.isCollapsible).toBe(isCollapsible);
+ });
+ });
+ });
+
+ describe('isExpanded', () => {
+ const testMatrix = [
+ { isCollapsed: false, alwaysOpen: false, isExpanded: true },
+ { isCollapsed: false, alwaysOpen: true, isExpanded: true },
+ { isCollapsed: true, alwaysOpen: false, isExpanded: false },
+ { isCollapsed: true, alwaysOpen: true, isExpanded: true },
+ ];
+
+ testMatrix.forEach(({ isCollapsed, alwaysOpen, isExpanded }) => {
+ const issues = isCollapsed ? 'is collapsed' : 'is not collapsed';
+ const open = alwaysOpen ? 'is always open' : 'is not always open';
+
+ it(`is ${isExpanded}, if the report ${issues} and ${open}`, () => {
+ createComponent({ props: { alwaysOpen }, data: { isCollapsed } });
+
+ expect(wrapper.vm.isExpanded).toBe(isExpanded);
+ });
+ });
+ });
+ });
+
+ describe('when it is loading', () => {
+ it('should render loading indicator', () => {
+ createComponent({
+ props: {
+ component: '',
+ status: 'LOADING',
+ loadingText: 'Loading Code Quality report',
+ errorText: 'foo',
+ successText: 'Code quality improved on 1 point and degraded on 1 point',
+ hasIssues: false,
+ },
+ });
+
+ expect(wrapper.text()).toBe('Loading Code Quality report');
+ });
+ });
+
+ describe('with success status', () => {
+ it('should render provided data', () => {
+ createComponent({ props: { hasIssues: true } });
+
+ expect(wrapper.find('.js-code-text').text()).toBe(
+ 'Code quality improved on 1 point and degraded on 1 point',
+ );
+ expect(wrapper.findAllComponents(ReportItem)).toHaveLength(resolvedIssues.length);
+ });
+
+ describe('toggleCollapsed', () => {
+ it('toggles issues', async () => {
+ createComponent({ props: { hasIssues: true } });
+
+ await findExpandButton().trigger('click');
+
+ expect(findReportSection().isVisible()).toBe(true);
+ expectExpandButtonOpen();
+
+ await findExpandButton().trigger('click');
+
+ expect(findReportSection().isVisible()).toBe(false);
+ expectExpandButtonClosed();
+ });
+
+ it('is always expanded, if always-open is set to true', () => {
+ createComponent({ props: { hasIssues: true, alwaysOpen: true } });
+
+ expect(findReportSection().isVisible()).toBe(true);
+ expect(findExpandButton().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('snowplow events', () => {
+ it('does emit an event on issue toggle if the shouldEmitToggleEvent prop does exist', () => {
+ createComponent({ props: { hasIssues: true, shouldEmitToggleEvent: true } });
+
+ expect(wrapper.emitted('toggleEvent')).toBeUndefined();
+
+ findExpandButton().trigger('click');
+
+ expect(wrapper.emitted('toggleEvent')).toEqual([[]]);
+ });
+
+ it('does not emit an event on issue toggle if the shouldEmitToggleEvent prop does not exist', () => {
+ createComponent({ props: { hasIssues: true } });
+
+ expect(wrapper.emitted('toggleEvent')).toBeUndefined();
+
+ findExpandButton().trigger('click');
+
+ expect(wrapper.emitted('toggleEvent')).toBeUndefined();
+ });
+
+ it('does not emit an event if always-open is set to true', () => {
+ createComponent({
+ props: { alwaysOpen: true, hasIssues: true, shouldEmitToggleEvent: true },
+ });
+
+ expect(wrapper.emitted('toggleEvent')).toBeUndefined();
+ });
+ });
+
+ describe('with failed request', () => {
+ it('should render error indicator', () => {
+ createComponent({
+ props: {
+ component: '',
+ status: 'ERROR',
+ loadingText: 'Loading Code Quality report',
+ errorText: 'Failed to load Code Quality report',
+ successText: 'Code quality improved on 1 point and degraded on 1 point',
+ hasIssues: false,
+ },
+ });
+
+ expect(wrapper.text()).toBe('Failed to load Code Quality report');
+ });
+ });
+
+ describe('with action buttons passed to the slot', () => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ status: 'SUCCESS',
+ successText: 'success',
+ hasIssues: true,
+ },
+ slots: {
+ 'action-buttons': ['Action!'],
+ },
+ });
+ });
+
+ it('should render the passed button', () => {
+ expect(wrapper.text()).toContain('Action!');
+ });
+
+ it('should still render the expand/collapse button', () => {
+ expectExpandButtonClosed();
+ });
+ });
+
+ describe('Success and Error slots', () => {
+ const createComponentWithSlots = (status) => {
+ createComponent({
+ props: {
+ status,
+ hasIssues: true,
+ },
+ slots: {
+ success: ['This is a success'],
+ loading: ['This is loading'],
+ error: ['This is an error'],
+ },
+ });
+ };
+
+ it('only renders success slot when status is "SUCCESS"', () => {
+ createComponentWithSlots('SUCCESS');
+
+ expect(wrapper.text()).toContain('This is a success');
+ expect(wrapper.text()).not.toContain('This is an error');
+ expect(wrapper.text()).not.toContain('This is loading');
+ });
+
+ it('only renders error slot when status is "ERROR"', () => {
+ createComponentWithSlots('ERROR');
+
+ expect(wrapper.text()).toContain('This is an error');
+ expect(wrapper.text()).not.toContain('This is a success');
+ expect(wrapper.text()).not.toContain('This is loading');
+ });
+
+ it('only renders loading slot when status is "LOADING"', () => {
+ createComponentWithSlots('LOADING');
+
+ expect(wrapper.text()).toContain('This is loading');
+ expect(wrapper.text()).not.toContain('This is an error');
+ expect(wrapper.text()).not.toContain('This is a success');
+ });
+ });
+
+ describe('help popover', () => {
+ describe('when popover options are defined', () => {
+ const options = {
+ title: 'foo',
+ content: 'bar',
+ };
+
+ beforeEach(() => {
+ createComponent({ props: { popoverOptions: options } });
+ });
+
+ it('popover is shown with options', () => {
+ expect(findPopover().props('options')).toEqual(options);
+ });
+ });
+
+ describe('when popover options are not defined', () => {
+ beforeEach(() => {
+ createComponent({ props: { popoverOptions: {} } });
+ });
+
+ it('popover is not shown', () => {
+ expect(findPopover().exists()).toBe(false);
+ });
+ });
+ });
+});