summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-03-17 09:09:20 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-03-17 09:09:20 +0000
commitfc1df8c8307fc5022f9e8aae04164c089d8fdf2e (patch)
treea759f58abf9e41200c48a60de73c84cab47a250d /spec
parentc8df22c555ab707a705e57c4257fd3ed1ce7c3b0 (diff)
downloadgitlab-ce-fc1df8c8307fc5022f9e8aae04164c089d8fdf2e.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/fixtures/lib/gitlab/import_export/invalid_json/project.json3
-rw-r--r--spec/frontend/__mocks__/mousetrap/index.js6
-rw-r--r--spec/frontend/diffs/components/app_spec.js (renamed from spec/javascripts/diffs/components/app_spec.js)91
-rw-r--r--spec/frontend/diffs/create_diffs_store.js15
-rw-r--r--spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap1
-rw-r--r--spec/frontend/lib/utils/icon_utils_spec.js72
-rw-r--r--spec/frontend/mocks/ce/diffs/workers/tree_worker.js8
-rw-r--r--spec/javascripts/diffs/create_diffs_store.js16
-rw-r--r--spec/lib/gitlab/import_export/json/legacy_reader_spec.rb149
-rw-r--r--spec/lib/gitlab/import_export/project/tree_loader_spec.rb49
-rw-r--r--spec/lib/gitlab/import_export/project/tree_restorer_spec.rb3
-rw-r--r--spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb27
-rw-r--r--spec/services/system_note_service_spec.rb10
-rw-r--r--spec/services/system_notes/issuables_service_spec.rb12
14 files changed, 319 insertions, 143 deletions
diff --git a/spec/fixtures/lib/gitlab/import_export/invalid_json/project.json b/spec/fixtures/lib/gitlab/import_export/invalid_json/project.json
new file mode 100644
index 00000000000..83cb34eea91
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/import_export/invalid_json/project.json
@@ -0,0 +1,3 @@
+{
+ "invalid" json
+}
diff --git a/spec/frontend/__mocks__/mousetrap/index.js b/spec/frontend/__mocks__/mousetrap/index.js
new file mode 100644
index 00000000000..63c92fa9a09
--- /dev/null
+++ b/spec/frontend/__mocks__/mousetrap/index.js
@@ -0,0 +1,6 @@
+/* global Mousetrap */
+// `mousetrap` uses amd which webpack understands but Jest does not
+// Thankfully it also writes to a global export so we can es6-ify it
+import 'mousetrap';
+
+export default Mousetrap;
diff --git a/spec/javascripts/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js
index 5f97182489e..15f91871437 100644
--- a/spec/javascripts/diffs/components/app_spec.js
+++ b/spec/frontend/diffs/components/app_spec.js
@@ -1,6 +1,7 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
+import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'spec/test_constants';
import Mousetrap from 'mousetrap';
import App from '~/diffs/components/app.vue';
@@ -12,14 +13,17 @@ import CommitWidget from '~/diffs/components/commit_widget.vue';
import TreeList from '~/diffs/components/tree_list.vue';
import { INLINE_DIFF_VIEW_TYPE, PARALLEL_DIFF_VIEW_TYPE } from '~/diffs/constants';
import createDiffsStore from '../create_diffs_store';
+import axios from '~/lib/utils/axios_utils';
import diffsMockData from '../mock_data/merge_request_diffs';
const mergeRequestDiff = { version_index: 1 };
+const TEST_ENDPOINT = `${TEST_HOST}/diff/endpoint`;
describe('diffs/components/app', () => {
const oldMrTabs = window.mrTabs;
let store;
let wrapper;
+ let mock;
function createComponent(props = {}, extendStore = () => {}) {
const localVue = createLocalVue();
@@ -34,7 +38,7 @@ describe('diffs/components/app', () => {
wrapper = shallowMount(localVue.extend(App), {
localVue,
propsData: {
- endpoint: `${TEST_HOST}/diff/endpoint`,
+ endpoint: TEST_ENDPOINT,
endpointMetadata: `${TEST_HOST}/diff/endpointMetadata`,
endpointBatch: `${TEST_HOST}/diff/endpointBatch`,
projectPath: 'namespace/project',
@@ -61,8 +65,12 @@ describe('diffs/components/app', () => {
beforeEach(() => {
// setup globals (needed for component to mount :/)
- window.mrTabs = jasmine.createSpyObj('mrTabs', ['resetViewContainer']);
- window.mrTabs.expandViewContainer = jasmine.createSpy();
+ window.mrTabs = {
+ resetViewContainer: jest.fn(),
+ };
+ window.mrTabs.expandViewContainer = jest.fn();
+ mock = new MockAdapter(axios);
+ mock.onGet(TEST_ENDPOINT).reply(200, {});
});
afterEach(() => {
@@ -71,6 +79,8 @@ describe('diffs/components/app', () => {
// reset component
wrapper.destroy();
+
+ mock.restore();
});
describe('fetch diff methods', () => {
@@ -80,15 +90,15 @@ describe('diffs/components/app', () => {
store.state.notes.discussions = 'test';
return Promise.resolve({ real_size: 100 });
};
- spyOn(window, 'requestIdleCallback').and.callFake(fn => fn());
+ jest.spyOn(window, 'requestIdleCallback').mockImplementation(fn => fn());
createComponent();
- spyOn(wrapper.vm, 'fetchDiffFiles').and.callFake(fetchResolver);
- spyOn(wrapper.vm, 'fetchDiffFilesMeta').and.callFake(fetchResolver);
- spyOn(wrapper.vm, 'fetchDiffFilesBatch').and.callFake(fetchResolver);
- spyOn(wrapper.vm, 'setDiscussions');
- spyOn(wrapper.vm, 'startRenderDiffsQueue');
- spyOn(wrapper.vm, 'unwatchDiscussions');
- spyOn(wrapper.vm, 'unwatchRetrievingBatches');
+ jest.spyOn(wrapper.vm, 'fetchDiffFiles').mockImplementation(fetchResolver);
+ jest.spyOn(wrapper.vm, 'fetchDiffFilesMeta').mockImplementation(fetchResolver);
+ jest.spyOn(wrapper.vm, 'fetchDiffFilesBatch').mockImplementation(fetchResolver);
+ jest.spyOn(wrapper.vm, 'setDiscussions').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm, 'startRenderDiffsQueue').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm, 'unwatchDiscussions').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm, 'unwatchRetrievingBatches').mockImplementation(() => {});
store.state.diffs.retrievingBatches = true;
store.state.diffs.diffFiles = [];
wrapper.vm.$nextTick(done);
@@ -236,7 +246,7 @@ describe('diffs/components/app', () => {
wrapper.vm.fetchData(false);
expect(wrapper.vm.fetchDiffFiles).toHaveBeenCalled();
- setTimeout(() => {
+ setImmediate(() => {
expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesMeta).not.toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesBatch).not.toHaveBeenCalled();
@@ -255,7 +265,7 @@ describe('diffs/components/app', () => {
wrapper.vm.fetchData(false);
expect(wrapper.vm.fetchDiffFiles).not.toHaveBeenCalled();
- setTimeout(() => {
+ setImmediate(() => {
expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesBatch).toHaveBeenCalled();
@@ -272,7 +282,7 @@ describe('diffs/components/app', () => {
wrapper.vm.fetchData(false);
expect(wrapper.vm.fetchDiffFiles).not.toHaveBeenCalled();
- setTimeout(() => {
+ setImmediate(() => {
expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesBatch).toHaveBeenCalled();
@@ -350,23 +360,21 @@ describe('diffs/components/app', () => {
});
// Component uses $nextTick so we wait until that has finished
- setTimeout(() => {
+ setImmediate(() => {
expect(store.state.diffs.highlightedRow).toBe('ABC_123');
done();
});
});
- it('marks current diff file based on currently highlighted row', done => {
+ it('marks current diff file based on currently highlighted row', () => {
createComponent({
shouldShow: true,
});
// Component uses $nextTick so we wait until that has finished
- setTimeout(() => {
+ return wrapper.vm.$nextTick().then(() => {
expect(store.state.diffs.currentDiffFileId).toBe('ABC');
-
- done();
});
});
});
@@ -403,7 +411,7 @@ describe('diffs/components/app', () => {
});
// Component uses $nextTick so we wait until that has finished
- setTimeout(() => {
+ setImmediate(() => {
expect(store.state.diffs.currentDiffFileId).toBe('ABC');
done();
@@ -449,7 +457,7 @@ describe('diffs/components/app', () => {
describe('visible app', () => {
beforeEach(() => {
- spy = jasmine.createSpy('spy');
+ spy = jest.fn();
createComponent({
shouldShow: true,
@@ -459,21 +467,18 @@ describe('diffs/components/app', () => {
});
});
- it('calls `jumpToFile()` with correct parameter whenever pre-defined key is pressed', done => {
- wrapper.vm
- .$nextTick()
- .then(() => {
- Object.keys(mappings).forEach(function(key) {
- Mousetrap.trigger(key);
+ it.each(Object.keys(mappings))(
+ 'calls `jumpToFile()` with correct parameter whenever pre-defined %s is pressed',
+ key => {
+ return wrapper.vm.$nextTick().then(() => {
+ expect(spy).not.toHaveBeenCalled();
- expect(spy.calls.mostRecent().args).toEqual([mappings[key]]);
- });
+ Mousetrap.trigger(key);
- expect(spy.calls.count()).toEqual(Object.keys(mappings).length);
- })
- .then(done)
- .catch(done.fail);
- });
+ expect(spy).toHaveBeenCalledWith(mappings[key]);
+ });
+ },
+ );
it('does not call `jumpToFile()` when unknown key is pressed', done => {
wrapper.vm
@@ -490,7 +495,7 @@ describe('diffs/components/app', () => {
describe('hideen app', () => {
beforeEach(() => {
- spy = jasmine.createSpy('spy');
+ spy = jest.fn();
createComponent({
shouldShow: false,
@@ -504,7 +509,7 @@ describe('diffs/components/app', () => {
wrapper.vm
.$nextTick()
.then(() => {
- Object.keys(mappings).forEach(function(key) {
+ Object.keys(mappings).forEach(key => {
Mousetrap.trigger(key);
expect(spy).not.toHaveBeenCalled();
@@ -520,7 +525,7 @@ describe('diffs/components/app', () => {
let spy;
beforeEach(() => {
- spy = jasmine.createSpy();
+ spy = jest.fn();
createComponent({}, () => {
store.state.diffs.diffFiles = [
@@ -545,15 +550,15 @@ describe('diffs/components/app', () => {
.then(() => {
wrapper.vm.jumpToFile(+1);
- expect(spy.calls.mostRecent().args).toEqual(['222.js']);
+ expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['222.js']);
store.state.diffs.currentDiffFileId = '222';
wrapper.vm.jumpToFile(+1);
- expect(spy.calls.mostRecent().args).toEqual(['333.js']);
+ expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['333.js']);
store.state.diffs.currentDiffFileId = '333';
wrapper.vm.jumpToFile(-1);
- expect(spy.calls.mostRecent().args).toEqual(['222.js']);
+ expect(spy.mock.calls[spy.mock.calls.length - 1]).toEqual(['222.js']);
})
.then(done)
.catch(done.fail);
@@ -602,7 +607,7 @@ describe('diffs/components/app', () => {
expect(wrapper.contains(CompareVersions)).toBe(true);
expect(wrapper.find(CompareVersions).props()).toEqual(
- jasmine.objectContaining({
+ expect.objectContaining({
targetBranch: {
branchName: 'target-branch',
versionIndex: -1,
@@ -625,7 +630,7 @@ describe('diffs/components/app', () => {
expect(wrapper.contains(HiddenFilesWarning)).toBe(true);
expect(wrapper.find(HiddenFilesWarning).props()).toEqual(
- jasmine.objectContaining({
+ expect.objectContaining({
total: '5',
plainDiffPath: 'plain diff path',
emailPatchPath: 'email patch path',
@@ -663,7 +668,7 @@ describe('diffs/components/app', () => {
let toggleShowTreeList;
beforeEach(() => {
- toggleShowTreeList = jasmine.createSpy('toggleShowTreeList');
+ toggleShowTreeList = jest.fn();
});
afterEach(() => {
diff --git a/spec/frontend/diffs/create_diffs_store.js b/spec/frontend/diffs/create_diffs_store.js
new file mode 100644
index 00000000000..aacde99964c
--- /dev/null
+++ b/spec/frontend/diffs/create_diffs_store.js
@@ -0,0 +1,15 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import diffsModule from '~/diffs/store/modules';
+import notesModule from '~/notes/stores/modules';
+
+Vue.use(Vuex);
+
+export default function createDiffsStore() {
+ return new Vuex.Store({
+ modules: {
+ diffs: diffsModule(),
+ notes: notesModule(),
+ },
+ });
+}
diff --git a/spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap b/spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap
index 177cd4559ca..efa58a4a47b 100644
--- a/spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap
+++ b/spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap
@@ -8,6 +8,7 @@ exports[`IDE pipelines list when loaded renders empty state when no latestPipeli
<empty-state-stub
cansetci="true"
+ class="mb-auto mt-auto"
emptystatesvgpath="http://test.host"
helppagepath="http://test.host"
/>
diff --git a/spec/frontend/lib/utils/icon_utils_spec.js b/spec/frontend/lib/utils/icon_utils_spec.js
index 816d634ad15..f798dc6744d 100644
--- a/spec/frontend/lib/utils/icon_utils_spec.js
+++ b/spec/frontend/lib/utils/icon_utils_spec.js
@@ -1,10 +1,14 @@
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
-import * as iconUtils from '~/lib/utils/icon_utils';
+import { clearSvgIconPathContentCache, getSvgIconPathContent } from '~/lib/utils/icon_utils';
describe('Icon utils', () => {
describe('getSvgIconPathContent', () => {
let spriteIcons;
+ let axiosMock;
+ const mockName = 'mockIconName';
+ const mockPath = 'mockPath';
+ const mockIcons = `<svg><symbol id="${mockName}"><path d="${mockPath}"/></symbol></svg>`;
beforeAll(() => {
spriteIcons = gon.sprite_icons;
@@ -15,45 +19,63 @@ describe('Icon utils', () => {
gon.sprite_icons = spriteIcons;
});
- let axiosMock;
- let mockEndpoint;
- const mockName = 'mockIconName';
- const mockPath = 'mockPath';
- const getIcon = () => iconUtils.getSvgIconPathContent(mockName);
-
beforeEach(() => {
axiosMock = new MockAdapter(axios);
- mockEndpoint = axiosMock.onGet(gon.sprite_icons);
});
afterEach(() => {
axiosMock.restore();
+ clearSvgIconPathContentCache();
});
- it('extracts svg icon path content from sprite icons', () => {
- mockEndpoint.replyOnce(
- 200,
- `<svg><symbol id="${mockName}"><path d="${mockPath}"/></symbol></svg>`,
- );
-
- return getIcon().then(path => {
- expect(path).toBe(mockPath);
+ describe('when the icons can be loaded', () => {
+ beforeEach(() => {
+ axiosMock.onGet(gon.sprite_icons).reply(200, mockIcons);
});
- });
- it('returns null if icon path content does not exist', () => {
- mockEndpoint.replyOnce(200, ``);
+ it('extracts svg icon path content from sprite icons', () => {
+ return getSvgIconPathContent(mockName).then(path => {
+ expect(path).toBe(mockPath);
+ });
+ });
- return getIcon().then(path => {
- expect(path).toBe(null);
+ it('returns null if icon path content does not exist', () => {
+ return getSvgIconPathContent('missing-icon').then(path => {
+ expect(path).toBe(null);
+ });
});
});
- it('returns null if an http error occurs', () => {
- mockEndpoint.replyOnce(500);
+ describe('when the icons cannot be loaded on the first 2 tries', () => {
+ beforeEach(() => {
+ axiosMock
+ .onGet(gon.sprite_icons)
+ .replyOnce(500)
+ .onGet(gon.sprite_icons)
+ .replyOnce(500)
+ .onGet(gon.sprite_icons)
+ .reply(200, mockIcons);
+ });
+
+ it('returns null', () => {
+ return getSvgIconPathContent(mockName).then(path => {
+ expect(path).toBe(null);
+ });
+ });
- return getIcon().then(path => {
- expect(path).toBe(null);
+ it('extracts svg icon path content, after 2 attempts', () => {
+ return getSvgIconPathContent(mockName)
+ .then(path1 => {
+ expect(path1).toBe(null);
+ return getSvgIconPathContent(mockName);
+ })
+ .then(path2 => {
+ expect(path2).toBe(null);
+ return getSvgIconPathContent(mockName);
+ })
+ .then(path3 => {
+ expect(path3).toBe(mockPath);
+ });
});
});
});
diff --git a/spec/frontend/mocks/ce/diffs/workers/tree_worker.js b/spec/frontend/mocks/ce/diffs/workers/tree_worker.js
new file mode 100644
index 00000000000..a33ddbbfe63
--- /dev/null
+++ b/spec/frontend/mocks/ce/diffs/workers/tree_worker.js
@@ -0,0 +1,8 @@
+/* eslint-disable class-methods-use-this */
+export default class TreeWorkerMock {
+ addEventListener() {}
+
+ terminate() {}
+
+ postMessage() {}
+}
diff --git a/spec/javascripts/diffs/create_diffs_store.js b/spec/javascripts/diffs/create_diffs_store.js
index aacde99964c..cfefd4238b8 100644
--- a/spec/javascripts/diffs/create_diffs_store.js
+++ b/spec/javascripts/diffs/create_diffs_store.js
@@ -1,15 +1 @@
-import Vue from 'vue';
-import Vuex from 'vuex';
-import diffsModule from '~/diffs/store/modules';
-import notesModule from '~/notes/stores/modules';
-
-Vue.use(Vuex);
-
-export default function createDiffsStore() {
- return new Vuex.Store({
- modules: {
- diffs: diffsModule(),
- notes: notesModule(),
- },
- });
-}
+export { default } from '../../frontend/diffs/create_diffs_store';
diff --git a/spec/lib/gitlab/import_export/json/legacy_reader_spec.rb b/spec/lib/gitlab/import_export/json/legacy_reader_spec.rb
new file mode 100644
index 00000000000..0009a5f81de
--- /dev/null
+++ b/spec/lib/gitlab/import_export/json/legacy_reader_spec.rb
@@ -0,0 +1,149 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::ImportExport::JSON::LegacyReader::User do
+ let(:relation_names) { [] }
+ let(:legacy_reader) { described_class.new(tree_hash, relation_names) }
+
+ describe '#valid?' do
+ subject { legacy_reader.valid? }
+
+ context 'tree_hash not present' do
+ let(:tree_hash) { nil }
+
+ it { is_expected.to be false }
+ end
+
+ context 'tree_hash presents' do
+ let(:tree_hash) { { "issues": [] } }
+
+ it { is_expected.to be true }
+ end
+ end
+end
+
+describe Gitlab::ImportExport::JSON::LegacyReader::File do
+ let(:fixture) { 'spec/fixtures/lib/gitlab/import_export/light/project.json' }
+ let(:project_tree) { JSON.parse(File.read(fixture)) }
+ let(:relation_names) { [] }
+ let(:legacy_reader) { described_class.new(path, relation_names) }
+
+ describe '#valid?' do
+ subject { legacy_reader.valid? }
+
+ context 'given valid path' do
+ let(:path) { fixture }
+
+ it { is_expected.to be true }
+ end
+
+ context 'given invalid path' do
+ let(:path) { 'spec/non-existing-folder/do-not-create-this-file.json' }
+
+ it { is_expected.to be false }
+ end
+ end
+
+ describe '#root_attributes' do
+ let(:path) { fixture }
+
+ subject { legacy_reader.root_attributes(excluded_attributes) }
+
+ context 'No excluded attributes' do
+ let(:excluded_attributes) { [] }
+ let(:relation_names) { [] }
+
+ it 'returns the whole tree from parsed JSON' do
+ expect(subject).to eq(project_tree)
+ end
+ end
+
+ context 'Some attributes are excluded' do
+ let(:excluded_attributes) { %w[milestones labels issues services snippets] }
+ let(:relation_names) { %w[import_type archived] }
+
+ it 'returns hash without excluded attributes and relations' do
+ expect(subject).not_to include('milestones', 'labels', 'issues', 'services', 'snippets', 'import_type', 'archived')
+ end
+ end
+ end
+
+ describe '#consume_relation' do
+ let(:path) { fixture }
+ let(:key) { 'description' }
+
+ context 'block not given' do
+ it 'returns value of the key' do
+ expect(legacy_reader).to receive(:relations).and_return({ key => 'test value' })
+ expect(legacy_reader.consume_relation(key)).to eq('test value')
+ end
+ end
+
+ context 'key has been consumed' do
+ before do
+ legacy_reader.consume_relation(key)
+ end
+
+ it 'does not yield' do
+ expect do |blk|
+ legacy_reader.consume_relation(key, &blk)
+ end.not_to yield_control
+ end
+ end
+
+ context 'value is nil' do
+ before do
+ expect(legacy_reader).to receive(:relations).and_return({ key => nil })
+ end
+
+ it 'does not yield' do
+ expect do |blk|
+ legacy_reader.consume_relation(key, &blk)
+ end.not_to yield_control
+ end
+ end
+
+ context 'value is not array' do
+ before do
+ expect(legacy_reader).to receive(:relations).and_return({ key => 'value' })
+ end
+
+ it 'yield the value with index 0' do
+ expect do |blk|
+ legacy_reader.consume_relation(key, &blk)
+ end.to yield_with_args('value', 0)
+ end
+ end
+
+ context 'value is an array' do
+ before do
+ expect(legacy_reader).to receive(:relations).and_return({ key => %w[item1 item2 item3] })
+ end
+
+ it 'yield each array element with index' do
+ expect do |blk|
+ legacy_reader.consume_relation(key, &blk)
+ end.to yield_successive_args(['item1', 0], ['item2', 1], ['item3', 2])
+ end
+ end
+ end
+
+ describe '#tree_hash' do
+ let(:path) { fixture }
+
+ subject { legacy_reader.send(:tree_hash) }
+
+ it 'parses the JSON into the expected tree' do
+ expect(subject).to eq(project_tree)
+ end
+
+ context 'invalid JSON' do
+ let(:path) { 'spec/fixtures/lib/gitlab/import_export/invalid_json/project.json' }
+
+ it 'raise Exception' do
+ expect { subject }.to raise_exception(Gitlab::ImportExport::Error, 'Incorrect JSON format')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/project/tree_loader_spec.rb b/spec/lib/gitlab/import_export/project/tree_loader_spec.rb
deleted file mode 100644
index e683eefa7c0..00000000000
--- a/spec/lib/gitlab/import_export/project/tree_loader_spec.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe Gitlab::ImportExport::Project::TreeLoader do
- let(:fixture) { 'spec/fixtures/lib/gitlab/import_export/with_duplicates.json' }
- let(:project_tree) { JSON.parse(File.read(fixture)) }
-
- context 'without de-duplicating entries' do
- let(:parsed_tree) do
- subject.load(fixture)
- end
-
- it 'parses the JSON into the expected tree' do
- expect(parsed_tree).to eq(project_tree)
- end
-
- it 'does not de-duplicate entries' do
- expect(parsed_tree['duped_hash_with_id']).not_to be(parsed_tree['array'][0]['duped_hash_with_id'])
- end
- end
-
- context 'with de-duplicating entries' do
- let(:parsed_tree) do
- subject.load(fixture, dedup_entries: true)
- end
-
- it 'parses the JSON into the expected tree' do
- expect(parsed_tree).to eq(project_tree)
- end
-
- it 'de-duplicates equal values' do
- expect(parsed_tree['duped_hash_with_id']).to be(parsed_tree['array'][0]['duped_hash_with_id'])
- expect(parsed_tree['duped_hash_with_id']).to be(parsed_tree['nested']['duped_hash_with_id'])
- expect(parsed_tree['duped_array']).to be(parsed_tree['array'][1]['duped_array'])
- expect(parsed_tree['duped_array']).to be(parsed_tree['nested']['duped_array'])
- end
-
- it 'does not de-duplicate hashes without IDs' do
- expect(parsed_tree['duped_hash_no_id']).to eq(parsed_tree['array'][2]['duped_hash_no_id'])
- expect(parsed_tree['duped_hash_no_id']).not_to be(parsed_tree['array'][2]['duped_hash_no_id'])
- end
-
- it 'keeps single entries intact' do
- expect(parsed_tree['simple']).to eq(42)
- expect(parsed_tree['nested']['array']).to eq(["don't touch"])
- end
- end
-end
diff --git a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
index 9c2b202d5bb..e38ef75d085 100644
--- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
@@ -783,7 +783,8 @@ describe Gitlab::ImportExport::Project::TreeRestorer do
end
before do
- expect(restorer).to receive(:read_tree_hash) { tree_hash }
+ allow_any_instance_of(Gitlab::ImportExport::JSON::LegacyReader::File).to receive(:valid?).and_return(true)
+ allow_any_instance_of(Gitlab::ImportExport::JSON::LegacyReader::File).to receive(:tree_hash) { tree_hash }
end
context 'no group visibility' do
diff --git a/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb
index 80901feb893..578418998c0 100644
--- a/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/relation_tree_restorer_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
# This spec is a lightweight version of:
-# * project_tree_restorer_spec.rb
+# * project/tree_restorer_spec.rb
#
# In depth testing is being done in the above specs.
# This spec tests that restore project works
@@ -25,7 +25,7 @@ describe Gitlab::ImportExport::RelationTreeRestorer do
described_class.new(
user: user,
shared: shared,
- tree_hash: tree_hash,
+ relation_reader: relation_reader,
importable: importable,
object_builder: object_builder,
members_mapper: members_mapper,
@@ -36,14 +36,7 @@ describe Gitlab::ImportExport::RelationTreeRestorer do
subject { relation_tree_restorer.restore }
- context 'when restoring a project' do
- let(:path) { 'spec/fixtures/lib/gitlab/import_export/complex/project.json' }
- let(:importable) { create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project') }
- let(:object_builder) { Gitlab::ImportExport::Project::ObjectBuilder }
- let(:relation_factory) { Gitlab::ImportExport::Project::RelationFactory }
- let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
- let(:tree_hash) { importable_hash }
-
+ shared_examples 'import project successfully' do
it 'restores project tree' do
expect(subject).to eq(true)
end
@@ -66,4 +59,18 @@ describe Gitlab::ImportExport::RelationTreeRestorer do
end
end
end
+
+ context 'when restoring a project' do
+ let(:path) { 'spec/fixtures/lib/gitlab/import_export/complex/project.json' }
+ let(:importable) { create(:project, :builds_enabled, :issues_disabled, name: 'project', path: 'project') }
+ let(:object_builder) { Gitlab::ImportExport::Project::ObjectBuilder }
+ let(:relation_factory) { Gitlab::ImportExport::Project::RelationFactory }
+ let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
+
+ context 'using legacy reader' do
+ let(:relation_reader) { Gitlab::ImportExport::JSON::LegacyReader::File.new(path, reader.project_relation_names) }
+
+ it_behaves_like 'import project successfully'
+ end
+ end
end
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 3df620d1fea..5b87ec022ae 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -625,4 +625,14 @@ describe SystemNoteService do
described_class.discussion_lock(issuable, double)
end
end
+
+ describe '.auto_resolve_prometheus_alert' do
+ it 'calls IssuableService' do
+ expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
+ expect(service).to receive(:auto_resolve_prometheus_alert)
+ end
+
+ described_class.auto_resolve_prometheus_alert(noteable, project, author)
+ end
+ end
end
diff --git a/spec/services/system_notes/issuables_service_spec.rb b/spec/services/system_notes/issuables_service_spec.rb
index c0aaa65971a..477f9eae39e 100644
--- a/spec/services/system_notes/issuables_service_spec.rb
+++ b/spec/services/system_notes/issuables_service_spec.rb
@@ -654,4 +654,16 @@ describe ::SystemNotes::IssuablesService do
.to eq('resolved the corresponding error and closed the issue.')
end
end
+
+ describe '#auto_resolve_prometheus_alert' do
+ subject { service.auto_resolve_prometheus_alert }
+
+ it_behaves_like 'a system note' do
+ let(:action) { 'closed' }
+ end
+
+ it 'creates the expected system note' do
+ expect(subject.note).to eq('automatically closed this issue because the alert resolved.')
+ end
+ end
end