summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-05-12 15:10:33 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-12 15:10:33 +0000
commit8ff63012e9b7e3dc2279e636868af9a438d1fa93 (patch)
tree4dd67f247345cbc2e8629c4a5f2b935dafc988e3 /spec
parentef7cfec30c9fab7b9e757877c472ca7ca2eccc2d (diff)
downloadgitlab-ce-8ff63012e9b7e3dc2279e636868af9a438d1fa93.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/frontend/diffs/store/getters_versions_dropdowns_spec.js9
-rw-r--r--spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap1
-rw-r--r--spec/frontend/monitoring/components/dashboards_dropdown_spec.js8
-rw-r--r--spec/frontend/monitoring/mock_data.js2
-rw-r--r--spec/frontend/monitoring/store/actions_spec.js44
-rw-r--r--spec/frontend/monitoring/store/getters_spec.js46
-rw-r--r--spec/frontend/monitoring/store/mutations_spec.js43
-rw-r--r--spec/frontend/static_site_editor/components/edit_area_spec.js79
-rw-r--r--spec/frontend/static_site_editor/pages/home_spec.js182
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js30
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js111
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js21
-rw-r--r--spec/helpers/milestones_helper_spec.rb15
-rw-r--r--spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb2
-rw-r--r--spec/lib/gitlab/cycle_analytics/summary/value_spec.rb29
-rw-r--r--spec/migrations/backfill_environment_id_on_deployment_merge_requests_spec.rb81
-rw-r--r--spec/models/merge_request_spec.rb38
-rw-r--r--spec/models/sent_notification_spec.rb22
-rw-r--r--spec/policies/ci/build_policy_spec.rb18
-rw-r--r--spec/requests/api/branches_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/branches/create_spec.rb2
-rw-r--r--spec/rubocop/cop/inject_enterprise_edition_module_spec.rb11
-rw-r--r--spec/services/branches/create_service_spec.rb30
23 files changed, 538 insertions, 288 deletions
diff --git a/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js b/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js
index eb0f2364a50..0343ef75732 100644
--- a/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js
+++ b/spec/frontend/diffs/store/getters_versions_dropdowns_spec.js
@@ -18,7 +18,6 @@ describe('Compare diff version dropdowns', () => {
};
localState.targetBranchName = 'baseVersion';
localState.mergeRequestDiffs = diffsMockData;
- gon.features = { diffCompareWithHead: true };
});
describe('selectedTargetIndex', () => {
@@ -129,14 +128,6 @@ describe('Compare diff version dropdowns', () => {
});
assertVersions(targetVersions);
});
-
- it('does not list head version if feature flag is not enabled', () => {
- gon.features = { diffCompareWithHead: false };
- setupTest();
- const targetVersions = getters.diffCompareDropdownTargetVersions(localState, getters);
-
- expect(targetVersions.find(version => version.isHead)).toBeUndefined();
- });
});
it('diffCompareDropdownSourceVersions', () => {
diff --git a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
index 6cb7821b341..5770778d8ee 100644
--- a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
+++ b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
@@ -16,7 +16,6 @@ exports[`Dashboard template matches the default snapshot 1`] = `
data-qa-selector="dashboards_filter_dropdown"
defaultbranch="master"
id="monitor-dashboards-dropdown"
- selecteddashboard="[object Object]"
toggle-class="dropdown-menu-toggle"
/>
</div>
diff --git a/spec/frontend/monitoring/components/dashboards_dropdown_spec.js b/spec/frontend/monitoring/components/dashboards_dropdown_spec.js
index 25b31a793f7..b29d86cbc5b 100644
--- a/spec/frontend/monitoring/components/dashboards_dropdown_spec.js
+++ b/spec/frontend/monitoring/components/dashboards_dropdown_spec.js
@@ -15,6 +15,7 @@ const notStarredDashboards = dashboardGitResponse.filter(({ starred }) => !starr
describe('DashboardsDropdown', () => {
let wrapper;
let mockDashboards;
+ let mockSelectedDashboard;
function createComponent(props, opts = {}) {
const storeOpts = {
@@ -23,6 +24,7 @@ describe('DashboardsDropdown', () => {
},
computed: {
allDashboards: () => mockDashboards,
+ selectedDashboard: () => mockSelectedDashboard,
},
};
@@ -46,6 +48,7 @@ describe('DashboardsDropdown', () => {
beforeEach(() => {
mockDashboards = dashboardGitResponse;
+ mockSelectedDashboard = null;
});
describe('when it receives dashboards data', () => {
@@ -153,13 +156,12 @@ describe('DashboardsDropdown', () => {
let modalDirective;
beforeEach(() => {
+ [mockSelectedDashboard] = dashboardGitResponse;
modalDirective = jest.fn();
duplicateDashboardAction = jest.fn().mockResolvedValue();
wrapper = createComponent(
- {
- selectedDashboard: dashboardGitResponse[0],
- },
+ {},
{
directives: {
GlModal: modalDirective,
diff --git a/spec/frontend/monitoring/mock_data.js b/spec/frontend/monitoring/mock_data.js
index dab560d197d..2fa88dfa87a 100644
--- a/spec/frontend/monitoring/mock_data.js
+++ b/spec/frontend/monitoring/mock_data.js
@@ -325,6 +325,7 @@ export const dashboardGitResponse = [
project_blob_path: null,
path: 'config/prometheus/common_metrics.yml',
starred: false,
+ user_starred_path: `${mockProjectDir}/metrics_user_starred_dashboards?dashboard_path=config/prometheus/common_metrics.yml`,
},
{
default: false,
@@ -334,6 +335,7 @@ export const dashboardGitResponse = [
project_blob_path: `${mockProjectDir}/-/blob/master/.gitlab/dashboards/dashboard.yml`,
path: '.gitlab/dashboards/dashboard.yml',
starred: true,
+ user_starred_path: `${mockProjectDir}/metrics_user_starred_dashboards?dashboard_path=.gitlab/dashboards/dashboard.yml`,
},
...customDashboardsData,
];
diff --git a/spec/frontend/monitoring/store/actions_spec.js b/spec/frontend/monitoring/store/actions_spec.js
index 901b698b703..44626bfcc57 100644
--- a/spec/frontend/monitoring/store/actions_spec.js
+++ b/spec/frontend/monitoring/store/actions_spec.js
@@ -18,6 +18,7 @@ import {
fetchEnvironmentsData,
fetchDashboardData,
fetchAnnotations,
+ toggleStarredValue,
fetchPrometheusMetric,
setInitialState,
filterEnvironments,
@@ -350,6 +351,49 @@ describe('Monitoring store actions', () => {
});
});
+ describe('Toggles starred value of current dashboard', () => {
+ const { state } = store;
+ let unstarredDashboard;
+ let starredDashboard;
+
+ beforeEach(() => {
+ state.isUpdatingStarredValue = false;
+ [unstarredDashboard, starredDashboard] = dashboardGitResponse;
+ });
+
+ describe('toggleStarredValue', () => {
+ it('performs no changes if no dashboard is selected', () => {
+ return testAction(toggleStarredValue, null, state, [], []);
+ });
+
+ it('performs no changes if already changing starred value', () => {
+ state.selectedDashboard = unstarredDashboard;
+ state.isUpdatingStarredValue = true;
+ return testAction(toggleStarredValue, null, state, [], []);
+ });
+
+ it('stars dashboard if it is not starred', () => {
+ state.selectedDashboard = unstarredDashboard;
+ mock.onPost(unstarredDashboard.user_starred_path).reply(200);
+
+ return testAction(toggleStarredValue, null, state, [
+ { type: types.REQUEST_DASHBOARD_STARRING },
+ { type: types.RECEIVE_DASHBOARD_STARRING_SUCCESS, payload: true },
+ ]);
+ });
+
+ it('unstars dashboard if it is starred', () => {
+ state.selectedDashboard = starredDashboard;
+ mock.onPost(starredDashboard.user_starred_path).reply(200);
+
+ return testAction(toggleStarredValue, null, state, [
+ { type: types.REQUEST_DASHBOARD_STARRING },
+ { type: types.RECEIVE_DASHBOARD_STARRING_FAILURE },
+ ]);
+ });
+ });
+ });
+
describe('Set initial state', () => {
let mockedState;
beforeEach(() => {
diff --git a/spec/frontend/monitoring/store/getters_spec.js b/spec/frontend/monitoring/store/getters_spec.js
index e9622071aeb..f07ae4c5a1e 100644
--- a/spec/frontend/monitoring/store/getters_spec.js
+++ b/spec/frontend/monitoring/store/getters_spec.js
@@ -3,7 +3,7 @@ import * as getters from '~/monitoring/stores/getters';
import mutations from '~/monitoring/stores/mutations';
import * as types from '~/monitoring/stores/mutation_types';
import { metricStates } from '~/monitoring/constants';
-import { environmentData, metricsResult } from '../mock_data';
+import { environmentData, metricsResult, dashboardGitResponse } from '../mock_data';
import {
metricsDashboardPayload,
metricResultStatus,
@@ -350,4 +350,48 @@ describe('Monitoring store Getters', () => {
expect(variablesArray).toEqual([]);
});
});
+
+ describe('selectedDashboard', () => {
+ const { selectedDashboard } = getters;
+
+ it('returns a dashboard', () => {
+ const state = {
+ allDashboards: dashboardGitResponse,
+ currentDashboard: dashboardGitResponse[0].path,
+ };
+ expect(selectedDashboard(state)).toEqual(dashboardGitResponse[0]);
+ });
+
+ it('returns a non-default dashboard', () => {
+ const state = {
+ allDashboards: dashboardGitResponse,
+ currentDashboard: dashboardGitResponse[1].path,
+ };
+ expect(selectedDashboard(state)).toEqual(dashboardGitResponse[1]);
+ });
+
+ it('returns a default dashboard when no dashboard is selected', () => {
+ const state = {
+ allDashboards: dashboardGitResponse,
+ currentDashboard: null,
+ };
+ expect(selectedDashboard(state)).toEqual(dashboardGitResponse[0]);
+ });
+
+ it('returns a default dashboard when dashboard cannot be found', () => {
+ const state = {
+ allDashboards: dashboardGitResponse,
+ currentDashboard: 'wrong_path',
+ };
+ expect(selectedDashboard(state)).toEqual(dashboardGitResponse[0]);
+ });
+
+ it('returns null when no dashboards are present', () => {
+ const state = {
+ allDashboards: [],
+ currentDashboard: dashboardGitResponse[0].path,
+ };
+ expect(selectedDashboard(state)).toEqual(null);
+ });
+ });
});
diff --git a/spec/frontend/monitoring/store/mutations_spec.js b/spec/frontend/monitoring/store/mutations_spec.js
index e6564f5e329..29628c99256 100644
--- a/spec/frontend/monitoring/store/mutations_spec.js
+++ b/spec/frontend/monitoring/store/mutations_spec.js
@@ -72,6 +72,49 @@ describe('Monitoring mutations', () => {
});
});
+ describe('Dashboard starring mutations', () => {
+ it('REQUEST_DASHBOARD_STARRING', () => {
+ stateCopy = { isUpdatingStarredValue: false };
+ mutations[types.REQUEST_DASHBOARD_STARRING](stateCopy);
+
+ expect(stateCopy.isUpdatingStarredValue).toBe(true);
+ });
+
+ describe('RECEIVE_DASHBOARD_STARRING_SUCCESS', () => {
+ let allDashboards;
+
+ beforeEach(() => {
+ allDashboards = [...dashboardGitResponse];
+ stateCopy = {
+ allDashboards,
+ currentDashboard: allDashboards[1].path,
+ isUpdatingStarredValue: true,
+ };
+ });
+
+ it('sets a dashboard as starred', () => {
+ mutations[types.RECEIVE_DASHBOARD_STARRING_SUCCESS](stateCopy, true);
+
+ expect(stateCopy.isUpdatingStarredValue).toBe(false);
+ expect(stateCopy.allDashboards[1].starred).toBe(true);
+ });
+
+ it('sets a dashboard as unstarred', () => {
+ mutations[types.RECEIVE_DASHBOARD_STARRING_SUCCESS](stateCopy, false);
+
+ expect(stateCopy.isUpdatingStarredValue).toBe(false);
+ expect(stateCopy.allDashboards[1].starred).toBe(false);
+ });
+ });
+
+ it('RECEIVE_DASHBOARD_STARRING_FAILURE', () => {
+ stateCopy = { isUpdatingStarredValue: true };
+ mutations[types.RECEIVE_DASHBOARD_STARRING_FAILURE](stateCopy);
+
+ expect(stateCopy.isUpdatingStarredValue).toBe(false);
+ });
+ });
+
describe('RECEIVE_DEPLOYMENTS_DATA_SUCCESS', () => {
it('stores the deployment data', () => {
stateCopy.deploymentData = [];
diff --git a/spec/frontend/static_site_editor/components/edit_area_spec.js b/spec/frontend/static_site_editor/components/edit_area_spec.js
new file mode 100644
index 00000000000..19330039812
--- /dev/null
+++ b/spec/frontend/static_site_editor/components/edit_area_spec.js
@@ -0,0 +1,79 @@
+import { shallowMount } from '@vue/test-utils';
+
+import RichContentEditor from '~/vue_shared/components/rich_content_editor/rich_content_editor.vue';
+
+import EditArea from '~/static_site_editor/components/edit_area.vue';
+import PublishToolbar from '~/static_site_editor/components/publish_toolbar.vue';
+import EditHeader from '~/static_site_editor/components/edit_header.vue';
+
+import { sourceContentTitle as title, sourceContent as content, returnUrl } from '../mock_data';
+
+describe('~/static_site_editor/components/edit_area.vue', () => {
+ let wrapper;
+ const savingChanges = true;
+ const newContent = `new ${content}`;
+
+ const buildWrapper = (propsData = {}) => {
+ wrapper = shallowMount(EditArea, {
+ provide: {
+ glFeatures: { richContentEditor: true },
+ },
+ propsData: {
+ title,
+ content,
+ returnUrl,
+ savingChanges,
+ ...propsData,
+ },
+ });
+ };
+
+ const findEditHeader = () => wrapper.find(EditHeader);
+ const findRichContentEditor = () => wrapper.find(RichContentEditor);
+ const findPublishToolbar = () => wrapper.find(PublishToolbar);
+
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders edit header', () => {
+ expect(findEditHeader().exists()).toBe(true);
+ expect(findEditHeader().props('title')).toBe(title);
+ });
+
+ it('renders rich content editor', () => {
+ expect(findRichContentEditor().exists()).toBe(true);
+ expect(findRichContentEditor().props('value')).toBe(content);
+ });
+
+ it('renders publish toolbar', () => {
+ expect(findPublishToolbar().exists()).toBe(true);
+ expect(findPublishToolbar().props('returnUrl')).toBe(returnUrl);
+ expect(findPublishToolbar().props('savingChanges')).toBe(savingChanges);
+ expect(findPublishToolbar().props('saveable')).toBe(false);
+ });
+
+ describe('when content changes', () => {
+ beforeEach(() => {
+ findRichContentEditor().vm.$emit('input', newContent);
+
+ return wrapper.vm.$nextTick();
+ });
+
+ it('sets publish toolbar as saveable when content changes', () => {
+ expect(findPublishToolbar().props('saveable')).toBe(true);
+ });
+
+ it('sets publish toolbar as not saveable when content changes are rollback', () => {
+ findRichContentEditor().vm.$emit('input', content);
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findPublishToolbar().props('saveable')).toBe(false);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/pages/home_spec.js b/spec/frontend/static_site_editor/pages/home_spec.js
index 69646abade5..281b764a801 100644
--- a/spec/frontend/static_site_editor/pages/home_spec.js
+++ b/spec/frontend/static_site_editor/pages/home_spec.js
@@ -1,21 +1,20 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { GlSkeletonLoader } from '@gitlab/ui';
import createState from '~/static_site_editor/store/state';
import Home from '~/static_site_editor/pages/home.vue';
-import RichContentEditor from '~/vue_shared/components/rich_content_editor/rich_content_editor.vue';
-import EditHeader from '~/static_site_editor/components/edit_header.vue';
+
+import SkeletonLoader from '~/static_site_editor/components/skeleton_loader.vue';
+import EditArea from '~/static_site_editor/components/edit_area.vue';
import InvalidContentMessage from '~/static_site_editor/components/invalid_content_message.vue';
-import PublishToolbar from '~/static_site_editor/components/publish_toolbar.vue';
import SubmitChangesError from '~/static_site_editor/components/submit_changes_error.vue';
import SavedChangesMessage from '~/static_site_editor/components/saved_changes_message.vue';
import {
returnUrl,
- sourceContent,
- sourceContentTitle,
+ sourceContent as content,
+ sourceContentTitle as title,
savedContentMeta,
submitChangesError,
} from '../mock_data';
@@ -27,13 +26,12 @@ localVue.use(Vuex);
describe('static_site_editor/pages/home', () => {
let wrapper;
let store;
- let loadContentActionMock;
+ let $apollo;
let setContentActionMock;
let submitChangesActionMock;
let dismissSubmitChangesErrorActionMock;
const buildStore = ({ initialState, getters } = {}) => {
- loadContentActionMock = jest.fn();
setContentActionMock = jest.fn();
submitChangesActionMock = jest.fn();
dismissSubmitChangesErrorActionMock = jest.fn();
@@ -47,53 +45,55 @@ describe('static_site_editor/pages/home', () => {
...getters,
},
actions: {
- loadContent: loadContentActionMock,
setContent: setContentActionMock,
submitChanges: submitChangesActionMock,
dismissSubmitChangesError: dismissSubmitChangesErrorActionMock,
},
});
};
- const buildContentLoadedStore = ({ initialState, getters } = {}) => {
- buildStore({
- initialState: {
- isContentLoaded: true,
- ...initialState,
- },
- getters: {
- ...getters,
+
+ const buildApollo = (queries = {}) => {
+ $apollo = {
+ queries: {
+ sourceContent: {
+ loading: false,
+ },
+ ...queries,
},
- });
+ };
};
- const buildWrapper = (data = { appData: { isSupportedContent: true } }) => {
+ const buildWrapper = (data = {}) => {
wrapper = shallowMount(Home, {
localVue,
store,
- provide: {
- glFeatures: { richContentEditor: true },
+ mocks: {
+ $apollo,
},
data() {
- return data;
+ return {
+ appData: { isSupportedContent: true, returnUrl },
+ ...data,
+ };
},
});
};
- const findRichContentEditor = () => wrapper.find(RichContentEditor);
- const findEditHeader = () => wrapper.find(EditHeader);
+ const findEditArea = () => wrapper.find(EditArea);
const findInvalidContentMessage = () => wrapper.find(InvalidContentMessage);
- const findPublishToolbar = () => wrapper.find(PublishToolbar);
- const findSkeletonLoader = () => wrapper.find(GlSkeletonLoader);
+ const findSkeletonLoader = () => wrapper.find(SkeletonLoader);
const findSubmitChangesError = () => wrapper.find(SubmitChangesError);
const findSavedChangesMessage = () => wrapper.find(SavedChangesMessage);
beforeEach(() => {
+ buildApollo();
buildStore();
- buildWrapper();
});
afterEach(() => {
wrapper.destroy();
+ wrapper = null;
+ $apollo = null;
});
it('renders the saved changes message when changes are submitted successfully', () => {
@@ -107,103 +107,69 @@ describe('static_site_editor/pages/home', () => {
});
});
- describe('when content is not loaded', () => {
- it('does not render rich content editor', () => {
- expect(findRichContentEditor().exists()).toBe(false);
- });
-
- it('does not render edit header', () => {
- expect(findEditHeader().exists()).toBe(false);
- });
-
- it('does not render toolbar', () => {
- expect(findPublishToolbar().exists()).toBe(false);
- });
+ it('does not render the saved changes message when changes are not submitted', () => {
+ buildWrapper();
- it('does not render saved changes message', () => {
- expect(findSavedChangesMessage().exists()).toBe(false);
- });
+ expect(findSavedChangesMessage().exists()).toBe(false);
});
describe('when content is loaded', () => {
- const content = sourceContent;
- const title = sourceContentTitle;
-
beforeEach(() => {
- buildContentLoadedStore({ initialState: { content, title } });
- buildWrapper();
+ buildStore({ initialState: { isSavingChanges: true } });
+ buildWrapper({ sourceContent: { title, content } });
});
- it('renders the rich content editor', () => {
- expect(findRichContentEditor().exists()).toBe(true);
+ it('renders edit area', () => {
+ expect(findEditArea().exists()).toBe(true);
});
- it('renders the edit header', () => {
- expect(findEditHeader().exists()).toBe(true);
+ it('provides source content to the edit area', () => {
+ expect(findEditArea().props()).toMatchObject({
+ title,
+ content,
+ });
});
- it('does not render skeleton loader', () => {
- expect(findSkeletonLoader().exists()).toBe(false);
+ it('provides returnUrl to the edit area', () => {
+ expect(findEditArea().props('returnUrl')).toBe(returnUrl);
});
- it('passes page content to the rich content editor', () => {
- expect(findRichContentEditor().props('value')).toBe(content);
+ it('provides isSavingChanges to the edit area', () => {
+ expect(findEditArea().props('savingChanges')).toBe(true);
});
+ });
- it('passes page title to edit header', () => {
- expect(findEditHeader().props('title')).toBe(title);
- });
+ it('does not render edit area when content is not loaded', () => {
+ buildWrapper({ sourceContent: null });
- it('renders toolbar', () => {
- expect(findPublishToolbar().exists()).toBe(true);
- });
+ expect(findEditArea().exists()).toBe(false);
});
- it('sets toolbar as saveable when content changes', () => {
- buildContentLoadedStore({
- getters: {
- contentChanged: () => true,
+ it('renders skeleton loader when content is not loading', () => {
+ buildApollo({
+ sourceContent: {
+ loading: true,
},
});
buildWrapper();
- expect(findPublishToolbar().props('saveable')).toBe(true);
- });
-
- it('displays skeleton loader when loading content', () => {
- buildStore({ initialState: { isLoadingContent: true } });
- buildWrapper();
-
expect(findSkeletonLoader().exists()).toBe(true);
});
- it('does not display submit changes error when an error does not exist', () => {
- buildContentLoadedStore();
- buildWrapper();
-
- expect(findSubmitChangesError().exists()).toBe(false);
- });
-
- it('sets toolbar as saving when saving changes', () => {
- buildContentLoadedStore({
- initialState: {
- isSavingChanges: true,
+ it('does not render skeleton loader when content is not loading', () => {
+ buildApollo({
+ sourceContent: {
+ loading: false,
},
});
buildWrapper();
- expect(findPublishToolbar().props('savingChanges')).toBe(true);
- });
-
- it('displays invalid content message when content is not supported', () => {
- buildWrapper({ appData: { isSupportedContent: false } });
-
- expect(findInvalidContentMessage().exists()).toBe(true);
+ expect(findSkeletonLoader().exists()).toBe(false);
});
describe('when submitting changes fail', () => {
beforeEach(() => {
- buildContentLoadedStore({
+ buildStore({
initialState: {
submitChangesError,
},
@@ -228,24 +194,32 @@ describe('static_site_editor/pages/home', () => {
});
});
- it('dispatches load content action', () => {
- expect(loadContentActionMock).toHaveBeenCalled();
- });
-
- it('dispatches setContent action when rich content editor emits input event', () => {
- buildContentLoadedStore();
+ it('does not display submit changes error when an error does not exist', () => {
buildWrapper();
- findRichContentEditor().vm.$emit('input', sourceContent);
+ expect(findSubmitChangesError().exists()).toBe(false);
+ });
- expect(setContentActionMock).toHaveBeenCalledWith(expect.anything(), sourceContent, undefined);
+ it('displays invalid content message when content is not supported', () => {
+ buildWrapper({ appData: { isSupportedContent: false } });
+
+ expect(findInvalidContentMessage().exists()).toBe(true);
});
- it('dispatches submitChanges action when toolbar emits submit event', () => {
- buildContentLoadedStore();
- buildWrapper();
- findPublishToolbar().vm.$emit('submit');
+ describe('when edit area emits submit event', () => {
+ const newContent = `new ${content}`;
- expect(submitChangesActionMock).toHaveBeenCalled();
+ beforeEach(() => {
+ buildWrapper({ sourceContent: { title, content } });
+ findEditArea().vm.$emit('submit', { content: newContent });
+ });
+
+ it('dispatches setContent property', () => {
+ expect(setContentActionMock).toHaveBeenCalledWith(expect.anything(), newContent, undefined);
+ });
+
+ it('dispatches submitChanges action', () => {
+ expect(submitChangesActionMock).toHaveBeenCalled();
+ });
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
index 951ee3c9b3d..74c769f86a3 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
@@ -1,9 +1,10 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { GlButton, GlLoadingIcon, GlIcon, GlSearchBoxByType, GlLink } from '@gitlab/ui';
+import { GlButton, GlLoadingIcon, GlSearchBoxByType, GlLink } from '@gitlab/ui';
import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
import DropdownContentsLabelsView from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue';
+import LabelItem from '~/vue_shared/components/sidebar/labels_select_vue/label_item.vue';
import defaultState from '~/vue_shared/components/sidebar/labels_select_vue/store/state';
import mutations from '~/vue_shared/components/sidebar/labels_select_vue/store/mutations';
@@ -78,16 +79,6 @@ describe('DropdownContentsLabelsView', () => {
});
describe('methods', () => {
- describe('getDropdownLabelBoxStyle', () => {
- it('returns an object containing `backgroundColor` based on provided `label` param', () => {
- expect(wrapper.vm.getDropdownLabelBoxStyle(mockRegularLabel)).toEqual(
- expect.objectContaining({
- backgroundColor: mockRegularLabel.color,
- }),
- );
- });
- });
-
describe('isLabelSelected', () => {
it('returns true when provided `label` param is one of the selected labels', () => {
expect(wrapper.vm.isLabelSelected(mockRegularLabel)).toBe(true);
@@ -234,16 +225,7 @@ describe('DropdownContentsLabelsView', () => {
});
it('renders label elements for all labels', () => {
- const labelsEl = wrapper.findAll('.dropdown-content li');
- const labelItemEl = labelsEl.at(0).find(GlLink);
-
- expect(labelsEl.length).toBe(mockLabels.length);
- expect(labelItemEl.exists()).toBe(true);
- expect(labelItemEl.find(GlIcon).props('name')).toBe('mobile-issue-close');
- expect(labelItemEl.find('.dropdown-label-box').attributes('style')).toBe(
- 'background-color: rgb(186, 218, 85);',
- );
- expect(labelItemEl.find(GlLink).text()).toContain(mockLabels[0].title);
+ expect(wrapper.findAll(LabelItem)).toHaveLength(mockLabels.length);
});
it('renders label element with "is-focused" when value of `currentHighlightItem` is more than -1', () => {
@@ -253,9 +235,9 @@ describe('DropdownContentsLabelsView', () => {
return wrapper.vm.$nextTick(() => {
const labelsEl = wrapper.findAll('.dropdown-content li');
- const labelItemEl = labelsEl.at(0).find(GlLink);
+ const labelItemEl = labelsEl.at(0).find(LabelItem);
- expect(labelItemEl.attributes('class')).toContain('is-focused');
+ expect(labelItemEl.props('highlight')).toBe(true);
});
});
@@ -267,7 +249,7 @@ describe('DropdownContentsLabelsView', () => {
return wrapper.vm.$nextTick(() => {
const noMatchEl = wrapper.find('.dropdown-content li');
- expect(noMatchEl.exists()).toBe(true);
+ expect(noMatchEl.isVisible()).toBe(true);
expect(noMatchEl.text()).toContain('No matching results');
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js
new file mode 100644
index 00000000000..401d208da5c
--- /dev/null
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js
@@ -0,0 +1,111 @@
+import { shallowMount } from '@vue/test-utils';
+
+import { GlIcon, GlLink } from '@gitlab/ui';
+import LabelItem from '~/vue_shared/components/sidebar/labels_select_vue/label_item.vue';
+import { mockRegularLabel } from './mock_data';
+
+const createComponent = ({ label = mockRegularLabel, highlight = true } = {}) =>
+ shallowMount(LabelItem, {
+ propsData: {
+ label,
+ highlight,
+ },
+ });
+
+describe('LabelItem', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('computed', () => {
+ describe('labelBoxStyle', () => {
+ it('returns an object containing `backgroundColor` based on `label` prop', () => {
+ expect(wrapper.vm.labelBoxStyle).toEqual(
+ expect.objectContaining({
+ backgroundColor: mockRegularLabel.color,
+ }),
+ );
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('handleClick', () => {
+ it('sets value of `isSet` data prop to opposite of its current value', () => {
+ wrapper.setData({
+ isSet: true,
+ });
+
+ wrapper.vm.handleClick();
+ expect(wrapper.vm.isSet).toBe(false);
+ wrapper.vm.handleClick();
+ expect(wrapper.vm.isSet).toBe(true);
+ });
+
+ it('emits event `clickLabel` on component with `label` prop as param', () => {
+ wrapper.vm.handleClick();
+
+ expect(wrapper.emitted('clickLabel')).toBeTruthy();
+ expect(wrapper.emitted('clickLabel')[0]).toEqual([mockRegularLabel]);
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders gl-link component', () => {
+ expect(wrapper.find(GlLink).exists()).toBe(true);
+ });
+
+ it('renders gl-link component with class `is-focused` when `highlight` prop is true', () => {
+ wrapper.setProps({
+ highlight: true,
+ });
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.find(GlLink).classes()).toContain('is-focused');
+ });
+ });
+
+ it('renders visible gl-icon component when `isSet` prop is true', () => {
+ wrapper.setData({
+ isSet: true,
+ });
+
+ return wrapper.vm.$nextTick(() => {
+ const iconEl = wrapper.find(GlIcon);
+
+ expect(iconEl.isVisible()).toBe(true);
+ expect(iconEl.props('name')).toBe('mobile-issue-close');
+ });
+ });
+
+ it('renders visible span element as placeholder instead of gl-icon when `isSet` prop is false', () => {
+ wrapper.setData({
+ isSet: false,
+ });
+
+ return wrapper.vm.$nextTick(() => {
+ const placeholderEl = wrapper.find('[data-testid="no-icon"]');
+
+ expect(placeholderEl.isVisible()).toBe(true);
+ });
+ });
+
+ it('renders label color element', () => {
+ const colorEl = wrapper.find('[data-testid="label-color-box"]');
+
+ expect(colorEl.exists()).toBe(true);
+ expect(colorEl.attributes('style')).toBe('background-color: rgb(186, 218, 85);');
+ });
+
+ it('renders label title', () => {
+ expect(wrapper.text()).toContain(mockRegularLabel.title);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js
index 3031df3362f..8081806e314 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js
@@ -155,29 +155,12 @@ describe('LabelsSelect Mutations', () => {
describe(`${types.UPDATE_SELECTED_LABELS}`, () => {
const labels = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }];
- it('updates `state.labels` to include `touched` and `set` props based on provided `labels` param when `state.allowMultiselect` is `true`', () => {
- const updatedLabelIds = [2, 4];
- const state = {
- labels,
- allowMultiselect: true,
- };
- mutations[types.UPDATE_SELECTED_LABELS](state, { labels });
-
- state.labels.forEach(label => {
- if (updatedLabelIds.includes(label.id)) {
- expect(label.touched).toBe(true);
- expect(label.set).toBe(true);
- }
- });
- });
-
- it('updates `state.labels` to include `touched` and `set` props based on provided `labels` param when `state.allowMultiselect` is `false`', () => {
+ it('updates `state.labels` to include `touched` and `set` props based on provided `labels` param', () => {
const updatedLabelIds = [2];
const state = {
labels,
- allowMultiselect: false,
};
- mutations[types.UPDATE_SELECTED_LABELS](state, { labels });
+ mutations[types.UPDATE_SELECTED_LABELS](state, { labels: [{ id: 2 }] });
state.labels.forEach(label => {
if (updatedLabelIds.includes(label.id)) {
diff --git a/spec/helpers/milestones_helper_spec.rb b/spec/helpers/milestones_helper_spec.rb
index 3574066e03e..4ce7143bdf0 100644
--- a/spec/helpers/milestones_helper_spec.rb
+++ b/spec/helpers/milestones_helper_spec.rb
@@ -85,4 +85,19 @@ describe MilestonesHelper do
end
end
end
+
+ describe "#group_milestone_route" do
+ let(:group) { build_stubbed(:group) }
+ let(:subgroup) { build_stubbed(:group, parent: group, name: "Test Subgrp") }
+
+ context "when in subgroup" do
+ let(:milestone) { build_stubbed(:group_milestone, group: subgroup) }
+
+ it 'generates correct url despite assigned @group' do
+ assign(:group, group)
+ milestone_path = "/groups/#{subgroup.full_path}/-/milestones/#{milestone.iid}"
+ expect(helper.group_milestone_route(milestone)).to eq(milestone_path)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb b/spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb
index c3bb975727b..34ac70071bb 100644
--- a/spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb
@@ -32,7 +32,7 @@ describe Gitlab::BackgroundMigration::BackfillEnvironmentIdDeploymentMergeReques
expect(deployment_merge_requests.where(environment_id: nil).count).to eq(3)
- migration.perform(1, mr.id)
+ migration.backfill_range(1, mr.id)
expect(deployment_merge_requests.where(environment_id: nil).count).to be_zero
expect(deployment_merge_requests.count).to eq(2)
diff --git a/spec/lib/gitlab/cycle_analytics/summary/value_spec.rb b/spec/lib/gitlab/cycle_analytics/summary/value_spec.rb
new file mode 100644
index 00000000000..21ee42295cd
--- /dev/null
+++ b/spec/lib/gitlab/cycle_analytics/summary/value_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::CycleAnalytics::Summary::Value do
+ describe Gitlab::CycleAnalytics::Summary::Value::None do
+ it 'returns `-`' do
+ expect(described_class.new.to_s).to eq('-')
+ end
+ end
+
+ describe Gitlab::CycleAnalytics::Summary::Value::Numeric do
+ it 'returns the string representation of the number' do
+ expect(described_class.new(3.2).to_s).to eq('3.2')
+ end
+ end
+
+ describe Gitlab::CycleAnalytics::Summary::Value::PrettyNumeric do
+ describe '#to_s' do
+ it 'returns `-` when the number is 0' do
+ expect(described_class.new(0).to_s).to eq('-')
+ end
+
+ it 'returns the string representation of the number' do
+ expect(described_class.new(100).to_s).to eq('100')
+ end
+ end
+ end
+end
diff --git a/spec/migrations/backfill_environment_id_on_deployment_merge_requests_spec.rb b/spec/migrations/backfill_environment_id_on_deployment_merge_requests_spec.rb
deleted file mode 100644
index 296ae07cc21..00000000000
--- a/spec/migrations/backfill_environment_id_on_deployment_merge_requests_spec.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20200312134637_backfill_environment_id_on_deployment_merge_requests.rb')
-
-describe BackfillEnvironmentIdOnDeploymentMergeRequests do
- let(:environments) { table(:environments) }
- let(:merge_requests) { table(:merge_requests) }
- let(:deployments) { table(:deployments) }
- let(:deployment_merge_requests) { table(:deployment_merge_requests) }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
-
- let(:migration_worker) { double('BackgroundMigrationWorker') }
-
- before do
- stub_const('BackgroundMigrationWorker', migration_worker)
- end
-
- it 'schedules nothing when there are no entries' do
- expect(migration_worker).not_to receive(:perform_in)
-
- migrate!
- end
-
- it 'batches the workload' do
- stub_const("#{described_class.name}::BATCH_SIZE", 10)
-
- namespace = namespaces.create!(name: 'foo', path: 'foo')
- project = projects.create!(namespace_id: namespace.id)
-
- environment = environments.create!(project_id: project.id, name: 'staging', slug: 'staging')
-
- # Batching is based on DeploymentMergeRequest.merge_request_id, in order to test it
- # we must generate more than described_class::BATCH_SIZE merge requests, deployments,
- # and deployment_merge_requests entries
- entries = 13
- expect(entries).to be > described_class::BATCH_SIZE
-
- # merge requests and deployments bulk generation
- mrs_params = []
- deployments_params = []
- entries.times do |i|
- mrs_params << { source_branch: 'x', target_branch: 'master', target_project_id: project.id }
-
- deployments_params << { environment_id: environment.id, iid: i + 1, project_id: project.id, ref: 'master', tag: false, sha: '123abcdef', status: 1 }
- end
-
- all_mrs = merge_requests.insert_all(mrs_params)
- all_deployments = deployments.insert_all(deployments_params)
-
- # deployment_merge_requests bulk generation
- dmr_params = []
- entries.times do |index|
- mr_id = all_mrs.rows[index].first
- deployment_id = all_deployments.rows[index].first
-
- dmr_params << { deployment_id: deployment_id, merge_request_id: mr_id }
- end
-
- deployment_merge_requests.insert_all(dmr_params)
-
- first_batch_limit = dmr_params[described_class::BATCH_SIZE][:merge_request_id]
- second_batch_limit = dmr_params.last[:merge_request_id]
-
- expect(migration_worker).to receive(:perform_in)
- .with(
- 0,
- 'BackfillEnvironmentIdDeploymentMergeRequests',
- [1, first_batch_limit]
- )
- expect(migration_worker).to receive(:perform_in)
- .with(
- described_class::DELAY,
- 'BackfillEnvironmentIdDeploymentMergeRequests',
- [first_batch_limit + 1, second_batch_limit]
- )
-
- migrate!
- end
-end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 5fe0a9052cf..38b92f22faf 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -3836,40 +3836,28 @@ describe MergeRequest do
end
describe '#diffable_merge_ref?' do
- context 'diff_compare_with_head enabled' do
- context 'merge request can be merged' do
- context 'merge_to_ref is not calculated' do
- it 'returns true' do
- expect(subject.diffable_merge_ref?).to eq(false)
- end
- end
-
- context 'merge_to_ref is calculated' do
- before do
- MergeRequests::MergeToRefService.new(subject.project, subject.author).execute(subject)
- end
-
- it 'returns true' do
- expect(subject.diffable_merge_ref?).to eq(true)
- end
+ context 'merge request can be merged' do
+ context 'merge_to_ref is not calculated' do
+ it 'returns true' do
+ expect(subject.diffable_merge_ref?).to eq(false)
end
end
- context 'merge request cannot be merged' do
- it 'returns false' do
- subject.mark_as_unchecked!
+ context 'merge_to_ref is calculated' do
+ before do
+ MergeRequests::MergeToRefService.new(subject.project, subject.author).execute(subject)
+ end
- expect(subject.diffable_merge_ref?).to eq(false)
+ it 'returns true' do
+ expect(subject.diffable_merge_ref?).to eq(true)
end
end
end
- context 'diff_compare_with_head disabled' do
- before do
- stub_feature_flags(diff_compare_with_head: { enabled: false, thing: subject.target_project })
- end
-
+ context 'merge request cannot be merged' do
it 'returns false' do
+ subject.mark_as_unchecked!
+
expect(subject.diffable_merge_ref?).to eq(false)
end
end
diff --git a/spec/models/sent_notification_spec.rb b/spec/models/sent_notification_spec.rb
index fedaae372c4..087bc957373 100644
--- a/spec/models/sent_notification_spec.rb
+++ b/spec/models/sent_notification_spec.rb
@@ -326,4 +326,26 @@ describe SentNotification do
end
end
end
+
+ describe "#position=" do
+ subject { build(:sent_notification, noteable: create(:issue)) }
+
+ it "doesn't accept non-hash JSON passed as a string" do
+ subject.position = "true"
+
+ expect(subject.attributes_before_type_cast["position"]).to be(nil)
+ end
+
+ it "does accept a position hash as a string" do
+ subject.position = '{ "base_sha": "test" }'
+
+ expect(subject.position.base_sha).to eq("test")
+ end
+
+ it "does accept a hash" do
+ subject.position = { "base_sha" => "test" }
+
+ expect(subject.position.base_sha).to eq("test")
+ end
+ end
end
diff --git a/spec/policies/ci/build_policy_spec.rb b/spec/policies/ci/build_policy_spec.rb
index 333f4e560cf..f29ed26f2aa 100644
--- a/spec/policies/ci/build_policy_spec.rb
+++ b/spec/policies/ci/build_policy_spec.rb
@@ -176,15 +176,21 @@ describe Ci::BuildPolicy do
end
context 'when developers can push to the branch' do
- before do
- create(:protected_branch, :developers_can_push,
- name: build.ref, project: project)
- end
-
context 'when the build was created by the developer' do
let(:owner) { user }
- it { expect(policy).to be_allowed :erase_build }
+ context 'when the build was created for a protected ref' do
+ before do
+ create(:protected_branch, :developers_can_push,
+ name: build.ref, project: project)
+ end
+
+ it { expect(policy).to be_disallowed :erase_build }
+ end
+
+ context 'when the build was created for an unprotected ref' do
+ it { expect(policy).to be_allowed :erase_build }
+ end
end
context 'when the build was created by the other' do
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index 5e8223ec3cc..f2dc5b1c045 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -630,7 +630,7 @@ describe API::Branches do
post api(route, user), params: { branch: 'new_design3', ref: 'foo' }
expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['message']).to eq('Invalid reference name: new_design3')
+ expect(json_response['message']).to eq('Invalid reference name: foo')
end
end
diff --git a/spec/requests/api/graphql/mutations/branches/create_spec.rb b/spec/requests/api/graphql/mutations/branches/create_spec.rb
index 406ab8959a2..8340f5a7db2 100644
--- a/spec/requests/api/graphql/mutations/branches/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/branches/create_spec.rb
@@ -38,7 +38,7 @@ describe 'Creation of a new branch' do
let(:ref) { 'unknown' }
it_behaves_like 'a mutation that returns errors in the response',
- errors: ['Invalid reference name: new_branch']
+ errors: ['Invalid reference name: unknown']
end
end
end
diff --git a/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb b/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb
index ce20d494542..3cb1dbbbc2c 100644
--- a/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb
+++ b/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb
@@ -159,6 +159,17 @@ describe RuboCop::Cop::InjectEnterpriseEditionModule do
SOURCE
end
+ it 'does not flag the double use of `X_if_ee` on the last line' do
+ expect_no_offenses(<<~SOURCE)
+ class Foo
+ end
+
+ Foo.extend_if_ee('EE::Foo')
+ Foo.include_if_ee('EE::Foo')
+ Foo.prepend_if_ee('EE::Foo')
+ SOURCE
+ end
+
it 'autocorrects offenses by just disabling the Cop' do
source = <<~SOURCE
class Foo
diff --git a/spec/services/branches/create_service_spec.rb b/spec/services/branches/create_service_spec.rb
index b0629c5e25a..072a86d17fc 100644
--- a/spec/services/branches/create_service_spec.rb
+++ b/spec/services/branches/create_service_spec.rb
@@ -3,39 +3,45 @@
require 'spec_helper'
describe Branches::CreateService do
- let(:user) { create(:user) }
-
subject(:service) { described_class.new(project, user) }
+ let_it_be(:project) { create(:project_empty_repo) }
+ let_it_be(:user) { create(:user) }
+
describe '#execute' do
context 'when repository is empty' do
- let(:project) { create(:project_empty_repo) }
-
it 'creates master branch' do
service.execute('my-feature', 'master')
expect(project.repository.branch_exists?('master')).to be_truthy
end
- it 'creates my-feature branch' do
- service.execute('my-feature', 'master')
+ it 'creates another-feature branch' do
+ service.execute('another-feature', 'master')
- expect(project.repository.branch_exists?('my-feature')).to be_truthy
+ expect(project.repository.branch_exists?('another-feature')).to be_truthy
end
end
- context 'when creating a branch fails' do
- let(:project) { create(:project_empty_repo) }
+ context 'when branch already exists' do
+ it 'returns an error' do
+ result = service.execute('master', 'master')
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Branch already exists')
+ end
+ end
+ context 'when incorrect reference is provided' do
before do
allow(project.repository).to receive(:add_branch).and_return(false)
end
- it 'returns an error with the branch name' do
- result = service.execute('my-feature', 'master')
+ it 'returns an error with a reference name' do
+ result = service.execute('new-feature', 'unknown')
expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq("Invalid reference name: my-feature")
+ expect(result[:message]).to eq('Invalid reference name: unknown')
end
end
end