diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-08 15:11:30 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-08 15:11:30 +0300 |
commit | 012f9a4b9ec4a78d9593d882b38f95e376c2cfe2 (patch) | |
tree | 07f1df76cb12d94744e8069eec540d36092bbaba /spec | |
parent | 3c050fb24b757425987a7df4cb3497e1d792be8e (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
27 files changed, 678 insertions, 123 deletions
diff --git a/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js b/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js index 1eac0733646..2ef87f6664b 100644 --- a/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js +++ b/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js @@ -18,14 +18,14 @@ describe('Blob Header Viewer Switcher', () => { }); } - afterEach(() => { - wrapper.destroy(); - }); + const findSimpleViewerButton = () => wrapper.findComponent('[data-viewer="simple"]'); + const findRichViewerButton = () => wrapper.findComponent('[data-viewer="rich"]'); describe('intiialization', () => { it('is initialized with simple viewer as active', () => { createComponent(); - expect(wrapper.vm.value).toBe(SIMPLE_BLOB_VIEWER); + expect(findSimpleViewerButton().props('selected')).toBe(true); + expect(findRichViewerButton().props('selected')).toBe(false); }); }); @@ -52,45 +52,34 @@ describe('Blob Header Viewer Switcher', () => { }); describe('viewer changes', () => { - let buttons; - let simpleBtn; - let richBtn; + it('does not switch the viewer if the selected one is already active', async () => { + createComponent(); + expect(findSimpleViewerButton().props('selected')).toBe(true); - function factory(propsData = {}) { - createComponent(propsData); - buttons = wrapper.findAllComponents(GlButton); - simpleBtn = buttons.at(0); - richBtn = buttons.at(1); - - jest.spyOn(wrapper.vm, '$emit'); - } - - it('does not switch the viewer if the selected one is already active', () => { - factory(); - expect(wrapper.vm.value).toBe(SIMPLE_BLOB_VIEWER); - simpleBtn.vm.$emit('click'); - expect(wrapper.vm.value).toBe(SIMPLE_BLOB_VIEWER); - expect(wrapper.vm.$emit).not.toHaveBeenCalled(); + findSimpleViewerButton().vm.$emit('click'); + await nextTick(); + + expect(findSimpleViewerButton().props('selected')).toBe(true); + expect(wrapper.emitted('input')).toBe(undefined); }); it('emits an event when a Rich Viewer button is clicked', async () => { - factory(); - expect(wrapper.vm.value).toBe(SIMPLE_BLOB_VIEWER); - - richBtn.vm.$emit('click'); + createComponent(); + expect(findSimpleViewerButton().props('selected')).toBe(true); + findRichViewerButton().vm.$emit('click'); await nextTick(); - expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', RICH_BLOB_VIEWER); + + expect(wrapper.emitted('input')).toEqual([[RICH_BLOB_VIEWER]]); }); it('emits an event when a Simple Viewer button is clicked', async () => { - factory({ - value: RICH_BLOB_VIEWER, - }); - simpleBtn.vm.$emit('click'); + createComponent({ value: RICH_BLOB_VIEWER }); + findSimpleViewerButton().vm.$emit('click'); await nextTick(); - expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', SIMPLE_BLOB_VIEWER); + + expect(wrapper.emitted('input')).toEqual([[SIMPLE_BLOB_VIEWER]]); }); }); }); diff --git a/spec/frontend/ci/runner/admin_register_runner/admin_register_runner_app_spec.js b/spec/frontend/ci/runner/admin_register_runner/admin_register_runner_app_spec.js index 42ca28eebc7..1ba3d9c317f 100644 --- a/spec/frontend/ci/runner/admin_register_runner/admin_register_runner_app_spec.js +++ b/spec/frontend/ci/runner/admin_register_runner/admin_register_runner_app_spec.js @@ -1,4 +1,4 @@ -import Vue from 'vue'; +import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import { GlButton } from '@gitlab/ui'; @@ -7,12 +7,15 @@ import createMockApollo from 'helpers/mock_apollo_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import setWindowLocation from 'helpers/set_window_location_helper'; +import { TEST_HOST } from 'helpers/test_constants'; import { s__ } from '~/locale'; +import { updateHistory } from '~/lib/utils/url_utility'; import runnerForRegistrationQuery from '~/ci/runner/graphql/register/runner_for_registration.query.graphql'; import { PARAM_KEY_PLATFORM, DEFAULT_PLATFORM, WINDOWS_PLATFORM } from '~/ci/runner/constants'; import AdminRegisterRunnerApp from '~/ci/runner/admin_register_runner/admin_register_runner_app.vue'; import RegistrationInstructions from '~/ci/runner/components/registration/registration_instructions.vue'; +import PlatformsDrawer from '~/ci/runner/components/registration/platforms_drawer.vue'; import { runnerForRegistration } from '../mock_data'; const mockRunner = runnerForRegistration.data.runner; @@ -22,11 +25,17 @@ const MOCK_TOKEN = 'MOCK_TOKEN'; Vue.use(VueApollo); +jest.mock('~/lib/utils/url_utility', () => ({ + ...jest.requireActual('~/lib/utils/url_utility'), + updateHistory: jest.fn(), +})); + describe('AdminRegisterRunnerApp', () => { let wrapper; let mockRunnerQuery; const findRegistrationInstructions = () => wrapper.findComponent(RegistrationInstructions); + const findPlatformsDrawer = () => wrapper.findComponent(PlatformsDrawer); const findBtn = () => wrapper.findComponent(GlButton); const createComponent = () => { @@ -69,6 +78,13 @@ describe('AdminRegisterRunnerApp', () => { }); }); + it('configures platform drawer', () => { + expect(findPlatformsDrawer().props()).toEqual({ + open: false, + platform: DEFAULT_PLATFORM, + }); + }); + it('shows runner list button', () => { expect(findBtn().attributes('href')).toEqual(mockRunnersPath); expect(findBtn().props('variant')).toEqual('confirm'); @@ -88,6 +104,52 @@ describe('AdminRegisterRunnerApp', () => { }); }); + describe('When opening install instructions', () => { + beforeEach(async () => { + createComponent(); + await waitForPromises(); + + findRegistrationInstructions().vm.$emit('toggleDrawer'); + await nextTick(); + }); + + it('opens platform drawer', () => { + expect(findPlatformsDrawer().props('open')).toEqual(true); + }); + + it('closes platform drawer', async () => { + findRegistrationInstructions().vm.$emit('toggleDrawer'); + await nextTick(); + + expect(findPlatformsDrawer().props('open')).toEqual(false); + }); + + it('closes platform drawer from drawer', async () => { + findPlatformsDrawer().vm.$emit('close'); + await nextTick(); + + expect(findPlatformsDrawer().props('open')).toEqual(false); + }); + + describe('when selecting a platform', () => { + beforeEach(async () => { + findPlatformsDrawer().vm.$emit('selectPlatform', WINDOWS_PLATFORM); + await nextTick(); + }); + + it('updates the url', () => { + expect(updateHistory).toHaveBeenCalledTimes(1); + expect(updateHistory).toHaveBeenCalledWith({ + url: `${TEST_HOST}/?${PARAM_KEY_PLATFORM}=${WINDOWS_PLATFORM}`, + }); + }); + + it('updates the registration instructions', () => { + expect(findRegistrationInstructions().props('platform')).toBe(WINDOWS_PLATFORM); + }); + }); + }); + describe('When runner is loading', () => { beforeEach(async () => { createComponent(); diff --git a/spec/frontend/ci/runner/components/registration/__snapshots__/utils_spec.js.snap b/spec/frontend/ci/runner/components/registration/__snapshots__/utils_spec.js.snap index c1cc6aa07a2..94b87d31ed0 100644 --- a/spec/frontend/ci/runner/components/registration/__snapshots__/utils_spec.js.snap +++ b/spec/frontend/ci/runner/components/registration/__snapshots__/utils_spec.js.snap @@ -1,10 +1,77 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`registration utils for "linux" platform commandPrompt matches snapshot 1`] = `"$"`; +exports[`registration utils for "linux" platform commandPrompt is correct 1`] = `"$"`; -exports[`registration utils for "linux" platform commandPrompt matches snapshot 2`] = `"$"`; +exports[`registration utils for "linux" platform installScript is correct for "386" architecture 1`] = ` +"# Download the binary for your system +sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-386 -exports[`registration utils for "linux" platform registerCommand matches snapshot 1`] = ` +# Give it permission to execute +sudo chmod +x /usr/local/bin/gitlab-runner + +# Create a GitLab Runner user +sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash + +# Install and run as a service +sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner +sudo gitlab-runner start" +`; + +exports[`registration utils for "linux" platform installScript is correct for "amd64" architecture 1`] = ` +"# Download the binary for your system +sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64 + +# Give it permission to execute +sudo chmod +x /usr/local/bin/gitlab-runner + +# Create a GitLab Runner user +sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash + +# Install and run as a service +sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner +sudo gitlab-runner start" +`; + +exports[`registration utils for "linux" platform installScript is correct for "arm" architecture 1`] = ` +"# Download the binary for your system +sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-arm + +# Give it permission to execute +sudo chmod +x /usr/local/bin/gitlab-runner + +# Create a GitLab Runner user +sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash + +# Install and run as a service +sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner +sudo gitlab-runner start" +`; + +exports[`registration utils for "linux" platform installScript is correct for "arm64" architecture 1`] = ` +"# Download the binary for your system +sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-arm64 + +# Give it permission to execute +sudo chmod +x /usr/local/bin/gitlab-runner + +# Create a GitLab Runner user +sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash + +# Install and run as a service +sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner +sudo gitlab-runner start" +`; + +exports[`registration utils for "linux" platform platformArchitectures returns correct list of architectures 1`] = ` +Array [ + "amd64", + "386", + "arm", + "arm64", +] +`; + +exports[`registration utils for "linux" platform registerCommand is correct 1`] = ` Array [ "gitlab-runner register", " --url http://test.host", @@ -12,21 +79,53 @@ Array [ ] `; -exports[`registration utils for "linux" platform registerCommand matches snapshot 2`] = ` +exports[`registration utils for "linux" platform registerCommand is correct 2`] = ` Array [ "gitlab-runner register", " --url http://test.host", - " --registration-token REGISTRATION_TOKEN", ] `; -exports[`registration utils for "linux" platform runCommand matches snapshot 1`] = `"gitlab-runner run"`; +exports[`registration utils for "linux" platform runCommand is correct 1`] = `"gitlab-runner run"`; + +exports[`registration utils for "osx" platform commandPrompt is correct 1`] = `"$"`; + +exports[`registration utils for "osx" platform installScript is correct for "amd64" architecture 1`] = ` +"# Download the binary for your system +sudo curl --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64 + +# Give it permission to execute +sudo chmod +x /usr/local/bin/gitlab-runner + +# The rest of the commands execute as the user who will run the runner +# Register the runner (steps below), then run +cd ~ +gitlab-runner install +gitlab-runner start" +`; + +exports[`registration utils for "osx" platform installScript is correct for "arm64" architecture 1`] = ` +"# Download the binary for your system +sudo curl --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-arm64 + +# Give it permission to execute +sudo chmod +x /usr/local/bin/gitlab-runner -exports[`registration utils for "linux" platform runCommand matches snapshot 2`] = `"gitlab-runner run"`; +# The rest of the commands execute as the user who will run the runner +# Register the runner (steps below), then run +cd ~ +gitlab-runner install +gitlab-runner start" +`; -exports[`registration utils for "null" platform commandPrompt matches snapshot 1`] = `"$"`; +exports[`registration utils for "osx" platform platformArchitectures returns correct list of architectures 1`] = ` +Array [ + "amd64", + "arm64", +] +`; -exports[`registration utils for "null" platform registerCommand matches snapshot 1`] = ` +exports[`registration utils for "osx" platform registerCommand is correct 1`] = ` Array [ "gitlab-runner register", " --url http://test.host", @@ -34,23 +133,57 @@ Array [ ] `; -exports[`registration utils for "null" platform runCommand matches snapshot 1`] = `"gitlab-runner run"`; - -exports[`registration utils for "osx" platform commandPrompt matches snapshot 1`] = `"$"`; - -exports[`registration utils for "osx" platform registerCommand matches snapshot 1`] = ` +exports[`registration utils for "osx" platform registerCommand is correct 2`] = ` Array [ "gitlab-runner register", " --url http://test.host", - " --registration-token REGISTRATION_TOKEN", ] `; -exports[`registration utils for "osx" platform runCommand matches snapshot 1`] = `"gitlab-runner run"`; +exports[`registration utils for "osx" platform runCommand is correct 1`] = `"gitlab-runner run"`; + +exports[`registration utils for "windows" platform commandPrompt is correct 1`] = `">"`; + +exports[`registration utils for "windows" platform installScript is correct for "386" architecture 1`] = ` +"# Run PowerShell: https://docs.microsoft.com/en-us/powershell/scripting/windows-powershell/starting-windows-powershell?view=powershell-7#with-administrative-privileges-run-as-administrator +# Create a folder somewhere on your system, for example: C:\\\\GitLab-Runner +New-Item -Path 'C:\\\\GitLab-Runner' -ItemType Directory + +# Change to the folder +cd 'C:\\\\GitLab-Runner' + +# Download binary +Invoke-WebRequest -Uri \\"https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-windows-386.exe\\" -OutFile \\"gitlab-runner.exe\\" + +# Register the runner (steps below), then run +.\\\\gitlab-runner.exe install +.\\\\gitlab-runner.exe start" +`; -exports[`registration utils for "windows" platform commandPrompt matches snapshot 1`] = `">"`; +exports[`registration utils for "windows" platform installScript is correct for "amd64" architecture 1`] = ` +"# Run PowerShell: https://docs.microsoft.com/en-us/powershell/scripting/windows-powershell/starting-windows-powershell?view=powershell-7#with-administrative-privileges-run-as-administrator +# Create a folder somewhere on your system, for example: C:\\\\GitLab-Runner +New-Item -Path 'C:\\\\GitLab-Runner' -ItemType Directory -exports[`registration utils for "windows" platform registerCommand matches snapshot 1`] = ` +# Change to the folder +cd 'C:\\\\GitLab-Runner' + +# Download binary +Invoke-WebRequest -Uri \\"https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-windows-amd64.exe\\" -OutFile \\"gitlab-runner.exe\\" + +# Register the runner (steps below), then run +.\\\\gitlab-runner.exe install +.\\\\gitlab-runner.exe start" +`; + +exports[`registration utils for "windows" platform platformArchitectures returns correct list of architectures 1`] = ` +Array [ + "amd64", + "386", +] +`; + +exports[`registration utils for "windows" platform registerCommand is correct 1`] = ` Array [ ".\\\\gitlab-runner.exe register", " --url http://test.host", @@ -58,4 +191,11 @@ Array [ ] `; -exports[`registration utils for "windows" platform runCommand matches snapshot 1`] = `".\\\\gitlab-runner.exe run"`; +exports[`registration utils for "windows" platform registerCommand is correct 2`] = ` +Array [ + ".\\\\gitlab-runner.exe register", + " --url http://test.host", +] +`; + +exports[`registration utils for "windows" platform runCommand is correct 1`] = `".\\\\gitlab-runner.exe run"`; diff --git a/spec/frontend/ci/runner/components/registration/platforms_drawer_spec.js b/spec/frontend/ci/runner/components/registration/platforms_drawer_spec.js new file mode 100644 index 00000000000..c1879efd45a --- /dev/null +++ b/spec/frontend/ci/runner/components/registration/platforms_drawer_spec.js @@ -0,0 +1,92 @@ +import { nextTick } from 'vue'; +import { GlDrawer } from '@gitlab/ui'; +import { s__ } from '~/locale'; +import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper'; + +import PlatformsDrawer from '~/ci/runner/components/registration/platforms_drawer.vue'; +import CliCommand from '~/ci/runner/components/registration/cli_command.vue'; +import { LINUX_PLATFORM, MACOS_PLATFORM, WINDOWS_PLATFORM } from '~/ci/runner/constants'; +import { installScript, platformArchitectures } from '~/ci/runner/components/registration/utils'; + +const MOCK_WRAPPER_HEIGHT = '99px'; +const LINUX_ARCHS = platformArchitectures({ platform: LINUX_PLATFORM }); +const MACOS_ARCHS = platformArchitectures({ platform: MACOS_PLATFORM }); + +jest.mock('~/lib/utils/dom_utils', () => ({ + getContentWrapperHeight: () => MOCK_WRAPPER_HEIGHT, +})); + +describe('RegistrationInstructions', () => { + let wrapper; + + const findDrawer = () => wrapper.findComponent(GlDrawer); + const findEnvironmentOptions = () => + wrapper.findByLabelText(s__('Runners|Environment')).findAll('option'); + const findArchitectureOptions = () => + wrapper.findByLabelText(s__('Runners|Architecture')).findAll('option'); + const findCliCommand = () => wrapper.findComponent(CliCommand); + + const createComponent = ({ props = {}, mountFn = shallowMountExtended } = {}) => { + wrapper = mountFn(PlatformsDrawer, { + propsData: { + open: true, + ...props, + }, + }); + }; + + it('shows drawer', () => { + createComponent(); + + expect(findDrawer().props()).toMatchObject({ + open: true, + headerHeight: MOCK_WRAPPER_HEIGHT, + }); + }); + + it('closes drawer', () => { + createComponent(); + findDrawer().vm.$emit('close'); + + expect(wrapper.emitted('close')).toHaveLength(1); + }); + + it('shows selection options', () => { + createComponent({ mountFn: mountExtended }); + + expect(findEnvironmentOptions().wrappers.map((w) => w.attributes('value'))).toEqual([ + LINUX_PLATFORM, + MACOS_PLATFORM, + WINDOWS_PLATFORM, + ]); + + expect(findArchitectureOptions().wrappers.map((w) => w.attributes('value'))).toEqual( + LINUX_ARCHS, + ); + }); + + it('shows script', () => { + createComponent(); + + expect(findCliCommand().props('command')).toBe( + installScript({ platform: LINUX_PLATFORM, architecture: LINUX_ARCHS[0] }), + ); + }); + + it('shows selection options for another platform', async () => { + createComponent({ mountFn: mountExtended }); + + findEnvironmentOptions().at(1).setSelected(); // macos + await nextTick(); + + expect(wrapper.emitted('selectPlatform')).toEqual([[MACOS_PLATFORM]]); + + expect(findArchitectureOptions().wrappers.map((w) => w.attributes('value'))).toEqual( + MACOS_ARCHS, + ); + + expect(findCliCommand().props('command')).toBe( + installScript({ platform: MACOS_PLATFORM, architecture: MACOS_ARCHS[0] }), + ); + }); +}); diff --git a/spec/frontend/ci/runner/components/registration/registration_instructions_spec.js b/spec/frontend/ci/runner/components/registration/registration_instructions_spec.js index 858b0732782..f81f96ceffb 100644 --- a/spec/frontend/ci/runner/components/registration/registration_instructions_spec.js +++ b/spec/frontend/ci/runner/components/registration/registration_instructions_spec.js @@ -1,11 +1,15 @@ -import { GlSprintf, GlLink, GlSkeletonLoader } from '@gitlab/ui'; +import { GlSprintf, GlSkeletonLoader } from '@gitlab/ui'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; -import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import { extendedWrapper, shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { TEST_HOST } from 'helpers/test_constants'; import RegistrationInstructions from '~/ci/runner/components/registration/registration_instructions.vue'; import CliCommand from '~/ci/runner/components/registration/cli_command.vue'; -import { DEFAULT_PLATFORM, INSTALL_HELP_URL, EXECUTORS_HELP_URL } from '~/ci/runner/constants'; +import { + DEFAULT_PLATFORM, + EXECUTORS_HELP_URL, + SERVICE_COMMANDS_HELP_URL, +} from '~/ci/runner/constants'; const REGISTRATION_TOKEN = 'REGISTRATION_TOKEN'; const DUMMY_GON = { @@ -16,9 +20,8 @@ describe('RegistrationInstructions', () => { let wrapper; let originalGon; - const findStepAt = (i) => wrapper.findAll('section').at(i); - const findLink = (href, container = wrapper) => - container.findAllComponents(GlLink).filter((w) => w.attributes('href') === href); + const findStepAt = (i) => extendedWrapper(wrapper.findAll('section').at(i)); + const findByText = (text, container = wrapper) => container.findByText(text); const createComponent = (props) => { wrapper = shallowMountExtended(RegistrationInstructions, { @@ -47,7 +50,9 @@ describe('RegistrationInstructions', () => { }); it('renders legacy instructions', () => { - expect(findLink(INSTALL_HELP_URL).exists()).toBe(true); + findByText('How do I install GitLab Runner?').vm.$emit('click'); + + expect(wrapper.emitted('toggleDrawer')).toHaveLength(1); }); it('renders step 1', () => { @@ -80,7 +85,9 @@ describe('RegistrationInstructions', () => { it('renders step 2', () => { const step2 = findStepAt(1); - expect(findLink(EXECUTORS_HELP_URL, step2).exists()).toBe(true); + expect(findByText('Not sure which one to select?', step2).attributes('href')).toBe( + EXECUTORS_HELP_URL, + ); }); it('renders step 3', () => { @@ -90,5 +97,9 @@ describe('RegistrationInstructions', () => { command: 'gitlab-runner run', prompt: '$', }); + + expect(findByText('system or user service', step3).attributes('href')).toBe( + SERVICE_COMMANDS_HELP_URL, + ); }); }); diff --git a/spec/frontend/ci/runner/components/registration/utils_spec.js b/spec/frontend/ci/runner/components/registration/utils_spec.js index aeb489ca7de..6c4bf65eaa6 100644 --- a/spec/frontend/ci/runner/components/registration/utils_spec.js +++ b/spec/frontend/ci/runner/components/registration/utils_spec.js @@ -10,6 +10,8 @@ import { commandPrompt, registerCommand, runCommand, + installScript, + platformArchitectures, } from '~/ci/runner/components/registration/utils'; const REGISTRATION_TOKEN = 'REGISTRATION_TOKEN'; @@ -29,24 +31,69 @@ describe('registration utils', () => { window.gon = originalGon; }); - describe.each([DEFAULT_PLATFORM, LINUX_PLATFORM, MACOS_PLATFORM, WINDOWS_PLATFORM, null])( + describe.each([LINUX_PLATFORM, MACOS_PLATFORM, WINDOWS_PLATFORM])( 'for "%s" platform', (platform) => { - describe('commandPrompt', () => { - it('matches snapshot', () => { - expect(commandPrompt({ platform })).toMatchSnapshot(); - }); + it('commandPrompt is correct', () => { + expect(commandPrompt({ platform })).toMatchSnapshot(); + }); + it('registerCommand is correct', () => { + expect( + registerCommand({ platform, registrationToken: REGISTRATION_TOKEN }), + ).toMatchSnapshot(); + + expect(registerCommand({ platform })).toMatchSnapshot(); + }); + it('runCommand is correct', () => { + expect(runCommand({ platform })).toMatchSnapshot(); + }); + }, + ); + + describe('for missing platform', () => { + it('commandPrompt uses the default', () => { + const expected = commandPrompt({ platform: DEFAULT_PLATFORM }); + + expect(commandPrompt({ platform: null })).toEqual(expected); + expect(commandPrompt({ platform: undefined })).toEqual(expected); + }); + + it('registerCommand uses the default', () => { + const expected = registerCommand({ + platform: DEFAULT_PLATFORM, + registrationToken: REGISTRATION_TOKEN, }); - describe('registerCommand', () => { - it('matches snapshot', () => { - expect( - registerCommand({ platform, registrationToken: REGISTRATION_TOKEN }), - ).toMatchSnapshot(); + + expect(registerCommand({ platform: null, registrationToken: REGISTRATION_TOKEN })).toEqual( + expected, + ); + expect( + registerCommand({ platform: undefined, registrationToken: REGISTRATION_TOKEN }), + ).toEqual(expected); + }); + + it('runCommand uses the default', () => { + const expected = runCommand({ platform: DEFAULT_PLATFORM }); + + expect(runCommand({ platform: null })).toEqual(expected); + expect(runCommand({ platform: undefined })).toEqual(expected); + }); + }); + + describe.each([LINUX_PLATFORM, MACOS_PLATFORM, WINDOWS_PLATFORM])( + 'for "%s" platform', + (platform) => { + describe('platformArchitectures', () => { + it('returns correct list of architectures', () => { + expect(platformArchitectures({ platform })).toMatchSnapshot(); }); }); - describe('runCommand', () => { - it('matches snapshot', () => { - expect(runCommand({ platform })).toMatchSnapshot(); + + describe('installScript', () => { + const architectures = platformArchitectures({ platform }); + + it.each(architectures)('is correct for "%s" architecture', (architecture) => { + expect(installScript({ platform, architecture })).toMatchSnapshot(); }); }); }, diff --git a/spec/frontend/monitoring/components/variables/text_field_spec.js b/spec/frontend/monitoring/components/variables/text_field_spec.js index 3073b3968aa..20e1937c5ac 100644 --- a/spec/frontend/monitoring/components/variables/text_field_spec.js +++ b/spec/frontend/monitoring/components/variables/text_field_spec.js @@ -33,25 +33,23 @@ describe('Text variable component', () => { it('triggers keyup enter', async () => { createShallowWrapper(); - jest.spyOn(wrapper.vm, '$emit'); findInput().element.value = 'prod-pod'; findInput().trigger('input'); findInput().trigger('keyup.enter'); await nextTick(); - expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', 'prod-pod'); + expect(wrapper.emitted('input')).toEqual([['prod-pod']]); }); it('triggers blur enter', async () => { createShallowWrapper(); - jest.spyOn(wrapper.vm, '$emit'); findInput().element.value = 'canary-pod'; findInput().trigger('input'); findInput().trigger('blur'); await nextTick(); - expect(wrapper.vm.$emit).toHaveBeenCalledWith('input', 'canary-pod'); + expect(wrapper.emitted('input')).toEqual([['canary-pod']]); }); }); diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js index 619d0cb5dd3..39316dfa249 100644 --- a/spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js +++ b/spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js @@ -29,28 +29,28 @@ const createComponent = (propsData = issuableTitleProps) => describe('IssuableTitle', () => { let wrapper; + const findStickyHeader = () => wrapper.findComponent('[data-testid="header"]'); + beforeEach(() => { wrapper = createComponent(); }); - afterEach(() => { - wrapper.destroy(); - }); - describe('methods', () => { describe('handleTitleAppear', () => { - it('sets value of `stickyTitleVisible` prop to false', () => { + it('sets value of `stickyTitleVisible` prop to false', async () => { wrapper.findComponent(GlIntersectionObserver).vm.$emit('appear'); + await nextTick(); - expect(wrapper.vm.stickyTitleVisible).toBe(false); + expect(findStickyHeader().exists()).toBe(false); }); }); describe('handleTitleDisappear', () => { - it('sets value of `stickyTitleVisible` prop to true', () => { + it('sets value of `stickyTitleVisible` prop to true', async () => { wrapper.findComponent(GlIntersectionObserver).vm.$emit('disappear'); + await nextTick(); - expect(wrapper.vm.stickyTitleVisible).toBe(true); + expect(findStickyHeader().exists()).toBe(true); }); }); }); @@ -87,14 +87,10 @@ describe('IssuableTitle', () => { }); it('renders sticky header when `stickyTitleVisible` prop is true', async () => { - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ - stickyTitleVisible: true, - }); - + wrapper.findComponent(GlIntersectionObserver).vm.$emit('disappear'); await nextTick(); - const stickyHeaderEl = wrapper.find('[data-testid="header"]'); + + const stickyHeaderEl = findStickyHeader(); expect(stickyHeaderEl.exists()).toBe(true); expect(stickyHeaderEl.findComponent(GlBadge).props('variant')).toBe('success'); diff --git a/spec/graphql/types/work_items/widget_interface_spec.rb b/spec/graphql/types/work_items/widget_interface_spec.rb index a2b12ed52dc..d1dcfb961cb 100644 --- a/spec/graphql/types/work_items/widget_interface_spec.rb +++ b/spec/graphql/types/work_items/widget_interface_spec.rb @@ -15,11 +15,12 @@ RSpec.describe Types::WorkItems::WidgetInterface do using RSpec::Parameterized::TableSyntax where(:widget_class, :widget_type_name) do - WorkItems::Widgets::Description | Types::WorkItems::Widgets::DescriptionType - WorkItems::Widgets::Hierarchy | Types::WorkItems::Widgets::HierarchyType - WorkItems::Widgets::Assignees | Types::WorkItems::Widgets::AssigneesType - WorkItems::Widgets::Labels | Types::WorkItems::Widgets::LabelsType - WorkItems::Widgets::Notes | Types::WorkItems::Widgets::NotesType + WorkItems::Widgets::Description | Types::WorkItems::Widgets::DescriptionType + WorkItems::Widgets::Hierarchy | Types::WorkItems::Widgets::HierarchyType + WorkItems::Widgets::Assignees | Types::WorkItems::Widgets::AssigneesType + WorkItems::Widgets::Labels | Types::WorkItems::Widgets::LabelsType + WorkItems::Widgets::Notes | Types::WorkItems::Widgets::NotesType + WorkItems::Widgets::Notifications | Types::WorkItems::Widgets::NotificationsType end with_them do diff --git a/spec/graphql/types/work_items/widgets/notifications_type_spec.rb b/spec/graphql/types/work_items/widgets/notifications_type_spec.rb new file mode 100644 index 00000000000..4f457a24710 --- /dev/null +++ b/spec/graphql/types/work_items/widgets/notifications_type_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Types::WorkItems::Widgets::NotificationsType, feature_category: :team_planning do + it 'exposes the expected fields' do + expected_fields = %i[subscribed type] + + expect(described_class.graphql_name).to eq('WorkItemWidgetNotifications') + expect(described_class).to have_graphql_fields(*expected_fields) + end +end diff --git a/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb b/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb index a5031ff6a82..dd04d63bcc0 100644 --- a/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb @@ -107,6 +107,22 @@ RSpec.describe Sidebars::Projects::Menus::InfrastructureMenu, feature_category: let(:item_id) { :terraform } it_behaves_like 'access rights checks' + + context 'if terraform_state.enabled=true' do + before do + stub_config(terraform_state: { enabled: true }) + end + + it_behaves_like 'access rights checks' + end + + context 'if terraform_state.enabled=false' do + before do + stub_config(terraform_state: { enabled: false }) + end + + it { is_expected.to be_nil } + end end describe 'Google Cloud' do diff --git a/spec/migrations/20230228142350_add_notifications_work_item_widget_spec.rb b/spec/migrations/20230228142350_add_notifications_work_item_widget_spec.rb new file mode 100644 index 00000000000..065b6d00ddb --- /dev/null +++ b/spec/migrations/20230228142350_add_notifications_work_item_widget_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe AddNotificationsWorkItemWidget, :migration, feature_category: :team_planning do + let(:migration) { described_class.new } + let(:work_item_definitions) { table(:work_item_widget_definitions) } + + describe '#up' do + it 'creates notifications widget definition in all types' do + work_item_definitions.where(name: 'Notifications').delete_all + + expect { migrate! }.to change { work_item_definitions.count }.by(7) + expect(work_item_definitions.all.pluck(:name)).to include('Notifications') + end + end + + describe '#down' do + it 'removes definitions for notifications widget' do + migrate! + + expect { migration.down }.to change { work_item_definitions.count }.by(-7) + expect(work_item_definitions.all.pluck(:name)).not_to include('Notifications') + end + end +end diff --git a/spec/models/concerns/subscribable_spec.rb b/spec/models/concerns/subscribable_spec.rb index a60a0a5e26d..80060802de8 100644 --- a/spec/models/concerns/subscribable_spec.rb +++ b/spec/models/concerns/subscribable_spec.rb @@ -215,5 +215,31 @@ RSpec.describe Subscribable, 'Subscribable' do expect(lazy_queries.count).to eq(0) expect(preloaded_queries.count).to eq(1) end + + context 'with work items' do + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project) } + let_it_be(:work_item) { create(:work_item, :task, project: project) } + let_it_be(:issue) { create(:issue, project: project) } + + before do + [issue, work_item].each do |item| + create(:subscription, user: user, subscribable: item, subscribed: true, project: project) + end + end + + it 'loads correct subscribable type' do + expect(issue).to receive(:subscribable_type).and_return('Issue') + issue.lazy_subscription(user, project) + + expect(work_item).to receive(:subscribable_type).and_return('Issue') + work_item.lazy_subscription(user, project) + end + + it 'matches existing subscription type' do + expect(issue.subscribed?(user, project)).to eq(true) + expect(work_item.subscribed?(user, project)).to eq(true) + end + end end end diff --git a/spec/models/work_items/widget_definition_spec.rb b/spec/models/work_items/widget_definition_spec.rb index 08f8f4d9663..3a4670c996f 100644 --- a/spec/models/work_items/widget_definition_spec.rb +++ b/spec/models/work_items/widget_definition_spec.rb @@ -11,7 +11,8 @@ RSpec.describe WorkItems::WidgetDefinition, feature_category: :team_planning do ::WorkItems::Widgets::Assignees, ::WorkItems::Widgets::StartAndDueDate, ::WorkItems::Widgets::Milestone, - ::WorkItems::Widgets::Notes + ::WorkItems::Widgets::Notes, + ::WorkItems::Widgets::Notifications ] if Gitlab.ee? diff --git a/spec/models/work_items/widgets/notifications_spec.rb b/spec/models/work_items/widgets/notifications_spec.rb new file mode 100644 index 00000000000..2942c149660 --- /dev/null +++ b/spec/models/work_items/widgets/notifications_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe WorkItems::Widgets::Notifications, feature_category: :team_planning do + let_it_be(:work_item) { create(:work_item) } + + describe '.type' do + it { expect(described_class.type).to eq(:notifications) } + end + + describe '#type' do + it { expect(described_class.new(work_item).type).to eq(:notifications) } + end + + describe '#subscribed?' do + it { expect(described_class.new(work_item).subscribed?(work_item.author, work_item.project)).to eq(true) } + end +end diff --git a/spec/policies/metrics/dashboard/annotation_policy_spec.rb b/spec/policies/metrics/dashboard/annotation_policy_spec.rb index 9ea9f843f2c..2d1ef0ee0cb 100644 --- a/spec/policies/metrics/dashboard/annotation_policy_spec.rb +++ b/spec/policies/metrics/dashboard/annotation_policy_spec.rb @@ -14,9 +14,7 @@ RSpec.describe Metrics::Dashboard::AnnotationPolicy, :models do end it { expect(policy).to be_disallowed :read_metrics_dashboard_annotation } - it { expect(policy).to be_disallowed :create_metrics_dashboard_annotation } - it { expect(policy).to be_disallowed :update_metrics_dashboard_annotation } - it { expect(policy).to be_disallowed :delete_metrics_dashboard_annotation } + it { expect(policy).to be_disallowed :admin_metrics_dashboard_annotation } end context 'when reporter' do @@ -25,9 +23,7 @@ RSpec.describe Metrics::Dashboard::AnnotationPolicy, :models do end it { expect(policy).to be_allowed :read_metrics_dashboard_annotation } - it { expect(policy).to be_disallowed :create_metrics_dashboard_annotation } - it { expect(policy).to be_disallowed :update_metrics_dashboard_annotation } - it { expect(policy).to be_disallowed :delete_metrics_dashboard_annotation } + it { expect(policy).to be_disallowed :admin_metrics_dashboard_annotation } end context 'when developer' do @@ -36,9 +32,7 @@ RSpec.describe Metrics::Dashboard::AnnotationPolicy, :models do end it { expect(policy).to be_allowed :read_metrics_dashboard_annotation } - it { expect(policy).to be_allowed :create_metrics_dashboard_annotation } - it { expect(policy).to be_allowed :update_metrics_dashboard_annotation } - it { expect(policy).to be_allowed :delete_metrics_dashboard_annotation } + it { expect(policy).to be_allowed :admin_metrics_dashboard_annotation } end context 'when maintainer' do @@ -47,9 +41,7 @@ RSpec.describe Metrics::Dashboard::AnnotationPolicy, :models do end it { expect(policy).to be_allowed :read_metrics_dashboard_annotation } - it { expect(policy).to be_allowed :create_metrics_dashboard_annotation } - it { expect(policy).to be_allowed :update_metrics_dashboard_annotation } - it { expect(policy).to be_allowed :delete_metrics_dashboard_annotation } + it { expect(policy).to be_allowed :admin_metrics_dashboard_annotation } end end diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index e7b548b8f3b..38c487f3c36 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -2275,6 +2275,12 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do describe 'infrastructure feature' do using RSpec::Parameterized::TableSyntax + before do + # assuming the default setting terraform_state.enabled=true + # the terraform_state permissions should follow the same logic as the other features + stub_config(terraform_state: { enabled: true }) + end + let(:guest_permissions) { [] } let(:developer_permissions) do @@ -2338,6 +2344,31 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end end end + + context 'when terraform state management is disabled' do + before do + stub_config(terraform_state: { enabled: false }) + end + + with_them do + let(:current_user) { user_subject(role) } + let(:project) { project_subject(project_visibility) } + + let(:developer_permissions) do + [:read_terraform_state] + end + + let(:maintainer_permissions) do + developer_permissions + [:admin_terraform_state] + end + + it 'always disallows the terraform_state feature' do + project.project_feature.update!(infrastructure_access_level: access_level) + + expect_disallowed(*permissions_abilities(role)) + end + end + end end describe 'access_security_and_compliance' do diff --git a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb index bce57b47aab..3c7f4a030f9 100644 --- a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb +++ b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb @@ -19,7 +19,7 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Create, feature_categ graphql_mutation_response(:create_annotation) end - specify { expect(described_class).to require_graphql_authorizations(:create_metrics_dashboard_annotation) } + specify { expect(described_class).to require_graphql_authorizations(:admin_metrics_dashboard_annotation) } context 'when annotation source is environment' do let(:mutation) do diff --git a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb index f505dc25dc0..c104138b725 100644 --- a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb +++ b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb @@ -17,7 +17,7 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Delete, feature_categ graphql_mutation_response(:delete_annotation) end - specify { expect(described_class).to require_graphql_authorizations(:delete_metrics_dashboard_annotation) } + specify { expect(described_class).to require_graphql_authorizations(:admin_metrics_dashboard_annotation) } context 'when the user has permission to delete the annotation' do before do diff --git a/spec/requests/api/graphql/project/work_items_spec.rb b/spec/requests/api/graphql/project/work_items_spec.rb index f49165a88ea..d5dd12de63e 100644 --- a/spec/requests/api/graphql/project/work_items_spec.rb +++ b/spec/requests/api/graphql/project/work_items_spec.rb @@ -313,6 +313,34 @@ RSpec.describe 'getting a work item list for a project', feature_category: :team end end + context 'when fetching work item notifications widget' do + let(:fields) do + <<~GRAPHQL + nodes { + widgets { + type + ... on WorkItemWidgetNotifications { + subscribed + } + } + } + GRAPHQL + end + + it 'executes limited number of N+1 queries', :use_sql_query_cache do + control = ActiveRecord::QueryRecorder.new(skip_cached: false) do + post_graphql(query, current_user: current_user) + end + + create_list(:work_item, 3, project: project) + + # Performs 1 extra query per item to fetch subscriptions + expect { post_graphql(query, current_user: current_user) } + .not_to exceed_all_query_limit(control).with_threshold(3) + expect_graphql_errors_to_be_empty + end + end + def item_ids graphql_dig_at(items_data, :node, :id) end diff --git a/spec/requests/api/graphql/work_item_spec.rb b/spec/requests/api/graphql/work_item_spec.rb index 0fad4f4ff3a..24c72a8bb00 100644 --- a/spec/requests/api/graphql/work_item_spec.rb +++ b/spec/requests/api/graphql/work_item_spec.rb @@ -373,6 +373,32 @@ RSpec.describe 'Query.work_item(id)', feature_category: :team_planning do ) end end + + describe 'notifications widget' do + let(:work_item_fields) do + <<~GRAPHQL + id + widgets { + type + ... on WorkItemWidgetNotifications { + subscribed + } + } + GRAPHQL + end + + it 'returns widget information' do + expect(work_item_data).to include( + 'id' => work_item.to_gid.to_s, + 'widgets' => include( + hash_including( + 'type' => 'NOTIFICATIONS', + 'subscribed' => work_item.subscribed?(current_user, project) + ) + ) + ) + end + end end context 'when an Issue Global ID is provided' do diff --git a/spec/requests/api/terraform/state_spec.rb b/spec/requests/api/terraform/state_spec.rb index 7784985f7f4..c94643242c9 100644 --- a/spec/requests/api/terraform/state_spec.rb +++ b/spec/requests/api/terraform/state_spec.rb @@ -21,6 +21,7 @@ RSpec.describe API::Terraform::State, :snowplow, feature_category: :infrastructu before do stub_terraform_state_object_storage + stub_config(terraform_state: { enabled: true }) end shared_examples 'endpoint with unique user tracking' do @@ -81,6 +82,7 @@ RSpec.describe API::Terraform::State, :snowplow, feature_category: :infrastructu subject(:request) { get api(state_path), headers: auth_header } it_behaves_like 'endpoint with unique user tracking' + it_behaves_like 'it depends on value of the `terraform_state.enabled` config' context 'without authentication' do let(:auth_header) { basic_auth_header('bad', 'token') } @@ -193,6 +195,7 @@ RSpec.describe API::Terraform::State, :snowplow, feature_category: :infrastructu subject(:request) { post api(state_path), headers: auth_header, as: :json, params: params } it_behaves_like 'endpoint with unique user tracking' + it_behaves_like 'it depends on value of the `terraform_state.enabled` config' context 'when terraform state with a given name is already present' do context 'with maintainer permissions' do @@ -371,6 +374,7 @@ RSpec.describe API::Terraform::State, :snowplow, feature_category: :infrastructu subject(:request) { delete api(state_path), headers: auth_header } it_behaves_like 'endpoint with unique user tracking' + it_behaves_like 'it depends on value of the `terraform_state.enabled` config' shared_examples 'schedules the state for deletion' do it 'returns empty body' do @@ -552,6 +556,10 @@ RSpec.describe API::Terraform::State, :snowplow, feature_category: :infrastructu let(:lock_id) { 'irrelevant to this test, just needs to be present' } end + it_behaves_like 'it depends on value of the `terraform_state.enabled` config' do + let(:lock_id) { '123.456' } + end + where(given_state_name: %w[test-state test.state test%2Ffoo]) with_them do let(:state_name) { given_state_name } diff --git a/spec/requests/api/terraform/state_version_spec.rb b/spec/requests/api/terraform/state_version_spec.rb index 28abbb5749d..24b3ca94581 100644 --- a/spec/requests/api/terraform/state_version_spec.rb +++ b/spec/requests/api/terraform/state_version_spec.rb @@ -22,9 +22,15 @@ RSpec.describe API::Terraform::StateVersion, feature_category: :infrastructure_a let(:version_serial) { version.version } let(:state_version_path) { "/projects/#{project_id}/terraform/state/#{state_name}/versions/#{version_serial}" } + before do + stub_config(terraform_state: { enabled: true }) + end + describe 'GET /projects/:id/terraform/state/:name/versions/:serial' do subject(:request) { get api(state_version_path), headers: auth_header } + it_behaves_like 'it depends on value of the `terraform_state.enabled` config' + context 'with invalid authentication' do let(:auth_header) { basic_auth_header('bad', 'token') } @@ -147,6 +153,8 @@ RSpec.describe API::Terraform::StateVersion, feature_category: :infrastructure_a describe 'DELETE /projects/:id/terraform/state/:name/versions/:serial' do subject(:request) { delete api(state_version_path), headers: auth_header } + it_behaves_like 'it depends on value of the `terraform_state.enabled` config', { success_status: :no_content } + context 'with invalid authentication' do let(:auth_header) { basic_auth_header('bad', 'token') } diff --git a/spec/support/shared_contexts/policies/group_policy_shared_context.rb b/spec/support/shared_contexts/policies/group_policy_shared_context.rb index ccfd403bebd..a9b12d47393 100644 --- a/spec/support/shared_contexts/policies/group_policy_shared_context.rb +++ b/spec/support/shared_contexts/policies/group_policy_shared_context.rb @@ -42,9 +42,7 @@ RSpec.shared_context 'GroupPolicy context' do let(:developer_permissions) do %i[ - create_metrics_dashboard_annotation - delete_metrics_dashboard_annotation - update_metrics_dashboard_annotation + admin_metrics_dashboard_annotation create_custom_emoji create_package read_cluster diff --git a/spec/support/shared_contexts/policies/project_policy_shared_context.rb b/spec/support/shared_contexts/policies/project_policy_shared_context.rb index afc7fc8766f..71244933702 100644 --- a/spec/support/shared_contexts/policies/project_policy_shared_context.rb +++ b/spec/support/shared_contexts/policies/project_policy_shared_context.rb @@ -52,12 +52,11 @@ RSpec.shared_context 'ProjectPolicy context' do admin_merge_request admin_tag create_build create_commit_status create_container_image create_deployment create_environment create_merge_request_from - create_metrics_dashboard_annotation create_pipeline create_release - create_wiki delete_metrics_dashboard_annotation - destroy_container_image push_code read_pod_logs read_terraform_state - resolve_note update_build update_commit_status update_container_image - update_deployment update_environment update_merge_request - update_metrics_dashboard_annotation update_pipeline update_release destroy_release + admin_metrics_dashboard_annotation create_pipeline create_release + create_wiki destroy_container_image push_code read_pod_logs + read_terraform_state resolve_note update_build update_commit_status + update_container_image update_deployment update_environment + update_merge_request update_pipeline update_release destroy_release read_resource_group update_resource_group update_escalation_status ] end diff --git a/spec/support/shared_contexts/rack_attack_shared_context.rb b/spec/support/shared_contexts/rack_attack_shared_context.rb index 12625ead72b..4e8c6e9dec6 100644 --- a/spec/support/shared_contexts/rack_attack_shared_context.rb +++ b/spec/support/shared_contexts/rack_attack_shared_context.rb @@ -5,8 +5,7 @@ RSpec.shared_context 'rack attack cache store' do # Instead of test environment's :null_store so the throttles can increment Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new - # Make time-dependent tests deterministic - freeze_time { example.run } + example.run Rack::Attack.cache.store = Rails.cache end diff --git a/spec/support/shared_examples/lib/api/terraform_state_enabled_shared_examples.rb b/spec/support/shared_examples/lib/api/terraform_state_enabled_shared_examples.rb new file mode 100644 index 00000000000..b88eade7db2 --- /dev/null +++ b/spec/support/shared_examples/lib/api/terraform_state_enabled_shared_examples.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'it depends on value of the `terraform_state.enabled` config' do |params = {}| + let(:expected_success_status) { params[:success_status] || :ok } + + context 'when terraform_state.enabled=false' do + before do + stub_config(terraform_state: { enabled: false }) + end + + it 'returns `forbidden` response' do + request + + expect(response).to have_gitlab_http_status(:forbidden) + end + end + + context 'when terraform_state.enabled=true' do + before do + stub_config(terraform_state: { enabled: true }) + end + + it 'returns a successful response' do + request + + expect(response).to have_gitlab_http_status(expected_success_status) + end + end +end |