Commit cd4b8d4c authored by Vitaly Slobodin's avatar Vitaly Slobodin

Merge branch '267504-unnest-message-display-logic' into 'master'

Show update branch message when MR branch diverged from target branch

See merge request gitlab-org/gitlab!64090
parents 0a7a0a2c 7e3da6b7
...@@ -309,7 +309,7 @@ export default { ...@@ -309,7 +309,7 @@ export default {
isMRActive() { isMRActive() {
return this.mrState !== mrStates.merged && this.mrState !== mrStates.closed; return this.mrState !== mrStates.merged && this.mrState !== mrStates.closed;
}, },
isMRBranchOutdated() { hasDivergedFromTargetBranch() {
return this.divergedCommitsCount > 0; return this.divergedCommitsCount > 0;
}, },
hasDastScannedResources() { hasDastScannedResources() {
...@@ -482,10 +482,10 @@ export default { ...@@ -482,10 +482,10 @@ export default {
</gl-button> </gl-button>
</template> </template>
<template v-if="isMRActive && isBaseSecurityReportOutOfDate" #sub-heading> <template v-if="isMRActive" #sub-heading>
<div class="text-secondary-700 text-1"> <div class="gl-text-gray-700 gl-font-sm">
<gl-sprintf <gl-sprintf
v-if="isMRBranchOutdated" v-if="hasDivergedFromTargetBranch"
:message=" :message="
__( __(
'Security report is out of date. Please update your branch with the latest changes from the target branch (%{targetBranchName})', 'Security report is out of date. Please update your branch with the latest changes from the target branch (%{targetBranchName})',
...@@ -493,12 +493,12 @@ export default { ...@@ -493,12 +493,12 @@ export default {
" "
> >
<template #targetBranchName> <template #targetBranchName>
<gl-link class="text-1" :href="targetBranchTreePath">{{ targetBranch }}</gl-link> <gl-link class="gl-font-sm" :href="targetBranchTreePath">{{ targetBranch }}</gl-link>
</template> </template>
</gl-sprintf> </gl-sprintf>
<gl-sprintf <gl-sprintf
v-else v-else-if="isBaseSecurityReportOutOfDate"
:message=" :message="
__( __(
'Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})', 'Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})',
...@@ -506,12 +506,12 @@ export default { ...@@ -506,12 +506,12 @@ export default {
" "
> >
<template #newPipelineLink="{ content }"> <template #newPipelineLink="{ content }">
<gl-link class="text-1" :href="`${newPipelinePath}?ref=${targetBranch}`">{{ <gl-link class="gl-font-sm" :href="`${newPipelinePath}?ref=${targetBranch}`">{{
content content
}}</gl-link> }}</gl-link>
</template> </template>
<template #targetBranchName> <template #targetBranchName>
<gl-link class="text-1" :href="targetBranchTreePath">{{ targetBranch }}</gl-link> <gl-link class="gl-font-sm" :href="targetBranchTreePath">{{ targetBranch }}</gl-link>
</template> </template>
</gl-sprintf> </gl-sprintf>
</div> </div>
......
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import Vue from 'vue'; import { nextTick } from 'vue';
import GroupedSecurityReportsApp from 'ee/vue_shared/security_reports/grouped_security_reports_app.vue'; import GroupedSecurityReportsApp from 'ee/vue_shared/security_reports/grouped_security_reports_app.vue';
import appStore from 'ee/vue_shared/security_reports/store'; import appStore from 'ee/vue_shared/security_reports/store';
import { trackMrSecurityReportDetails } from 'ee/vue_shared/security_reports/store/constants'; import { trackMrSecurityReportDetails } from 'ee/vue_shared/security_reports/store/constants';
...@@ -41,6 +41,12 @@ describe('Grouped security reports app', () => { ...@@ -41,6 +41,12 @@ describe('Grouped security reports app', () => {
let mock; let mock;
const findReportSection = () => wrapper.find(ReportSection); const findReportSection = () => wrapper.find(ReportSection);
const findReportSummary = () => wrapper.find('[data-testid="report-section-code-text"]');
const findCollapseButton = () => wrapper.find('.js-collapse-btn');
const findSpinner = () => wrapper.find('.gl-spinner');
const findSecretScanReport = () => wrapper.find('[data-testid="secret-scan-report"]');
const findViewFullReportButton = () => wrapper.find('.report-btn');
const findDastJobLink = () => wrapper.find('[data-testid="dast-ci-job-link"]');
const props = { const props = {
headBlobPath: 'path', headBlobPath: 'path',
...@@ -160,32 +166,21 @@ describe('Grouped security reports app', () => { ...@@ -160,32 +166,21 @@ describe('Grouped security reports app', () => {
}); });
it('renders error state', () => { it('renders error state', () => {
expect(wrapper.vm.$el.querySelector('.gl-spinner')).toBeNull(); expect(findSpinner().exists()).toBe(false);
expect( expect(findReportSummary().text()).toEqual('Security scanning failed loading any results');
wrapper.vm.$el
.querySelector('[data-testid="report-section-code-text"]')
.textContent.trim(),
).toEqual('Security scanning failed loading any results');
expect(wrapper.vm.$el.querySelector('.js-collapse-btn').textContent.trim()).toEqual(
'Expand',
);
expect(trimText(wrapper.vm.$el.textContent)).toContain( expect(findCollapseButton().text()).toEqual('Expand');
'SAST: Loading resulted in an error',
);
expect(trimText(wrapper.vm.$el.textContent)).toContain( const wrapperText = wrapper.text();
'Dependency scanning: Loading resulted in an error', expect(wrapperText).toContain('SAST: Loading resulted in an error');
);
expect(wrapper.vm.$el.textContent).toContain( expect(wrapperText).toContain('Dependency scanning: Loading resulted in an error');
'Container scanning: Loading resulted in an error',
);
expect(wrapper.vm.$el.textContent).toContain('DAST: Loading resulted in an error'); expect(wrapperText).toContain('Container scanning: Loading resulted in an error');
expect(wrapper.text()).toContain('Secret scanning: Loading resulted in an error'); expect(wrapperText).toContain('DAST: Loading resulted in an error');
expect(wrapperText).toContain('Secret scanning: Loading resulted in an error');
}); });
}); });
...@@ -204,23 +199,18 @@ describe('Grouped security reports app', () => { ...@@ -204,23 +199,18 @@ describe('Grouped security reports app', () => {
}); });
it('renders loading summary text + spinner', () => { it('renders loading summary text + spinner', () => {
expect(wrapper.vm.$el.querySelector('.gl-spinner')).not.toBeNull(); expect(findSpinner().exists()).toBe(true);
expect( expect(findReportSummary().text()).toEqual('Security scanning is loading');
wrapper.vm.$el
.querySelector('[data-testid="report-section-code-text"]')
.textContent.trim(),
).toEqual('Security scanning is loading');
expect(wrapper.vm.$el.querySelector('.js-collapse-btn').textContent.trim()).toEqual(
'Expand',
);
expect(wrapper.vm.$el.textContent).toContain('SAST is loading'); expect(findCollapseButton().text()).toEqual('Expand');
expect(wrapper.vm.$el.textContent).toContain('Dependency scanning is loading');
expect(wrapper.vm.$el.textContent).toContain('Container scanning is loading'); const wrapperText = wrapper.text();
expect(wrapper.vm.$el.textContent).toContain('DAST is loading'); expect(wrapperText).toContain('SAST is loading');
expect(wrapper.vm.$el.textContent).toContain('Coverage fuzzing is loading'); expect(wrapperText).toContain('Dependency scanning is loading');
expect(wrapper.vm.$el.textContent).toContain('API fuzzing is loading'); expect(wrapperText).toContain('Container scanning is loading');
expect(wrapperText).toContain('DAST is loading');
expect(wrapperText).toContain('Coverage fuzzing is loading');
expect(wrapperText).toContain('API fuzzing is loading');
}); });
}); });
...@@ -253,38 +243,32 @@ describe('Grouped security reports app', () => { ...@@ -253,38 +243,32 @@ describe('Grouped security reports app', () => {
it('renders reports', () => { it('renders reports', () => {
// It's not loading // It's not loading
expect(wrapper.vm.$el.querySelector('.gl-spinner')).toBeNull(); expect(findSpinner().exists()).toBe(false);
// Renders the summary text // Renders the summary text
expect( expect(findReportSummary().text()).toEqual(
wrapper.vm.$el 'Security scanning detected no vulnerabilities.',
.querySelector('[data-testid="report-section-code-text"]') );
.textContent.trim(),
).toEqual('Security scanning detected no vulnerabilities.'); const wrapperText = wrapper.text();
// Renders Sast result // Renders Sast result
expect(trimText(wrapper.vm.$el.textContent)).toContain('SAST detected no vulnerabilities.'); expect(wrapperText).toContain('SAST detected no vulnerabilities.');
// Renders DSS result // Renders DSS result
expect(trimText(wrapper.vm.$el.textContent)).toContain( expect(wrapper.text()).toContain('Dependency scanning detected no vulnerabilities.');
'Dependency scanning detected no vulnerabilities.',
);
// Renders container scanning result // Renders container scanning result
expect(wrapper.vm.$el.textContent).toContain( expect(wrapperText).toContain('Container scanning detected no vulnerabilities.');
'Container scanning detected no vulnerabilities.',
);
// Renders DAST result // Renders DAST result
expect(wrapper.vm.$el.textContent).toContain('DAST detected no vulnerabilities.'); expect(wrapperText).toContain('DAST detected no vulnerabilities.');
// Renders Coverage Fuzzing result // Renders Coverage Fuzzing result
expect(wrapper.vm.$el.textContent).toContain( expect(wrapperText).toContain('Coverage fuzzing detected no vulnerabilities.');
'Coverage fuzzing detected no vulnerabilities.',
);
// Renders API Fuzzing result // Renders API Fuzzing result
expect(wrapper.vm.$el.textContent).toContain('API fuzzing detected no vulnerabilities.'); expect(wrapperText).toContain('API fuzzing detected no vulnerabilities.');
}); });
}); });
...@@ -316,65 +300,61 @@ describe('Grouped security reports app', () => { ...@@ -316,65 +300,61 @@ describe('Grouped security reports app', () => {
it('renders reports', () => { it('renders reports', () => {
// It's not loading // It's not loading
expect(wrapper.vm.$el.querySelector('.gl-spinner')).toBeNull(); expect(findSpinner().exists()).toBe(false);
// Renders the summary text // Renders the summary text
expect( expect(trimText(findReportSummary().text())).toEqual(
trimText(
wrapper.vm.$el.querySelector('[data-testid="report-section-code-text"]').textContent,
),
).toEqual(
'Security scanning detected 12 potential vulnerabilities 7 Critical 5 High and 0 Others', 'Security scanning detected 12 potential vulnerabilities 7 Critical 5 High and 0 Others',
); );
// Renders the expand button // Renders the expand button
expect(wrapper.vm.$el.querySelector('.js-collapse-btn').textContent.trim()).toEqual( expect(findCollapseButton().text()).toEqual('Expand');
'Expand',
); const normalizedWrapperText = trimText(wrapper.text());
// Renders Sast result // Renders Sast result
expect(trimText(wrapper.vm.$el.textContent)).toContain( expect(normalizedWrapperText).toContain(
'SAST detected 1 potential vulnerability 1 Critical 0 High and 0 Others', 'SAST detected 1 potential vulnerability 1 Critical 0 High and 0 Others',
); );
// Renders DSS result // Renders DSS result
expect(trimText(wrapper.vm.$el.textContent)).toContain( expect(normalizedWrapperText).toContain(
'Dependency scanning detected 2 potential vulnerabilities 1 Critical 1 High and 0 Others', 'Dependency scanning detected 2 potential vulnerabilities 1 Critical 1 High and 0 Others',
); );
// Renders container scanning result // Renders container scanning result
expect(trimText(wrapper.vm.$el.textContent)).toContain( expect(normalizedWrapperText).toContain(
'Container scanning detected 2 potential vulnerabilities 1 Critical 1 High and 0 Others', 'Container scanning detected 2 potential vulnerabilities 1 Critical 1 High and 0 Others',
); );
// Renders DAST result // Renders DAST result
expect(trimText(wrapper.vm.$el.textContent)).toContain( expect(normalizedWrapperText).toContain(
'DAST detected 1 potential vulnerability 1 Critical 0 High and 0 Others', 'DAST detected 1 potential vulnerability 1 Critical 0 High and 0 Others',
); );
// Renders coverage fuzzing scanning result // Renders coverage fuzzing scanning result
expect(trimText(wrapper.vm.$el.textContent)).toContain( expect(normalizedWrapperText).toContain(
'Coverage fuzzing detected 2 potential vulnerabilities 1 Critical 1 High and 0 Others', 'Coverage fuzzing detected 2 potential vulnerabilities 1 Critical 1 High and 0 Others',
); );
// Renders api fuzzing scanning result // Renders api fuzzing scanning result
expect(trimText(wrapper.vm.$el.textContent)).toContain( expect(normalizedWrapperText).toContain(
'API fuzzing detected 2 potential vulnerabilities 1 Critical 1 High and 0 Others', 'API fuzzing detected 2 potential vulnerabilities 1 Critical 1 High and 0 Others',
); );
}); });
it('opens modal with more information', () => { it('opens modal with more information', async () => {
wrapper.vm.$el.querySelector('[aria-label="Vulnerability Name"]').click(); wrapper.find('[aria-label="Vulnerability Name"]').trigger('click');
return Vue.nextTick().then(() => { await nextTick();
expect(document.querySelector('.modal-title').textContent.trim()).toEqual(
mockFindings[0].name,
);
expect(document.querySelector('.modal-body').textContent).toContain( expect(document.querySelector('.modal-title').textContent.trim()).toEqual(
mockFindings[0].solution, mockFindings[0].name,
); );
});
expect(document.querySelector('.modal-body').textContent).toContain(
mockFindings[0].solution,
);
}); });
it.each` it.each`
...@@ -417,14 +397,14 @@ describe('Grouped security reports app', () => { ...@@ -417,14 +397,14 @@ describe('Grouped security reports app', () => {
}); });
it('should calculate the security tab path', () => { it('should calculate the security tab path', () => {
const button = wrapper.find('.report-btn'); expect(findViewFullReportButton().attributes()).toMatchObject({
expect(button.attributes('target')).toBe('_blank'); target: '_blank',
expect(button.attributes('href')).toBe(`${pipelinePath}/security`); href: `${pipelinePath}/security`,
});
}); });
it('should render view full report button', () => { it('should render view full report button', () => {
const button = wrapper.find('.report-btn'); expect(findViewFullReportButton().exists()).toBe(true);
expect(button.exists()).toBe(true);
}); });
}); });
...@@ -522,7 +502,7 @@ describe('Grouped security reports app', () => { ...@@ -522,7 +502,7 @@ describe('Grouped security reports app', () => {
}); });
it('should display the correct numbers of vulnerabilities', () => { it('should display the correct numbers of vulnerabilities', () => {
expect(trimText(wrapper.vm.$el.textContent)).toContain( expect(trimText(wrapper.text())).toContain(
'Dependency scanning detected 2 potential vulnerabilities 1 Critical 1 High and 0 Others', 'Dependency scanning detected 2 potential vulnerabilities 1 Critical 1 High and 0 Others',
); );
}); });
...@@ -550,20 +530,21 @@ describe('Grouped security reports app', () => { ...@@ -550,20 +530,21 @@ describe('Grouped security reports app', () => {
}); });
it('should display the correct numbers of vulnerabilities', () => { it('should display the correct numbers of vulnerabilities', () => {
expect(trimText(wrapper.vm.$el.textContent)).toContain( expect(trimText(wrapper.text())).toContain(
'DAST detected 1 potential vulnerability 1 Critical 0 High and 0 Others', 'DAST detected 1 potential vulnerability 1 Critical 0 High and 0 Others',
); );
}); });
it('shows the scanned URLs count and opens a modal', async () => { it('shows the scanned URLs count and opens a modal', async () => {
const jobLink = wrapper.find('[data-testid="dast-ci-job-link"]'); const jobLink = findDastJobLink();
expect(wrapper.text()).toContain('211 URLs scanned'); expect(wrapper.text()).toContain('211 URLs scanned');
expect(jobLink.exists()).toBe(true); expect(jobLink.exists()).toBe(true);
expect(jobLink.text()).toBe('View details'); expect(jobLink.text()).toBe('View details');
jobLink.vm.$emit('click'); jobLink.vm.$emit('click');
await wrapper.vm.$nextTick();
await nextTick();
expect(glModalDirective).toHaveBeenCalled(); expect(glModalDirective).toHaveBeenCalled();
}); });
...@@ -596,7 +577,7 @@ describe('Grouped security reports app', () => { ...@@ -596,7 +577,7 @@ describe('Grouped security reports app', () => {
return waitForMutation(wrapper.vm.$store, types.RECEIVE_DAST_DIFF_SUCCESS).then(() => { return waitForMutation(wrapper.vm.$store, types.RECEIVE_DAST_DIFF_SUCCESS).then(() => {
expect(wrapper.text()).not.toContain('0 URLs scanned'); expect(wrapper.text()).not.toContain('0 URLs scanned');
expect(wrapper.find('[data-testid="dast-ci-job-link"]').exists()).toBe(false); expect(findDastJobLink().exists()).toBe(false);
}); });
}); });
...@@ -627,7 +608,7 @@ describe('Grouped security reports app', () => { ...@@ -627,7 +608,7 @@ describe('Grouped security reports app', () => {
return waitForMutation(wrapper.vm.$store, types.RECEIVE_DAST_DIFF_SUCCESS).then(() => { return waitForMutation(wrapper.vm.$store, types.RECEIVE_DAST_DIFF_SUCCESS).then(() => {
const findDownloadLink = wrapper.find('[data-testid="download-link"]'); const findDownloadLink = wrapper.find('[data-testid="download-link"]');
expect(findDownloadLink.vm.$el.querySelector('[data-testid="download-icon"]')).toExist(); expect(findDownloadLink.find('[data-testid="download-icon"]').exists()).toBe(true);
expect(findDownloadLink.exists()).toBe(true); expect(findDownloadLink.exists()).toBe(true);
expect(findDownloadLink.attributes('href')).toBe('http://test'); expect(findDownloadLink.attributes('href')).toBe('http://test');
}); });
...@@ -657,7 +638,7 @@ describe('Grouped security reports app', () => { ...@@ -657,7 +638,7 @@ describe('Grouped security reports app', () => {
}); });
it('should render the component', () => { it('should render the component', () => {
expect(wrapper.find('[data-testid="secret-scan-report"]').exists()).toBe(true); expect(findSecretScanReport().exists()).toBe(true);
}); });
it('should set diffEndpoint', () => { it('should set diffEndpoint', () => {
...@@ -679,7 +660,7 @@ describe('Grouped security reports app', () => { ...@@ -679,7 +660,7 @@ describe('Grouped security reports app', () => {
}); });
it('should not render the component', () => { it('should not render the component', () => {
expect(wrapper.find('[data-testid="secret-scan-report"]').exists()).toBe(false); expect(findSecretScanReport().exists()).toBe(false);
}); });
}); });
}); });
...@@ -703,17 +684,17 @@ describe('Grouped security reports app', () => { ...@@ -703,17 +684,17 @@ describe('Grouped security reports app', () => {
}); });
it('should display the correct numbers of vulnerabilities', () => { it('should display the correct numbers of vulnerabilities', () => {
expect(trimText(wrapper.vm.$el.textContent)).toContain( expect(trimText(wrapper.text())).toContain(
'SAST detected 1 potential vulnerability 1 Critical 0 High and 0 Others', 'SAST detected 1 potential vulnerability 1 Critical 0 High and 0 Others',
); );
}); });
}); });
describe('Out of date report', () => { describe('Out of date report', () => {
const createComponent = (extraProp, done) => { const createComponent = ({ baseReportOutOfDate = false, ...extraProp }) => {
mock mock
.onGet(SAST_DIFF_ENDPOINT) .onGet(SAST_DIFF_ENDPOINT)
.reply(200, { ...sastDiffSuccessMock, base_report_out_of_date: true }); .reply(200, { ...sastDiffSuccessMock, base_report_out_of_date: baseReportOutOfDate });
createWrapper({ createWrapper({
...props, ...props,
...@@ -724,52 +705,84 @@ describe('Grouped security reports app', () => { ...@@ -724,52 +705,84 @@ describe('Grouped security reports app', () => {
}, },
}); });
waitForMutation(wrapper.vm.$store, `sast/${sastTypes.RECEIVE_DIFF_SUCCESS}`) return waitForMutation(wrapper.vm.$store, `sast/${sastTypes.RECEIVE_DIFF_SUCCESS}`);
.then(done)
.catch(done.fail);
}; };
describe('with active MR', () => { describe('with active MR and base report is out of date', () => {
beforeEach((done) => { beforeEach(() => {
createComponent({ mrState: mrStates.open }, done); return createComponent({ mrState: mrStates.open, baseReportOutOfDate: true });
}); });
it('should display out of date message', () => { it('should display out of date message', () => {
expect(wrapper.vm.$el.textContent).toContain( expect(wrapper.text()).toContain(
'Security report is out of date. Run a new pipeline for the target branch (main)', 'Security report is out of date. Run a new pipeline for the target branch (main)',
); );
}); });
}); });
describe('with active MR and diverged commit', () => { describe('with active MR and diverged commit', () => {
beforeEach((done) => { beforeEach(() => {
createComponent({ mrState: mrStates.open, divergedCommitsCount: 1 }, done); return createComponent({ mrState: mrStates.open, divergedCommitsCount: 1 });
}); });
it('should display out of date message', () => { it('should display out of date message', () => {
expect(wrapper.vm.$el.textContent).toContain( expect(wrapper.text()).toContain(
'Security report is out of date. Please update your branch with the latest changes from the target branch (main)', 'Security report is out of date. Please update your branch with the latest changes from the target branch (main)',
); );
}); });
}); });
describe('with active MR, base report out of date and diverged commit', () => {
beforeEach(() => {
return createComponent({
mrState: mrStates.open,
divergedCommitsCount: 1,
baseReportOutOfDate: true,
});
});
it('should display out of date message', () => {
expect(wrapper.text()).toContain(
'Security report is out of date. Please update your branch with the latest changes from the target branch (main)',
);
});
});
describe('with active MR', () => {
beforeEach(() => {
return createComponent({ mrState: mrStates.open });
});
it('should not display out of date message', () => {
expect(wrapper.text()).not.toContain('Security report is out of date.');
});
});
describe('with closed MR', () => { describe('with closed MR', () => {
beforeEach((done) => { beforeEach(() => {
createComponent({ mrState: mrStates.closed }, done); return createComponent({
mrState: mrStates.closed,
divergedCommitsCount: 1,
baseReportOutOfDate: true,
});
}); });
it('should not display out of date message', () => { it('should not display out of date message', () => {
expect(wrapper.vm.$el.textContent).not.toContain('Security report is out of date.'); expect(wrapper.text()).not.toContain('Security report is out of date.');
}); });
}); });
describe('with merged MR', () => { describe('with merged MR', () => {
beforeEach((done) => { beforeEach(() => {
createComponent({ mrState: mrStates.merged }, done); return createComponent({
mrState: mrStates.merged,
divergedCommitsCount: 1,
baseReportOutOfDate: true,
});
}); });
it('should not display out of date message', () => { it('should not display out of date message', () => {
expect(wrapper.vm.$el.textContent).not.toContain('Security report is out of date.'); expect(wrapper.text()).not.toContain('Security report is out of date.');
}); });
}); });
}); });
...@@ -780,37 +793,37 @@ describe('Grouped security reports app', () => { ...@@ -780,37 +793,37 @@ describe('Grouped security reports app', () => {
beforeEach(() => { beforeEach(() => {
createWrapper(props); createWrapper(props);
trackingSpy = mockTracking(category, wrapper.vm.$el, jest.spyOn); trackingSpy = mockTracking(category, wrapper.element, jest.spyOn);
}); });
afterEach(() => { afterEach(() => {
unmockTracking(); unmockTracking();
}); });
it('tracks an event when toggled', () => { it('tracks an event when toggled', async () => {
expect(trackingSpy).not.toHaveBeenCalled(); expect(trackingSpy).not.toHaveBeenCalled();
findReportSection().vm.$emit('toggleEvent'); findReportSection().vm.$emit('toggleEvent');
return wrapper.vm.$nextTick().then(() => {
expect(trackingSpy).toHaveBeenCalledWith(category, action); await nextTick();
});
expect(trackingSpy).toHaveBeenCalledWith(category, action);
}); });
it('tracks an event only the first time it is toggled', () => { it('tracks an event only the first time it is toggled', async () => {
const report = findReportSection(); const report = findReportSection();
expect(trackingSpy).not.toHaveBeenCalled(); expect(trackingSpy).not.toHaveBeenCalled();
report.vm.$emit('toggleEvent'); report.vm.$emit('toggleEvent');
return wrapper.vm
.$nextTick() await nextTick();
.then(() => {
expect(trackingSpy).toHaveBeenCalledWith(category, action); expect(trackingSpy).toHaveBeenCalledWith(category, action);
expect(trackingSpy).toHaveBeenCalledTimes(1); expect(trackingSpy).toHaveBeenCalledTimes(1);
report.vm.$emit('toggleEvent'); report.vm.$emit('toggleEvent');
})
.then(wrapper.vm.$nextTick()) await nextTick();
.then(() => {
expect(trackingSpy).toHaveBeenCalledTimes(1); expect(trackingSpy).toHaveBeenCalledTimes(1);
});
}); });
}); });
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment