diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-10-08 15:11:10 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-10-08 15:11:10 +0300 |
commit | af97e4dd4beb0ba1aa0cb3c31df413333cbce77d (patch) | |
tree | 499b6ca6ce2881fe7c0449d680e1c45dbc4e26c0 /spec | |
parent | d4c5231ca2df8cb4aa919c5bfa2dd570de32c0c3 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
38 files changed, 169 insertions, 252 deletions
diff --git a/spec/controllers/every_controller_spec.rb b/spec/controllers/every_controller_spec.rb index 54bbb5dbd01..902872b6e92 100644 --- a/spec/controllers/every_controller_spec.rb +++ b/spec/controllers/every_controller_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe "Every controller" do context "feature categories" do let_it_be(:feature_categories) do - YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).map(&:to_sym).to_set + Gitlab::FeatureCategories.default.categories.map(&:to_sym).to_set end let_it_be(:controller_actions) do diff --git a/spec/features/groups/container_registry_spec.rb b/spec/features/groups/container_registry_spec.rb index 65374263f45..be694374d62 100644 --- a/spec/features/groups/container_registry_spec.rb +++ b/spec/features/groups/container_registry_spec.rb @@ -81,6 +81,7 @@ RSpec.describe 'Container Registry', :js do expect(service).to receive(:execute).with(container_repository) { { status: :success } } expect(Projects::ContainerRepository::DeleteTagsService).to receive(:new).with(container_repository.project, user, tags: ['latest']) { service } + first('[data-testid="additional-actions"]').click first('[data-testid="single-delete-button"]').click expect(find('.modal .modal-title')).to have_content _('Remove tag') find('.modal .modal-footer .btn-danger').click diff --git a/spec/features/projects/container_registry_spec.rb b/spec/features/projects/container_registry_spec.rb index 40d0260eafd..facee24f656 100644 --- a/spec/features/projects/container_registry_spec.rb +++ b/spec/features/projects/container_registry_spec.rb @@ -96,6 +96,7 @@ RSpec.describe 'Container Registry', :js do expect(service).to receive(:execute).with(container_repository) { { status: :success } } expect(Projects::ContainerRepository::DeleteTagsService).to receive(:new).with(container_repository.project, user, tags: ['1']) { service } + first('[data-testid="additional-actions"]').click first('[data-testid="single-delete-button"]').click expect(find('.modal .modal-title')).to have_content _('Remove tag') find('.modal .modal-footer .btn-danger').click diff --git a/spec/frontend/commit/commit_pipeline_status_component_spec.js b/spec/frontend/commit/commit_pipeline_status_component_spec.js index 8082b8524e7..3a549e66eb7 100644 --- a/spec/frontend/commit/commit_pipeline_status_component_spec.js +++ b/spec/frontend/commit/commit_pipeline_status_component_spec.js @@ -1,7 +1,7 @@ import { GlLoadingIcon } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import Visibility from 'visibilityjs'; -import { getJSONFixture } from 'helpers/fixtures'; +import fixture from 'test_fixtures/pipelines/pipelines.json'; import createFlash from '~/flash'; import Poll from '~/lib/utils/poll'; import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue'; @@ -20,7 +20,7 @@ jest.mock('~/projects/tree/services/commit_pipeline_service', () => describe('Commit pipeline status component', () => { let wrapper; - const { pipelines } = getJSONFixture('pipelines/pipelines.json'); + const { pipelines } = fixture; const { status: mockCiStatus } = pipelines[0].details; const defaultProps = { diff --git a/spec/frontend/commit/pipelines/pipelines_table_spec.js b/spec/frontend/commit/pipelines/pipelines_table_spec.js index 1defb3d586c..17f7be9d1d7 100644 --- a/spec/frontend/commit/pipelines/pipelines_table_spec.js +++ b/spec/frontend/commit/pipelines/pipelines_table_spec.js @@ -1,6 +1,7 @@ import { GlEmptyState, GlLoadingIcon, GlModal, GlTable } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; +import fixture from 'test_fixtures/pipelines/pipelines.json'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import Api from '~/api'; @@ -8,7 +9,6 @@ import PipelinesTable from '~/commit/pipelines/pipelines_table.vue'; import axios from '~/lib/utils/axios_utils'; describe('Pipelines table in Commits and Merge requests', () => { - const jsonFixtureName = 'pipelines/pipelines.json'; let wrapper; let pipeline; let mock; @@ -37,7 +37,7 @@ describe('Pipelines table in Commits and Merge requests', () => { beforeEach(() => { mock = new MockAdapter(axios); - const { pipelines } = getJSONFixture(jsonFixtureName); + const { pipelines } = fixture; pipeline = pipelines.find((p) => p.user !== null && p.commit !== null); }); diff --git a/spec/frontend/monitoring/fixture_data.js b/spec/frontend/monitoring/fixture_data.js index d20a111c701..6a19815883a 100644 --- a/spec/frontend/monitoring/fixture_data.js +++ b/spec/frontend/monitoring/fixture_data.js @@ -1,3 +1,4 @@ +import fixture from 'test_fixtures/metrics_dashboard/environment_metrics_dashboard.json'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { metricStates } from '~/monitoring/constants'; import { mapToDashboardViewModel } from '~/monitoring/stores/utils'; @@ -5,10 +6,7 @@ import { stateAndPropsFromDataset } from '~/monitoring/utils'; import { metricsResult } from './mock_data'; -// Use globally available `getJSONFixture` so this file can be imported by both karma and jest specs -export const metricsDashboardResponse = getJSONFixture( - 'metrics_dashboard/environment_metrics_dashboard.json', -); +export const metricsDashboardResponse = fixture; export const metricsDashboardPayload = metricsDashboardResponse.dashboard; diff --git a/spec/frontend/notebook/cells/code_spec.js b/spec/frontend/notebook/cells/code_spec.js index e14767f2594..669bdc2f89a 100644 --- a/spec/frontend/notebook/cells/code_spec.js +++ b/spec/frontend/notebook/cells/code_spec.js @@ -1,14 +1,17 @@ import Vue from 'vue'; +import fixture from 'test_fixtures/blob/notebook/basic.json'; import CodeComponent from '~/notebook/cells/code.vue'; const Component = Vue.extend(CodeComponent); describe('Code component', () => { let vm; + let json; beforeEach(() => { - json = getJSONFixture('blob/notebook/basic.json'); + // Clone fixture as it could be modified by tests + json = JSON.parse(JSON.stringify(fixture)); }); const setupComponent = (cell) => { diff --git a/spec/frontend/notebook/cells/markdown_spec.js b/spec/frontend/notebook/cells/markdown_spec.js index 707efa21528..36b1e91f15f 100644 --- a/spec/frontend/notebook/cells/markdown_spec.js +++ b/spec/frontend/notebook/cells/markdown_spec.js @@ -1,6 +1,9 @@ import { mount } from '@vue/test-utils'; import katex from 'katex'; import Vue from 'vue'; +import markdownTableJson from 'test_fixtures/blob/notebook/markdown-table.json'; +import basicJson from 'test_fixtures/blob/notebook/basic.json'; +import mathJson from 'test_fixtures/blob/notebook/math.json'; import MarkdownComponent from '~/notebook/cells/markdown.vue'; const Component = Vue.extend(MarkdownComponent); @@ -35,7 +38,7 @@ describe('Markdown component', () => { let json; beforeEach(() => { - json = getJSONFixture('blob/notebook/basic.json'); + json = basicJson; // eslint-disable-next-line prefer-destructuring cell = json.cells[1]; @@ -104,7 +107,7 @@ describe('Markdown component', () => { describe('tables', () => { beforeEach(() => { - json = getJSONFixture('blob/notebook/markdown-table.json'); + json = markdownTableJson; }); it('renders images and text', () => { @@ -135,7 +138,7 @@ describe('Markdown component', () => { describe('katex', () => { beforeEach(() => { - json = getJSONFixture('blob/notebook/math.json'); + json = mathJson; }); it('renders multi-line katex', async () => { diff --git a/spec/frontend/notebook/cells/output/index_spec.js b/spec/frontend/notebook/cells/output/index_spec.js index 2985abf0f4f..7ece73d375c 100644 --- a/spec/frontend/notebook/cells/output/index_spec.js +++ b/spec/frontend/notebook/cells/output/index_spec.js @@ -1,11 +1,11 @@ import Vue from 'vue'; +import json from 'test_fixtures/blob/notebook/basic.json'; import CodeComponent from '~/notebook/cells/output/index.vue'; const Component = Vue.extend(CodeComponent); describe('Output component', () => { let vm; - let json; const createComponent = (output) => { vm = new Component({ @@ -17,11 +17,6 @@ describe('Output component', () => { vm.$mount(); }; - beforeEach(() => { - // This is the output after rendering a jupyter notebook - json = getJSONFixture('blob/notebook/basic.json'); - }); - describe('text output', () => { beforeEach((done) => { const textType = json.cells[2]; diff --git a/spec/frontend/notebook/index_spec.js b/spec/frontend/notebook/index_spec.js index 4d0dacaf37e..cd531d628b3 100644 --- a/spec/frontend/notebook/index_spec.js +++ b/spec/frontend/notebook/index_spec.js @@ -1,18 +1,13 @@ import { mount } from '@vue/test-utils'; import Vue from 'vue'; +import json from 'test_fixtures/blob/notebook/basic.json'; +import jsonWithWorksheet from 'test_fixtures/blob/notebook/worksheets.json'; import Notebook from '~/notebook/index.vue'; const Component = Vue.extend(Notebook); describe('Notebook component', () => { let vm; - let json; - let jsonWithWorksheet; - - beforeEach(() => { - json = getJSONFixture('blob/notebook/basic.json'); - jsonWithWorksheet = getJSONFixture('blob/notebook/worksheets.json'); - }); function buildComponent(notebook) { return mount(Component, { diff --git a/spec/frontend/notes/components/diff_with_note_spec.js b/spec/frontend/notes/components/diff_with_note_spec.js index e997fc4da50..c352265654b 100644 --- a/spec/frontend/notes/components/diff_with_note_spec.js +++ b/spec/frontend/notes/components/diff_with_note_spec.js @@ -1,10 +1,9 @@ import { shallowMount } from '@vue/test-utils'; +import discussionFixture from 'test_fixtures/merge_requests/diff_discussion.json'; +import imageDiscussionFixture from 'test_fixtures/merge_requests/image_diff_discussion.json'; import { createStore } from '~/mr_notes/stores'; import DiffWithNote from '~/notes/components/diff_with_note.vue'; -const discussionFixture = 'merge_requests/diff_discussion.json'; -const imageDiscussionFixture = 'merge_requests/image_diff_discussion.json'; - describe('diff_with_note', () => { let store; let wrapper; @@ -35,7 +34,7 @@ describe('diff_with_note', () => { describe('text diff', () => { beforeEach(() => { - const diffDiscussion = getJSONFixture(discussionFixture)[0]; + const diffDiscussion = discussionFixture[0]; wrapper = shallowMount(DiffWithNote, { propsData: { @@ -75,7 +74,7 @@ describe('diff_with_note', () => { describe('image diff', () => { beforeEach(() => { - const imageDiscussion = getJSONFixture(imageDiscussionFixture)[0]; + const imageDiscussion = imageDiscussionFixture[0]; wrapper = shallowMount(DiffWithNote, { propsData: { discussion: imageDiscussion, diffFile: {} }, store, diff --git a/spec/frontend/notes/components/noteable_discussion_spec.js b/spec/frontend/notes/components/noteable_discussion_spec.js index a364a524e7b..727ef02dcbb 100644 --- a/spec/frontend/notes/components/noteable_discussion_spec.js +++ b/spec/frontend/notes/components/noteable_discussion_spec.js @@ -1,5 +1,6 @@ import { mount } from '@vue/test-utils'; import { nextTick } from 'vue'; +import discussionWithTwoUnresolvedNotes from 'test_fixtures/merge_requests/resolved_diff_discussion.json'; import { trimText } from 'helpers/text_helper'; import mockDiffFile from 'jest/diffs/mock_data/diff_file'; import DiscussionNotes from '~/notes/components/discussion_notes.vue'; @@ -17,8 +18,6 @@ import { userDataMock, } from '../mock_data'; -const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json'; - describe('noteable_discussion component', () => { let store; let wrapper; @@ -119,7 +118,7 @@ describe('noteable_discussion component', () => { describe('for resolved thread', () => { beforeEach(() => { - const discussion = getJSONFixture(discussionWithTwoUnresolvedNotes)[0]; + const discussion = discussionWithTwoUnresolvedNotes[0]; wrapper.setProps({ discussion }); }); @@ -133,7 +132,7 @@ describe('noteable_discussion component', () => { describe('for unresolved thread', () => { beforeEach(() => { const discussion = { - ...getJSONFixture(discussionWithTwoUnresolvedNotes)[0], + ...discussionWithTwoUnresolvedNotes[0], expanded: true, }; discussion.resolved = false; diff --git a/spec/frontend/notes/stores/getters_spec.js b/spec/frontend/notes/stores/getters_spec.js index 3adb5da020e..9a11fdba508 100644 --- a/spec/frontend/notes/stores/getters_spec.js +++ b/spec/frontend/notes/stores/getters_spec.js @@ -1,3 +1,4 @@ +import discussionWithTwoUnresolvedNotes from 'test_fixtures/merge_requests/resolved_diff_discussion.json'; import { DESC, ASC } from '~/notes/constants'; import * as getters from '~/notes/stores/getters'; import { @@ -17,8 +18,6 @@ import { draftDiffDiscussion, } from '../mock_data'; -const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json'; - // Helper function to ensure that we're using the same schema across tests. const createDiscussionNeighborParams = (discussionId, diffOrder, step) => ({ discussionId, @@ -123,7 +122,7 @@ describe('Getters Notes Store', () => { describe('resolvedDiscussionsById', () => { it('ignores unresolved system notes', () => { - const [discussion] = getJSONFixture(discussionWithTwoUnresolvedNotes); + const [discussion] = discussionWithTwoUnresolvedNotes; discussion.notes[0].resolved = true; discussion.notes[1].resolved = false; state.discussions.push(discussion); diff --git a/spec/frontend/pipelines/components/pipelines_list/pipeline_mini_graph_spec.js b/spec/frontend/pipelines/components/pipelines_list/pipeline_mini_graph_spec.js index 154828aff4b..1cb43c199aa 100644 --- a/spec/frontend/pipelines/components/pipelines_list/pipeline_mini_graph_spec.js +++ b/spec/frontend/pipelines/components/pipelines_list/pipeline_mini_graph_spec.js @@ -1,8 +1,8 @@ import { shallowMount } from '@vue/test-utils'; +import { pipelines } from 'test_fixtures/pipelines/pipelines.json'; import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue'; import PipelineStage from '~/pipelines/components/pipelines_list/pipeline_stage.vue'; -const { pipelines } = getJSONFixture('pipelines/pipelines.json'); const mockStages = pipelines[0].details.stages; describe('Pipeline Mini Graph', () => { diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js index aa30062c987..2875498bb52 100644 --- a/spec/frontend/pipelines/pipelines_spec.js +++ b/spec/frontend/pipelines/pipelines_spec.js @@ -4,6 +4,7 @@ import { mount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; import { chunk } from 'lodash'; import { nextTick } from 'vue'; +import mockPipelinesResponse from 'test_fixtures/pipelines/pipelines.json'; import setWindowLocation from 'helpers/set_window_location_helper'; import { TEST_HOST } from 'helpers/test_constants'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; @@ -33,7 +34,6 @@ jest.mock('~/experimentation/utils', () => ({ const mockProjectPath = 'twitter/flight'; const mockProjectId = '21'; const mockPipelinesEndpoint = `/${mockProjectPath}/pipelines.json`; -const mockPipelinesResponse = getJSONFixture('pipelines/pipelines.json'); const mockPipelinesIds = mockPipelinesResponse.pipelines.map(({ id }) => id); const mockPipelineWithStages = mockPipelinesResponse.pipelines.find( (p) => p.details.stages && p.details.stages.length, diff --git a/spec/frontend/pipelines/pipelines_table_spec.js b/spec/frontend/pipelines/pipelines_table_spec.js index 4472a5ae70d..fb019b463b1 100644 --- a/spec/frontend/pipelines/pipelines_table_spec.js +++ b/spec/frontend/pipelines/pipelines_table_spec.js @@ -1,6 +1,7 @@ import '~/commons'; import { GlTable } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; +import fixture from 'test_fixtures/pipelines/pipelines.json'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue'; import PipelineOperations from '~/pipelines/components/pipelines_list/pipeline_operations.vue'; @@ -20,8 +21,6 @@ describe('Pipelines Table', () => { let pipeline; let wrapper; - const jsonFixtureName = 'pipelines/pipelines.json'; - const defaultProps = { pipelines: [], viewType: 'root', @@ -29,7 +28,8 @@ describe('Pipelines Table', () => { }; const createMockPipeline = () => { - const { pipelines } = getJSONFixture(jsonFixtureName); + // Clone fixture as it could be modified by tests + const { pipelines } = JSON.parse(JSON.stringify(fixture)); return pipelines.find((p) => p.user !== null && p.commit !== null); }; diff --git a/spec/frontend/pipelines/test_reports/stores/actions_spec.js b/spec/frontend/pipelines/test_reports/stores/actions_spec.js index e931ddb8496..84a9f4776b9 100644 --- a/spec/frontend/pipelines/test_reports/stores/actions_spec.js +++ b/spec/frontend/pipelines/test_reports/stores/actions_spec.js @@ -1,5 +1,5 @@ import MockAdapter from 'axios-mock-adapter'; -import { getJSONFixture } from 'helpers/fixtures'; +import testReports from 'test_fixtures/pipelines/test_report.json'; import { TEST_HOST } from 'helpers/test_constants'; import testAction from 'helpers/vuex_action_helper'; import createFlash from '~/flash'; @@ -13,7 +13,6 @@ describe('Actions TestReports Store', () => { let mock; let state; - const testReports = getJSONFixture('pipelines/test_report.json'); const summary = { total_count: 1 }; const suiteEndpoint = `${TEST_HOST}/tests/suite.json`; diff --git a/spec/frontend/pipelines/test_reports/stores/getters_spec.js b/spec/frontend/pipelines/test_reports/stores/getters_spec.js index f8298fdaba5..70e3a01dbf1 100644 --- a/spec/frontend/pipelines/test_reports/stores/getters_spec.js +++ b/spec/frontend/pipelines/test_reports/stores/getters_spec.js @@ -1,4 +1,4 @@ -import { getJSONFixture } from 'helpers/fixtures'; +import testReports from 'test_fixtures/pipelines/test_report.json'; import * as getters from '~/pipelines/stores/test_reports/getters'; import { iconForTestStatus, @@ -9,8 +9,6 @@ import { describe('Getters TestReports Store', () => { let state; - const testReports = getJSONFixture('pipelines/test_report.json'); - const defaultState = { blobPath: '/test/blob/path', testReports, diff --git a/spec/frontend/pipelines/test_reports/stores/mutations_spec.js b/spec/frontend/pipelines/test_reports/stores/mutations_spec.js index 191e9e7391c..f2dbeec6a06 100644 --- a/spec/frontend/pipelines/test_reports/stores/mutations_spec.js +++ b/spec/frontend/pipelines/test_reports/stores/mutations_spec.js @@ -1,12 +1,10 @@ -import { getJSONFixture } from 'helpers/fixtures'; +import testReports from 'test_fixtures/pipelines/test_report.json'; import * as types from '~/pipelines/stores/test_reports/mutation_types'; import mutations from '~/pipelines/stores/test_reports/mutations'; describe('Mutations TestReports Store', () => { let mockState; - const testReports = getJSONFixture('pipelines/test_report.json'); - const defaultState = { endpoint: '', testReports: {}, diff --git a/spec/frontend/pipelines/test_reports/test_reports_spec.js b/spec/frontend/pipelines/test_reports/test_reports_spec.js index e44d59ba888..384b7cf6930 100644 --- a/spec/frontend/pipelines/test_reports/test_reports_spec.js +++ b/spec/frontend/pipelines/test_reports/test_reports_spec.js @@ -1,7 +1,7 @@ import { GlLoadingIcon } from '@gitlab/ui'; import { shallowMount, createLocalVue } from '@vue/test-utils'; import Vuex from 'vuex'; -import { getJSONFixture } from 'helpers/fixtures'; +import testReports from 'test_fixtures/pipelines/test_report.json'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import EmptyState from '~/pipelines/components/test_reports/empty_state.vue'; import TestReports from '~/pipelines/components/test_reports/test_reports.vue'; @@ -16,8 +16,6 @@ describe('Test reports app', () => { let wrapper; let store; - const testReports = getJSONFixture('pipelines/test_report.json'); - const loadingSpinner = () => wrapper.findComponent(GlLoadingIcon); const testsDetail = () => wrapper.findByTestId('tests-detail'); const emptyState = () => wrapper.findComponent(EmptyState); diff --git a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js b/spec/frontend/pipelines/test_reports/test_suite_table_spec.js index a87145cc557..793bad6b82a 100644 --- a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js +++ b/spec/frontend/pipelines/test_reports/test_suite_table_spec.js @@ -1,7 +1,7 @@ import { GlButton, GlFriendlyWrap, GlLink, GlPagination } from '@gitlab/ui'; import { shallowMount, createLocalVue } from '@vue/test-utils'; import Vuex from 'vuex'; -import { getJSONFixture } from 'helpers/fixtures'; +import testReports from 'test_fixtures/pipelines/test_report.json'; import SuiteTable from '~/pipelines/components/test_reports/test_suite_table.vue'; import { TestStatus } from '~/pipelines/constants'; import * as getters from '~/pipelines/stores/test_reports/getters'; @@ -17,7 +17,7 @@ describe('Test reports suite table', () => { const { test_suites: [testSuite], - } = getJSONFixture('pipelines/test_report.json'); + } = testReports; testSuite.test_cases = [...testSuite.test_cases, ...skippedTestCases]; const testCases = testSuite.test_cases; diff --git a/spec/frontend/pipelines/test_reports/test_summary_spec.js b/spec/frontend/pipelines/test_reports/test_summary_spec.js index df404d87c99..7eed6671fb9 100644 --- a/spec/frontend/pipelines/test_reports/test_summary_spec.js +++ b/spec/frontend/pipelines/test_reports/test_summary_spec.js @@ -1,5 +1,5 @@ import { mount } from '@vue/test-utils'; -import { getJSONFixture } from 'helpers/fixtures'; +import testReports from 'test_fixtures/pipelines/test_report.json'; import Summary from '~/pipelines/components/test_reports/test_summary.vue'; import { formattedTime } from '~/pipelines/stores/test_reports/utils'; @@ -8,7 +8,7 @@ describe('Test reports summary', () => { const { test_suites: [testSuite], - } = getJSONFixture('pipelines/test_report.json'); + } = testReports; const backButton = () => wrapper.find('.js-back-button'); const totalTests = () => wrapper.find('.js-total-tests'); diff --git a/spec/frontend/pipelines/test_reports/test_summary_table_spec.js b/spec/frontend/pipelines/test_reports/test_summary_table_spec.js index 892a3742fea..0813739d72f 100644 --- a/spec/frontend/pipelines/test_reports/test_summary_table_spec.js +++ b/spec/frontend/pipelines/test_reports/test_summary_table_spec.js @@ -1,6 +1,6 @@ import { mount, createLocalVue } from '@vue/test-utils'; import Vuex from 'vuex'; -import { getJSONFixture } from 'helpers/fixtures'; +import testReports from 'test_fixtures/pipelines/test_report.json'; import SummaryTable from '~/pipelines/components/test_reports/test_summary_table.vue'; import * as getters from '~/pipelines/stores/test_reports/getters'; @@ -11,8 +11,6 @@ describe('Test reports summary table', () => { let wrapper; let store; - const testReports = getJSONFixture('pipelines/test_report.json'); - const allSuitesRows = () => wrapper.findAll('.js-suite-row'); const noSuitesToShow = () => wrapper.find('.js-no-tests-suites'); diff --git a/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js b/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js index c8fcb3116cd..7716443a42a 100644 --- a/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js +++ b/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js @@ -1,13 +1,12 @@ -import { GlFormCheckbox, GlSprintf, GlIcon } from '@gitlab/ui'; +import { GlFormCheckbox, GlSprintf, GlIcon, GlDropdown, GlDropdownItem } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import { nextTick } from 'vue'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; -import DeleteButton from '~/registry/explorer/components/delete_button.vue'; + import component from '~/registry/explorer/components/details_page/tags_list_row.vue'; import { REMOVE_TAG_BUTTON_TITLE, - REMOVE_TAG_BUTTON_DISABLE_TOOLTIP, MISSING_MANIFEST_WARNING_TOOLTIP, NOT_AVAILABLE_TEXT, NOT_AVAILABLE_SIZE, @@ -25,19 +24,20 @@ describe('tags list row', () => { const defaultProps = { tag, isMobile: false, index: 0 }; - const findCheckbox = () => wrapper.find(GlFormCheckbox); + const findCheckbox = () => wrapper.findComponent(GlFormCheckbox); const findName = () => wrapper.find('[data-testid="name"]'); const findSize = () => wrapper.find('[data-testid="size"]'); const findTime = () => wrapper.find('[data-testid="time"]'); const findShortRevision = () => wrapper.find('[data-testid="digest"]'); - const findClipboardButton = () => wrapper.find(ClipboardButton); - const findDeleteButton = () => wrapper.find(DeleteButton); - const findTimeAgoTooltip = () => wrapper.find(TimeAgoTooltip); + const findClipboardButton = () => wrapper.findComponent(ClipboardButton); + const findTimeAgoTooltip = () => wrapper.findComponent(TimeAgoTooltip); const findDetailsRows = () => wrapper.findAll(DetailsRow); const findPublishedDateDetail = () => wrapper.find('[data-testid="published-date-detail"]'); const findManifestDetail = () => wrapper.find('[data-testid="manifest-detail"]'); const findConfigurationDetail = () => wrapper.find('[data-testid="configuration-detail"]'); - const findWarningIcon = () => wrapper.find(GlIcon); + const findWarningIcon = () => wrapper.findComponent(GlIcon); + const findAdditionalActionsMenu = () => wrapper.findComponent(GlDropdown); + const findDeleteButton = () => wrapper.findComponent(GlDropdownItem); const mountComponent = (propsData = defaultProps) => { wrapper = shallowMount(component, { @@ -45,6 +45,7 @@ describe('tags list row', () => { GlSprintf, ListItem, DetailsRow, + GlDropdown, }, propsData, directives: { @@ -262,44 +263,59 @@ describe('tags list row', () => { }); }); - describe('delete button', () => { + describe('additional actions menu', () => { it('exists', () => { mountComponent(); - expect(findDeleteButton().exists()).toBe(true); + expect(findAdditionalActionsMenu().exists()).toBe(true); }); - it('has the correct props/attributes', () => { + it('has the correct props', () => { mountComponent(); - expect(findDeleteButton().attributes()).toMatchObject({ - title: REMOVE_TAG_BUTTON_TITLE, - tooltiptitle: REMOVE_TAG_BUTTON_DISABLE_TOOLTIP, - tooltipdisabled: 'true', + expect(findAdditionalActionsMenu().props()).toMatchObject({ + icon: 'ellipsis_v', + text: 'More actions', + textSrOnly: true, + category: 'tertiary', + right: true, }); }); it.each` - canDelete | digest | disabled - ${true} | ${null} | ${true} - ${false} | ${'foo'} | ${true} - ${false} | ${null} | ${true} - ${true} | ${'foo'} | ${true} + canDelete | digest | disabled | visible + ${true} | ${null} | ${true} | ${false} + ${false} | ${'foo'} | ${true} | ${false} + ${false} | ${null} | ${true} | ${false} + ${true} | ${'foo'} | ${true} | ${false} + ${true} | ${'foo'} | ${false} | ${true} `( - 'is disabled when canDelete is $canDelete and digest is $digest and disabled is $disabled', - ({ canDelete, digest, disabled }) => { + 'is $visible that is visible when canDelete is $canDelete and digest is $digest and disabled is $disabled', + ({ canDelete, digest, disabled, visible }) => { mountComponent({ ...defaultProps, tag: { ...tag, canDelete, digest }, disabled }); - expect(findDeleteButton().attributes('disabled')).toBe('true'); + expect(findAdditionalActionsMenu().exists()).toBe(visible); }, ); - it('delete event emits delete', () => { - mountComponent(); + describe('delete button', () => { + it('exists and has the correct attrs', () => { + mountComponent(); + + expect(findDeleteButton().exists()).toBe(true); + expect(findDeleteButton().attributes()).toMatchObject({ + variant: 'danger', + }); + expect(findDeleteButton().text()).toBe(REMOVE_TAG_BUTTON_TITLE); + }); - findDeleteButton().vm.$emit('delete'); + it('delete event emits delete', () => { + mountComponent(); - expect(wrapper.emitted('delete')).toEqual([[]]); + findDeleteButton().vm.$emit('click'); + + expect(wrapper.emitted('delete')).toEqual([[]]); + }); }); }); diff --git a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js index ba332e0f918..33e9c122080 100644 --- a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js +++ b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js @@ -14,7 +14,6 @@ import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_ import RunnerList from '~/runner/components/runner_list.vue'; import RunnerManualSetupHelp from '~/runner/components/runner_manual_setup_help.vue'; import RunnerPagination from '~/runner/components/runner_pagination.vue'; -import RunnerTypeHelp from '~/runner/components/runner_type_help.vue'; import { ADMIN_FILTERED_SEARCH_NAMESPACE, @@ -51,7 +50,6 @@ describe('AdminRunnersApp', () => { let wrapper; let mockRunnersQuery; - const findRunnerTypeHelp = () => wrapper.findComponent(RunnerTypeHelp); const findRunnerManualSetupHelp = () => wrapper.findComponent(RunnerManualSetupHelp); const findRunnerList = () => wrapper.findComponent(RunnerList); const findRunnerPagination = () => extendedWrapper(wrapper.findComponent(RunnerPagination)); @@ -88,10 +86,6 @@ describe('AdminRunnersApp', () => { wrapper.destroy(); }); - it('shows the runner type help', () => { - expect(findRunnerTypeHelp().exists()).toBe(true); - }); - it('shows the runner setup instructions', () => { expect(findRunnerManualSetupHelp().props('registrationToken')).toBe(mockRegistrationToken); }); diff --git a/spec/frontend/runner/components/runner_type_help_spec.js b/spec/frontend/runner/components/runner_type_help_spec.js deleted file mode 100644 index f0d03282f8e..00000000000 --- a/spec/frontend/runner/components/runner_type_help_spec.js +++ /dev/null @@ -1,32 +0,0 @@ -import { GlBadge } from '@gitlab/ui'; -import { mount } from '@vue/test-utils'; -import RunnerTypeHelp from '~/runner/components/runner_type_help.vue'; - -describe('RunnerTypeHelp', () => { - let wrapper; - - const findBadges = () => wrapper.findAllComponents(GlBadge); - - const createComponent = () => { - wrapper = mount(RunnerTypeHelp); - }; - - beforeEach(() => { - createComponent(); - }); - - afterEach(() => { - wrapper.destroy(); - }); - - it('Displays each of the runner types', () => { - expect(findBadges().at(0).text()).toBe('shared'); - expect(findBadges().at(1).text()).toBe('group'); - expect(findBadges().at(2).text()).toBe('specific'); - }); - - it('Displays runner states', () => { - expect(findBadges().at(3).text()).toBe('locked'); - expect(findBadges().at(4).text()).toBe('paused'); - }); -}); diff --git a/spec/frontend/runner/group_runners/group_runners_app_spec.js b/spec/frontend/runner/group_runners/group_runners_app_spec.js index aeab297c8f4..5f3aabd4bc3 100644 --- a/spec/frontend/runner/group_runners/group_runners_app_spec.js +++ b/spec/frontend/runner/group_runners/group_runners_app_spec.js @@ -13,7 +13,6 @@ import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_ import RunnerList from '~/runner/components/runner_list.vue'; import RunnerManualSetupHelp from '~/runner/components/runner_manual_setup_help.vue'; import RunnerPagination from '~/runner/components/runner_pagination.vue'; -import RunnerTypeHelp from '~/runner/components/runner_type_help.vue'; import { CREATED_ASC, @@ -49,7 +48,6 @@ describe('GroupRunnersApp', () => { let wrapper; let mockGroupRunnersQuery; - const findRunnerTypeHelp = () => wrapper.findComponent(RunnerTypeHelp); const findRunnerManualSetupHelp = () => wrapper.findComponent(RunnerManualSetupHelp); const findRunnerList = () => wrapper.findComponent(RunnerList); const findRunnerPagination = () => extendedWrapper(wrapper.findComponent(RunnerPagination)); @@ -83,10 +81,6 @@ describe('GroupRunnersApp', () => { await waitForPromises(); }); - it('shows the runner type help', () => { - expect(findRunnerTypeHelp().exists()).toBe(true); - }); - it('shows the runner setup instructions', () => { expect(findRunnerManualSetupHelp().props('registrationToken')).toBe(mockRegistrationToken); }); diff --git a/spec/frontend/sidebar/todo_spec.js b/spec/frontend/sidebar/todo_spec.js index ff6da3abad0..6829e688c65 100644 --- a/spec/frontend/sidebar/todo_spec.js +++ b/spec/frontend/sidebar/todo_spec.js @@ -27,7 +27,7 @@ describe('SidebarTodo', () => { it.each` state | classes ${false} | ${['gl-button', 'btn', 'btn-default', 'btn-todo', 'issuable-header-btn', 'float-right']} - ${true} | ${['btn-blank', 'btn-todo', 'sidebar-collapsed-icon', 'dont-change-state']} + ${true} | ${['btn-blank', 'btn-todo', 'sidebar-collapsed-icon', 'js-dont-change-state']} `('returns todo button classes for when `collapsed` prop is `$state`', ({ state, classes }) => { createComponent({ collapsed: state }); expect(wrapper.find('button').classes()).toStrictEqual(classes); diff --git a/spec/lib/api/every_api_endpoint_spec.rb b/spec/lib/api/every_api_endpoint_spec.rb index a9f325edefd..5fe14823a29 100644 --- a/spec/lib/api/every_api_endpoint_spec.rb +++ b/spec/lib/api/every_api_endpoint_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe 'Every API endpoint' do context 'feature categories' do let_it_be(:feature_categories) do - YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).map(&:to_sym).to_set + Gitlab::FeatureCategories.default.categories.map(&:to_sym).to_set end let_it_be(:api_endpoints) do diff --git a/spec/lib/gitlab/etag_caching/router/graphql_spec.rb b/spec/lib/gitlab/etag_caching/router/graphql_spec.rb index d151dcba413..9a6787e3640 100644 --- a/spec/lib/gitlab/etag_caching/router/graphql_spec.rb +++ b/spec/lib/gitlab/etag_caching/router/graphql_spec.rb @@ -11,7 +11,7 @@ RSpec.describe Gitlab::EtagCaching::Router::Graphql do end it 'has a valid feature category for every route', :aggregate_failures do - feature_categories = YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).to_set + feature_categories = Gitlab::FeatureCategories.default.categories described_class::ROUTES.each do |route| expect(feature_categories).to include(route.feature_category), "#{route.name} has a category of #{route.feature_category}, which is not valid" diff --git a/spec/lib/gitlab/etag_caching/router/restful_spec.rb b/spec/lib/gitlab/etag_caching/router/restful_spec.rb index 1f5cac09b6d..a0fc480369c 100644 --- a/spec/lib/gitlab/etag_caching/router/restful_spec.rb +++ b/spec/lib/gitlab/etag_caching/router/restful_spec.rb @@ -107,7 +107,7 @@ RSpec.describe Gitlab::EtagCaching::Router::Restful do end it 'has a valid feature category for every route', :aggregate_failures do - feature_categories = YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).to_set + feature_categories = Gitlab::FeatureCategories.default.categories described_class::ROUTES.each do |route| expect(feature_categories).to include(route.feature_category), "#{route.name} has a category of #{route.feature_category}, which is not valid" diff --git a/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb b/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb index 192c0c7d02f..5870f9a8f68 100644 --- a/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb +++ b/spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb @@ -349,7 +349,7 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do it 'has every label in config/feature_categories.yml' do defaults = [::Gitlab::FeatureCategories::FEATURE_CATEGORY_DEFAULT, 'not_owned'] - feature_categories = YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).map(&:strip) + defaults + feature_categories = Gitlab::FeatureCategories.default.categories + defaults expect(described_class::FEATURE_CATEGORIES_TO_INITIALIZE).to all(be_in(feature_categories)) end diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index a19acbd196d..087cd3287f8 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -2883,121 +2883,30 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end end - describe '#execute_hooks' do + describe 'hooks trigerring' do let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) } - let!(:build_a) { create_build('a', 0) } - let!(:build_b) { create_build('b', 0) } + %i[ + enqueue + request_resource + prepare + run + skip + drop + succeed + cancel + block + delay + ].each do |action| + context "when pipeline action is #{action}" do + let(:pipeline_action) { action } - let!(:hook) do - create(:project_hook, pipeline_events: enabled) - end - - before do - WebHookWorker.drain - end - - context 'with pipeline hooks enabled' do - let(:enabled) { true } - - before do - stub_full_request(hook.url, method: :post) - end - - context 'with multiple builds', :sidekiq_inline do - context 'when build is queued' do - before do - build_a.reload.enqueue - build_b.reload.enqueue - end - - it 'receives a pending event once' do - expect(WebMock).to have_requested_pipeline_hook('pending').once - end - - it 'builds hook data once' do - create(:pipelines_email_integration) + it 'schedules a new PipelineHooksWorker job' do + expect(PipelineHooksWorker).to receive(:perform_async).with(pipeline.id) - expect(Gitlab::DataBuilder::Pipeline).to receive(:build).once.and_call_original - - pipeline.execute_hooks - end + pipeline.reload.public_send(pipeline_action) end - - context 'when build is run' do - before do - build_a.reload.enqueue - build_a.reload.run! - build_b.reload.enqueue - build_b.reload.run! - end - - it 'receives a running event once' do - expect(WebMock).to have_requested_pipeline_hook('running').once - end - end - - context 'when all builds succeed' do - before do - build_a.success - - # We have to reload build_b as this is in next stage and it gets triggered by PipelineProcessWorker - build_b.reload.success - end - - it 'receives a success event once' do - expect(WebMock).to have_requested_pipeline_hook('success').once - end - end - - context 'when stage one failed' do - let!(:build_b) { create_build('b', 1) } - - before do - build_a.drop - end - - it 'receives a failed event once' do - expect(WebMock).to have_requested_pipeline_hook('failed').once - end - end - - def have_requested_pipeline_hook(status) - have_requested(:post, stubbed_hostname(hook.url)).with do |req| - json_body = Gitlab::Json.parse(req.body) - json_body['object_attributes']['status'] == status && - json_body['builds'].length == 2 - end - end - end - end - - context 'with pipeline hooks disabled' do - let(:enabled) { false } - - before do - build_a.enqueue - build_b.enqueue end - - it 'did not execute pipeline_hook after touched' do - expect(WebMock).not_to have_requested(:post, hook.url) - end - - it 'does not build hook data' do - expect(Gitlab::DataBuilder::Pipeline).not_to receive(:build) - - pipeline.execute_hooks - end - end - - def create_build(name, stage_idx) - create(:ci_build, - :created, - pipeline: pipeline, - name: name, - stage: "stage:#{stage_idx}", - stage_idx: stage_idx) end end diff --git a/spec/services/ci/pipelines/hook_service_spec.rb b/spec/services/ci/pipelines/hook_service_spec.rb new file mode 100644 index 00000000000..0e1ef6afd0d --- /dev/null +++ b/spec/services/ci/pipelines/hook_service_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Ci::Pipelines::HookService do + describe '#execute_hooks' do + let_it_be(:namespace) { create(:namespace) } + let_it_be(:project) { create(:project, :repository, namespace: namespace) } + let_it_be(:pipeline) { create(:ci_empty_pipeline, :created, project: project) } + + let(:hook_enabled) { true } + let!(:hook) { create(:project_hook, project: project, pipeline_events: hook_enabled) } + let(:hook_data) { double } + + subject(:service) { described_class.new(pipeline) } + + describe 'HOOK_NAME' do + specify { expect(described_class::HOOK_NAME).to eq(:pipeline_hooks) } + end + + context 'with pipeline hooks enabled' do + before do + allow(Gitlab::DataBuilder::Pipeline).to receive(:build).with(pipeline).once.and_return(hook_data) + end + + it 'calls pipeline.project.execute_hooks and pipeline.project.execute_integrations' do + create(:pipelines_email_integration, project: project) + + expect(pipeline.project).to receive(:execute_hooks).with(hook_data, described_class::HOOK_NAME) + expect(pipeline.project).to receive(:execute_integrations).with(hook_data, described_class::HOOK_NAME) + + service.execute + end + end + + context 'with pipeline hooks and integrations disabled' do + let(:hook_enabled) { false } + + it 'does not call pipeline.project.execute_hooks and pipeline.project.execute_integrations' do + expect(pipeline.project).not_to receive(:execute_hooks) + expect(pipeline.project).not_to receive(:execute_integrations) + + service.execute + end + end + end +end diff --git a/spec/services/ci/stuck_builds/drop_service_spec.rb b/spec/services/ci/stuck_builds/drop_pending_service_spec.rb index d57fbbe895a..aa0526edf57 100644 --- a/spec/services/ci/stuck_builds/drop_service_spec.rb +++ b/spec/services/ci/stuck_builds/drop_pending_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Ci::StuckBuilds::DropService do +RSpec.describe Ci::StuckBuilds::DropPendingService do let!(:runner) { create :ci_runner } let!(:job) { create :ci_build, runner: runner } let(:created_at) { } diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb index bb4767c9c11..9a4b27997e9 100644 --- a/spec/workers/every_sidekiq_worker_spec.rb +++ b/spec/workers/every_sidekiq_worker_spec.rb @@ -48,7 +48,7 @@ RSpec.describe 'Every Sidekiq worker' do describe "feature category declarations" do let(:feature_categories) do - YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).map(&:to_sym).to_set + Gitlab::FeatureCategories.default.categories.map(&:to_sym).to_set end # All Sidekiq worker classes should declare a valid `feature_category` @@ -161,6 +161,7 @@ RSpec.describe 'Every Sidekiq worker' do 'Ci::DropPipelineWorker' => 3, 'Ci::InitialPipelineProcessWorker' => 3, 'Ci::MergeRequests::AddTodoWhenBuildFailsWorker' => 3, + 'Ci::Minutes::UpdateProjectAndNamespaceUsageWorker' => 3, 'Ci::PipelineArtifacts::CoverageReportWorker' => 3, 'Ci::PipelineArtifacts::CreateQualityReportWorker' => 3, 'Ci::PipelineBridgeStatusWorker' => 3, diff --git a/spec/workers/pipeline_hooks_worker_spec.rb b/spec/workers/pipeline_hooks_worker_spec.rb index 0ed00c0c66a..13a86c3d4fe 100644 --- a/spec/workers/pipeline_hooks_worker_spec.rb +++ b/spec/workers/pipeline_hooks_worker_spec.rb @@ -8,8 +8,10 @@ RSpec.describe PipelineHooksWorker do let(:pipeline) { create(:ci_pipeline) } it 'executes hooks for the pipeline' do - expect_any_instance_of(Ci::Pipeline) - .to receive(:execute_hooks) + hook_service = double + + expect(Ci::Pipelines::HookService).to receive(:new).and_return(hook_service) + expect(hook_service).to receive(:execute) described_class.new.perform(pipeline.id) end @@ -17,6 +19,8 @@ RSpec.describe PipelineHooksWorker do context 'when pipeline does not exist' do it 'does not raise exception' do + expect(Ci::Pipelines::HookService).not_to receive(:new) + expect { described_class.new.perform(123) } .not_to raise_error end diff --git a/spec/workers/stuck_ci_jobs_worker_spec.rb b/spec/workers/stuck_ci_jobs_worker_spec.rb index aedf7f1c0b5..19ff8ec55c2 100644 --- a/spec/workers/stuck_ci_jobs_worker_spec.rb +++ b/spec/workers/stuck_ci_jobs_worker_spec.rb @@ -23,10 +23,10 @@ RSpec.describe StuckCiJobsWorker do subject end - it 'executes an instance of Ci::StuckBuilds::DropService' do + it 'executes an instance of Ci::StuckBuilds::DropPendingService' do expect_to_obtain_exclusive_lease(worker.lease_key, lease_uuid) - expect_next_instance_of(Ci::StuckBuilds::DropService) do |service| + expect_next_instance_of(Ci::StuckBuilds::DropPendingService) do |service| expect(service).to receive(:execute).exactly(:once) end |