diff options
Diffstat (limited to 'spec')
-rw-r--r-- | spec/frontend/ide/components/commit_sidebar/actions_spec.js | 32 | ||||
-rw-r--r-- | spec/frontend/ide/stores/getters_spec.js | 49 | ||||
-rw-r--r-- | spec/frontend/ide/stores/modules/commit/getters_spec.js | 11 | ||||
-rw-r--r-- | spec/frontend/monitoring/components/charts/annotations_spec.js | 73 | ||||
-rw-r--r-- | spec/frontend/monitoring/components/charts/time_series_spec.js | 11 | ||||
-rw-r--r-- | spec/frontend/monitoring/mock_data.js | 24 | ||||
-rw-r--r-- | spec/javascripts/ide/stores/actions/project_spec.js | 112 | ||||
-rw-r--r-- | spec/lib/gitlab/import_export/project/tree_restorer_spec.rb | 31 | ||||
-rw-r--r-- | spec/lib/gitlab/project_template_spec.rb | 3 | ||||
-rw-r--r-- | spec/policies/base_policy_spec.rb | 12 |
10 files changed, 246 insertions, 112 deletions
diff --git a/spec/frontend/ide/components/commit_sidebar/actions_spec.js b/spec/frontend/ide/components/commit_sidebar/actions_spec.js index b3b98a64891..a303e2b9bee 100644 --- a/spec/frontend/ide/components/commit_sidebar/actions_spec.js +++ b/spec/frontend/ide/components/commit_sidebar/actions_spec.js @@ -17,7 +17,11 @@ describe('IDE commit sidebar actions', () => { let store; let vm; - const createComponent = ({ hasMR = false, currentBranchId = 'master' } = {}) => { + const createComponent = ({ + hasMR = false, + currentBranchId = 'master', + emptyRepo = false, + } = {}) => { const Component = Vue.extend(commitActions); vm = createComponentWithStore(Component, store); @@ -27,6 +31,7 @@ describe('IDE commit sidebar actions', () => { const proj = { ...projectData }; proj.branches[currentBranchId] = branches.find(branch => branch.name === currentBranchId); + proj.empty_repo = emptyRepo; Vue.set(vm.$store.state.projects, 'abcproject', proj); @@ -52,24 +57,27 @@ describe('IDE commit sidebar actions', () => { vm = null; }); + const findText = () => vm.$el.textContent; + const findRadios = () => Array.from(vm.$el.querySelectorAll('input[type="radio"]')); + it('renders 2 groups', () => { createComponent(); - expect(vm.$el.querySelectorAll('input[type="radio"]').length).toBe(2); + expect(findRadios().length).toBe(2); }); it('renders current branch text', () => { createComponent(); - expect(vm.$el.textContent).toContain('Commit to master branch'); + expect(findText()).toContain('Commit to master branch'); }); it('hides merge request option when project merge requests are disabled', done => { - createComponent({ mergeRequestsEnabled: false }); + createComponent({ hasMR: false }); vm.$nextTick(() => { - expect(vm.$el.querySelectorAll('input[type="radio"]').length).toBe(2); - expect(vm.$el.textContent).not.toContain('Create a new branch and merge request'); + expect(findRadios().length).toBe(2); + expect(findText()).not.toContain('Create a new branch and merge request'); done(); }); @@ -119,6 +127,7 @@ describe('IDE commit sidebar actions', () => { it.each` input | expectedOption ${{ currentBranchId: BRANCH_DEFAULT }} | ${consts.COMMIT_TO_NEW_BRANCH} + ${{ currentBranchId: BRANCH_DEFAULT, emptyRepo: true }} | ${consts.COMMIT_TO_CURRENT_BRANCH} ${{ currentBranchId: BRANCH_PROTECTED, hasMR: true }} | ${consts.COMMIT_TO_CURRENT_BRANCH} ${{ currentBranchId: BRANCH_PROTECTED, hasMR: false }} | ${consts.COMMIT_TO_CURRENT_BRANCH} ${{ currentBranchId: BRANCH_PROTECTED_NO_ACCESS, hasMR: true }} | ${consts.COMMIT_TO_NEW_BRANCH} @@ -138,4 +147,15 @@ describe('IDE commit sidebar actions', () => { }, ); }); + + describe('when empty project', () => { + beforeEach(() => { + createComponent({ emptyRepo: true }); + }); + + it('only renders commit to current branch', () => { + expect(findRadios().length).toBe(1); + expect(findText()).toContain('Commit to master branch'); + }); + }); }); diff --git a/spec/frontend/ide/stores/getters_spec.js b/spec/frontend/ide/stores/getters_spec.js index 011be95c1d2..408ea2b2939 100644 --- a/spec/frontend/ide/stores/getters_spec.js +++ b/spec/frontend/ide/stores/getters_spec.js @@ -280,39 +280,21 @@ describe('IDE store getters', () => { }); describe('canPushToBranch', () => { - it('returns false when no currentBranch exists', () => { - const localGetters = { - currentProject: undefined, - }; - - expect(getters.canPushToBranch({}, localGetters)).toBeFalsy(); - }); - - it('returns true when can_push to currentBranch', () => { - const localGetters = { - currentProject: { - default_branch: 'master', - }, - currentBranch: { - can_push: true, - }, - }; - - expect(getters.canPushToBranch({}, localGetters)).toBeTruthy(); - }); - - it('returns false when !can_push to currentBranch', () => { - const localGetters = { - currentProject: { - default_branch: 'master', - }, - currentBranch: { - can_push: false, - }, - }; - - expect(getters.canPushToBranch({}, localGetters)).toBeFalsy(); - }); + it.each` + currentBranch | canPushCode | expectedValue + ${undefined} | ${undefined} | ${false} + ${{ can_push: true }} | ${false} | ${true} + ${{ can_push: true }} | ${true} | ${true} + ${{ can_push: false }} | ${false} | ${false} + ${{ can_push: false }} | ${true} | ${false} + ${undefined} | ${true} | ${true} + ${undefined} | ${false} | ${false} + `( + 'with currentBranch ($currentBranch) and canPushCode ($canPushCode), it is $expectedValue', + ({ currentBranch, canPushCode, expectedValue }) => { + expect(getters.canPushToBranch({}, { currentBranch, canPushCode })).toBe(expectedValue); + }, + ); }); describe('isFileDeletedAndReadded', () => { @@ -422,6 +404,7 @@ describe('IDE store getters', () => { getterName | permissionKey ${'canReadMergeRequests'} | ${'readMergeRequest'} ${'canCreateMergeRequests'} | ${'createMergeRequestIn'} + ${'canPushCode'} | ${'pushCode'} `('$getterName', ({ getterName, permissionKey }) => { it.each([true, false])('finds permission for current project (%s)', val => { localState.projects[TEST_PROJECT_ID] = { diff --git a/spec/frontend/ide/stores/modules/commit/getters_spec.js b/spec/frontend/ide/stores/modules/commit/getters_spec.js index 07445c22917..adbfd7c6835 100644 --- a/spec/frontend/ide/stores/modules/commit/getters_spec.js +++ b/spec/frontend/ide/stores/modules/commit/getters_spec.js @@ -292,4 +292,15 @@ describe('IDE commit module getters', () => { expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBeFalsy(); }); }); + + describe('shouldDisableNewMrOption', () => { + it.each` + rootGetters | expectedValue + ${{ canCreateMergeRequests: false, emptyRepo: false }} | ${true} + ${{ canCreateMergeRequests: true, emptyRepo: true }} | ${true} + ${{ canCreateMergeRequests: true, emptyRepo: false }} | ${false} + `('with $rootGetters, it is $expectedValue', ({ rootGetters, expectedValue }) => { + expect(getters.shouldDisableNewMrOption(state, getters, {}, rootGetters)).toBe(expectedValue); + }); + }); }); diff --git a/spec/frontend/monitoring/components/charts/annotations_spec.js b/spec/frontend/monitoring/components/charts/annotations_spec.js index 100b13eabf4..69bf1fe4ced 100644 --- a/spec/frontend/monitoring/components/charts/annotations_spec.js +++ b/spec/frontend/monitoring/components/charts/annotations_spec.js @@ -1,27 +1,90 @@ import { generateAnnotationsSeries } from '~/monitoring/components/charts/annotations'; -import { deploymentData } from '../../mock_data'; +import { deploymentData, annotationsData } from '../../mock_data'; describe('annotations spec', () => { describe('generateAnnotationsSeries', () => { - it('default options', () => { + it('with default options', () => { const annotations = generateAnnotationsSeries(); - expect(annotations).toEqual([]); + + expect(annotations).toEqual( + expect.objectContaining({ + type: 'scatter', + yAxisIndex: 1, + data: [], + markLine: { + data: [], + symbol: 'none', + silent: true, + }, + }), + ); }); - it('with deployments', () => { - const annotations = generateAnnotationsSeries(deploymentData); + it('when only deployments data is passed', () => { + const annotations = generateAnnotationsSeries({ deployments: deploymentData }); expect(annotations).toEqual( expect.objectContaining({ type: 'scatter', yAxisIndex: 1, data: expect.any(Array), + markLine: { + data: [], + symbol: 'none', + silent: true, + }, }), ); annotations.data.forEach(annotation => { expect(annotation).toEqual(expect.any(Object)); }); + + expect(annotations.data).toHaveLength(deploymentData.length); + }); + + it('when only annotations data is passed', () => { + const annotations = generateAnnotationsSeries({ + annotations: annotationsData, + }); + + expect(annotations).toEqual( + expect.objectContaining({ + type: 'scatter', + yAxisIndex: 1, + data: expect.any(Array), + markLine: expect.any(Object), + }), + ); + + annotations.markLine.data.forEach(annotation => { + expect(annotation).toEqual(expect.any(Object)); + }); + + expect(annotations.data).toHaveLength(annotationsData.length); + expect(annotations.markLine.data).toHaveLength(annotationsData.length); + }); + + it('when deploments and annotations data is passed', () => { + const annotations = generateAnnotationsSeries({ + deployments: deploymentData, + annotations: annotationsData, + }); + + expect(annotations).toEqual( + expect.objectContaining({ + type: 'scatter', + yAxisIndex: 1, + data: expect.any(Array), + markLine: expect.any(Object), + }), + ); + + annotations.markLine.data.forEach(annotation => { + expect(annotation).toEqual(expect.any(Object)); + }); + + expect(annotations.data).toHaveLength(deploymentData.length + annotationsData.length); }); }); }); diff --git a/spec/frontend/monitoring/components/charts/time_series_spec.js b/spec/frontend/monitoring/components/charts/time_series_spec.js index f2478a583dc..c9b670fd7a8 100644 --- a/spec/frontend/monitoring/components/charts/time_series_spec.js +++ b/spec/frontend/monitoring/components/charts/time_series_spec.js @@ -169,6 +169,7 @@ describe('Time series component', () => { componentSubType: type, value: [mockDate, 5.55555], dataIndex: 0, + ...(type === 'scatter' && { name: 'deployments' }), }, ], value: mockDate, @@ -225,6 +226,10 @@ describe('Time series component', () => { timeSeriesChart.vm.formatTooltipText(generateSeriesData('scatter')); }); + it('set tooltip type to deployments', () => { + expect(timeSeriesChart.vm.tooltip.type).toBe('deployments'); + }); + it('formats tooltip title', () => { expect(timeSeriesChart.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM'); }); @@ -521,7 +526,11 @@ describe('Time series component', () => { const commitUrl = `${mockProjectDir}/-/commit/${mockSha}`; beforeEach(done => { - timeSeriesAreaChart.vm.tooltip.isDeployment = true; + timeSeriesAreaChart.setData({ + tooltip: { + type: 'deployments', + }, + }); timeSeriesAreaChart.vm.$nextTick(done); }); diff --git a/spec/frontend/monitoring/mock_data.js b/spec/frontend/monitoring/mock_data.js index dde47178c1d..c9f2b110147 100644 --- a/spec/frontend/monitoring/mock_data.js +++ b/spec/frontend/monitoring/mock_data.js @@ -210,6 +210,30 @@ export const deploymentData = [ }, ]; +export const annotationsData = [ + { + id: 'gid://gitlab/Metrics::Dashboard::Annotation/1', + from: '2020-04-01T12:51:58.373Z', + to: null, + panelId: null, + description: 'This is a test annotation', + }, + { + id: 'gid://gitlab/Metrics::Dashboard::Annotation/2', + description: 'test annotation 2', + from: '2020-04-02T12:51:58.373Z', + to: null, + panelId: null, + }, + { + id: 'gid://gitlab/Metrics::Dashboard::Annotation/3', + description: 'test annotation 3', + from: '2020-04-04T12:51:58.373Z', + to: null, + panelId: null, + }, +]; + export const metricsNewGroupsAPIResponse = [ { group: 'System metrics (Kubernetes)', diff --git a/spec/javascripts/ide/stores/actions/project_spec.js b/spec/javascripts/ide/stores/actions/project_spec.js index bd51222ac3c..e962224d1ad 100644 --- a/spec/javascripts/ide/stores/actions/project_spec.js +++ b/spec/javascripts/ide/stores/actions/project_spec.js @@ -4,7 +4,7 @@ import { refreshLastCommitData, showBranchNotFoundError, createNewBranchFromDefault, - showEmptyState, + loadEmptyBranch, openBranch, loadFile, loadBranch, @@ -16,6 +16,8 @@ import router from '~/ide/ide_router'; import { resetStore } from '../../helpers'; import testAction from '../../../helpers/vuex_action_helper'; +const TEST_PROJECT_ID = 'abc/def'; + describe('IDE store project actions', () => { let mock; let store; @@ -24,7 +26,7 @@ describe('IDE store project actions', () => { store = createStore(); mock = new MockAdapter(axios); - store.state.projects['abc/def'] = { + store.state.projects[TEST_PROJECT_ID] = { branches: {}, }; }); @@ -83,7 +85,7 @@ describe('IDE store project actions', () => { { type: 'SET_BRANCH_COMMIT', payload: { - projectId: 'abc/def', + projectId: TEST_PROJECT_ID, branchId: 'master', commit: { id: '123' }, }, @@ -200,17 +202,17 @@ describe('IDE store project actions', () => { }); }); - describe('showEmptyState', () => { + describe('loadEmptyBranch', () => { it('creates a blank tree and sets loading state to false', done => { testAction( - showEmptyState, - { projectId: 'abc/def', branchId: 'master' }, + loadEmptyBranch, + { projectId: TEST_PROJECT_ID, branchId: 'master' }, store.state, [ - { type: 'CREATE_TREE', payload: { treePath: 'abc/def/master' } }, + { type: 'CREATE_TREE', payload: { treePath: `${TEST_PROJECT_ID}/master` } }, { type: 'TOGGLE_LOADING', - payload: { entry: store.state.trees['abc/def/master'], forceValue: false }, + payload: { entry: store.state.trees[`${TEST_PROJECT_ID}/master`], forceValue: false }, }, ], jasmine.any(Object), @@ -218,13 +220,15 @@ describe('IDE store project actions', () => { ); }); - it('sets the currentBranchId to the branchId that was passed', done => { + it('does nothing, if tree already exists', done => { + const trees = { [`${TEST_PROJECT_ID}/master`]: [] }; + testAction( - showEmptyState, - { projectId: 'abc/def', branchId: 'master' }, - store.state, - jasmine.any(Object), - [{ type: 'setCurrentBranchId', payload: 'master' }], + loadEmptyBranch, + { projectId: TEST_PROJECT_ID, branchId: 'master' }, + { trees }, + [], + [], done, ); }); @@ -278,10 +282,29 @@ describe('IDE store project actions', () => { }); describe('loadBranch', () => { - const projectId = 'abc/def'; + const projectId = TEST_PROJECT_ID; const branchId = '123-lorem'; const ref = 'abcd2322'; + it('when empty repo, loads empty branch', done => { + const mockGetters = { emptyRepo: true }; + + testAction( + loadBranch, + { projectId, branchId }, + { ...store.state, ...mockGetters }, + [], + [{ type: 'loadEmptyBranch', payload: { projectId, branchId } }], + done, + ); + }); + + it('when branch already exists, does nothing', done => { + store.state.projects[projectId].branches[branchId] = {}; + + testAction(loadBranch, { projectId, branchId }, store.state, [], [], done); + }); + it('fetches branch data', done => { const mockGetters = { findBranch: () => ({ commit: { id: ref } }) }; spyOn(store, 'dispatch').and.returnValue(Promise.resolve()); @@ -317,7 +340,7 @@ describe('IDE store project actions', () => { }); describe('openBranch', () => { - const projectId = 'abc/def'; + const projectId = TEST_PROJECT_ID; const branchId = '123-lorem'; const branch = { @@ -335,55 +358,6 @@ describe('IDE store project actions', () => { }); }); - it('loads file right away if the branch has already been fetched', done => { - spyOn(store, 'dispatch'); - - Object.assign(store.state, { - projects: { - [projectId]: { - branches: { - [branchId]: { foo: 'bar' }, - }, - }, - }, - }); - - openBranch(store, branch) - .then(() => { - expect(store.dispatch.calls.allArgs()).toEqual([['loadFile', { basePath: undefined }]]); - }) - .then(done) - .catch(done.fail); - }); - - describe('empty repo', () => { - beforeEach(() => { - spyOn(store, 'dispatch').and.returnValue(Promise.resolve()); - - Object.assign(store.state, { - currentProjectId: 'abc/def', - projects: { - 'abc/def': { - empty_repo: true, - }, - }, - }); - }); - - afterEach(() => { - resetStore(store); - }); - - it('dispatches showEmptyState action right away', done => { - openBranch(store, branch) - .then(() => { - expect(store.dispatch.calls.allArgs()).toEqual([['showEmptyState', branch]]); - done(); - }) - .catch(done.fail); - }); - }); - describe('existing branch', () => { beforeEach(() => { spyOn(store, 'dispatch').and.returnValue(Promise.resolve()); @@ -410,11 +384,17 @@ describe('IDE store project actions', () => { it('dispatches correct branch actions', done => { openBranch(store, branch) - .then(() => { + .then(val => { expect(store.dispatch.calls.allArgs()).toEqual([ ['setCurrentBranchId', branchId], ['loadBranch', { projectId, branchId }], ]); + + expect(val).toEqual( + new Error( + `An error occurred while getting files for - <strong>${projectId}/${branchId}</strong>`, + ), + ); }) .then(done) .catch(done.fail); 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 c8229eeee94..9fc0fdeb1bc 100644 --- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb @@ -956,6 +956,37 @@ describe Gitlab::ImportExport::Project::TreeRestorer do end end end + + context 'with project members' do + let(:user) { create(:user, :admin) } + let(:user2) { create(:user) } + let(:project_members) do + [ + { + "id" => 2, + "access_level" => 40, + "source_type" => "Project", + "notification_level" => 3, + "user" => { + "id" => user2.id, + "email" => user2.email, + "username" => 'test' + } + } + ] + end + let(:tree_hash) { { 'project_members' => project_members } } + + before do + project.add_maintainer(user) + end + + it 'restores project members' do + restorer.restore + + expect(project.members.map(&:user)).to contain_exactly(user, user2) + end + end end context 'JSON with invalid records' do diff --git a/spec/lib/gitlab/project_template_spec.rb b/spec/lib/gitlab/project_template_spec.rb index 3948e53bc17..ddc41e64147 100644 --- a/spec/lib/gitlab/project_template_spec.rb +++ b/spec/lib/gitlab/project_template_spec.rb @@ -25,7 +25,8 @@ describe Gitlab::ProjectTemplate do described_class.new('nfgitbook', 'Netlify/GitBook', _('A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features.'), 'https://gitlab.com/pages/nfgitbook'), described_class.new('nfhexo', 'Netlify/Hexo', _('A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features.'), 'https://gitlab.com/pages/nfhexo'), described_class.new('salesforcedx', 'SalesforceDX', _('A project boilerplate for Salesforce App development with Salesforce Developer tools.'), 'https://gitlab.com/gitlab-org/project-templates/salesforcedx'), - described_class.new('serverless_framework', 'Serverless Framework/JS', _('A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages'), 'https://gitlab.com/gitlab-org/project-templates/serverless-framework', 'illustrations/logos/serverless_framework.svg') + described_class.new('serverless_framework', 'Serverless Framework/JS', _('A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages'), 'https://gitlab.com/gitlab-org/project-templates/serverless-framework', 'illustrations/logos/serverless_framework.svg'), + described_class.new('cluster_management', 'GitLab Cluster Management', _('An example project for managing Kubernetes clusters integrated with GitLab.'), 'https://gitlab.com/gitlab-org/project-templates/cluster-management') ] expect(described_class.all).to be_an(Array) diff --git a/spec/policies/base_policy_spec.rb b/spec/policies/base_policy_spec.rb index ae5af9e0f29..e15221492c3 100644 --- a/spec/policies/base_policy_spec.rb +++ b/spec/policies/base_policy_spec.rb @@ -30,6 +30,12 @@ describe BasePolicy, :do_not_mock_admin_mode do it { is_expected.to be_allowed(:read_cross_project) } + context 'for anonymous' do + let(:current_user) { nil } + + it { is_expected.to be_allowed(:read_cross_project) } + end + context 'when an external authorization service is enabled' do before do enable_external_authorization_service_check @@ -52,6 +58,12 @@ describe BasePolicy, :do_not_mock_admin_mode do is_expected.not_to be_allowed(:read_cross_project) end end + + context 'for anonymous' do + let(:current_user) { nil } + + it { is_expected.not_to be_allowed(:read_cross_project) } + end end end |