diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-09-08 21:10:47 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-09-08 21:10:47 +0300 |
commit | 03a8aa2ca6a7d7aced2fde7815c8ef85d681db60 (patch) | |
tree | 915b00839e8f0ae30f1c6756880f3ed4339d74c4 /spec | |
parent | f8c7f38d02ebf964cbf40d9445f0f9f843710701 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
26 files changed, 280 insertions, 147 deletions
diff --git a/spec/controllers/admin/cohorts_controller_spec.rb b/spec/controllers/admin/cohorts_controller_spec.rb index d271276a3e4..766073977c6 100644 --- a/spec/controllers/admin/cohorts_controller_spec.rb +++ b/spec/controllers/admin/cohorts_controller_spec.rb @@ -13,5 +13,17 @@ RSpec.describe Admin::CohortsController do it_behaves_like 'tracking unique visits', :index do let(:target_id) { 'i_analytics_cohorts' } end + + it_behaves_like 'Snowplow event tracking' do + subject { get :index } + + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:category) { described_class.name } + let(:action) { 'perform_analytics_usage_action' } + let(:label) { 'redis_hll_counters.analytics.analytics_total_unique_counts_monthly' } + let(:property) { 'i_analytics_cohorts' } + let(:namespace) { nil } + let(:project) { nil } + end end end diff --git a/spec/controllers/projects/settings/integration_hook_logs_controller_spec.rb b/spec/controllers/projects/settings/integration_hook_logs_controller_spec.rb index 8261461e8aa..9569fe22b1f 100644 --- a/spec/controllers/projects/settings/integration_hook_logs_controller_spec.rb +++ b/spec/controllers/projects/settings/integration_hook_logs_controller_spec.rb @@ -5,7 +5,8 @@ require 'spec_helper' RSpec.describe Projects::Settings::IntegrationHookLogsController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } - let(:integration) { create(:drone_ci_integration, project: project) } + let(:service_hook) { create(:service_hook) } + let(:integration) { create(:drone_ci_integration, project: project, service_hook: service_hook) } let(:log) { create(:web_hook_log, web_hook: integration.service_hook) } let(:log_params) do { diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb index 1d3effd4a2a..c2a0e528ea7 100644 --- a/spec/features/merge_request/user_sees_merge_widget_spec.rb +++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb @@ -219,7 +219,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do shared_examples 'pipeline widget' do it 'shows head pipeline information', :sidekiq_might_not_need_inline do within '.ci-widget-content' do - expect(page).to have_content("Detached merge request pipeline ##{pipeline.id} pending for #{pipeline.short_sha}") + expect(page).to have_content("Merge request pipeline ##{pipeline.id} pending for #{pipeline.short_sha}") end end end diff --git a/spec/features/projects/pipelines/legacy_pipeline_spec.rb b/spec/features/projects/pipelines/legacy_pipeline_spec.rb index f36fe1c778c..250a336469c 100644 --- a/spec/features/projects/pipelines/legacy_pipeline_spec.rb +++ b/spec/features/projects/pipelines/legacy_pipeline_spec.rb @@ -73,9 +73,9 @@ RSpec.describe 'Pipeline', :js do visit_pipeline expect(page).to have_selector('.js-pipeline-graph') - expect(page).to have_content('Build') - expect(page).to have_content('Test') - expect(page).to have_content('Deploy') + expect(page).to have_content('build') + expect(page).to have_content('test') + expect(page).to have_content('deploy') expect(page).to have_content('Retry') expect(page).to have_content('Cancel running') end @@ -668,9 +668,9 @@ RSpec.describe 'Pipeline', :js do it 'shows the pipeline graph' do expect(page).to have_selector('.js-pipeline-graph') - expect(page).to have_content('Build') - expect(page).to have_content('Test') - expect(page).to have_content('Deploy') + expect(page).to have_content('build') + expect(page).to have_content('test') + expect(page).to have_content('deploy') expect(page).to have_content('Retry') expect(page).to have_content('Cancel running') end diff --git a/spec/features/projects/pipelines/legacy_pipelines_spec.rb b/spec/features/projects/pipelines/legacy_pipelines_spec.rb index 2b3a6569c56..2e0ea695ab3 100644 --- a/spec/features/projects/pipelines/legacy_pipelines_spec.rb +++ b/spec/features/projects/pipelines/legacy_pipelines_spec.rb @@ -652,10 +652,10 @@ RSpec.describe 'Pipelines', :js do expect(page).to have_link(pipeline.user.name, href: user_path(pipeline.user)) # stages - expect(page).to have_text('Build') - expect(page).to have_text('Test') - expect(page).to have_text('Deploy') - expect(page).to have_text('External') + expect(page).to have_text('build') + expect(page).to have_text('test') + expect(page).to have_text('deploy') + expect(page).to have_text('external') # builds expect(page).to have_text('rspec') diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index a8b582ba486..51a6fbc4d36 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -72,9 +72,9 @@ RSpec.describe 'Pipeline', :js do visit_pipeline expect(page).to have_selector('.js-pipeline-graph') - expect(page).to have_content('Build') - expect(page).to have_content('Test') - expect(page).to have_content('Deploy') + expect(page).to have_content('build') + expect(page).to have_content('test') + expect(page).to have_content('deploy') expect(page).to have_content('Retry') expect(page).to have_content('Cancel running') end @@ -793,9 +793,9 @@ RSpec.describe 'Pipeline', :js do it 'shows the pipeline graph' do expect(page).to have_selector('.js-pipeline-graph') - expect(page).to have_content('Build') - expect(page).to have_content('Test') - expect(page).to have_content('Deploy') + expect(page).to have_content('build') + expect(page).to have_content('test') + expect(page).to have_content('deploy') expect(page).to have_content('Retry') expect(page).to have_content('Cancel running') end diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index d5705d1da04..404e51048bc 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -635,10 +635,10 @@ RSpec.describe 'Pipelines', :js do expect(page).to have_link(pipeline.user.name, href: user_path(pipeline.user)) # stages - expect(page).to have_text('Build') - expect(page).to have_text('Test') - expect(page).to have_text('Deploy') - expect(page).to have_text('External') + expect(page).to have_text('build') + expect(page).to have_text('test') + expect(page).to have_text('deploy') + expect(page).to have_text('external') # builds expect(page).to have_text('rspec') diff --git a/spec/frontend/content_editor/remark_markdown_processing_spec.js b/spec/frontend/content_editor/remark_markdown_processing_spec.js index 61a6fd0debe..bc43af9bd8b 100644 --- a/spec/frontend/content_editor/remark_markdown_processing_spec.js +++ b/spec/frontend/content_editor/remark_markdown_processing_spec.js @@ -23,6 +23,7 @@ import Sourcemap from '~/content_editor/extensions/sourcemap'; import Strike from '~/content_editor/extensions/strike'; import Table from '~/content_editor/extensions/table'; import TableHeader from '~/content_editor/extensions/table_header'; +import TableOfContents from '~/content_editor/extensions/table_of_contents'; import TableRow from '~/content_editor/extensions/table_row'; import TableCell from '~/content_editor/extensions/table_cell'; import TaskList from '~/content_editor/extensions/task_list'; @@ -61,6 +62,7 @@ const tiptapEditor = createTestEditor({ TableRow, TableHeader, TableCell, + TableOfContents, TaskList, TaskItem, Video, @@ -98,6 +100,7 @@ const { tableRow, tableHeader, tableCell, + tableOfContents, taskItem, taskList, video, @@ -130,6 +133,7 @@ const { tableCell: { nodeType: TableCell.name }, tableHeader: { nodeType: TableHeader.name }, tableRow: { nodeType: TableRow.name }, + tableOfContents: { nodeType: TableOfContents.name }, taskItem: { nodeType: TaskItem.name }, taskList: { nodeType: TaskList.name }, video: { nodeType: Video.name }, @@ -1294,6 +1298,14 @@ content expectedDoc: doc(diagram({ ...source(markdown), language }, 'content')), }; }), + { + markdown: '[[_TOC_]]', + expectedDoc: doc(tableOfContents(source('[[_TOC_]]'))), + }, + { + markdown: '[TOC]', + expectedDoc: doc(tableOfContents(source('[TOC]'))), + }, ]; const runOnly = examples.find((example) => example.only === true); diff --git a/spec/frontend/content_editor/render_html_and_json_for_all_examples.js b/spec/frontend/content_editor/render_html_and_json_for_all_examples.js index fc88c0ea445..bd48b7fdd23 100644 --- a/spec/frontend/content_editor/render_html_and_json_for_all_examples.js +++ b/spec/frontend/content_editor/render_html_and_json_for_all_examples.js @@ -34,6 +34,7 @@ import Table from '~/content_editor/extensions/table'; import TableCell from '~/content_editor/extensions/table_cell'; import TableHeader from '~/content_editor/extensions/table_header'; import TableRow from '~/content_editor/extensions/table_row'; +import TableOfContents from '~/content_editor/extensions/table_of_contents'; import TaskItem from '~/content_editor/extensions/task_item'; import TaskList from '~/content_editor/extensions/task_list'; import Video from '~/content_editor/extensions/video'; @@ -75,6 +76,7 @@ const tiptapEditor = createTestEditor({ TableCell, TableHeader, TableRow, + TableOfContents, TaskItem, TaskList, Video, diff --git a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js index 34784a88ba9..454b3814d8c 100644 --- a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js +++ b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js @@ -299,7 +299,7 @@ describe('Pipeline graph wrapper', () => { const groupsInFirstColumn = mockPipelineResponse.data.project.pipeline.stages.nodes[0].groups.nodes.length; expect(getAllStageColumnGroupsInColumn()).toHaveLength(groupsInFirstColumn); - expect(getStageColumnTitle().text()).toBe('Build'); + expect(getStageColumnTitle().text()).toBe('build'); await getViewSelector().vm.$emit('updateViewType', LAYER_VIEW); expect(getAllStageColumnGroupsInColumn()).toHaveLength(groupsInFirstColumn + 1); expect(getStageColumnTitle().text()).toBe(''); diff --git a/spec/frontend/pipelines/graph/stage_column_component_spec.js b/spec/frontend/pipelines/graph/stage_column_component_spec.js index 99e8ea9d0a4..b081258edc0 100644 --- a/spec/frontend/pipelines/graph/stage_column_component_spec.js +++ b/spec/frontend/pipelines/graph/stage_column_component_spec.js @@ -126,9 +126,9 @@ describe('stage column component', () => { }); }); - it('capitalizes and escapes name', () => { - expect(findStageColumnTitle().text()).toBe( - 'Test <img src=x onerror=alert(document.domain)>', + it('escapes name', () => { + expect(findStageColumnTitle().html()).toContain( + 'test <img src=x onerror=alert(document.domain)>', ); }); diff --git a/spec/frontend/runner/components/runner_projects_spec.js b/spec/frontend/runner/components/runner_projects_spec.js index c988fb8477d..eca042cae86 100644 --- a/spec/frontend/runner/components/runner_projects_spec.js +++ b/spec/frontend/runner/components/runner_projects_spec.js @@ -1,4 +1,4 @@ -import { GlSkeletonLoader } from '@gitlab/ui'; +import { GlSearchBoxByType, GlSkeletonLoader } from '@gitlab/ui'; import Vue from 'vue'; import VueApollo from 'vue-apollo'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; @@ -8,7 +8,9 @@ import { createAlert } from '~/flash'; import { sprintf } from '~/locale'; import { I18N_ASSIGNED_PROJECTS, - I18N_NONE, + I18N_CLEAR_FILTER_PROJECTS, + I18N_FILTER_PROJECTS, + I18N_NO_PROJECTS_FOUND, RUNNER_DETAILS_PROJECTS_PAGE_SIZE, } from '~/runner/constants'; import RunnerProjects from '~/runner/components/runner_projects.vue'; @@ -35,6 +37,7 @@ describe('RunnerProjects', () => { const findHeading = () => wrapper.find('h3'); const findGlSkeletonLoading = () => wrapper.findComponent(GlSkeletonLoader); + const findGlSearchBoxByType = () => wrapper.findComponent(GlSearchBoxByType); const findRunnerAssignedItems = () => wrapper.findAllComponents(RunnerAssignedItem); const findRunnerPagination = () => wrapper.findComponent(RunnerPagination); @@ -64,10 +67,21 @@ describe('RunnerProjects', () => { expect(mockRunnerProjectsQuery).toHaveBeenCalledTimes(1); expect(mockRunnerProjectsQuery).toHaveBeenCalledWith({ id: mockRunner.id, + search: '', first: RUNNER_DETAILS_PROJECTS_PAGE_SIZE, }); }); + it('Shows a filter box', () => { + createComponent(); + + expect(findGlSearchBoxByType().attributes()).toMatchObject({ + clearbuttontitle: I18N_CLEAR_FILTER_PROJECTS, + debounce: '500', + placeholder: I18N_FILTER_PROJECTS, + }); + }); + describe('When there are projects assigned', () => { beforeEach(async () => { mockRunnerProjectsQuery.mockResolvedValueOnce(runnerProjectsData); @@ -110,6 +124,7 @@ describe('RunnerProjects', () => { expect(mockRunnerProjectsQuery).toHaveBeenCalledTimes(2); expect(mockRunnerProjectsQuery).toHaveBeenLastCalledWith({ id: mockRunner.id, + search: '', first: RUNNER_DETAILS_PROJECTS_PAGE_SIZE, after: 'AFTER_CURSOR', }); @@ -123,10 +138,51 @@ describe('RunnerProjects', () => { expect(mockRunnerProjectsQuery).toHaveBeenCalledTimes(3); expect(mockRunnerProjectsQuery).toHaveBeenLastCalledWith({ id: mockRunner.id, + search: '', last: RUNNER_DETAILS_PROJECTS_PAGE_SIZE, before: 'BEFORE_CURSOR', }); }); + + it('When user filters after paginating, the first page is requested', async () => { + findGlSearchBoxByType().vm.$emit('input', 'my search'); + await waitForPromises(); + + expect(mockRunnerProjectsQuery).toHaveBeenCalledTimes(3); + expect(mockRunnerProjectsQuery).toHaveBeenLastCalledWith({ + id: mockRunner.id, + search: 'my search', + first: RUNNER_DETAILS_PROJECTS_PAGE_SIZE, + }); + }); + }); + + describe('When user filters', () => { + it('Filtered results are requested', async () => { + expect(mockRunnerProjectsQuery).toHaveBeenCalledTimes(1); + + findGlSearchBoxByType().vm.$emit('input', 'my search'); + await waitForPromises(); + + expect(mockRunnerProjectsQuery).toHaveBeenCalledTimes(2); + expect(mockRunnerProjectsQuery).toHaveBeenLastCalledWith({ + id: mockRunner.id, + search: 'my search', + first: RUNNER_DETAILS_PROJECTS_PAGE_SIZE, + }); + }); + + it('Filtered results are not requested for short searches', async () => { + expect(mockRunnerProjectsQuery).toHaveBeenCalledTimes(1); + + findGlSearchBoxByType().vm.$emit('input', 'm'); + await waitForPromises(); + + findGlSearchBoxByType().vm.$emit('input', 'my'); + await waitForPromises(); + + expect(mockRunnerProjectsQuery).toHaveBeenCalledTimes(1); + }); }); }); @@ -136,10 +192,11 @@ describe('RunnerProjects', () => { expect(findGlSkeletonLoading().exists()).toBe(true); - expect(wrapper.findByText(I18N_NONE).exists()).toBe(false); + expect(wrapper.findByText(I18N_NO_PROJECTS_FOUND).exists()).toBe(false); expect(findRunnerAssignedItems().length).toBe(0); expect(findRunnerPagination().attributes('disabled')).toBe('true'); + expect(findGlSearchBoxByType().props('isLoading')).toBe(true); }); }); @@ -168,7 +225,7 @@ describe('RunnerProjects', () => { }); it('Shows a "None" label', () => { - expect(wrapper.findByText(I18N_NONE).exists()).toBe(true); + expect(wrapper.findByText(I18N_NO_PROJECTS_FOUND).exists()).toBe(true); }); }); diff --git a/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_spec.js index d9bb60e876a..7f0173b7445 100644 --- a/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_spec.js @@ -262,13 +262,13 @@ describe('MRWidgetPipeline', () => { }); describe('for a detached merge request pipeline', () => { - it('renders a pipeline widget that reads "Detached merge request pipeline <ID> <status> for <SHA>"', () => { - pipeline.details.name = 'Detached merge request pipeline'; + it('renders a pipeline widget that reads "Merge request pipeline <ID> <status> for <SHA>"', () => { + pipeline.details.name = 'Merge request pipeline'; pipeline.merge_request_event_type = 'detached'; factory(); - const expected = `Detached merge request pipeline #${pipeline.id} ${pipeline.details.status.label} for ${pipeline.commit.short_id}`; + const expected = `Merge request pipeline #${pipeline.id} ${pipeline.details.status.label} for ${pipeline.commit.short_id}`; const actual = trimText(findPipelineInfoContainer().text()); expect(actual).toBe(expected); diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb index 890ba51157a..b6cb07bf119 100644 --- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb @@ -97,15 +97,15 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do let(:attributes) do { name: 'rspec', ref: 'master', - job_variables: [{ key: 'VAR1', value: 'var 1', public: true }, - { key: 'VAR2', value: 'var 2', public: true }], + job_variables: [{ key: 'VAR1', value: 'var 1' }, + { key: 'VAR2', value: 'var 2' }], rules: [{ if: '$VAR == null', variables: { VAR1: 'new var 1', VAR3: 'var 3' } }] } end it do - is_expected.to include(yaml_variables: [{ key: 'VAR1', value: 'new var 1', public: true }, - { key: 'VAR2', value: 'var 2', public: true }, - { key: 'VAR3', value: 'var 3', public: true }]) + is_expected.to include(yaml_variables: [{ key: 'VAR1', value: 'new var 1' }, + { key: 'VAR2', value: 'var 2' }, + { key: 'VAR3', value: 'var 3' }]) end end @@ -114,13 +114,13 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do { name: 'rspec', ref: 'master', - job_variables: [{ key: 'VARIABLE', value: 'value', public: true }], + job_variables: [{ key: 'VARIABLE', value: 'value' }], tag_list: ['static-tag', '$VARIABLE', '$NO_VARIABLE'] } end it { is_expected.to include(tag_list: ['static-tag', 'value', '$NO_VARIABLE']) } - it { is_expected.to include(yaml_variables: [{ key: 'VARIABLE', value: 'value', public: true }]) } + it { is_expected.to include(yaml_variables: [{ key: 'VARIABLE', value: 'value' }]) } end context 'with cache:key' do @@ -257,19 +257,19 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do let(:attributes) do { name: 'rspec', ref: 'master', - yaml_variables: [{ key: 'VAR2', value: 'var 2', public: true }, - { key: 'VAR3', value: 'var 3', public: true }], - job_variables: [{ key: 'VAR2', value: 'var 2', public: true }, - { key: 'VAR3', value: 'var 3', public: true }], + yaml_variables: [{ key: 'VAR2', value: 'var 2' }, + { key: 'VAR3', value: 'var 3' }], + job_variables: [{ key: 'VAR2', value: 'var 2' }, + { key: 'VAR3', value: 'var 3' }], root_variables_inheritance: root_variables_inheritance } end context 'when the pipeline has variables' do let(:root_variables) do - [{ key: 'VAR1', value: 'var overridden pipeline 1', public: true }, - { key: 'VAR2', value: 'var pipeline 2', public: true }, - { key: 'VAR3', value: 'var pipeline 3', public: true }, - { key: 'VAR4', value: 'new var pipeline 4', public: true }] + [{ key: 'VAR1', value: 'var overridden pipeline 1' }, + { key: 'VAR2', value: 'var pipeline 2' }, + { key: 'VAR3', value: 'var pipeline 3' }, + { key: 'VAR4', value: 'new var pipeline 4' }] end context 'when root_variables_inheritance is true' do @@ -277,10 +277,10 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do it 'returns calculated yaml variables' do expect(subject[:yaml_variables]).to match_array( - [{ key: 'VAR1', value: 'var overridden pipeline 1', public: true }, - { key: 'VAR2', value: 'var 2', public: true }, - { key: 'VAR3', value: 'var 3', public: true }, - { key: 'VAR4', value: 'new var pipeline 4', public: true }] + [{ key: 'VAR1', value: 'var overridden pipeline 1' }, + { key: 'VAR2', value: 'var 2' }, + { key: 'VAR3', value: 'var 3' }, + { key: 'VAR4', value: 'new var pipeline 4' }] ) end end @@ -290,8 +290,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do it 'returns job variables' do expect(subject[:yaml_variables]).to match_array( - [{ key: 'VAR2', value: 'var 2', public: true }, - { key: 'VAR3', value: 'var 3', public: true }] + [{ key: 'VAR2', value: 'var 2' }, + { key: 'VAR3', value: 'var 3' }] ) end end @@ -301,9 +301,9 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do it 'returns calculated yaml variables' do expect(subject[:yaml_variables]).to match_array( - [{ key: 'VAR1', value: 'var overridden pipeline 1', public: true }, - { key: 'VAR2', value: 'var 2', public: true }, - { key: 'VAR3', value: 'var 3', public: true }] + [{ key: 'VAR1', value: 'var overridden pipeline 1' }, + { key: 'VAR2', value: 'var 2' }, + { key: 'VAR3', value: 'var 3' }] ) end end @@ -314,8 +314,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do it 'returns seed yaml variables' do expect(subject[:yaml_variables]).to match_array( - [{ key: 'VAR2', value: 'var 2', public: true }, - { key: 'VAR3', value: 'var 3', public: true }]) + [{ key: 'VAR2', value: 'var 2' }, + { key: 'VAR3', value: 'var 3' }]) end end end @@ -324,8 +324,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do let(:attributes) do { name: 'rspec', ref: 'master', - yaml_variables: [{ key: 'VAR1', value: 'var 1', public: true }], - job_variables: [{ key: 'VAR1', value: 'var 1', public: true }], + yaml_variables: [{ key: 'VAR1', value: 'var 1' }], + job_variables: [{ key: 'VAR1', value: 'var 1' }], root_variables_inheritance: root_variables_inheritance, rules: rules } end @@ -338,14 +338,14 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do end it 'recalculates the variables' do - expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1', public: true }, - { key: 'VAR2', value: 'new var 2', public: true }) + expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1' }, + { key: 'VAR2', value: 'new var 2' }) end end context 'when the rules use root variables' do let(:root_variables) do - [{ key: 'VAR2', value: 'var pipeline 2', public: true }] + [{ key: 'VAR2', value: 'var pipeline 2' }] end let(:rules) do @@ -353,15 +353,15 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do end it 'recalculates the variables' do - expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1', public: true }, - { key: 'VAR2', value: 'overridden var 2', public: true }) + expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1' }, + { key: 'VAR2', value: 'overridden var 2' }) end context 'when the root_variables_inheritance is false' do let(:root_variables_inheritance) { false } it 'does not recalculate the variables' do - expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'var 1', public: true }) + expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'var 1' }) end end end diff --git a/spec/lib/gitlab/ci/variables/helpers_spec.rb b/spec/lib/gitlab/ci/variables/helpers_spec.rb index fc1055751bd..ece456ee2d3 100644 --- a/spec/lib/gitlab/ci/variables/helpers_spec.rb +++ b/spec/lib/gitlab/ci/variables/helpers_spec.rb @@ -15,9 +15,9 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do end let(:result) do - [{ key: 'key1', value: 'value1', public: true }, - { key: 'key2', value: 'value22', public: true }, - { key: 'key3', value: 'value3', public: true }] + [{ key: 'key1', value: 'value1' }, + { key: 'key2', value: 'value22' }, + { key: 'key3', value: 'value3' }] end subject { described_class.merge_variables(current_variables, new_variables) } @@ -43,8 +43,8 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do context 'when new variables is nil' do let(:new_variables) {} let(:result) do - [{ key: 'key1', value: 'value1', public: true }, - { key: 'key2', value: 'value2', public: true }] + [{ key: 'key1', value: 'value1' }, + { key: 'key2', value: 'value2' }] end it { is_expected.to eq(result) } @@ -57,8 +57,8 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do end let(:result) do - [{ key: 'key1', value: 'value1', public: true }, - { key: 'key2', value: 'value2', public: true }] + [{ key: 'key1', value: 'value1' }, + { key: 'key2', value: 'value2' }] end subject { described_class.transform_to_yaml_variables(variables) } @@ -74,8 +74,8 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do describe '.transform_from_yaml_variables' do let(:variables) do - [{ key: 'key1', value: 'value1', public: true }, - { key: 'key2', value: 'value2', public: true }] + [{ key: 'key1', value: 'value1' }, + { key: 'key2', value: 'value2' }] end let(:result) do @@ -127,9 +127,9 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do let(:inheritance) { true } let(:result) do - [{ key: 'key1', value: 'value1', public: true }, - { key: 'key2', value: 'value22', public: true }, - { key: 'key3', value: 'value3', public: true }] + [{ key: 'key1', value: 'value1' }, + { key: 'key2', value: 'value22' }, + { key: 'key3', value: 'value3' }] end subject { described_class.inherit_yaml_variables(from: from, to: to, inheritance: inheritance) } @@ -140,8 +140,8 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do let(:inheritance) { false } let(:result) do - [{ key: 'key2', value: 'value22', public: true }, - { key: 'key3', value: 'value3', public: true }] + [{ key: 'key2', value: 'value22' }, + { key: 'key3', value: 'value3' }] end it { is_expected.to eq(result) } @@ -151,8 +151,8 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do let(:inheritance) { ['key2'] } let(:result) do - [{ key: 'key2', value: 'value22', public: true }, - { key: 'key3', value: 'value3', public: true }] + [{ key: 'key2', value: 'value22' }, + { key: 'key3', value: 'value3' }] end it { is_expected.to eq(result) } diff --git a/spec/lib/gitlab/ci/yaml_processor/result_spec.rb b/spec/lib/gitlab/ci/yaml_processor/result_spec.rb index 8416501e949..f7a0905d9da 100644 --- a/spec/lib/gitlab/ci/yaml_processor/result_spec.rb +++ b/spec/lib/gitlab/ci/yaml_processor/result_spec.rb @@ -72,8 +72,8 @@ module Gitlab it 'returns calculated variables with root and job variables' do is_expected.to match_array([ - { key: 'VAR1', value: 'value 11', public: true }, - { key: 'VAR2', value: 'value 2', public: true } + { key: 'VAR1', value: 'value 11' }, + { key: 'VAR2', value: 'value 2' } ]) end diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb index b68b12d8f43..cc327f5b5f1 100644 --- a/spec/lib/gitlab/ci/yaml_processor_spec.rb +++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb @@ -448,7 +448,7 @@ module Gitlab it 'parses the root:variables as #root_variables' do expect(subject.root_variables) - .to contain_exactly({ key: 'SUPPORTED', value: 'parsed', public: true }) + .to contain_exactly({ key: 'SUPPORTED', value: 'parsed' }) end end @@ -490,7 +490,7 @@ module Gitlab it 'parses the root:variables as #root_variables' do expect(subject.root_variables) - .to contain_exactly({ key: 'SUPPORTED', value: 'parsed', public: true }) + .to contain_exactly({ key: 'SUPPORTED', value: 'parsed' }) end end @@ -1077,8 +1077,8 @@ module Gitlab it 'returns job variables' do expect(job_variables).to contain_exactly( - { key: 'VAR1', value: 'value1', public: true }, - { key: 'VAR2', value: 'value2', public: true } + { key: 'VAR1', value: 'value1' }, + { key: 'VAR2', value: 'value2' } ) expect(root_variables_inheritance).to eq(true) end @@ -1154,9 +1154,9 @@ module Gitlab it 'returns job variables' do expect(job_variables).to contain_exactly( - { key: 'VAR1', value: 'value1', public: true }, - { key: 'VAR2', value: 'value2', public: true }, - { key: 'VAR3', value: '123', public: true } + { key: 'VAR1', value: 'value1' }, + { key: 'VAR2', value: 'value2' }, + { key: 'VAR3', value: '123' } ) expect(root_variables_inheritance).to eq(true) end @@ -1232,21 +1232,21 @@ module Gitlab expect(config_processor.builds[0]).to include( name: 'test1', options: { script: ['test'] }, - job_variables: [{ key: 'VAR1', value: 'test1 var 1', public: true }, - { key: 'VAR2', value: 'test2 var 2', public: true }] + job_variables: [{ key: 'VAR1', value: 'test1 var 1' }, + { key: 'VAR2', value: 'test2 var 2' }] ) expect(config_processor.builds[1]).to include( name: 'test2', options: { script: ['test'] }, - job_variables: [{ key: 'VAR1', value: 'base var 1', public: true }, - { key: 'VAR2', value: 'test2 var 2', public: true }] + job_variables: [{ key: 'VAR1', value: 'base var 1' }, + { key: 'VAR2', value: 'test2 var 2' }] ) expect(config_processor.builds[2]).to include( name: 'test3', options: { script: ['test'] }, - job_variables: [{ key: 'VAR1', value: 'base var 1', public: true }] + job_variables: [{ key: 'VAR1', value: 'base var 1' }] ) expect(config_processor.builds[3]).to include( diff --git a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb index 277276bb1d3..bca549b9574 100644 --- a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb +++ b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb @@ -156,35 +156,84 @@ RSpec.describe Gitlab::GitalyClient::RefService do end describe '#local_branches' do - it 'sends a find_local_branches message' do - expect_any_instance_of(Gitaly::RefService::Stub) - .to receive(:find_local_branches) - .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) - .and_return([]) + let(:remote_name) { 'my_remote' } - client.local_branches - end + shared_examples 'common examples' do + it 'sends a find_local_branches message' do + target_commits = create_list(:gitaly_commit, 4) + branches = target_commits.each_with_index.map do |gitaly_commit, i| + Gitaly::FindLocalBranchResponse.new( + name: "#{remote_name}/#{i}", + commit: gitaly_commit, + commit_author: Gitaly::FindLocalBranchCommitAuthor.new( + name: gitaly_commit.author.name, + email: gitaly_commit.author.email, + date: gitaly_commit.author.date, + timezone: gitaly_commit.author.timezone + ), + commit_committer: Gitaly::FindLocalBranchCommitAuthor.new( + name: gitaly_commit.committer.name, + email: gitaly_commit.committer.email, + date: gitaly_commit.committer.date, + timezone: gitaly_commit.committer.timezone + ) + ) + end + local_branches = target_commits.each_with_index.map do |gitaly_commit, i| + Gitaly::Branch.new(name: "#{remote_name}/#{i}", target_commit: gitaly_commit) + end + response = [ + Gitaly::FindLocalBranchesResponse.new(branches: branches[0, 2], local_branches: local_branches[0, 2]), + Gitaly::FindLocalBranchesResponse.new(branches: branches[2, 2], local_branches: local_branches[2, 2]) + ] - it 'parses and sends the sort parameter' do - expect_any_instance_of(Gitaly::RefService::Stub) - .to receive(:find_local_branches) - .with(gitaly_request_with_params(sort_by: :UPDATED_DESC), kind_of(Hash)) - .and_return([]) + expect_any_instance_of(Gitaly::RefService::Stub) + .to receive(:find_local_branches) + .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) + .and_return(response) + + subject = client.local_branches - client.local_branches(sort_by: 'updated_desc') + expect(subject.length).to be(target_commits.length) + end + + it 'parses and sends the sort parameter' do + expect_any_instance_of(Gitaly::RefService::Stub) + .to receive(:find_local_branches) + .with(gitaly_request_with_params(sort_by: :UPDATED_DESC), kind_of(Hash)) + .and_return([]) + + client.local_branches(sort_by: 'updated_desc') + end + + it 'translates known mismatches on sort param values' do + expect_any_instance_of(Gitaly::RefService::Stub) + .to receive(:find_local_branches) + .with(gitaly_request_with_params(sort_by: :NAME), kind_of(Hash)) + .and_return([]) + + client.local_branches(sort_by: 'name_asc') + end + + it 'raises an argument error if an invalid sort_by parameter is passed' do + expect { client.local_branches(sort_by: 'invalid_sort') }.to raise_error(ArgumentError) + end end - it 'translates known mismatches on sort param values' do - expect_any_instance_of(Gitaly::RefService::Stub) - .to receive(:find_local_branches) - .with(gitaly_request_with_params(sort_by: :NAME), kind_of(Hash)) - .and_return([]) + context 'when feature flag :gitaly_simplify_find_local_branches_response is enabled' do + before do + stub_feature_flags(gitaly_simplify_find_local_branches_response: true) + end - client.local_branches(sort_by: 'name_asc') + it_behaves_like 'common examples' end - it 'raises an argument error if an invalid sort_by parameter is passed' do - expect { client.local_branches(sort_by: 'invalid_sort') }.to raise_error(ArgumentError) + context 'when feature flag :gitaly_simplify_find_local_branches_response is disabled' do + before do + stub_feature_flags(gitaly_simplify_find_local_branches_response: false) + end + + it_behaves_like 'common examples' end end diff --git a/spec/lib/gitlab/web_hooks/rate_limiter_spec.rb b/spec/lib/gitlab/web_hooks/rate_limiter_spec.rb index b25ce4ea9da..3a5864e1832 100644 --- a/spec/lib/gitlab/web_hooks/rate_limiter_spec.rb +++ b/spec/lib/gitlab/web_hooks/rate_limiter_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Gitlab::WebHooks::RateLimiter, :clean_gitlab_redis_rate_limiting let_it_be(:plan) { create(:default_plan) } let_it_be_with_reload(:project_hook) { create(:project_hook) } let_it_be_with_reload(:system_hook) { create(:system_hook) } - let_it_be_with_reload(:integration_hook) { create(:jenkins_integration).service_hook } + let_it_be_with_reload(:integration_hook) { create(:service_hook) } let_it_be(:limit) { 1 } using RSpec::Parameterized::TableSyntax diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 8beb54bca4d..1f53c472c5c 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -167,6 +167,17 @@ RSpec.describe Notify do is_expected.to have_header('X-GitLab-NotificationReason', NotificationReason::ASSIGNED) end end + + context 'when sent with a non default locale' do + let(:email_obj) { create(:email, :confirmed, user_id: recipient.id, email: '123@abc') } + let(:recipient) { create(:user, preferred_language: :zh_CN) } + + it 'is translated into zh_CN' do + recipient.notification_email = email_obj.email + recipient.save! + is_expected.to have_body_text '指派人从 <strong>Previous Assignee</strong> 更改为 <strong>John Doe</strong>' + end + end end describe 'that have been relabeled' do diff --git a/spec/mailers/repository_check_mailer_spec.rb b/spec/mailers/repository_check_mailer_spec.rb index 8b1bc33d8be..5edd9c2d023 100644 --- a/spec/mailers/repository_check_mailer_spec.rb +++ b/spec/mailers/repository_check_mailer_spec.rb @@ -14,6 +14,15 @@ RSpec.describe RepositoryCheckMailer do expect(mail).to deliver_to admins.map(&:email) end + it 'email with I18n.default_locale' do + admins = [create(:admin, preferred_language: :zh_CN), create(:admin, preferred_language: :zh_CN)] + + mail = described_class.notify(3) + + expect(mail).to deliver_to admins.map(&:email) + expect(mail).to have_subject 'GitLab Admin | 3 projects failed their last repository check' + end + it 'omits blocked admins' do blocked = create(:admin, :blocked) admins = create_list(:admin, 3) diff --git a/spec/models/integrations/drone_ci_spec.rb b/spec/models/integrations/drone_ci_spec.rb index 905fee075ad..c43d969eec8 100644 --- a/spec/models/integrations/drone_ci_spec.rb +++ b/spec/models/integrations/drone_ci_spec.rb @@ -115,6 +115,7 @@ RSpec.describe Integrations::DroneCi, :use_clean_rails_memory_store_caching do it_behaves_like Integrations::HasWebHook do include_context :drone_ci_integration + let(:drone_url) { 'https://cloud.drone.io' } let(:integration) { drone } let(:hook_url) { "#{drone_url}/hook?owner=#{project.namespace.full_path}&name=#{project.path}&access_token=#{token}" } diff --git a/spec/presenters/ci/pipeline_presenter_spec.rb b/spec/presenters/ci/pipeline_presenter_spec.rb index a278d4dad83..4539c3d06f6 100644 --- a/spec/presenters/ci/pipeline_presenter_spec.rb +++ b/spec/presenters/ci/pipeline_presenter_spec.rb @@ -100,7 +100,7 @@ RSpec.describe Ci::PipelinePresenter do context 'for a detached merge request pipeline' do let(:event_type) { :detached } - it { is_expected.to eq('Detached merge request pipeline') } + it { is_expected.to eq('Merge request pipeline') } end context 'for a merged result pipeline' do diff --git a/spec/services/ci/create_downstream_pipeline_service_spec.rb b/spec/services/ci/create_downstream_pipeline_service_spec.rb index c990d195e51..e2c42ab04d0 100644 --- a/spec/services/ci/create_downstream_pipeline_service_spec.rb +++ b/spec/services/ci/create_downstream_pipeline_service_spec.rb @@ -5,9 +5,12 @@ require 'spec_helper' RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do include Ci::SourcePipelineHelpers - let_it_be(:user) { create(:user) } + # Using let_it_be on user and projects for these specs can cause + # spec-ordering failures due to the project-based permissions + # associating them. They should be recreated every time. + let(:user) { create(:user) } let(:upstream_project) { create(:project, :repository) } - let_it_be(:downstream_project, refind: true) { create(:project, :repository) } + let(:downstream_project) { create(:project, :repository) } let!(:upstream_pipeline) do create(:ci_pipeline, :running, project: upstream_project) diff --git a/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb b/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb index 49adaf5ef53..513cbbed6cd 100644 --- a/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb +++ b/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb @@ -36,7 +36,7 @@ RSpec.describe Ci::CreatePipelineService, '#execute', :yaml_processor_feature_fl expect(pipeline.statuses).to match_array [test, bridge] expect(bridge.options).to eq(expected_bridge_options) expect(bridge.yaml_variables) - .to include(key: 'CROSS', value: 'downstream', public: true) + .to include(key: 'CROSS', value: 'downstream') end end diff --git a/spec/support/shared_examples/models/integrations/has_web_hook_shared_examples.rb b/spec/support/shared_examples/models/integrations/has_web_hook_shared_examples.rb index 2f693edeb53..64b2dcb8d36 100644 --- a/spec/support/shared_examples/models/integrations/has_web_hook_shared_examples.rb +++ b/spec/support/shared_examples/models/integrations/has_web_hook_shared_examples.rb @@ -7,30 +7,6 @@ RSpec.shared_examples Integrations::HasWebHook do it { is_expected.to have_one(:service_hook).inverse_of(:integration).with_foreign_key(:service_id) } end - describe 'callbacks' do - it 'calls #update_web_hook! when enabled' do - expect(integration).to receive(:update_web_hook!) - - integration.active = true - integration.save! - end - - it 'does not call #update_web_hook! when disabled' do - expect(integration).not_to receive(:update_web_hook!) - - integration.active = false - integration.save! - end - - it 'does not call #update_web_hook! when validation fails' do - expect(integration).not_to receive(:update_web_hook!) - - integration.active = true - integration.project = nil - expect(integration.save).to be(false) - end - end - describe '#hook_url' do it 'returns a string' do expect(integration.hook_url).to be_a(String) |