summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-04-09 15:09:29 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-04-09 15:09:29 +0000
commit209bd8cf1f542f6ba2a069b368a9187faa871e96 (patch)
tree6b77dc8183135b8316cc70c8dbc9c4e7c18cf05a /spec
parenta9ced7da447785c57477b3d8dbccc73a78cface1 (diff)
downloadgitlab-ce-209bd8cf1f542f6ba2a069b368a9187faa871e96.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/frontend/diffs/store/mutations_spec.js2
-rw-r--r--spec/frontend/header_spec.js96
-rw-r--r--spec/frontend/helpers/monitor_helper_spec.js26
-rw-r--r--spec/frontend/monitoring/store/utils_spec.js6
-rw-r--r--spec/frontend/repository/router_spec.js17
-rw-r--r--spec/frontend/static_site_editor/components/publish_toolbar_spec.js43
-rw-r--r--spec/frontend/static_site_editor/components/static_site_editor_spec.js54
-rw-r--r--spec/frontend/static_site_editor/store/actions_spec.js11
-rw-r--r--spec/frontend/static_site_editor/store/getters_spec.js24
-rw-r--r--spec/frontend/static_site_editor/store/mutations_spec.js11
-rw-r--r--spec/lib/gitlab/ci/config/entry/include_spec.rb72
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb48
-rw-r--r--spec/lib/gitlab/git/blob_spec.rb24
-rw-r--r--spec/lib/gitlab/git/diff_stats_collection_spec.rb12
-rw-r--r--spec/models/ci/build_dependencies_spec.rb8
-rw-r--r--spec/models/ci/processable_spec.rb14
-rw-r--r--spec/models/merge_request_spec.rb25
-rw-r--r--spec/models/snippet_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb200
-rw-r--r--spec/services/ci/pipeline_processing/shared_processing_service.rb77
-rw-r--r--spec/workers/post_receive_spec.rb1
21 files changed, 554 insertions, 219 deletions
diff --git a/spec/frontend/diffs/store/mutations_spec.js b/spec/frontend/diffs/store/mutations_spec.js
index ad05f27b325..c44feaf4b63 100644
--- a/spec/frontend/diffs/store/mutations_spec.js
+++ b/spec/frontend/diffs/store/mutations_spec.js
@@ -796,11 +796,13 @@ describe('DiffsStoreMutations', () => {
it('sets showWhitespace', () => {
const state = {
showWhitespace: true,
+ diffFiles: ['test'],
};
mutations[types.SET_SHOW_WHITESPACE](state, false);
expect(state.showWhitespace).toBe(false);
+ expect(state.diffFiles).toEqual([]);
});
});
diff --git a/spec/frontend/header_spec.js b/spec/frontend/header_spec.js
index 00b5b306d66..0a74799283a 100644
--- a/spec/frontend/header_spec.js
+++ b/spec/frontend/header_spec.js
@@ -1,53 +1,87 @@
import $ from 'jquery';
-import initTodoToggle from '~/header';
+import initTodoToggle, { initNavUserDropdownTracking } from '~/header';
+import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
describe('Header', () => {
- const todosPendingCount = '.todos-count';
- const fixtureTemplate = 'issues/open-issue.html';
+ describe('Todos notification', () => {
+ const todosPendingCount = '.todos-count';
+ const fixtureTemplate = 'issues/open-issue.html';
- function isTodosCountHidden() {
- return $(todosPendingCount).hasClass('hidden');
- }
+ function isTodosCountHidden() {
+ return $(todosPendingCount).hasClass('hidden');
+ }
- function triggerToggle(newCount) {
- $(document).trigger('todo:toggle', newCount);
- }
+ function triggerToggle(newCount) {
+ $(document).trigger('todo:toggle', newCount);
+ }
- preloadFixtures(fixtureTemplate);
- beforeEach(() => {
- initTodoToggle();
- loadFixtures(fixtureTemplate);
- });
+ preloadFixtures(fixtureTemplate);
+ beforeEach(() => {
+ initTodoToggle();
+ loadFixtures(fixtureTemplate);
+ });
- it('should update todos-count after receiving the todo:toggle event', () => {
- triggerToggle(5);
+ it('should update todos-count after receiving the todo:toggle event', () => {
+ triggerToggle(5);
- expect($(todosPendingCount).text()).toEqual('5');
- });
+ expect($(todosPendingCount).text()).toEqual('5');
+ });
- it('should hide todos-count when it is 0', () => {
- triggerToggle(0);
+ it('should hide todos-count when it is 0', () => {
+ triggerToggle(0);
- expect(isTodosCountHidden()).toEqual(true);
- });
+ expect(isTodosCountHidden()).toEqual(true);
+ });
+
+ it('should show todos-count when it is more than 0', () => {
+ triggerToggle(10);
+
+ expect(isTodosCountHidden()).toEqual(false);
+ });
+
+ describe('when todos-count is 1000', () => {
+ beforeEach(() => {
+ triggerToggle(1000);
+ });
- it('should show todos-count when it is more than 0', () => {
- triggerToggle(10);
+ it('should show todos-count', () => {
+ expect(isTodosCountHidden()).toEqual(false);
+ });
- expect(isTodosCountHidden()).toEqual(false);
+ it('should show 99+ for todos-count', () => {
+ expect($(todosPendingCount).text()).toEqual('99+');
+ });
+ });
});
- describe('when todos-count is 1000', () => {
+ describe('Track user dropdown open', () => {
+ let trackingSpy;
+
beforeEach(() => {
- triggerToggle(1000);
+ setFixtures(`
+ <li class="js-nav-user-dropdown">
+ <a class="js-buy-ci-minutes-link" data-track-event="click_buy_ci_minutes" data-track-label="free" data-track-property="user_dropdown">Buy CI minutes
+ </a>
+ </li>`);
+
+ trackingSpy = mockTracking('_category_', $('.js-nav-user-dropdown').element, jest.spyOn);
+ document.body.dataset.page = 'some:page';
+
+ initNavUserDropdownTracking();
});
- it('should show todos-count', () => {
- expect(isTodosCountHidden()).toEqual(false);
+ afterEach(() => {
+ unmockTracking();
});
- it('should show 99+ for todos-count', () => {
- expect($(todosPendingCount).text()).toEqual('99+');
+ it('sends a tracking event when the dropdown is opened and contains Buy CI minutes link', () => {
+ $('.js-nav-user-dropdown').trigger('shown.bs.dropdown');
+
+ expect(trackingSpy).toHaveBeenCalledTimes(1);
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'show_buy_ci_minutes', {
+ label: 'free',
+ property: 'user_dropdown',
+ });
});
});
});
diff --git a/spec/frontend/helpers/monitor_helper_spec.js b/spec/frontend/helpers/monitor_helper_spec.js
index 0798ca580e2..f7163d496d2 100644
--- a/spec/frontend/helpers/monitor_helper_spec.js
+++ b/spec/frontend/helpers/monitor_helper_spec.js
@@ -56,6 +56,32 @@ describe('monitor helper', () => {
expect(result.name).toEqual('brpop');
});
+ it('supports a multi metric label template expression', () => {
+ const config = {
+ ...defaultConfig,
+ name: '',
+ };
+
+ const [result] = monitorHelper.makeDataSeries(
+ [
+ {
+ metric: {
+ backend: 'HA Server',
+ frontend: 'BA Server',
+ app: 'prometheus',
+ instance: 'k8 cluster 1',
+ },
+ values: series,
+ },
+ ],
+ config,
+ );
+
+ expect(result.name).toBe(
+ 'backend: HA Server, frontend: BA Server, app: prometheus, instance: k8 cluster 1',
+ );
+ });
+
it('supports space-padded template expressions', () => {
const config = {
...defaultConfig,
diff --git a/spec/frontend/monitoring/store/utils_spec.js b/spec/frontend/monitoring/store/utils_spec.js
index e1c8e694122..fcc5614850b 100644
--- a/spec/frontend/monitoring/store/utils_spec.js
+++ b/spec/frontend/monitoring/store/utils_spec.js
@@ -251,7 +251,7 @@ describe('mapToDashboardViewModel', () => {
};
it('creates a metric', () => {
- const dashboard = dashboardWithMetric({});
+ const dashboard = dashboardWithMetric({ label: 'Panel Label' });
expect(getMappedMetric(dashboard)).toEqual({
label: expect.any(String),
@@ -268,11 +268,11 @@ describe('mapToDashboardViewModel', () => {
expect(getMappedMetric(dashboard).metricId).toEqual('1_http_responses');
});
- it('creates a metric with a default label', () => {
+ it('creates a metric without a default label', () => {
const dashboard = dashboardWithMetric({});
expect(getMappedMetric(dashboard)).toMatchObject({
- label: defaultLabel,
+ label: undefined,
});
});
diff --git a/spec/frontend/repository/router_spec.js b/spec/frontend/repository/router_spec.js
index 8f3ac53c37a..6944b23558a 100644
--- a/spec/frontend/repository/router_spec.js
+++ b/spec/frontend/repository/router_spec.js
@@ -4,14 +4,15 @@ import createRouter from '~/repository/router';
describe('Repository router spec', () => {
it.each`
- path | component | componentName
- ${'/'} | ${IndexPage} | ${'IndexPage'}
- ${'/tree/master'} | ${TreePage} | ${'TreePage'}
- ${'/-/tree/master'} | ${TreePage} | ${'TreePage'}
- ${'/-/tree/master/app/assets'} | ${TreePage} | ${'TreePage'}
- ${'/-/tree/123/app/assets'} | ${null} | ${'null'}
- `('sets component as $componentName for path "$path"', ({ path, component }) => {
- const router = createRouter('', 'master');
+ path | branch | component | componentName
+ ${'/'} | ${'master'} | ${IndexPage} | ${'IndexPage'}
+ ${'/tree/master'} | ${'master'} | ${TreePage} | ${'TreePage'}
+ ${'/-/tree/master'} | ${'master'} | ${TreePage} | ${'TreePage'}
+ ${'/-/tree/master/app/assets'} | ${'master'} | ${TreePage} | ${'TreePage'}
+ ${'/-/tree/feature/test-%23/app/assets'} | ${'feature/test-#'} | ${TreePage} | ${'TreePage'}
+ ${'/-/tree/123/app/assets'} | ${'master'} | ${null} | ${'null'}
+ `('sets component as $componentName for path "$path"', ({ path, component, branch }) => {
+ const router = createRouter('', branch);
const componentsForRoute = router.getMatchedComponents(path);
diff --git a/spec/frontend/static_site_editor/components/publish_toolbar_spec.js b/spec/frontend/static_site_editor/components/publish_toolbar_spec.js
new file mode 100644
index 00000000000..55e30825621
--- /dev/null
+++ b/spec/frontend/static_site_editor/components/publish_toolbar_spec.js
@@ -0,0 +1,43 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlNewButton } from '@gitlab/ui';
+
+import PublishToolbar from '~/static_site_editor/components/publish_toolbar.vue';
+
+describe('Static Site Editor Toolbar', () => {
+ let wrapper;
+
+ const buildWrapper = (propsData = {}) => {
+ wrapper = shallowMount(PublishToolbar, {
+ propsData: {
+ saveable: false,
+ ...propsData,
+ },
+ });
+ };
+
+ const findSaveChangesButton = () => wrapper.find(GlNewButton);
+
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders Submit Changes button', () => {
+ expect(findSaveChangesButton().exists()).toBe(true);
+ });
+
+ it('disables Submit Changes button', () => {
+ expect(findSaveChangesButton().attributes('disabled')).toBe('true');
+ });
+
+ describe('when saveable', () => {
+ it('enables Submit Changes button', () => {
+ buildWrapper({ saveable: true });
+
+ expect(findSaveChangesButton().attributes('disabled')).toBeFalsy();
+ });
+ });
+});
diff --git a/spec/frontend/static_site_editor/components/static_site_editor_spec.js b/spec/frontend/static_site_editor/components/static_site_editor_spec.js
index cde95d0a21e..ec984102250 100644
--- a/spec/frontend/static_site_editor/components/static_site_editor_spec.js
+++ b/spec/frontend/static_site_editor/components/static_site_editor_spec.js
@@ -7,6 +7,7 @@ import createState from '~/static_site_editor/store/state';
import StaticSiteEditor from '~/static_site_editor/components/static_site_editor.vue';
import EditArea from '~/static_site_editor/components/edit_area.vue';
+import PublishToolbar from '~/static_site_editor/components/publish_toolbar.vue';
const localVue = createLocalVue();
@@ -16,18 +17,31 @@ describe('StaticSiteEditor', () => {
let wrapper;
let store;
let loadContentActionMock;
+ let setContentActionMock;
const buildStore = ({ initialState, getters } = {}) => {
loadContentActionMock = jest.fn();
+ setContentActionMock = jest.fn();
store = new Vuex.Store({
state: createState(initialState),
getters: {
isContentLoaded: () => false,
+ contentChanged: () => false,
...getters,
},
actions: {
loadContent: loadContentActionMock,
+ setContent: setContentActionMock,
+ },
+ });
+ };
+ const buildContentLoadedStore = ({ initialState, getters } = {}) => {
+ buildStore({
+ initialState,
+ getters: {
+ isContentLoaded: () => true,
+ ...getters,
},
});
};
@@ -40,6 +54,8 @@ describe('StaticSiteEditor', () => {
};
const findEditArea = () => wrapper.find(EditArea);
+ const findPublishToolbar = () => wrapper.find(PublishToolbar);
+ const findSkeletonLoader = () => wrapper.find(GlSkeletonLoader);
beforeEach(() => {
buildStore();
@@ -54,6 +70,10 @@ describe('StaticSiteEditor', () => {
it('does not render edit area', () => {
expect(findEditArea().exists()).toBe(false);
});
+
+ it('does not render toolbar', () => {
+ expect(findPublishToolbar().exists()).toBe(false);
+ });
});
describe('when content is loaded', () => {
@@ -68,19 +88,49 @@ describe('StaticSiteEditor', () => {
expect(findEditArea().exists()).toBe(true);
});
+ it('does not render skeleton loader', () => {
+ expect(findSkeletonLoader().exists()).toBe(false);
+ });
+
it('passes page content to edit area', () => {
expect(findEditArea().props('value')).toBe(content);
});
+
+ it('renders toolbar', () => {
+ expect(findPublishToolbar().exists()).toBe(true);
+ });
+ });
+
+ it('sets toolbar as saveable when content changes', () => {
+ buildContentLoadedStore({
+ getters: {
+ contentChanged: () => true,
+ },
+ });
+ buildWrapper();
+
+ expect(findPublishToolbar().props('saveable')).toBe(true);
});
- it('displays skeleton loader while loading content', () => {
+ it('displays skeleton loader when loading content', () => {
buildStore({ initialState: { isLoadingContent: true } });
buildWrapper();
- expect(wrapper.find(GlSkeletonLoader).exists()).toBe(true);
+ expect(findSkeletonLoader().exists()).toBe(true);
});
it('dispatches load content action', () => {
expect(loadContentActionMock).toHaveBeenCalled();
});
+
+ it('dispatches setContent action when edit area emits input event', () => {
+ const content = 'new content';
+
+ buildContentLoadedStore();
+ buildWrapper();
+
+ findEditArea().vm.$emit('input', content);
+
+ expect(setContentActionMock).toHaveBeenCalledWith(expect.anything(), content, undefined);
+ });
});
diff --git a/spec/frontend/static_site_editor/store/actions_spec.js b/spec/frontend/static_site_editor/store/actions_spec.js
index 98d7d0d2c2d..4ad1e798ccd 100644
--- a/spec/frontend/static_site_editor/store/actions_spec.js
+++ b/spec/frontend/static_site_editor/store/actions_spec.js
@@ -73,4 +73,15 @@ describe('Static Site Editor Store actions', () => {
});
});
});
+
+ describe('setContent', () => {
+ it('commits setContent mutation', () => {
+ testAction(actions.setContent, content, state, [
+ {
+ type: mutationTypes.SET_CONTENT,
+ payload: content,
+ },
+ ]);
+ });
+ });
});
diff --git a/spec/frontend/static_site_editor/store/getters_spec.js b/spec/frontend/static_site_editor/store/getters_spec.js
index 8800216f3b0..1b482db9366 100644
--- a/spec/frontend/static_site_editor/store/getters_spec.js
+++ b/spec/frontend/static_site_editor/store/getters_spec.js
@@ -1,15 +1,29 @@
import createState from '~/static_site_editor/store/state';
-import { isContentLoaded } from '~/static_site_editor/store/getters';
+import { isContentLoaded, contentChanged } from '~/static_site_editor/store/getters';
import { sourceContent as content } from '../mock_data';
describe('Static Site Editor Store getters', () => {
describe('isContentLoaded', () => {
- it('returns true when content is not empty', () => {
- expect(isContentLoaded(createState({ content }))).toBe(true);
+ it('returns true when originalContent is not empty', () => {
+ expect(isContentLoaded(createState({ originalContent: content }))).toBe(true);
});
- it('returns false when content is empty', () => {
- expect(isContentLoaded(createState({ content: '' }))).toBe(false);
+ it('returns false when originalContent is empty', () => {
+ expect(isContentLoaded(createState({ originalContent: '' }))).toBe(false);
+ });
+ });
+
+ describe('contentChanged', () => {
+ it('returns true when content and originalContent are different', () => {
+ const state = createState({ content, originalContent: 'something else' });
+
+ expect(contentChanged(state)).toBe(true);
+ });
+
+ it('returns false when content and originalContent are the same', () => {
+ const state = createState({ content, originalContent: content });
+
+ expect(contentChanged(state)).toBe(false);
});
});
});
diff --git a/spec/frontend/static_site_editor/store/mutations_spec.js b/spec/frontend/static_site_editor/store/mutations_spec.js
index c7055fbb2f0..db3a1081af5 100644
--- a/spec/frontend/static_site_editor/store/mutations_spec.js
+++ b/spec/frontend/static_site_editor/store/mutations_spec.js
@@ -35,8 +35,9 @@ describe('Static Site Editor Store mutations', () => {
expect(state.title).toBe(payload.title);
});
- it('sets content', () => {
+ it('sets originalContent and content', () => {
expect(state.content).toBe(payload.content);
+ expect(state.originalContent).toBe(payload.content);
});
});
@@ -49,4 +50,12 @@ describe('Static Site Editor Store mutations', () => {
expect(state.isLoadingContent).toBe(false);
});
});
+
+ describe('setContent', () => {
+ it('sets content', () => {
+ mutations[types.SET_CONTENT](state, content);
+
+ expect(state.content).toBe(content);
+ });
+ });
});
diff --git a/spec/lib/gitlab/ci/config/entry/include_spec.rb b/spec/lib/gitlab/ci/config/entry/include_spec.rb
new file mode 100644
index 00000000000..bab11f26fa1
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/entry/include_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ::Gitlab::Ci::Config::Entry::Include do
+ subject(:include_entry) { described_class.new(config) }
+
+ describe 'validations' do
+ before do
+ include_entry.compose!
+ end
+
+ context 'when value is a string' do
+ let(:config) { 'test.yml' }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when value is hash' do
+ context 'when using not allowed keys' do
+ let(:config) do
+ { not_allowed: 'key' }
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when using "local"' do
+ let(:config) { { local: 'test.yml' } }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when using "file"' do
+ let(:config) { { file: 'test.yml' } }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when using "template"' do
+ let(:config) { { template: 'test.yml' } }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when using "artifact"' do
+ context 'and specifying "job"' do
+ let(:config) { { artifact: 'test.yml', job: 'generator' } }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'without "job"' do
+ let(:config) { { artifact: 'test.yml' } }
+
+ it { is_expected.not_to be_valid }
+
+ it 'has specific error' do
+ expect(include_entry.errors)
+ .to include('include config must specify the job where to fetch the artifact from')
+ end
+ end
+ end
+ end
+
+ context 'when value is something else' do
+ let(:config) { 123 }
+
+ it { is_expected.not_to be_valid }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index 62adba4319e..70c3c5ab339 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -2052,6 +2052,54 @@ module Gitlab
end
end
+ describe 'with parent-child pipeline' do
+ context 'when artifact and job are specified' do
+ let(:config) do
+ YAML.dump({
+ build1: { stage: 'build', script: 'test' },
+ test1: { stage: 'test', trigger: {
+ include: [{ artifact: 'generated.yml', job: 'build1' }]
+ } }
+ })
+ end
+
+ it { expect { subject }.not_to raise_error }
+ end
+
+ context 'when job is not specified specified while artifact is' do
+ let(:config) do
+ YAML.dump({
+ build1: { stage: 'build', script: 'test' },
+ test1: { stage: 'test', trigger: {
+ include: [{ artifact: 'generated.yml' }]
+ } }
+ })
+ end
+
+ it do
+ expect { subject }.to raise_error(
+ described_class::ValidationError,
+ /include config must specify the job where to fetch the artifact from/)
+ end
+ end
+
+ context 'when include is a string' do
+ let(:config) do
+ YAML.dump({
+ build1: { stage: 'build', script: 'test' },
+ test1: {
+ stage: 'test',
+ trigger: {
+ include: 'generated.yml'
+ }
+ }
+ })
+ end
+
+ it { expect { subject }.not_to raise_error }
+ end
+ end
+
describe "Error handling" do
it "fails to parse YAML" do
expect do
diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb
index f25383ef416..06f9767d58b 100644
--- a/spec/lib/gitlab/git/blob_spec.rb
+++ b/spec/lib/gitlab/git/blob_spec.rb
@@ -301,26 +301,12 @@ describe Gitlab::Git::Blob, :seed_helper do
stub_const('Gitlab::Git::Blob::BATCH_SIZE', 2)
end
- context 'blobs_fetch_in_batches is enabled' do
- it 'fetches the blobs in batches' do
- expect(client).to receive(:get_blobs).with(first_batch, limit).ordered
- expect(client).to receive(:get_blobs).with(second_batch, limit).ordered
- expect(client).to receive(:get_blobs).with(third_batch, limit).ordered
+ it 'fetches the blobs in batches' do
+ expect(client).to receive(:get_blobs).with(first_batch, limit).ordered
+ expect(client).to receive(:get_blobs).with(second_batch, limit).ordered
+ expect(client).to receive(:get_blobs).with(third_batch, limit).ordered
- subject
- end
- end
-
- context 'blobs_fetch_in_batches is disabled' do
- before do
- stub_feature_flags(blobs_fetch_in_batches: false)
- end
-
- it 'fetches the blobs in a single batch' do
- expect(client).to receive(:get_blobs).with(blob_references, limit)
-
- subject
- end
+ subject
end
end
end
diff --git a/spec/lib/gitlab/git/diff_stats_collection_spec.rb b/spec/lib/gitlab/git/diff_stats_collection_spec.rb
index b07690ef39c..82d15a49062 100644
--- a/spec/lib/gitlab/git/diff_stats_collection_spec.rb
+++ b/spec/lib/gitlab/git/diff_stats_collection_spec.rb
@@ -29,4 +29,16 @@ describe Gitlab::Git::DiffStatsCollection do
expect(collection.paths).to eq %w[foo bar]
end
end
+
+ describe '#real_size' do
+ it 'returns the number of modified files' do
+ expect(collection.real_size).to eq('2')
+ end
+
+ it 'returns capped number when it is bigger than max_files' do
+ allow(::Commit).to receive(:max_diff_options).and_return(max_files: 1)
+
+ expect(collection.real_size).to eq('1+')
+ end
+ end
end
diff --git a/spec/models/ci/build_dependencies_spec.rb b/spec/models/ci/build_dependencies_spec.rb
index 6db69d0f34c..8f2199ac360 100644
--- a/spec/models/ci/build_dependencies_spec.rb
+++ b/spec/models/ci/build_dependencies_spec.rb
@@ -96,14 +96,6 @@ describe Ci::BuildDependencies do
end
it { is_expected.to contain_exactly(build, rspec_test, staging) }
-
- context 'when ci_dag_support is disabled' do
- before do
- stub_feature_flags(ci_dag_support: false)
- end
-
- it { is_expected.to contain_exactly(build, rspec_test, rubocop_test, staging) }
- end
end
context 'when need artifacts are defined' do
diff --git a/spec/models/ci/processable_spec.rb b/spec/models/ci/processable_spec.rb
index e03f54aa728..e8ef7b29681 100644
--- a/spec/models/ci/processable_spec.rb
+++ b/spec/models/ci/processable_spec.rb
@@ -25,20 +25,6 @@ describe Ci::Processable do
it 'returns all needs' do
expect(with_aggregated_needs.first.aggregated_needs_names).to contain_exactly('test1', 'test2')
end
-
- context 'with ci_dag_support disabled' do
- before do
- stub_feature_flags(ci_dag_support: false)
- end
-
- it 'returns all processables' do
- expect(with_aggregated_needs).to contain_exactly(processable)
- end
-
- it 'returns empty needs' do
- expect(with_aggregated_needs.first.aggregated_needs_names).to be_nil
- end
- end
end
context 'without needs' do
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index bfad1da1e21..50bb194ef71 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -874,7 +874,7 @@ describe MergeRequest do
subject(:merge_request) { build(:merge_request) }
before do
- expect(diff).to receive(:modified_paths).and_return(paths)
+ allow(diff).to receive(:modified_paths).and_return(paths)
end
context 'when past_merge_request_diff is specified' do
@@ -890,10 +890,29 @@ describe MergeRequest do
let(:compare) { double(:compare) }
let(:diff) { compare }
- it 'returns affected file paths from compare' do
+ before do
merge_request.compare = compare
- expect(merge_request.modified_paths).to eq(paths)
+ expect(merge_request).to receive(:diff_stats).and_return(diff_stats)
+ end
+
+ context 'and diff_stats are not present' do
+ let(:diff_stats) { nil }
+
+ it 'returns affected file paths from compare' do
+ expect(merge_request.modified_paths).to eq(paths)
+ end
+ end
+
+ context 'and diff_stats are present' do
+ let(:diff_stats) { double(:diff_stats) }
+
+ it 'returns affected file paths from compare' do
+ diff_stats_path = double(:diff_stats_paths)
+ expect(diff_stats).to receive(:paths).and_return(diff_stats_path)
+
+ expect(merge_request.modified_paths).to eq(diff_stats_path)
+ end
end
end
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 8c4d1951697..2061084d5ea 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -703,7 +703,7 @@ describe Snippet do
let(:current_size) { 60 }
before do
- allow(subject.repository).to receive(:_uncached_size).and_return(current_size)
+ allow(subject.repository).to receive(:size).and_return(current_size)
end
it 'sets up size checker', :aggregate_failures do
diff --git a/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb b/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
index b4071d1b0fe..a76e83f2d60 100644
--- a/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
+++ b/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
@@ -18,25 +18,10 @@ describe Ci::CreatePipelineService, '#execute' do
before do
project.add_developer(user)
- stub_ci_pipeline_to_return_yaml_file
+ stub_ci_pipeline_yaml_file(config)
end
- describe 'child pipeline triggers' do
- before do
- stub_ci_pipeline_yaml_file <<~YAML
- test:
- script: rspec
-
- deploy:
- variables:
- CROSS: downstream
- stage: deploy
- trigger:
- include:
- - local: path/to/child.yml
- YAML
- end
-
+ shared_examples 'successful creation' do
it 'creates bridge jobs correctly' do
pipeline = create_pipeline!
@@ -48,58 +33,140 @@ describe Ci::CreatePipelineService, '#execute' do
expect(bridge).to be_a Ci::Bridge
expect(bridge.stage).to eq 'deploy'
expect(pipeline.statuses).to match_array [test, bridge]
- expect(bridge.options).to eq(
- 'trigger' => { 'include' => [{ 'local' => 'path/to/child.yml' }] }
- )
+ expect(bridge.options).to eq(expected_bridge_options)
expect(bridge.yaml_variables)
.to include(key: 'CROSS', value: 'downstream', public: true)
end
end
+ shared_examples 'creation failure' do
+ it 'returns errors' do
+ pipeline = create_pipeline!
+
+ expect(pipeline.errors.full_messages.first).to match(expected_error)
+ expect(pipeline.failure_reason).to eq 'config_error'
+ expect(pipeline).to be_persisted
+ expect(pipeline.status).to eq 'failed'
+ end
+ end
+
+ describe 'child pipeline triggers' do
+ let(:config) do
+ <<~YAML
+ test:
+ script: rspec
+ deploy:
+ variables:
+ CROSS: downstream
+ stage: deploy
+ trigger:
+ include:
+ - local: path/to/child.yml
+ YAML
+ end
+
+ it_behaves_like 'successful creation' do
+ let(:expected_bridge_options) do
+ {
+ 'trigger' => {
+ 'include' => [
+ { 'local' => 'path/to/child.yml' }
+ ]
+ }
+ }
+ end
+ end
+ end
+
describe 'child pipeline triggers' do
context 'when YAML is valid' do
- before do
- stub_ci_pipeline_yaml_file <<~YAML
+ let(:config) do
+ <<~YAML
+ test:
+ script: rspec
+ deploy:
+ variables:
+ CROSS: downstream
+ stage: deploy
+ trigger:
+ include:
+ - local: path/to/child.yml
+ YAML
+ end
+
+ it_behaves_like 'successful creation' do
+ let(:expected_bridge_options) do
+ {
+ 'trigger' => {
+ 'include' => [
+ { 'local' => 'path/to/child.yml' }
+ ]
+ }
+ }
+ end
+ end
+
+ context 'when trigger:include is specified as a string' do
+ let(:config) do
+ <<~YAML
test:
script: rspec
+ deploy:
+ variables:
+ CROSS: downstream
+ stage: deploy
+ trigger:
+ include: path/to/child.yml
+ YAML
+ end
+
+ it_behaves_like 'successful creation' do
+ let(:expected_bridge_options) do
+ {
+ 'trigger' => {
+ 'include' => 'path/to/child.yml'
+ }
+ }
+ end
+ end
+ end
+ context 'when trigger:include is specified as array of strings' do
+ let(:config) do
+ <<~YAML
+ test:
+ script: rspec
deploy:
variables:
CROSS: downstream
stage: deploy
trigger:
include:
- - local: path/to/child.yml
- YAML
- end
+ - path/to/child.yml
+ - path/to/child2.yml
+ YAML
+ end
- it 'creates bridge jobs correctly' do
- pipeline = create_pipeline!
-
- test = pipeline.statuses.find_by(name: 'test')
- bridge = pipeline.statuses.find_by(name: 'deploy')
-
- expect(pipeline).to be_persisted
- expect(test).to be_a Ci::Build
- expect(bridge).to be_a Ci::Bridge
- expect(bridge.stage).to eq 'deploy'
- expect(pipeline.statuses).to match_array [test, bridge]
- expect(bridge.options).to eq(
- 'trigger' => { 'include' => [{ 'local' => 'path/to/child.yml' }] }
- )
- expect(bridge.yaml_variables)
- .to include(key: 'CROSS', value: 'downstream', public: true)
+ it_behaves_like 'successful creation' do
+ let(:expected_bridge_options) do
+ {
+ 'trigger' => {
+ 'include' => ['path/to/child.yml', 'path/to/child2.yml']
+ }
+ }
+ end
+ end
end
end
- context 'when YAML is invalid' do
+ context 'when limit of includes is reached' do
let(:config) do
- {
+ YAML.dump({
test: { script: 'rspec' },
deploy: {
trigger: { include: included_files }
}
- }
+ })
end
let(:included_files) do
@@ -112,17 +179,46 @@ describe Ci::CreatePipelineService, '#execute' do
Gitlab::Ci::Config::Entry::Trigger::ComplexTrigger::SameProjectTrigger::INCLUDE_MAX_SIZE
end
- before do
- stub_ci_pipeline_yaml_file(YAML.dump(config))
+ it_behaves_like 'creation failure' do
+ let(:expected_error) { /trigger:include config is too long/ }
end
+ end
- it 'returns errors' do
- pipeline = create_pipeline!
+ context 'when including configs from artifact' do
+ context 'when specified dependency is in the wrong order' do
+ let(:config) do
+ <<~YAML
+ test:
+ trigger:
+ include:
+ - job: generator
+ artifact: 'generated.yml'
+ generator:
+ stage: 'deploy'
+ script: 'generator'
+ YAML
+ end
- expect(pipeline.errors.full_messages.first).to match(/trigger:include config is too long/)
- expect(pipeline.failure_reason).to eq 'config_error'
- expect(pipeline).to be_persisted
- expect(pipeline.status).to eq 'failed'
+ it_behaves_like 'creation failure' do
+ let(:expected_error) { /test job: dependency generator is not defined in prior stages/ }
+ end
+ end
+
+ context 'when specified dependency is missing :job key' do
+ let(:config) do
+ <<~YAML
+ test:
+ trigger:
+ include:
+ - artifact: 'generated.yml'
+ YAML
+ end
+
+ it_behaves_like 'creation failure' do
+ let(:expected_error) do
+ /include config must specify the job where to fetch the artifact from/
+ end
+ end
end
end
end
diff --git a/spec/services/ci/pipeline_processing/shared_processing_service.rb b/spec/services/ci/pipeline_processing/shared_processing_service.rb
index ca003299535..ffe5eacfc48 100644
--- a/spec/services/ci/pipeline_processing/shared_processing_service.rb
+++ b/spec/services/ci/pipeline_processing/shared_processing_service.rb
@@ -757,73 +757,19 @@ shared_examples 'Pipeline Processing Service' do
expect(builds.pending).to contain_exactly(deploy)
end
- context 'when feature ci_dag_support is disabled' do
- before do
- stub_feature_flags(ci_dag_support: false)
- end
-
- it 'when linux:build finishes first it follows stages' do
- expect(process_pipeline).to be_truthy
-
- expect(stages).to eq(%w(pending created created))
- expect(builds.pending).to contain_exactly(linux_build, mac_build)
-
- # we follow the single path of linux
- linux_build.reset.success!
-
- expect(stages).to eq(%w(running created created))
- expect(builds.success).to contain_exactly(linux_build)
- expect(builds.pending).to contain_exactly(mac_build)
-
- mac_build.reset.success!
-
- expect(stages).to eq(%w(success pending created))
- expect(builds.success).to contain_exactly(linux_build, mac_build)
- expect(builds.pending).to contain_exactly(
- linux_rspec, linux_rubocop, mac_rspec, mac_rubocop)
-
- linux_rspec.reset.success!
- linux_rubocop.reset.success!
- mac_rspec.reset.success!
- mac_rubocop.reset.success!
-
- expect(stages).to eq(%w(success success pending))
- expect(builds.success).to contain_exactly(
- linux_build, linux_rspec, linux_rubocop, mac_build, mac_rspec, mac_rubocop)
- expect(builds.pending).to contain_exactly(deploy)
- end
- end
-
context 'when one of the jobs is run on a failure' do
let!(:linux_notify) { create_build('linux:notify', stage: 'deploy', stage_idx: 2, when: 'on_failure', scheduling_type: :dag) }
let!(:linux_notify_on_build) { create(:ci_build_need, build: linux_notify, name: 'linux:build') }
context 'when another job in build phase fails first' do
- context 'when ci_dag_support is enabled' do
- it 'does skip linux:notify' do
- expect(process_pipeline).to be_truthy
-
- mac_build.reset.drop!
- linux_build.reset.success!
-
- expect(linux_notify.reset).to be_skipped
- end
- end
-
- context 'when ci_dag_support is disabled' do
- before do
- stub_feature_flags(ci_dag_support: false)
- end
-
- it 'does run linux:notify' do
- expect(process_pipeline).to be_truthy
+ it 'does skip linux:notify' do
+ expect(process_pipeline).to be_truthy
- mac_build.reset.drop!
- linux_build.reset.success!
+ mac_build.reset.drop!
+ linux_build.reset.success!
- expect(linux_notify.reset).to be_pending
- end
+ expect(linux_notify.reset).to be_skipped
end
end
@@ -864,19 +810,6 @@ shared_examples 'Pipeline Processing Service' do
expect(stages).to eq(%w(success success running))
expect(builds.pending).to contain_exactly(deploy)
end
-
- context 'when ci_dag_support is disabled' do
- before do
- stub_feature_flags(ci_dag_support: false)
- end
-
- it 'does run deploy_pages at the start' do
- expect(process_pipeline).to be_truthy
-
- expect(stages).to eq(%w(pending created created))
- expect(builds.pending).to contain_exactly(linux_build, mac_build)
- end
- end
end
end
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index ac17919d7f0..a51e0b79075 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -394,6 +394,7 @@ describe PostReceive do
it 'expires the status cache' do
expect(snippet.repository).to receive(:empty?).and_return(true)
expect(snippet.repository).to receive(:expire_status_cache)
+ expect(snippet.repository).to receive(:expire_statistics_caches)
perform
end