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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-04-01 03:17:41 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-04-01 03:17:41 +0300
commitbd98eab3fac88fdde059fafc59bc59b150b56d43 (patch)
tree73e0f2c85d5646166821341085baf1eabaaa8a8a /spec
parent83c5e07949cb1023dde1d282b3969def6f182472 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/frontend/ide/components/new_dropdown/index_spec.js56
-rw-r--r--spec/frontend/lib/apollo/indexed_db_persistent_storage_spec.js90
-rw-r--r--spec/frontend/lib/apollo/mock_data/cache_with_persist_directive_and_field.json151
-rw-r--r--spec/frontend/test_setup.js13
-rw-r--r--spec/lib/backup/gitaly_backup_spec.rb11
-rw-r--r--spec/lib/backup/repositories_spec.rb10
6 files changed, 153 insertions, 178 deletions
diff --git a/spec/frontend/ide/components/new_dropdown/index_spec.js b/spec/frontend/ide/components/new_dropdown/index_spec.js
index 01dcb174c41..a2371abe955 100644
--- a/spec/frontend/ide/components/new_dropdown/index_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/index_spec.js
@@ -1,33 +1,50 @@
-import { mount } from '@vue/test-utils';
+import Vue from 'vue';
+import Vuex from 'vuex';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import NewDropdown from '~/ide/components/new_dropdown/index.vue';
import Button from '~/ide/components/new_dropdown/button.vue';
-import { createStore } from '~/ide/stores';
+import Modal from '~/ide/components/new_dropdown/modal.vue';
+import { stubComponent } from 'helpers/stub_component';
+
+Vue.use(Vuex);
describe('new dropdown component', () => {
let wrapper;
+ const openMock = jest.fn();
+ const deleteEntryMock = jest.fn();
const findAllButtons = () => wrapper.findAllComponents(Button);
- const mountComponent = () => {
- const store = createStore();
- store.state.currentProjectId = 'abcproject';
- store.state.path = '';
- store.state.trees['abcproject/mybranch'] = { tree: [] };
+ const mountComponent = (props = {}) => {
+ const fakeStore = () => {
+ return new Vuex.Store({
+ actions: {
+ deleteEntry: deleteEntryMock,
+ },
+ });
+ };
- wrapper = mount(NewDropdown, {
- store,
+ wrapper = mountExtended(NewDropdown, {
+ store: fakeStore(),
propsData: {
branch: 'main',
path: '',
mouseOver: false,
type: 'tree',
+ ...props,
+ },
+ stubs: {
+ NewModal: stubComponent(Modal, {
+ methods: {
+ open: openMock,
+ },
+ }),
},
});
};
beforeEach(() => {
mountComponent();
- jest.spyOn(wrapper.vm.$refs.newModal, 'open').mockImplementation(() => {});
});
it('renders new file, upload and new directory links', () => {
@@ -38,37 +55,34 @@ describe('new dropdown component', () => {
describe('createNewItem', () => {
it('opens modal for a blob when new file is clicked', () => {
- findAllButtons().at(0).trigger('click');
+ findAllButtons().at(0).vm.$emit('click');
- expect(wrapper.vm.$refs.newModal.open).toHaveBeenCalledWith('blob', '');
+ expect(openMock).toHaveBeenCalledWith('blob', '');
});
it('opens modal for a tree when new directory is clicked', () => {
- findAllButtons().at(2).trigger('click');
+ findAllButtons().at(2).vm.$emit('click');
- expect(wrapper.vm.$refs.newModal.open).toHaveBeenCalledWith('tree', '');
+ expect(openMock).toHaveBeenCalledWith('tree', '');
});
});
describe('isOpen', () => {
it('scrolls dropdown into view', async () => {
- jest.spyOn(wrapper.vm.$refs.dropdownMenu, 'scrollIntoView').mockImplementation(() => {});
+ const dropdownMenu = wrapper.findByTestId('dropdown-menu');
+ const scrollIntoViewSpy = jest.spyOn(dropdownMenu.element, 'scrollIntoView');
await wrapper.setProps({ isOpen: true });
- expect(wrapper.vm.$refs.dropdownMenu.scrollIntoView).toHaveBeenCalledWith({
- block: 'nearest',
- });
+ expect(scrollIntoViewSpy).toHaveBeenCalledWith({ block: 'nearest' });
});
});
describe('delete entry', () => {
it('calls delete action', () => {
- jest.spyOn(wrapper.vm, 'deleteEntry').mockImplementation(() => {});
-
findAllButtons().at(4).trigger('click');
- expect(wrapper.vm.deleteEntry).toHaveBeenCalledWith('');
+ expect(deleteEntryMock).toHaveBeenCalledWith(expect.anything(), '');
});
});
});
diff --git a/spec/frontend/lib/apollo/indexed_db_persistent_storage_spec.js b/spec/frontend/lib/apollo/indexed_db_persistent_storage_spec.js
new file mode 100644
index 00000000000..f96364a918e
--- /dev/null
+++ b/spec/frontend/lib/apollo/indexed_db_persistent_storage_spec.js
@@ -0,0 +1,90 @@
+import { IndexedDBPersistentStorage } from '~/lib/apollo/indexed_db_persistent_storage';
+import { db } from '~/lib/apollo/local_db';
+import CACHE_WITH_PERSIST_DIRECTIVE_AND_FIELDS from './mock_data/cache_with_persist_directive_and_field.json';
+
+describe('IndexedDBPersistentStorage', () => {
+ let subject;
+
+ const seedData = async (cacheKey, data = CACHE_WITH_PERSIST_DIRECTIVE_AND_FIELDS) => {
+ const { ROOT_QUERY, ...rest } = data;
+
+ await db.table('queries').put(ROOT_QUERY, cacheKey);
+
+ const asyncPuts = Object.entries(rest).map(async ([key, value]) => {
+ const {
+ groups: { type, gid },
+ } = /^(?<type>.+?):(?<gid>.+)$/.exec(key);
+ const tableName = type.toLowerCase();
+
+ if (tableName !== 'projectmember' && tableName !== 'groupmember') {
+ await db.table(tableName).put(value, gid);
+ }
+ });
+
+ await Promise.all(asyncPuts);
+ };
+
+ beforeEach(async () => {
+ subject = await IndexedDBPersistentStorage.create();
+ });
+
+ afterEach(() => {
+ db.close();
+ });
+
+ it('returns empty response if there is nothing stored in the DB', async () => {
+ const result = await subject.getItem('some-query');
+
+ expect(result).toEqual({});
+ });
+
+ it('returns stored cache if cache was persisted in IndexedDB', async () => {
+ await seedData('issues_list', CACHE_WITH_PERSIST_DIRECTIVE_AND_FIELDS);
+
+ const result = await subject.getItem('issues_list');
+ expect(result).toEqual(CACHE_WITH_PERSIST_DIRECTIVE_AND_FIELDS);
+ });
+
+ it('puts the results in database on `setItem` call', async () => {
+ await subject.setItem(
+ 'issues_list',
+ JSON.stringify({
+ ROOT_QUERY: 'ROOT_QUERY_KEY',
+ 'Project:gid://gitlab/Project/6': {
+ __typename: 'Project',
+ id: 'gid://gitlab/Project/6',
+ },
+ }),
+ );
+
+ await expect(db.table('queries').get('issues_list')).resolves.toEqual('ROOT_QUERY_KEY');
+ await expect(db.table('project').get('gid://gitlab/Project/6')).resolves.toEqual({
+ __typename: 'Project',
+ id: 'gid://gitlab/Project/6',
+ });
+ });
+
+ it('does not put results into non-existent table', async () => {
+ const queryId = 'issues_list';
+
+ await subject.setItem(
+ queryId,
+ JSON.stringify({
+ ROOT_QUERY: 'ROOT_QUERY_KEY',
+ 'DNE:gid://gitlab/DNE/1': {},
+ }),
+ );
+
+ expect(db.tables.map((x) => x.name)).not.toContain('dne');
+ });
+
+ it('when removeItem is called, clears all data', async () => {
+ await seedData('issues_list', CACHE_WITH_PERSIST_DIRECTIVE_AND_FIELDS);
+
+ await subject.removeItem();
+
+ const actual = await Promise.all(db.tables.map((x) => x.toArray()));
+
+ expect(actual).toEqual(db.tables.map(() => []));
+ });
+});
diff --git a/spec/frontend/lib/apollo/mock_data/cache_with_persist_directive_and_field.json b/spec/frontend/lib/apollo/mock_data/cache_with_persist_directive_and_field.json
index c0651517986..0dfc2240cc3 100644
--- a/spec/frontend/lib/apollo/mock_data/cache_with_persist_directive_and_field.json
+++ b/spec/frontend/lib/apollo/mock_data/cache_with_persist_directive_and_field.json
@@ -171,38 +171,6 @@
}
]
},
- "projectMembers({\"relations\":[\"DIRECT\",\"INHERITED\",\"INVITED_GROUPS\"],\"search\":\"\"})": {
- "__typename": "MemberInterfaceConnection",
- "nodes": [
- {
- "__ref": "ProjectMember:gid://gitlab/ProjectMember/54"
- },
- {
- "__ref": "ProjectMember:gid://gitlab/ProjectMember/53"
- },
- {
- "__ref": "ProjectMember:gid://gitlab/ProjectMember/52"
- },
- {
- "__ref": "GroupMember:gid://gitlab/GroupMember/26"
- },
- {
- "__ref": "GroupMember:gid://gitlab/GroupMember/25"
- },
- {
- "__ref": "GroupMember:gid://gitlab/GroupMember/11"
- },
- {
- "__ref": "GroupMember:gid://gitlab/GroupMember/10"
- },
- {
- "__ref": "GroupMember:gid://gitlab/GroupMember/9"
- },
- {
- "__ref": "GroupMember:gid://gitlab/GroupMember/1"
- }
- ]
- },
"milestones({\"includeAncestors\":true,\"searchTitle\":\"\",\"sort\":\"EXPIRED_LAST_DUE_DATE_ASC\",\"state\":\"active\"})": {
"__typename": "MilestoneConnection",
"nodes": [
@@ -1999,125 +1967,6 @@
"healthStatus": null,
"weight": null
},
- "UserCore:gid://gitlab/User/9": {
- "__typename": "UserCore",
- "id": "gid://gitlab/User/9",
- "avatarUrl": "https://secure.gravatar.com/avatar/175e76e391370beeb21914ab74c2efd4?s=80&d=identicon",
- "name": "Kiyoko Bahringer",
- "username": "jamie"
- },
- "ProjectMember:gid://gitlab/ProjectMember/54": {
- "__typename": "ProjectMember",
- "id": "gid://gitlab/ProjectMember/54",
- "user": {
- "__ref": "UserCore:gid://gitlab/User/9"
- }
- },
- "UserCore:gid://gitlab/User/19": {
- "__typename": "UserCore",
- "id": "gid://gitlab/User/19",
- "avatarUrl": "https://secure.gravatar.com/avatar/3126153e3301ebf7cc8f7c99e57007f2?s=80&d=identicon",
- "name": "Cecile Hermann",
- "username": "jeannetta_breitenberg"
- },
- "ProjectMember:gid://gitlab/ProjectMember/53": {
- "__typename": "ProjectMember",
- "id": "gid://gitlab/ProjectMember/53",
- "user": {
- "__ref": "UserCore:gid://gitlab/User/19"
- }
- },
- "UserCore:gid://gitlab/User/2": {
- "__typename": "UserCore",
- "id": "gid://gitlab/User/2",
- "avatarUrl": "https://secure.gravatar.com/avatar/a138e401136c90561f949297387a3bb9?s=80&d=identicon",
- "name": "Tish Treutel",
- "username": "liana.larkin"
- },
- "ProjectMember:gid://gitlab/ProjectMember/52": {
- "__typename": "ProjectMember",
- "id": "gid://gitlab/ProjectMember/52",
- "user": {
- "__ref": "UserCore:gid://gitlab/User/2"
- }
- },
- "UserCore:gid://gitlab/User/13": {
- "__typename": "UserCore",
- "id": "gid://gitlab/User/13",
- "avatarUrl": "https://secure.gravatar.com/avatar/0ce8057f452296a13b5620bb2d9ede57?s=80&d=identicon",
- "name": "Tammy Gusikowski",
- "username": "xuan_oreilly"
- },
- "GroupMember:gid://gitlab/GroupMember/26": {
- "__typename": "GroupMember",
- "id": "gid://gitlab/GroupMember/26",
- "user": {
- "__ref": "UserCore:gid://gitlab/User/13"
- }
- },
- "UserCore:gid://gitlab/User/21": {
- "__typename": "UserCore",
- "id": "gid://gitlab/User/21",
- "avatarUrl": "https://secure.gravatar.com/avatar/415b09d256f26403384363d7948c4d77?s=80&d=identicon",
- "name": "Twanna Hegmann",
- "username": "jamaal"
- },
- "GroupMember:gid://gitlab/GroupMember/25": {
- "__typename": "GroupMember",
- "id": "gid://gitlab/GroupMember/25",
- "user": {
- "__ref": "UserCore:gid://gitlab/User/21"
- }
- },
- "UserCore:gid://gitlab/User/14": {
- "__typename": "UserCore",
- "id": "gid://gitlab/User/14",
- "avatarUrl": "https://secure.gravatar.com/avatar/e99697c6664381b0351b7617717dd49b?s=80&d=identicon",
- "name": "Francie Cole",
- "username": "greg.wisoky"
- },
- "GroupMember:gid://gitlab/GroupMember/11": {
- "__typename": "GroupMember",
- "id": "gid://gitlab/GroupMember/11",
- "user": {
- "__ref": "UserCore:gid://gitlab/User/14"
- }
- },
- "UserCore:gid://gitlab/User/7": {
- "__typename": "UserCore",
- "id": "gid://gitlab/User/7",
- "avatarUrl": "https://secure.gravatar.com/avatar/3a382857e362d6cce60d3806dd173444?s=80&d=identicon",
- "name": "Ivan Carter",
- "username": "ethyl"
- },
- "GroupMember:gid://gitlab/GroupMember/10": {
- "__typename": "GroupMember",
- "id": "gid://gitlab/GroupMember/10",
- "user": {
- "__ref": "UserCore:gid://gitlab/User/7"
- }
- },
- "UserCore:gid://gitlab/User/15": {
- "__typename": "UserCore",
- "id": "gid://gitlab/User/15",
- "avatarUrl": "https://secure.gravatar.com/avatar/79653006ff557e081db02deaa4ca281c?s=80&d=identicon",
- "name": "Danuta Dare",
- "username": "maddie_hintz"
- },
- "GroupMember:gid://gitlab/GroupMember/9": {
- "__typename": "GroupMember",
- "id": "gid://gitlab/GroupMember/9",
- "user": {
- "__ref": "UserCore:gid://gitlab/User/15"
- }
- },
- "GroupMember:gid://gitlab/GroupMember/1": {
- "__typename": "GroupMember",
- "id": "gid://gitlab/GroupMember/1",
- "user": {
- "__ref": "UserCore:gid://gitlab/User/1"
- }
- },
"Milestone:gid://gitlab/Milestone/30": {
"__typename": "Milestone",
"id": "gid://gitlab/Milestone/30",
diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js
index 3fb226e5ed3..03ce96bce5f 100644
--- a/spec/frontend/test_setup.js
+++ b/spec/frontend/test_setup.js
@@ -1,8 +1,15 @@
/* Setup for unit test environment */
// eslint-disable-next-line no-restricted-syntax
import { setImmediate } from 'timers';
+import Dexie from 'dexie';
+import { IDBKeyRange, IDBFactory } from 'fake-indexeddb';
import 'helpers/shared_test_setup';
+const indexedDB = new IDBFactory();
+
+Dexie.dependencies.indexedDB = indexedDB;
+Dexie.dependencies.IDBKeyRange = IDBKeyRange;
+
afterEach(() =>
// give Promises a bit more time so they fail the right test
// eslint-disable-next-line no-restricted-syntax
@@ -11,3 +18,9 @@ afterEach(() =>
jest.runOnlyPendingTimers();
}),
);
+
+afterEach(async () => {
+ const dbs = await indexedDB.databases();
+
+ await Promise.all(dbs.map(async (db) => indexedDB.deleteDatabase(db.name)));
+});
diff --git a/spec/lib/backup/gitaly_backup_spec.rb b/spec/lib/backup/gitaly_backup_spec.rb
index ad0e5553fa1..172fc28dd3e 100644
--- a/spec/lib/backup/gitaly_backup_spec.rb
+++ b/spec/lib/backup/gitaly_backup_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Backup::GitalyBackup do
+RSpec.describe Backup::GitalyBackup, feature_category: :backup_restore do
let(:max_parallelism) { nil }
let(:storage_parallelism) { nil }
let(:destination) { File.join(Gitlab.config.backup.path, 'repositories') }
@@ -181,6 +181,15 @@ RSpec.describe Backup::GitalyBackup do
expect(collect_commit_shas.call(project_snippet.repository)).to match_array(['6e44ba56a4748be361a841e759c20e421a1651a1'])
end
+ it 'clears specified storages when remove_all_repositories is set' do
+ expect(Open3).to receive(:popen2).with(expected_env, anything, 'restore', '-path', anything, '-layout', 'pointer', '-remove-all-repositories', 'default').and_call_original
+
+ copy_bundle_to_backup_path('project_repo.bundle', project.disk_path + '.bundle')
+ subject.start(:restore, destination, backup_id: backup_id, remove_all_repositories: %w[default])
+ subject.enqueue(project, Gitlab::GlRepository::PROJECT)
+ subject.finish!
+ end
+
context 'parallel option set' do
let(:max_parallelism) { 3 }
diff --git a/spec/lib/backup/repositories_spec.rb b/spec/lib/backup/repositories_spec.rb
index 8bcf1e46c33..c75f6c2ac89 100644
--- a/spec/lib/backup/repositories_spec.rb
+++ b/spec/lib/backup/repositories_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Backup::Repositories do
+RSpec.describe Backup::Repositories, feature_category: :backup_restore do
let(:progress) { spy(:stdout) }
let(:strategy) { spy(:strategy) }
let(:storages) { [] }
@@ -165,7 +165,7 @@ RSpec.describe Backup::Repositories do
it 'calls enqueue for each repository type', :aggregate_failures do
subject.restore(destination)
- expect(strategy).to have_received(:start).with(:restore, destination)
+ expect(strategy).to have_received(:start).with(:restore, destination, remove_all_repositories: %w[default])
expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::PROJECT)
expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::WIKI)
expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::DESIGN)
@@ -246,7 +246,7 @@ RSpec.describe Backup::Repositories do
subject.restore(destination)
- expect(strategy).to have_received(:start).with(:restore, destination)
+ expect(strategy).to have_received(:start).with(:restore, destination, remove_all_repositories: %w[default])
expect(strategy).not_to have_received(:enqueue).with(excluded_project, Gitlab::GlRepository::PROJECT)
expect(strategy).not_to have_received(:enqueue).with(excluded_project_snippet, Gitlab::GlRepository::SNIPPET)
expect(strategy).not_to have_received(:enqueue).with(excluded_personal_snippet, Gitlab::GlRepository::SNIPPET)
@@ -268,7 +268,7 @@ RSpec.describe Backup::Repositories do
subject.restore(destination)
- expect(strategy).to have_received(:start).with(:restore, destination)
+ expect(strategy).to have_received(:start).with(:restore, destination, remove_all_repositories: nil)
expect(strategy).not_to have_received(:enqueue).with(excluded_project, Gitlab::GlRepository::PROJECT)
expect(strategy).not_to have_received(:enqueue).with(excluded_project_snippet, Gitlab::GlRepository::SNIPPET)
expect(strategy).not_to have_received(:enqueue).with(excluded_personal_snippet, Gitlab::GlRepository::SNIPPET)
@@ -289,7 +289,7 @@ RSpec.describe Backup::Repositories do
subject.restore(destination)
- expect(strategy).to have_received(:start).with(:restore, destination)
+ expect(strategy).to have_received(:start).with(:restore, destination, remove_all_repositories: nil)
expect(strategy).not_to have_received(:enqueue).with(excluded_project, Gitlab::GlRepository::PROJECT)
expect(strategy).not_to have_received(:enqueue).with(excluded_project_snippet, Gitlab::GlRepository::SNIPPET)
expect(strategy).not_to have_received(:enqueue).with(excluded_personal_snippet, Gitlab::GlRepository::SNIPPET)