Skip to content
代码片段 群组 项目
未验证 提交 796d47b5 编辑于 作者: Jose Ivan Vargas's avatar Jose Ivan Vargas 提交者: GitLab
浏览文件

Merge branch 'refactor-header-spec' into 'master'

No related branches found
No related tags found
无相关合并请求
...@@ -109,7 +109,6 @@ describe('Vulnerability Header', () => { ...@@ -109,7 +109,6 @@ describe('Vulnerability Header', () => {
const findStatusDescription = () => wrapper.findComponent(StatusDescription); const findStatusDescription = () => wrapper.findComponent(StatusDescription);
const findBadge = () => wrapper.findComponent(GlBadge); const findBadge = () => wrapper.findComponent(GlBadge);
// Helpers
const changeStatus = (action) => { const changeStatus = (action) => {
const dropdown = wrapper.findComponent(VulnerabilityStateDropdown); const dropdown = wrapper.findComponent(VulnerabilityStateDropdown);
dropdown.vm.$emit('change', { action }); dropdown.vm.$emit('change', { action });
...@@ -139,6 +138,123 @@ describe('Vulnerability Header', () => { ...@@ -139,6 +138,123 @@ describe('Vulnerability Header', () => {
createAlert.mockReset(); createAlert.mockReset();
}); });
// Resolution Alert
describe('the vulnerability is no longer detected on the default branch', () => {
const branchName = 'main';
beforeEach(() => {
createWrapper({
vulnerability: {
resolvedOnDefaultBranch: true,
projectDefaultBranch: branchName,
},
});
});
it('should show the resolution alert component', () => {
expect(findResolutionAlert().exists()).toBe(true);
});
it('should pass down the default branch name', () => {
expect(findResolutionAlert().props('defaultBranchName')).toEqual(branchName);
});
it('should not show the alert component when the vulnerability is resolved', async () => {
createWrapper({
vulnerability: {
state: 'resolved',
},
});
await nextTick();
const alert = findResolutionAlert();
expect(alert.exists()).toBe(false);
});
});
describe('status description', () => {
it('the status description is rendered and passed the correct data', () => {
const user = createRandomUser();
const vulnerability = {
...defaultVulnerability,
state: 'confirmed',
confirmedById: user.id,
};
createWrapper({ vulnerability });
return waitForPromises().then(() => {
expect(findStatusDescription().exists()).toBe(true);
expect(findStatusDescription().props()).toEqual({
vulnerability,
user,
isLoadingVulnerability: false,
isLoadingUser: false,
isStatusBolded: false,
});
});
});
it.each(vulnerabilityStateEntries)(
`loads the correct user for the vulnerability state "%s"`,
(state) => {
const user = createRandomUser();
createWrapper({ vulnerability: { state, [`${state}ById`]: user.id } });
return waitForPromises().then(() => {
expect(mockAxios.history.get).toHaveLength(1);
expect(findStatusDescription().props('user')).toEqual(user);
});
},
);
it('does not load a user if there is no user ID', () => {
createWrapper({ vulnerability: { state: 'detected' } });
return waitForPromises().then(() => {
expect(mockAxios.history.get).toHaveLength(0);
expect(findStatusDescription().props('user')).toBeUndefined();
});
});
it('will show an error when the user cannot be loaded', () => {
createWrapper({ vulnerability: { state: 'confirmed', confirmedById: 1 } });
mockAxios.onGet().replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR);
return waitForPromises().then(() => {
expect(createAlert).toHaveBeenCalledTimes(1);
expect(mockAxios.history.get).toHaveLength(1);
});
});
it('will set the isLoadingUser property correctly when the user is loading and finished loading', () => {
const user = createRandomUser();
createWrapper({ vulnerability: { state: 'confirmed', confirmedById: user.id } });
expect(findStatusDescription().props('isLoadingUser')).toBe(true);
return waitForPromises().then(() => {
expect(mockAxios.history.get).toHaveLength(1);
expect(findStatusDescription().props('isLoadingUser')).toBe(false);
});
});
});
describe('state button', () => {
it('renders the disabled state button when user can not admin the vulnerability', () => {
createWrapper({ vulnerability: getVulnerability({ canAdmin: true }) });
expect(findStateButton().props('disabled')).toBe(false);
});
it('renders the enabled state button when user can admin the vulnerability', () => {
createWrapper({ vulnerability: getVulnerability({ canAdmin: false }) });
expect(findStateButton().props('disabled')).toBe(true);
});
});
describe.each` describe.each`
action | queryName | expected action | queryName | expected
${'dismiss'} | ${'vulnerabilityDismiss'} | ${'dismissed'} ${'dismiss'} | ${'vulnerabilityDismiss'} | ${'dismissed'}
...@@ -189,7 +305,7 @@ describe('Vulnerability Header', () => { ...@@ -189,7 +305,7 @@ describe('Vulnerability Header', () => {
}); });
}); });
describe('when API call is failed', () => { describe('when API call fails', () => {
beforeEach(() => { beforeEach(() => {
const apolloProvider = createApolloProvider([ const apolloProvider = createApolloProvider([
vulnerabilityStateMutations[action], vulnerabilityStateMutations[action],
...@@ -206,7 +322,7 @@ describe('Vulnerability Header', () => { ...@@ -206,7 +322,7 @@ describe('Vulnerability Header', () => {
createWrapper({ apolloProvider }); createWrapper({ apolloProvider });
}); });
it('when the vulnerability state changes but the API call fails, an error message is displayed', async () => { it('shows an error message', async () => {
changeStatus(action); changeStatus(action);
await waitForPromises(); await waitForPromises();
...@@ -215,95 +331,83 @@ describe('Vulnerability Header', () => { ...@@ -215,95 +331,83 @@ describe('Vulnerability Header', () => {
}); });
}); });
describe('state button', () => { describe('action buttons', () => {
it('renders the disabled state button when user can not admin the vulnerability', () => { describe('split action button', () => {
createWrapper({ vulnerability: getVulnerability({ canAdmin: true }) }); it('renders the correct amount of buttons', async () => {
createWrapper({
expect(findStateButton().props('disabled')).toBe(false); vulnerability: getVulnerability({
}); canCreateMergeRequest: true,
canDownloadPatch: true,
it('renders the enabled state button when user can admin the vulnerability', () => { canResolveWithAI: true,
createWrapper({ vulnerability: getVulnerability({ canAdmin: false }) }); }),
});
expect(findStateButton().props('disabled')).toBe(true); await waitForPromises();
}); const buttons = findSplitButton().props('buttons');
}); expect(buttons).toHaveLength(3);
describe('split button', () => {
it('renders the correct amount of buttons', async () => {
createWrapper({
vulnerability: getVulnerability({
canCreateMergeRequest: true,
canDownloadPatch: true,
canResolveWithAI: true,
}),
}); });
await waitForPromises();
const buttons = findSplitButton().props('buttons');
expect(buttons).toHaveLength(3);
});
it.each` it.each`
index | name | tagline index | name | tagline
${0} | ${'Resolve with merge request'} | ${'Automatically apply the patch in a new branch'} ${0} | ${'Resolve with merge request'} | ${'Automatically apply the patch in a new branch'}
${1} | ${'Download patch to resolve'} | ${'Download the patch to apply it manually'} ${1} | ${'Download patch to resolve'} | ${'Download the patch to apply it manually'}
${2} | ${'Resolve with AI'} | ${'Automatically opens a merge request with a solution generated by AI'} ${2} | ${'Resolve with AI'} | ${'Automatically opens a merge request with a solution generated by AI'}
`('renders the button for $name at index $index', async ({ index, name, tagline }) => { `('renders the button for $name at index $index', async ({ index, name, tagline }) => {
createWrapper({ createWrapper({
vulnerability: getVulnerability({ vulnerability: getVulnerability({
canCreateMergeRequest: true, canCreateMergeRequest: true,
canDownloadPatch: true, canDownloadPatch: true,
canResolveWithAI: true, canResolveWithAI: true,
}), }),
});
await waitForPromises();
const buttons = findSplitButton().props('buttons');
expect(buttons[index].name).toBe(name);
expect(buttons[index].tagline).toBe(tagline);
}); });
await waitForPromises();
const buttons = findSplitButton().props('buttons'); it('does not render the split button if there is only one action', () => {
expect(buttons[index].name).toBe(name); createWrapper({
expect(buttons[index].tagline).toBe(tagline); vulnerability: getVulnerability({
}); canCreateMergeRequest: false,
canDownloadPatch: false,
canResolveWithAI: true,
}),
});
it('does not render the split button if there is only one action', () => { expect(findSplitButton().exists()).toBe(false);
createWrapper({
vulnerability: getVulnerability({
canCreateMergeRequest: false,
canDownloadPatch: false,
canResolveWithAI: true,
}),
}); });
expect(findSplitButton().exists()).toBe(false);
}); });
});
describe('single action button', () => { describe('single action button', () => {
it('does not display if there are no actions', () => { it('does not display if there are no actions', () => {
createWrapper({ createWrapper({
vulnerability: getVulnerability({ vulnerability: getVulnerability({
canCreateMergeRequest: false, canCreateMergeRequest: false,
canDownloadPatch: false, canDownloadPatch: false,
canResolveWithAI: false, canResolveWithAI: false,
}), }),
}); });
expect(findGlButton().exists()).toBe(false); expect(findGlButton().exists()).toBe(false);
}); });
it.each` it.each`
state | name state | name
${'canCreateMergeRequest'} | ${'Resolve with merge request'} ${'canCreateMergeRequest'} | ${'Resolve with merge request'}
${'canDownloadPatch'} | ${'Download patch to resolve'} ${'canDownloadPatch'} | ${'Download patch to resolve'}
${'canResolveWithAI'} | ${'Resolve with AI Experiment'} ${'canResolveWithAI'} | ${'Resolve with AI Experiment'}
`('renders the $name button', ({ state, name }) => { `('renders the $name button', ({ state, name }) => {
createWrapper({ createWrapper({
vulnerability: getVulnerability({ vulnerability: getVulnerability({
[state]: true, [state]: true,
}), }),
});
expect(findGlButton().text()).toMatchInterpolatedText(name);
}); });
expect(findGlButton().text()).toMatchInterpolatedText(name);
}); });
describe('create merge request', () => { describe('create merge request button', () => {
beforeEach(() => { beforeEach(() => {
createWrapper({ createWrapper({
vulnerability: getVulnerability({ vulnerability: getVulnerability({
...@@ -353,7 +457,7 @@ describe('Vulnerability Header', () => { ...@@ -353,7 +457,7 @@ describe('Vulnerability Header', () => {
}); });
}); });
describe('can download patch', () => { describe('can download patch button', () => {
beforeEach(() => { beforeEach(() => {
createWrapper({ createWrapper({
vulnerability: getVulnerability({ vulnerability: getVulnerability({
...@@ -369,7 +473,7 @@ describe('Vulnerability Header', () => { ...@@ -369,7 +473,7 @@ describe('Vulnerability Header', () => {
}); });
}); });
describe('resolve with AI', () => { describe('resolve with AI button', () => {
let visitUrlMock; let visitUrlMock;
let mockSubscription; let mockSubscription;
let subscriptionSpy; let subscriptionSpy;
...@@ -477,116 +581,6 @@ describe('Vulnerability Header', () => { ...@@ -477,116 +581,6 @@ describe('Vulnerability Header', () => {
}); });
}); });
describe('status description', () => {
let vulnerability;
let user;
beforeEach(() => {
user = createRandomUser();
vulnerability = {
...defaultVulnerability,
state: 'confirmed',
confirmedById: user.id,
};
createWrapper({ vulnerability });
});
it('the status description is rendered and passed the correct data', () => {
return waitForPromises().then(() => {
expect(findStatusDescription().exists()).toBe(true);
expect(findStatusDescription().props()).toEqual({
vulnerability,
user,
isLoadingVulnerability: false,
isLoadingUser: false,
isStatusBolded: false,
});
});
});
});
describe('when the vulnerability is no longer detected on the default branch', () => {
const branchName = 'main';
beforeEach(() => {
createWrapper({
vulnerability: {
resolvedOnDefaultBranch: true,
projectDefaultBranch: branchName,
},
});
});
it('should show the resolution alert component', () => {
expect(findResolutionAlert().exists()).toBe(true);
});
it('should pass down the default branch name', () => {
expect(findResolutionAlert().props('defaultBranchName')).toEqual(branchName);
});
it('the resolution alert component should not be shown if when the vulnerability is already resolved', async () => {
createWrapper({
vulnerability: {
state: 'resolved',
},
});
await nextTick();
const alert = findResolutionAlert();
expect(alert.exists()).toBe(false);
});
});
describe('vulnerability user watcher', () => {
it.each(vulnerabilityStateEntries)(
`loads the correct user for the vulnerability state "%s"`,
(state) => {
const user = createRandomUser();
createWrapper({ vulnerability: { state, [`${state}ById`]: user.id } });
return waitForPromises().then(() => {
expect(mockAxios.history.get).toHaveLength(1);
expect(findStatusDescription().props('user')).toEqual(user);
});
},
);
it('does not load a user if there is no user ID', () => {
createWrapper({ vulnerability: { state: 'detected' } });
return waitForPromises().then(() => {
expect(mockAxios.history.get).toHaveLength(0);
expect(findStatusDescription().props('user')).toBeUndefined();
});
});
it('will show an error when the user cannot be loaded', () => {
createWrapper({ vulnerability: { state: 'confirmed', confirmedById: 1 } });
mockAxios.onGet().replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR);
return waitForPromises().then(() => {
expect(createAlert).toHaveBeenCalledTimes(1);
expect(mockAxios.history.get).toHaveLength(1);
});
});
it('will set the isLoadingUser property correctly when the user is loading and finished loading', () => {
const user = createRandomUser();
createWrapper({ vulnerability: { state: 'confirmed', confirmedById: user.id } });
expect(findStatusDescription().props('isLoadingUser')).toBe(true);
return waitForPromises().then(() => {
expect(mockAxios.history.get).toHaveLength(1);
expect(findStatusDescription().props('isLoadingUser')).toBe(false);
});
});
});
describe('when FF "resolveVulnerabilityAi" is disabled', () => { describe('when FF "resolveVulnerabilityAi" is disabled', () => {
describe('split button', () => { describe('split button', () => {
it('renders the create merge request and issue button as a split button', async () => { it('renders the create merge request and issue button as a split button', async () => {
......
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册