Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-04-04 03:09:37 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-04-04 03:09:37 +0300
commite3bdfa1a13d7e6c92716324c78b5b20c07eeb7c6 (patch)
treee8776263096b027d32d4be5118cccc87b00de2bc /spec
parentc1a50b8195f4e36fda9b233acbde57a449bcf6c3 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/admin/integrations_controller_spec.rb34
-rw-r--r--spec/controllers/groups/settings/integrations_controller_spec.rb35
-rw-r--r--spec/frontend/__mocks__/lodash/debounce.js11
-rw-r--r--spec/frontend/clusters/components/applications_spec.js41
-rw-r--r--spec/frontend/clusters/components/knative_domain_editor_spec.js36
-rw-r--r--spec/frontend/clusters/stores/clusters_store_spec.js2
-rw-r--r--spec/frontend/ide/components/branches/search_list_spec.js2
-rw-r--r--spec/frontend/ide/components/merge_requests/list_spec.js2
-rw-r--r--spec/frontend/lib/utils/url_utility_spec.js26
-rw-r--r--spec/frontend/test_setup.js2
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap115
-rw-r--r--spec/frontend/vue_shared/components/clone_dropdown_spec.js74
-rw-r--r--spec/models/service_spec.rb18
-rw-r--r--spec/services/metrics/dashboard/update_dashboard_service_spec.rb36
14 files changed, 320 insertions, 114 deletions
diff --git a/spec/controllers/admin/integrations_controller_spec.rb b/spec/controllers/admin/integrations_controller_spec.rb
index 50748918893..8e48ecddd0f 100644
--- a/spec/controllers/admin/integrations_controller_spec.rb
+++ b/spec/controllers/admin/integrations_controller_spec.rb
@@ -3,7 +3,6 @@
require 'spec_helper'
describe Admin::IntegrationsController do
- let_it_be(:project) { create(:project) }
let(:admin) { create(:admin) }
before do
@@ -34,7 +33,7 @@ describe Admin::IntegrationsController do
end
describe '#update' do
- let(:integration) { create(:jira_service, project: project) }
+ let(:integration) { create(:jira_service, :instance) }
before do
put :update, params: { id: integration.class.to_param, service: { url: url } }
@@ -52,34 +51,9 @@ describe Admin::IntegrationsController do
context 'invalid params' do
let(:url) { 'https://jira.localhost' }
- it 'does not update the integration' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to render_template(:edit)
- expect(integration.reload.url).not_to eq(url)
- end
- end
- end
-
- describe '#test' do
- context 'testable' do
- let(:integration) { create(:jira_service, project: project) }
-
- it 'returns ok' do
- allow_any_instance_of(integration.class).to receive(:test) { { success: true } }
-
- put :test, params: { id: integration.class.to_param }
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- context 'not testable' do
- let(:integration) { create(:alerts_service, project: project) }
-
- it 'returns not found' do
- put :test, params: { id: integration.class.to_param }
-
- expect(response).to have_gitlab_http_status(:not_found)
+ it 'updates the integration' do
+ expect(response).to have_gitlab_http_status(:found)
+ expect(integration.reload.url).to eq(url)
end
end
end
diff --git a/spec/controllers/groups/settings/integrations_controller_spec.rb b/spec/controllers/groups/settings/integrations_controller_spec.rb
index bbf215a4bb9..eee65476dab 100644
--- a/spec/controllers/groups/settings/integrations_controller_spec.rb
+++ b/spec/controllers/groups/settings/integrations_controller_spec.rb
@@ -67,40 +67,11 @@ describe Groups::Settings::IntegrationsController do
end
context 'invalid params' do
- let(:url) { 'ftp://jira.localhost' }
+ let(:url) { 'https://jira.localhost' }
it 'does not update the integration' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to render_template(:edit)
- expect(integration.reload.url).not_to eq(url)
- end
- end
- end
-
- describe '#test' do
- context 'testable' do
- let(:integration) { create(:jira_service, project: project) }
-
- before do
- group.add_owner(user)
- end
-
- it 'returns ok' do
- allow_any_instance_of(integration.class).to receive(:test) { { success: true } }
-
- put :test, params: { group_id: group, id: integration.class.to_param }
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- context 'not testable' do
- let(:integration) { create(:alerts_service, project: project) }
-
- it 'returns not found' do
- put :test, params: { group_id: group, id: integration.class.to_param }
-
- expect(response).to have_gitlab_http_status(:not_found)
+ expect(response).to have_gitlab_http_status(:found)
+ expect(integration.reload.url).to eq(url)
end
end
end
diff --git a/spec/frontend/__mocks__/lodash/debounce.js b/spec/frontend/__mocks__/lodash/debounce.js
new file mode 100644
index 00000000000..97fdb39097a
--- /dev/null
+++ b/spec/frontend/__mocks__/lodash/debounce.js
@@ -0,0 +1,11 @@
+// `lodash/debounce` has a non-trivial implementation which can lead to
+// [flaky spec errors][1]. This mock simply makes `debounce` calls synchronous.
+//
+// In the future we could enhance this by injecting some test values in
+// the function passed to it. See [this issue][2] for more information.
+//
+// [1]: https://gitlab.com/gitlab-org/gitlab/-/issues/212532
+// [2]: https://gitlab.com/gitlab-org/gitlab/-/issues/213378
+// Further reference: https://github.com/facebook/jest/issues/3465
+
+export default fn => fn;
diff --git a/spec/frontend/clusters/components/applications_spec.js b/spec/frontend/clusters/components/applications_spec.js
index db5d5c84820..782e5215ad8 100644
--- a/spec/frontend/clusters/components/applications_spec.js
+++ b/spec/frontend/clusters/components/applications_spec.js
@@ -400,6 +400,10 @@ describe('Applications', () => {
});
describe('Knative application', () => {
+ const availableDomain = {
+ id: 4,
+ domain: 'newhostname.com',
+ };
const propsData = {
applications: {
...APPLICATIONS_MOCK_STATE,
@@ -409,10 +413,11 @@ describe('Applications', () => {
status: 'installed',
externalIp: '1.1.1.1',
installed: true,
+ availableDomains: [availableDomain],
+ pagesDomain: null,
},
},
};
- const newHostname = 'newhostname.com';
let wrapper;
let knativeDomainEditor;
@@ -428,20 +433,44 @@ describe('Applications', () => {
});
it('emits saveKnativeDomain event when knative domain editor emits save event', () => {
- knativeDomainEditor.vm.$emit('save', newHostname);
+ propsData.applications.knative.hostname = availableDomain.domain;
+ propsData.applications.knative.pagesDomain = availableDomain;
+ knativeDomainEditor.vm.$emit('save');
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('saveKnativeDomain', {
+ id: 'knative',
+ params: {
+ hostname: availableDomain.domain,
+ pages_domain_id: availableDomain.id,
+ },
+ });
+ });
+
+ it('emits saveKnativeDomain event when knative domain editor emits save event with custom domain', () => {
+ const newHostName = 'someothernewhostname.com';
+ propsData.applications.knative.hostname = newHostName;
+ propsData.applications.knative.pagesDomain = null;
+ knativeDomainEditor.vm.$emit('save');
expect(eventHub.$emit).toHaveBeenCalledWith('saveKnativeDomain', {
id: 'knative',
- params: { hostname: newHostname },
+ params: {
+ hostname: newHostName,
+ pages_domain_id: undefined,
+ },
});
});
it('emits setKnativeHostname event when knative domain editor emits change event', () => {
- wrapper.find(KnativeDomainEditor).vm.$emit('set', newHostname);
+ wrapper.find(KnativeDomainEditor).vm.$emit('set', {
+ domain: availableDomain.domain,
+ domainId: availableDomain.id,
+ });
- expect(eventHub.$emit).toHaveBeenCalledWith('setKnativeHostname', {
+ expect(eventHub.$emit).toHaveBeenCalledWith('setKnativeDomain', {
id: 'knative',
- hostname: newHostname,
+ domain: availableDomain.domain,
+ domainId: availableDomain.id,
});
});
});
diff --git a/spec/frontend/clusters/components/knative_domain_editor_spec.js b/spec/frontend/clusters/components/knative_domain_editor_spec.js
index 6514d883c0d..2de04f7da1f 100644
--- a/spec/frontend/clusters/components/knative_domain_editor_spec.js
+++ b/spec/frontend/clusters/components/knative_domain_editor_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { GlDropdownItem } from '@gitlab/ui';
import KnativeDomainEditor from '~/clusters/components/knative_domain_editor.vue';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import { APPLICATION_STATUS } from '~/clusters/constants';
@@ -80,7 +81,7 @@ describe('KnativeDomainEditor', () => {
it('triggers save event and pass current knative hostname', () => {
wrapper.find(LoadingButton).vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('save')[0]).toEqual([knative.hostname]);
+ expect(wrapper.emitted('save').length).toEqual(1);
});
});
});
@@ -104,14 +105,43 @@ describe('KnativeDomainEditor', () => {
describe('when knative domain name input changes', () => {
it('emits "set" event with updated domain name', () => {
- createComponent({ knative });
+ const newDomain = {
+ id: 4,
+ domain: 'newhostname.com',
+ };
+
+ createComponent({ knative: { ...knative, availableDomains: [newDomain] } });
+ jest.spyOn(wrapper.vm, 'selectDomain');
+
+ wrapper.find(GlDropdownItem).vm.$emit('click');
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.selectDomain).toHaveBeenCalledWith(newDomain);
+ expect(wrapper.emitted('set')[0]).toEqual([
+ {
+ domain: newDomain.domain,
+ domainId: newDomain.id,
+ },
+ ]);
+ });
+ });
+
+ it('emits "set" event with updated custom domain name', () => {
const newHostname = 'newhostname.com';
+ createComponent({ knative });
+ jest.spyOn(wrapper.vm, 'selectCustomDomain');
+
wrapper.setData({ knativeHostname: newHostname });
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('set')[0]).toEqual([newHostname]);
+ expect(wrapper.vm.selectCustomDomain).toHaveBeenCalledWith(newHostname);
+ expect(wrapper.emitted('set')[0]).toEqual([
+ {
+ domain: newHostname,
+ domainId: null,
+ },
+ ]);
});
});
});
diff --git a/spec/frontend/clusters/stores/clusters_store_spec.js b/spec/frontend/clusters/stores/clusters_store_spec.js
index 0207fda84c4..9fafc688af9 100644
--- a/spec/frontend/clusters/stores/clusters_store_spec.js
+++ b/spec/frontend/clusters/stores/clusters_store_spec.js
@@ -140,7 +140,7 @@ describe('Clusters Store', () => {
statusReason: mockResponseData.applications[5].status_reason,
requestReason: null,
hostname: null,
- isEditingHostName: false,
+ isEditingDomain: false,
externalIp: null,
externalHostname: null,
installed: false,
diff --git a/spec/frontend/ide/components/branches/search_list_spec.js b/spec/frontend/ide/components/branches/search_list_spec.js
index 826d51b24f1..fe142d70698 100644
--- a/spec/frontend/ide/components/branches/search_list_spec.js
+++ b/spec/frontend/ide/components/branches/search_list_spec.js
@@ -9,8 +9,6 @@ import { branches } from '../../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
-jest.mock('lodash/debounce', () => jest.fn);
-
describe('IDE branches search list', () => {
let wrapper;
const fetchBranchesMock = jest.fn();
diff --git a/spec/frontend/ide/components/merge_requests/list_spec.js b/spec/frontend/ide/components/merge_requests/list_spec.js
index ae94ee4efa7..e2c6ac49e07 100644
--- a/spec/frontend/ide/components/merge_requests/list_spec.js
+++ b/spec/frontend/ide/components/merge_requests/list_spec.js
@@ -134,9 +134,7 @@ describe('IDE merge requests list', () => {
createComponent(defaultStateWithMergeRequests);
const input = findTokenedInput();
input.vm.$emit('input', 'something');
- fetchMergeRequestsMock.mockClear();
- jest.runAllTimers();
return wrapper.vm.$nextTick().then(() => {
expect(fetchMergeRequestsMock).toHaveBeenCalledWith(
expect.any(Object),
diff --git a/spec/frontend/lib/utils/url_utility_spec.js b/spec/frontend/lib/utils/url_utility_spec.js
index d0abf2c03a9..4960895890f 100644
--- a/spec/frontend/lib/utils/url_utility_spec.js
+++ b/spec/frontend/lib/utils/url_utility_spec.js
@@ -485,4 +485,30 @@ describe('URL utility', () => {
);
});
});
+
+ describe('getHTTPProtocol', () => {
+ const httpProtocol = 'http:';
+ const httpsProtocol = 'https:';
+
+ it.each([[httpProtocol], [httpsProtocol]])(
+ 'when no url passed, returns correct protocol for %i from window location',
+ protocol => {
+ setWindowLocation({
+ protocol,
+ });
+ expect(urlUtils.getHTTPProtocol()).toBe(protocol.slice(0, -1));
+ },
+ );
+
+ it.each`
+ url | expectation
+ ${'not-a-url'} | ${undefined}
+ ${'wss://example.com'} | ${'wss'}
+ ${'https://foo.bar'} | ${'https'}
+ ${'http://foo.bar'} | ${'http'}
+ ${'http://foo.bar:8080'} | ${'http'}
+ `('returns correct protocol for $url', ({ url, expectation }) => {
+ expect(urlUtils.getHTTPProtocol(url)).toBe(expectation);
+ });
+ });
});
diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js
index fff76f158dd..e216f49630f 100644
--- a/spec/frontend/test_setup.js
+++ b/spec/frontend/test_setup.js
@@ -20,7 +20,7 @@ afterEach(() =>
// give Promises a bit more time so they fail the right test
new Promise(setImmediate).then(() => {
// wait for pending setTimeout()s
- jest.runAllTimers();
+ jest.runOnlyPendingTimers();
}),
);
diff --git a/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap
new file mode 100644
index 00000000000..d837c793784
--- /dev/null
+++ b/spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap
@@ -0,0 +1,115 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Clone Dropdown Button rendering matches the snapshot 1`] = `
+<gl-new-dropdown-stub
+ category="primary"
+ headertext=""
+ size="medium"
+ text="Clone"
+ variant="info"
+>
+ <div
+ class="pb-2 mx-1"
+ >
+ <gl-new-dropdown-header-stub>
+ Clone with SSH
+ </gl-new-dropdown-header-stub>
+
+ <div
+ class="mx-3"
+ >
+ <div
+ readonly="readonly"
+ >
+ <b-input-group-stub
+ tag="div"
+ >
+ <b-input-group-prepend-stub
+ tag="div"
+ >
+
+ <!---->
+ </b-input-group-prepend-stub>
+
+ <b-form-input-stub
+ class="gl-form-input"
+ debounce="0"
+ readonly="true"
+ type="text"
+ value="ssh://foo.bar"
+ />
+
+ <b-input-group-append-stub
+ tag="div"
+ >
+ <gl-new-button-stub
+ category="tertiary"
+ data-clipboard-text="ssh://foo.bar"
+ icon=""
+ size="medium"
+ title="Copy URL"
+ variant="default"
+ >
+ <gl-icon-stub
+ name="copy-to-clipboard"
+ size="16"
+ title="Copy URL"
+ />
+ </gl-new-button-stub>
+ </b-input-group-append-stub>
+ </b-input-group-stub>
+ </div>
+ </div>
+
+ <gl-new-dropdown-header-stub>
+ Clone with HTTP
+ </gl-new-dropdown-header-stub>
+
+ <div
+ class="mx-3"
+ >
+ <div
+ readonly="readonly"
+ >
+ <b-input-group-stub
+ tag="div"
+ >
+ <b-input-group-prepend-stub
+ tag="div"
+ >
+
+ <!---->
+ </b-input-group-prepend-stub>
+
+ <b-form-input-stub
+ class="gl-form-input"
+ debounce="0"
+ readonly="true"
+ type="text"
+ value="http://foo.bar"
+ />
+
+ <b-input-group-append-stub
+ tag="div"
+ >
+ <gl-new-button-stub
+ category="tertiary"
+ data-clipboard-text="http://foo.bar"
+ icon=""
+ size="medium"
+ title="Copy URL"
+ variant="default"
+ >
+ <gl-icon-stub
+ name="copy-to-clipboard"
+ size="16"
+ title="Copy URL"
+ />
+ </gl-new-button-stub>
+ </b-input-group-append-stub>
+ </b-input-group-stub>
+ </div>
+ </div>
+ </div>
+</gl-new-dropdown-stub>
+`;
diff --git a/spec/frontend/vue_shared/components/clone_dropdown_spec.js b/spec/frontend/vue_shared/components/clone_dropdown_spec.js
new file mode 100644
index 00000000000..38e0cadfe83
--- /dev/null
+++ b/spec/frontend/vue_shared/components/clone_dropdown_spec.js
@@ -0,0 +1,74 @@
+import CloneDropdown from '~/vue_shared/components/clone_dropdown.vue';
+import { shallowMount } from '@vue/test-utils';
+import { GlFormInputGroup, GlNewDropdownHeader } from '@gitlab/ui';
+
+describe('Clone Dropdown Button', () => {
+ let wrapper;
+ const sshLink = 'ssh://foo.bar';
+ const httpLink = 'http://foo.bar';
+ const httpsLink = 'https://foo.bar';
+ const defaultPropsData = {
+ sshLink,
+ httpLink,
+ };
+
+ const createComponent = (propsData = defaultPropsData) => {
+ wrapper = shallowMount(CloneDropdown, {
+ propsData,
+ stubs: {
+ 'gl-form-input-group': GlFormInputGroup,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('rendering', () => {
+ it('matches the snapshot', () => {
+ createComponent();
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it.each`
+ name | index | value
+ ${'SSH'} | ${0} | ${sshLink}
+ ${'HTTP'} | ${1} | ${httpLink}
+ `('renders correct link and a copy-button for $name', ({ index, value }) => {
+ createComponent();
+ const group = wrapper.findAll(GlFormInputGroup).at(index);
+ expect(group.props('value')).toBe(value);
+ expect(group.contains(GlFormInputGroup)).toBe(true);
+ });
+
+ it.each`
+ name | value
+ ${'sshLink'} | ${sshLink}
+ ${'httpLink'} | ${httpLink}
+ `('does not fail if only $name is set', ({ name, value }) => {
+ createComponent({ [name]: value });
+
+ expect(wrapper.find(GlFormInputGroup).props('value')).toBe(value);
+ expect(wrapper.findAll(GlNewDropdownHeader).length).toBe(1);
+ });
+ });
+
+ describe('functionality', () => {
+ it.each`
+ name | value
+ ${'sshLink'} | ${null}
+ ${'httpLink'} | ${null}
+ `('allows null values for the props', ({ name, value }) => {
+ createComponent({ ...defaultPropsData, [name]: value });
+
+ expect(wrapper.findAll(GlNewDropdownHeader).length).toBe(1);
+ });
+
+ it('correctly calculates httpLabel for HTTPS protocol', () => {
+ createComponent({ httpLink: httpsLink });
+ expect(wrapper.find(GlNewDropdownHeader).text()).toContain('HTTPS');
+ });
+ });
+});
diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb
index d1a4924c07e..cb8122b6573 100644
--- a/spec/models/service_spec.rb
+++ b/spec/models/service_spec.rb
@@ -104,21 +104,29 @@ describe Service do
describe "Test Button" do
describe '#can_test?' do
+ subject { service.can_test? }
+
let(:service) { create(:service, project: project) }
context 'when repository is not empty' do
let(:project) { create(:project, :repository) }
- it 'returns true' do
- expect(service.can_test?).to be true
- end
+ it { is_expected.to be true }
end
context 'when repository is empty' do
let(:project) { create(:project) }
- it 'returns true' do
- expect(service.can_test?).to be true
+ it { is_expected.to be true }
+ end
+
+ context 'when instance-level service' do
+ Service.available_services_types.each do |service_type|
+ let(:service) do
+ service_type.constantize.new(instance: true)
+ end
+
+ it { is_expected.to be_falsey }
end
end
end
diff --git a/spec/services/metrics/dashboard/update_dashboard_service_spec.rb b/spec/services/metrics/dashboard/update_dashboard_service_spec.rb
index 72d36959bce..fce027688d9 100644
--- a/spec/services/metrics/dashboard/update_dashboard_service_spec.rb
+++ b/spec/services/metrics/dashboard/update_dashboard_service_spec.rb
@@ -27,14 +27,7 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto
end
context 'user does not have push right to repository' do
- it 'returns an appropriate message and status code', :aggregate_failures do
- result = service_call
-
- expect(result.keys).to contain_exactly(:message, :http_status, :status, :last_step)
- expect(result[:status]).to eq(:error)
- expect(result[:http_status]).to eq(:forbidden)
- expect(result[:message]).to eq("You are not allowed to push into this branch. Create another branch or open a merge request.")
- end
+ it_behaves_like 'misconfigured dashboard service response with stepable', :forbidden, 'You are not allowed to push into this branch. Create another branch or open a merge request.'
end
context 'with rights to push to the repository' do
@@ -46,27 +39,13 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto
context 'with a yml extension' do
let(:file_name) { 'config/prometheus/../database.yml' }
- it 'returns an appropriate message and status code', :aggregate_failures do
- result = service_call
-
- expect(result.keys).to contain_exactly(:message, :http_status, :status, :last_step)
- expect(result[:status]).to eq(:error)
- expect(result[:http_status]).to eq(:bad_request)
- expect(result[:message]).to eq("A file with this name doesn't exist")
- end
+ it_behaves_like 'misconfigured dashboard service response with stepable', :bad_request, "A file with this name doesn't exist"
end
context 'without a yml extension' do
let(:file_name) { '../../..../etc/passwd' }
- it 'returns an appropriate message and status code', :aggregate_failures do
- result = service_call
-
- expect(result.keys).to contain_exactly(:message, :http_status, :status, :last_step)
- expect(result[:status]).to eq(:error)
- expect(result[:http_status]).to eq(:bad_request)
- expect(result[:message]).to eq("The file name should have a .yml extension")
- end
+ it_behaves_like 'misconfigured dashboard service response with stepable', :bad_request, 'The file name should have a .yml extension'
end
end
@@ -81,14 +60,7 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto
project.repository.add_branch(user, branch, 'master')
end
- it 'returns an appropriate message and status code', :aggregate_failures do
- result = service_call
-
- expect(result.keys).to contain_exactly(:message, :http_status, :status, :last_step)
- expect(result[:status]).to eq(:error)
- expect(result[:http_status]).to eq(:bad_request)
- expect(result[:message]).to eq("There was an error updating the dashboard, branch named: existing_branch already exists.")
- end
+ it_behaves_like 'misconfigured dashboard service response with stepable', :bad_request, 'There was an error updating the dashboard, branch named: existing_branch already exists.'
end
context 'Files::UpdateService success' do