diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-04-01 03:17:41 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-04-01 03:17:41 +0300 |
commit | bd98eab3fac88fdde059fafc59bc59b150b56d43 (patch) | |
tree | 73e0f2c85d5646166821341085baf1eabaaa8a8a /spec | |
parent | 83c5e07949cb1023dde1d282b3969def6f182472 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r-- | spec/frontend/ide/components/new_dropdown/index_spec.js | 56 | ||||
-rw-r--r-- | spec/frontend/lib/apollo/indexed_db_persistent_storage_spec.js | 90 | ||||
-rw-r--r-- | spec/frontend/lib/apollo/mock_data/cache_with_persist_directive_and_field.json | 151 | ||||
-rw-r--r-- | spec/frontend/test_setup.js | 13 | ||||
-rw-r--r-- | spec/lib/backup/gitaly_backup_spec.rb | 11 | ||||
-rw-r--r-- | spec/lib/backup/repositories_spec.rb | 10 |
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) |