diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-21 00:09:21 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-21 00:09:21 +0300 |
commit | c972699d3975e61785389602bfc8078d3bc40091 (patch) | |
tree | 37099f37fbe720f3dc988cbb6d92359428243eaf /spec | |
parent | 995bcca3fc5544e5d2d8ee274dc9275d5b4ce375 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
66 files changed, 416 insertions, 233 deletions
diff --git a/spec/controllers/import/fogbugz_controller_spec.rb b/spec/controllers/import/fogbugz_controller_spec.rb index 3b099ba2613..273dfd6a9c7 100644 --- a/spec/controllers/import/fogbugz_controller_spec.rb +++ b/spec/controllers/import/fogbugz_controller_spec.rb @@ -17,7 +17,7 @@ RSpec.describe Import::FogbugzController, feature_category: :importers do end describe 'POST #callback' do - let(:xml_response) { %Q(<?xml version=\"1.0\" encoding=\"UTF-8\"?><response><token><![CDATA[#{token}]]></token></response>) } + let(:xml_response) { %(<?xml version=\"1.0\" encoding=\"UTF-8\"?><response><token><![CDATA[#{token}]]></token></response>) } before do stub_request(:post, "https://example.com/api.asp").to_return(status: 200, body: xml_response, headers: {}) diff --git a/spec/controllers/projects/artifacts_controller_spec.rb b/spec/controllers/projects/artifacts_controller_spec.rb index c7b74b5cf68..44615506e5d 100644 --- a/spec/controllers/projects/artifacts_controller_spec.rb +++ b/spec/controllers/projects/artifacts_controller_spec.rb @@ -104,7 +104,7 @@ RSpec.describe Projects::ArtifactsController, feature_category: :build_artifacts download_artifact - expect(response.headers['Content-Disposition']).to eq(%Q(attachment; filename="#{filename}"; filename*=UTF-8''#{filename})) + expect(response.headers['Content-Disposition']).to eq(%(attachment; filename="#{filename}"; filename*=UTF-8''#{filename})) end end @@ -135,7 +135,7 @@ RSpec.describe Projects::ArtifactsController, feature_category: :build_artifacts download_artifact(file_type: 'archive') expect(response).to have_gitlab_http_status(:ok) - expect(response.headers['Content-Disposition']).to eq(%Q(attachment; filename="#{filename}"; filename*=UTF-8''#{filename})) + expect(response.headers['Content-Disposition']).to eq(%(attachment; filename="#{filename}"; filename*=UTF-8''#{filename})) end end end @@ -168,7 +168,7 @@ RSpec.describe Projects::ArtifactsController, feature_category: :build_artifacts download_artifact(file_type: file_type) - expect(response.headers['Content-Disposition']).to eq(%Q(attachment; filename="#{filename}"; filename*=UTF-8''#{filename})) + expect(response.headers['Content-Disposition']).to eq(%(attachment; filename="#{filename}"; filename*=UTF-8''#{filename})) end end @@ -264,7 +264,7 @@ RSpec.describe Projects::ArtifactsController, feature_category: :build_artifacts expect(response).to have_gitlab_http_status(:ok) expect(response.headers['Content-Disposition']) - .to eq(%Q(attachment; filename="#{filename}"; filename*=UTF-8''#{filename})) + .to eq(%(attachment; filename="#{filename}"; filename*=UTF-8''#{filename})) end end end diff --git a/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb b/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb index a7f3212a6f9..eaef455837f 100644 --- a/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb +++ b/spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb @@ -129,7 +129,7 @@ RSpec.describe Projects::DesignManagement::Designs::RawImagesController do it 'serves files with `Content-Disposition: attachment`' do subject - expect(response.header['Content-Disposition']).to eq(%Q(attachment; filename=\"#{filename}\"; filename*=UTF-8''#{filename})) + expect(response.header['Content-Disposition']).to eq(%(attachment; filename=\"#{filename}\"; filename*=UTF-8''#{filename})) end it 'sets appropriate caching headers' do diff --git a/spec/controllers/projects/design_management/designs/resized_image_controller_spec.rb b/spec/controllers/projects/design_management/designs/resized_image_controller_spec.rb index 1bb5112681c..5ed670a4f0b 100644 --- a/spec/controllers/projects/design_management/designs/resized_image_controller_spec.rb +++ b/spec/controllers/projects/design_management/designs/resized_image_controller_spec.rb @@ -51,7 +51,7 @@ RSpec.describe Projects::DesignManagement::Designs::ResizedImageController, feat it 'sets Content-Disposition as attachment' do filename = design.filename - expect(response.header['Content-Disposition']).to eq(%Q(attachment; filename=\"#{filename}\"; filename*=UTF-8''#{filename})) + expect(response.header['Content-Disposition']).to eq(%(attachment; filename=\"#{filename}\"; filename*=UTF-8''#{filename})) end it 'serves files with Workhorse' do diff --git a/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb b/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb index 7f6a044a575..d35f037247d 100644 --- a/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb +++ b/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb @@ -12,9 +12,9 @@ RSpec.describe 'Resolving all open threads in a merge request from an issue', :j url = new_project_issue_path(project, merge_request_to_resolve_discussions_of: merge_request.iid) if title.empty? - %Q{a[href="#{url}"]} + %{a[href="#{url}"]} else - %Q{a[title="#{title}"][href="#{url}"]} + %{a[title="#{title}"][href="#{url}"]} end end @@ -30,7 +30,7 @@ RSpec.describe 'Resolving all open threads in a merge request from an issue', :j end it 'shows a button to resolve all threads by creating a new issue' do - find('.discussions-counter .dropdown-toggle').click + find('.discussions-counter .gl-new-dropdown-toggle').click within('.discussions-counter') do expect(page).to have_link(_("Resolve all with new issue"), href: new_project_issue_path(project, merge_request_to_resolve_discussions_of: merge_request.iid)) @@ -49,7 +49,7 @@ RSpec.describe 'Resolving all open threads in a merge request from an issue', :j context 'creating an issue for threads' do before do - find('.discussions-counter .dropdown-toggle').click + find('.discussions-counter .gl-new-dropdown-toggle').click find(resolve_all_discussions_link_selector).click end @@ -65,7 +65,7 @@ RSpec.describe 'Resolving all open threads in a merge request from an issue', :j before do project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED) visit project_merge_request_path(project, merge_request) - find('.discussions-counter .dropdown-toggle').click + find('.discussions-counter .gl-new-dropdown-toggle').click end it 'does not show a link to create a new issue' do diff --git a/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb b/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb index 48dcb95e09b..eaf57c566e8 100644 --- a/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb +++ b/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb @@ -9,7 +9,7 @@ RSpec.describe "User downloads artifacts", feature_category: :build_artifacts do shared_examples "downloading" do it "downloads the zip" do - expect(page.response_headers['Content-Disposition']).to eq(%Q{attachment; filename="#{job.artifacts_file.filename}"; filename*=UTF-8''#{job.artifacts_file.filename}}) + expect(page.response_headers['Content-Disposition']).to eq(%{attachment; filename="#{job.artifacts_file.filename}"; filename*=UTF-8''#{job.artifacts_file.filename}}) expect(page.response_headers['Content-Transfer-Encoding']).to eq("binary") expect(page.response_headers['Content-Type']).to eq("application/zip") expect(page.source.b).to eq(job.artifacts_file.file.read.b) diff --git a/spec/features/projects/badges/coverage_spec.rb b/spec/features/projects/badges/coverage_spec.rb index 3c8b17607ca..38a7bdf65c3 100644 --- a/spec/features/projects/badges/coverage_spec.rb +++ b/spec/features/projects/badges/coverage_spec.rb @@ -197,7 +197,7 @@ RSpec.describe 'test coverage badge', feature_category: :code_testing do def expect_coverage_badge(coverage) svg = Nokogiri::XML.parse(page.body) expect(page.response_headers['Content-Type']).to include('image/svg+xml') - expect(svg.at(%Q{text:contains("#{coverage}")})).to be_truthy + expect(svg.at(%{text:contains("#{coverage}")})).to be_truthy end def expect_coverage_badge_color(color) diff --git a/spec/features/projects/badges/pipeline_badge_spec.rb b/spec/features/projects/badges/pipeline_badge_spec.rb index c0f5d0ffead..94772c9fc1e 100644 --- a/spec/features/projects/badges/pipeline_badge_spec.rb +++ b/spec/features/projects/badges/pipeline_badge_spec.rb @@ -75,7 +75,7 @@ RSpec.describe 'Pipeline Badge', feature_category: :continuous_integration do def expect_badge(status) svg = Nokogiri::XML.parse(page.body) expect(page.response_headers['Content-Type']).to include('image/svg+xml') - expect(svg.at(%Q{text:contains("#{status}")})).to be_truthy + expect(svg.at(%{text:contains("#{status}")})).to be_truthy end end end diff --git a/spec/features/projects/issuable_templates_spec.rb b/spec/features/projects/issuable_templates_spec.rb index 72695680809..bb43d019701 100644 --- a/spec/features/projects/issuable_templates_spec.rb +++ b/spec/features/projects/issuable_templates_spec.rb @@ -18,7 +18,7 @@ RSpec.describe 'issuable templates', :js, feature_category: :groups_and_projects context 'user creates an issue using templates' do let(:template_content) { 'this is a test "bug" template' } - let(:longtemplate_content) { %Q(this\n\n\n\n\nis\n\n\n\n\na\n\n\n\n\nbug\n\n\n\n\ntemplate) } + let(:longtemplate_content) { %(this\n\n\n\n\nis\n\n\n\n\na\n\n\n\n\nbug\n\n\n\n\ntemplate) } let(:issue) { create(:issue, author: user, assignees: [user], project: project) } let(:description_addition) { ' appending to description' } diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index fcd07d33535..c203e644280 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -306,7 +306,7 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state, feature_category: :grou artifact_request = requests.find { |req| req.url.include?('artifacts/download') } - expect(artifact_request.response_headers['Content-Disposition']).to eq(%Q{attachment; filename="#{job.artifacts_file.filename}"; filename*=UTF-8''#{job.artifacts_file.filename}}) + expect(artifact_request.response_headers['Content-Disposition']).to eq(%{attachment; filename="#{job.artifacts_file.filename}"; filename*=UTF-8''#{job.artifacts_file.filename}}) expect(artifact_request.response_headers['Content-Transfer-Encoding']).to eq("binary") expect(artifact_request.response_headers['Content-Type']).to eq("image/gif") expect(artifact_request.body).to eq(job.artifacts_file.file.read.b) diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index abc9e3d30fc..6d96d77519c 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -1358,7 +1358,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do page.within(all('.well-segment')[1]) do expect(page).to have_selector( - %Q{span[title="#{pipeline.yaml_errors}"]}) + %{span[title="#{pipeline.yaml_errors}"]}) end end @@ -1371,7 +1371,7 @@ RSpec.describe 'Pipeline', :js, feature_category: :groups_and_projects do page.within(all('.well-segment')[1]) do expect(page).to have_selector( - %Q{span[title="#{pipeline.present.failure_reason}"]}) + %{span[title="#{pipeline.present.failure_reason}"]}) end end diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index 441f39e6999..cbaad4e069b 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -259,7 +259,7 @@ RSpec.describe 'Pipelines', :js, feature_category: :groups_and_projects do it 'contains badge with tooltip which contains error' do expect(pipeline).to have_yaml_errors expect(page).to have_selector( - %Q{span[title="#{pipeline.yaml_errors}"]}) + %{span[title="#{pipeline.yaml_errors}"]}) end it 'contains badge that indicates failure reason' do @@ -269,7 +269,7 @@ RSpec.describe 'Pipelines', :js, feature_category: :groups_and_projects do it 'contains badge with tooltip which contains failure reason' do expect(pipeline.failure_reason?).to eq true expect(page).to have_selector( - %Q{span[title="#{pipeline.present.failure_reason}"]}) + %{span[title="#{pipeline.present.failure_reason}"]}) end end @@ -656,7 +656,7 @@ RSpec.describe 'Pipelines', :js, feature_category: :groups_and_projects do # header expect(page).to have_text("##{pipeline.id}") - expect(page).to have_selector(%Q(img[src="#{pipeline.user.avatar_url}"])) + expect(page).to have_selector(%(img[src="#{pipeline.user.avatar_url}"])) expect(page).to have_link(pipeline.user.name, href: user_path(pipeline.user)) # stages diff --git a/spec/features/uploads/user_uploads_avatar_to_group_spec.rb b/spec/features/uploads/user_uploads_avatar_to_group_spec.rb index 02e98905662..2872446ed6b 100644 --- a/spec/features/uploads/user_uploads_avatar_to_group_spec.rb +++ b/spec/features/uploads/user_uploads_avatar_to_group_spec.rb @@ -22,7 +22,7 @@ RSpec.describe 'User uploads avatar to group', feature_category: :user_profile d visit group_path(group) - expect(page).to have_selector(%Q(img[data-src$="/uploads/-/system/group/avatar/#{group.id}/dk.png"])) + expect(page).to have_selector(%(img[data-src$="/uploads/-/system/group/avatar/#{group.id}/dk.png"])) # Cheating here to verify something that isn't user-facing, but is important expect(group.reload.avatar.file).to exist diff --git a/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb b/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb index 03b072ea417..cc296259b80 100644 --- a/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb +++ b/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb @@ -18,7 +18,7 @@ RSpec.describe 'User uploads avatar to profile', feature_category: :user_profile visit user_path(user) - expect(page).to have_selector(%Q(img[src$="/uploads/-/system/user/avatar/#{user.id}/dk.png?width=96"])) + expect(page).to have_selector(%(img[src$="/uploads/-/system/user/avatar/#{user.id}/dk.png?width=96"])) # Cheating here to verify something that isn't user-facing, but is important expect(user.reload.avatar.file).to exist diff --git a/spec/frontend/api/user_api_spec.js b/spec/frontend/api/user_api_spec.js index b2ecfeb8394..a6e08e1cf4b 100644 --- a/spec/frontend/api/user_api_spec.js +++ b/spec/frontend/api/user_api_spec.js @@ -2,6 +2,7 @@ import MockAdapter from 'axios-mock-adapter'; import projects from 'test_fixtures/api/users/projects/get.json'; import followers from 'test_fixtures/api/users/followers/get.json'; +import following from 'test_fixtures/api/users/following/get.json'; import { followUser, unfollowUser, @@ -9,6 +10,7 @@ import { updateUserStatus, getUserProjects, getUserFollowers, + getUserFollowing, } from '~/api/user_api'; import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_OK } from '~/lib/utils/http_status'; @@ -131,4 +133,23 @@ describe('~/api/user_api', () => { expect(axiosMock.history.get[0].params).toEqual({ ...params, per_page: DEFAULT_PER_PAGE }); }); }); + + describe('getUserFollowing', () => { + it('calls correct URL and returns expected response', async () => { + const MOCK_USER_ID = 1; + const MOCK_PAGE = 2; + + const expectedUrl = `/api/v4/users/${MOCK_USER_ID}/following`; + const expectedResponse = { data: following }; + const params = { page: MOCK_PAGE }; + + axiosMock.onGet(expectedUrl).replyOnce(HTTP_STATUS_OK, expectedResponse); + + await expect(getUserFollowing(MOCK_USER_ID, params)).resolves.toEqual( + expect.objectContaining({ data: expectedResponse }), + ); + expect(axiosMock.history.get[0].url).toBe(expectedUrl); + expect(axiosMock.history.get[0].params).toEqual({ ...params, per_page: DEFAULT_PER_PAGE }); + }); + }); }); diff --git a/spec/frontend/fixtures/users.rb b/spec/frontend/fixtures/users.rb index 89bffea7e4c..800a9af194e 100644 --- a/spec/frontend/fixtures/users.rb +++ b/spec/frontend/fixtures/users.rb @@ -7,7 +7,8 @@ RSpec.describe 'Users (JavaScript fixtures)', feature_category: :user_profile do include ApiHelpers let_it_be(:followers) { create_list(:user, 5) } - let_it_be(:user) { create(:user, followers: followers) } + let_it_be(:followees) { create_list(:user, 5) } + let_it_be(:user) { create(:user, followers: followers, followees: followees) } describe API::Users, '(JavaScript fixtures)', type: :request do it 'api/users/followers/get.json' do @@ -15,6 +16,12 @@ RSpec.describe 'Users (JavaScript fixtures)', feature_category: :user_profile do expect(response).to be_successful end + + it 'api/users/following/get.json' do + get api("/users/#{user.id}/following", user) + + expect(response).to be_successful + end end describe UsersController, '(JavaScript fixtures)', type: :controller do diff --git a/spec/frontend/notes/components/discussion_counter_spec.js b/spec/frontend/notes/components/discussion_counter_spec.js index ac677841ee1..e52dd87f784 100644 --- a/spec/frontend/notes/components/discussion_counter_spec.js +++ b/spec/frontend/notes/components/discussion_counter_spec.js @@ -1,11 +1,11 @@ -import { GlDropdownItem } from '@gitlab/ui'; +import { GlDisclosureDropdown, GlDisclosureDropdownItem } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import DiscussionCounter from '~/notes/components/discussion_counter.vue'; import notesModule from '~/notes/stores/modules'; import * as types from '~/notes/stores/mutation_types'; -import { noteableDataMock, discussionMock, notesDataMock, userDataMock } from '../mock_data'; +import { discussionMock, noteableDataMock, notesDataMock, userDataMock } from '../mock_data'; describe('DiscussionCounter component', () => { let store; @@ -101,9 +101,24 @@ describe('DiscussionCounter component', () => { `('renders correctly if $title', async ({ resolved, groupLength }) => { updateStore({ resolvable: true, resolved }); wrapper = mount(DiscussionCounter, { store, propsData: { blocksMerge: true } }); - await wrapper.find('.dropdown-toggle').trigger('click'); + await wrapper.findComponent(GlDisclosureDropdown).trigger('click'); - expect(wrapper.findAllComponents(GlDropdownItem)).toHaveLength(groupLength); + expect(wrapper.findAllComponents(GlDisclosureDropdownItem)).toHaveLength(groupLength); + }); + + describe('resolve all with new issue link', () => { + it('has correct href prop', async () => { + updateStore({ resolvable: true }); + wrapper = mount(DiscussionCounter, { store, propsData: { blocksMerge: true } }); + + const resolveDiscussionsPath = + store.getters.getNoteableData.create_issue_to_resolve_discussions_path; + + await wrapper.findComponent(GlDisclosureDropdown).trigger('click'); + const resolveAllLink = wrapper.find('[data-testid="resolve-all-with-issue-link"]'); + + expect(resolveAllLink.attributes('href')).toBe(resolveDiscussionsPath); + }); }); }); @@ -114,7 +129,7 @@ describe('DiscussionCounter component', () => { store.commit(types.ADD_OR_UPDATE_DISCUSSIONS, [discussion]); store.dispatch('updateResolvableDiscussionsCounts'); wrapper = mount(DiscussionCounter, { store, propsData: { blocksMerge: true } }); - await wrapper.find('.dropdown-toggle').trigger('click'); + await wrapper.findComponent(GlDisclosureDropdown).trigger('click'); toggleAllButton = wrapper.find('[data-testid="toggle-all-discussions-btn"]'); }; diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/version_row_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/version_row_spec.js index f7c8e909ff6..bc7203f73c9 100644 --- a/spec/frontend/packages_and_registries/package_registry/components/details/version_row_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/components/details/version_row_spec.js @@ -1,5 +1,13 @@ -import { GlDropdownItem, GlFormCheckbox, GlIcon, GlLink, GlSprintf, GlTruncate } from '@gitlab/ui'; -import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import { + GlDisclosureDropdown, + GlDisclosureDropdownItem, + GlFormCheckbox, + GlIcon, + GlLink, + GlSprintf, + GlTruncate, +} from '@gitlab/ui'; +import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import ListItem from '~/vue_shared/components/registry/list_item.vue'; import PackageTags from '~/packages_and_registries/shared/components/package_tags.vue'; @@ -24,10 +32,16 @@ describe('VersionRow', () => { const findPackageName = () => wrapper.findComponent(GlTruncate); const findWarningIcon = () => wrapper.findComponent(GlIcon); const findBulkDeleteAction = () => wrapper.findComponent(GlFormCheckbox); - const findDeleteDropdownItem = () => wrapper.findComponent(GlDropdownItem); + const findDeleteDropdownItem = () => wrapper.findComponent(GlDisclosureDropdownItem); - function createComponent({ packageEntity = packageVersion, selected = false } = {}) { - wrapper = shallowMountExtended(VersionRow, { + function createComponent(options = {}) { + const { + mountFn = shallowMountExtended, + packageEntity = packageVersion, + selected = false, + } = options; + + wrapper = mountFn(VersionRow, { propsData: { packageEntity, selected, @@ -35,6 +49,7 @@ describe('VersionRow', () => { stubs: { GlSprintf, GlTruncate, + GlDisclosureDropdown, }, directives: { GlTooltip: createMockDirective('gl-tooltip'), @@ -100,9 +115,7 @@ describe('VersionRow', () => { }); it('renders checkbox in selected state if selected', () => { - createComponent({ - selected: true, - }); + createComponent({ selected: true }); expect(findBulkDeleteAction().attributes('checked')).toBe('true'); expect(findListItem().props('selected')).toBe(true); @@ -116,19 +129,16 @@ describe('VersionRow', () => { expect(findDeleteDropdownItem().exists()).toBe(false); }); - it('exists and has the correct props', () => { + it('exists', () => { createComponent(); expect(findDeleteDropdownItem().exists()).toBe(true); - expect(findDeleteDropdownItem().attributes()).toMatchObject({ - variant: 'danger', - }); }); - it('emits the delete event when the delete button is clicked', () => { - createComponent(); + it('emits the delete event when the delete button is clicked', async () => { + createComponent({ mountFn: mountExtended }); - findDeleteDropdownItem().vm.$emit('click'); + await findDeleteDropdownItem().find('button').trigger('click'); expect(wrapper.emitted('delete')).toHaveLength(1); }); diff --git a/spec/frontend/profile/components/following_tab_spec.js b/spec/frontend/profile/components/following_tab_spec.js index c0583cf4877..1eadb2c7388 100644 --- a/spec/frontend/profile/components/following_tab_spec.js +++ b/spec/frontend/profile/components/following_tab_spec.js @@ -1,32 +1,112 @@ import { GlBadge, GlTab } from '@gitlab/ui'; - +import { shallowMount } from '@vue/test-utils'; +import following from 'test_fixtures/api/users/following/get.json'; import { s__ } from '~/locale'; import FollowingTab from '~/profile/components/following_tab.vue'; -import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import Follow from '~/profile/components/follow.vue'; +import { getUserFollowing } from '~/rest_api'; +import { createAlert } from '~/alert'; +import waitForPromises from 'helpers/wait_for_promises'; + +const MOCK_FOLLOWEES_COUNT = 2; +const MOCK_TOTAL_FOLLOWING = 6; +const MOCK_PAGE = 1; + +jest.mock('~/rest_api'); +jest.mock('~/alert'); describe('FollowingTab', () => { let wrapper; const createComponent = () => { - wrapper = shallowMountExtended(FollowingTab, { + wrapper = shallowMount(FollowingTab, { provide: { - followeesCount: 3, + followeesCount: MOCK_FOLLOWEES_COUNT, + userId: 1, + }, + stubs: { + GlTab, }, }); }; - it('renders `GlTab` and sets title', () => { - createComponent(); + const findGlBadge = () => wrapper.findComponent(GlBadge); + const findFollow = () => wrapper.findComponent(Follow); + + describe('when API request is loading', () => { + beforeEach(() => { + getUserFollowing.mockReturnValueOnce(new Promise(() => {})); + createComponent(); + }); + + it('renders `Follow` component and sets `loading` prop to `true`', () => { + expect(findFollow().props('loading')).toBe(true); + }); + }); + + describe('when API request is successful', () => { + beforeEach(() => { + getUserFollowing.mockResolvedValueOnce({ + data: following, + headers: { 'X-TOTAL': `${MOCK_TOTAL_FOLLOWING}` }, + }); + createComponent(); + }); + + it('renders `GlTab` and sets title', () => { + expect(wrapper.findComponent(GlTab).text()).toContain(s__('UserProfile|Following')); + }); + + it('renders `GlBadge`, sets size and content', () => { + expect(findGlBadge().props('size')).toBe('sm'); + expect(findGlBadge().text()).toBe(`${MOCK_FOLLOWEES_COUNT}`); + }); + + it('renders `Follow` component and passes correct props', () => { + expect(findFollow().props()).toMatchObject({ + users: following, + loading: false, + page: MOCK_PAGE, + totalItems: MOCK_TOTAL_FOLLOWING, + }); + }); + + describe('when `Follow` component emits `pagination-input` event', () => { + it('calls API and updates `users` and `page` props', async () => { + const NEXT_PAGE = MOCK_PAGE + 1; + const NEXT_PAGE_FOLLOWING = [{ id: 999, name: 'page 2 following' }]; - expect(wrapper.findComponent(GlTab).element.textContent).toContain( - s__('UserProfile|Following'), - ); + getUserFollowing.mockResolvedValueOnce({ + data: NEXT_PAGE_FOLLOWING, + headers: { 'X-TOTAL': `${MOCK_TOTAL_FOLLOWING}` }, + }); + + findFollow().vm.$emit('pagination-input', NEXT_PAGE); + + await waitForPromises(); + + expect(findFollow().props()).toMatchObject({ + users: NEXT_PAGE_FOLLOWING, + loading: false, + page: NEXT_PAGE, + totalItems: MOCK_TOTAL_FOLLOWING, + }); + }); + }); }); - it('renders `GlBadge`, sets size and content', () => { - createComponent(); + describe('when API request is not successful', () => { + beforeEach(() => { + getUserFollowing.mockRejectedValueOnce(new Error()); + createComponent(); + }); - expect(wrapper.findComponent(GlBadge).attributes('size')).toBe('sm'); - expect(wrapper.findComponent(GlBadge).element.textContent).toBe('3'); + it('shows error alert', () => { + expect(createAlert).toHaveBeenCalledWith({ + message: FollowingTab.i18n.errorMessage, + error: new Error(), + captureError: true, + }); + }); }); }); diff --git a/spec/graphql/resolvers/echo_resolver_spec.rb b/spec/graphql/resolvers/echo_resolver_spec.rb index 59a121ac7de..02ec7327f74 100644 --- a/spec/graphql/resolvers/echo_resolver_spec.rb +++ b/spec/graphql/resolvers/echo_resolver_spec.rb @@ -14,7 +14,7 @@ RSpec.describe Resolvers::EchoResolver do describe '#resolve' do it 'echoes text and username' do - expect(resolve_echo(text)).to eq %Q("#{current_user.username}" says: #{text}) + expect(resolve_echo(text)).to eq %("#{current_user.username}" says: #{text}) end it 'echoes text and nil as username' do diff --git a/spec/helpers/markup_helper_spec.rb b/spec/helpers/markup_helper_spec.rb index a9f99f29f6d..562d6683d97 100644 --- a/spec/helpers/markup_helper_spec.rb +++ b/spec/helpers/markup_helper_spec.rb @@ -278,7 +278,7 @@ RSpec.describe MarkupHelper do it 'ignores reference links when they are the entire body' do text = issues[0].to_reference act = helper.link_to_markdown(text, '/foo') - expect(act).to eq %Q(<a href="/foo">#{issues[0].to_reference}</a>) + expect(act).to eq %(<a href="/foo">#{issues[0].to_reference}</a>) end it 'replaces commit message with emoji to link' do diff --git a/spec/lib/banzai/filter/autolink_filter_spec.rb b/spec/lib/banzai/filter/autolink_filter_spec.rb index 2c75377ec42..c8b5a9ffa0b 100644 --- a/spec/lib/banzai/filter/autolink_filter_spec.rb +++ b/spec/lib/banzai/filter/autolink_filter_spec.rb @@ -169,7 +169,7 @@ RSpec.describe Banzai::Filter::AutolinkFilter, feature_category: :team_planning it 'removes one closing punctuation mark when the punctuation in the link is unbalanced' do complicated_link = "(#{link}(a'b[c'd]))'" - expected_complicated_link = %Q{(<a href="#{link}(a'b[c'd]))">#{link}(a'b[c'd]))</a>'} + expected_complicated_link = %{(<a href="#{link}(a'b[c'd]))">#{link}(a'b[c'd]))</a>'} actual = unescape(filter(complicated_link).to_html) expect(actual).to eq(Rinku.auto_link(complicated_link)) @@ -178,7 +178,7 @@ RSpec.describe Banzai::Filter::AutolinkFilter, feature_category: :team_planning it 'does not double-encode HTML entities' do encoded_link = "#{link}?foo=bar&baz=quux" - expected_encoded_link = %Q{<a href="#{encoded_link}">#{encoded_link}</a>} + expected_encoded_link = %{<a href="#{encoded_link}">#{encoded_link}</a>} actual = unescape(filter(encoded_link).to_html) expect(actual).to eq(Rinku.auto_link(encoded_link)) diff --git a/spec/lib/banzai/filter/external_link_filter_spec.rb b/spec/lib/banzai/filter/external_link_filter_spec.rb index de259342998..300b8601dcb 100644 --- a/spec/lib/banzai/filter/external_link_filter_spec.rb +++ b/spec/lib/banzai/filter/external_link_filter_spec.rb @@ -34,7 +34,7 @@ RSpec.describe Banzai::Filter::ExternalLinkFilter, feature_category: :team_plann it 'skips internal links' do internal = Gitlab.config.gitlab.url - exp = act = %Q(<a href="#{internal}/sign_in">Login</a>) + exp = act = %(<a href="#{internal}/sign_in">Login</a>) expect(filter(act).to_html).to eq exp end @@ -90,7 +90,7 @@ RSpec.describe Banzai::Filter::ExternalLinkFilter, feature_category: :team_plann context 'with an impersonated username' do let(:internal) { Gitlab.config.gitlab.url } - let(:doc) { filter %Q(<a href="https://#{internal}@example.com" target="_blank">Reverse Tabnabbing</a>) } + let(:doc) { filter %(<a href="https://#{internal}@example.com" target="_blank">Reverse Tabnabbing</a>) } it_behaves_like 'an external link with rel attribute' end @@ -112,8 +112,8 @@ RSpec.describe Banzai::Filter::ExternalLinkFilter, feature_category: :team_plann it 'skips internal links' do internal_link = Gitlab.config.gitlab.url + "/sign_in" url = internal_link.gsub(/\Ahttp/, 'HtTp') - act = %Q(<a href="#{url}">Login</a>) - exp = %Q(<a href="#{internal_link}">Login</a>) + act = %(<a href="#{url}">Login</a>) + exp = %(<a href="#{internal_link}">Login</a>) expect(filter(act).to_html).to eq(exp) end @@ -131,7 +131,7 @@ RSpec.describe Banzai::Filter::ExternalLinkFilter, feature_category: :team_plann context 'links with RTLO character' do # In rendered text this looks like "http://example.com/evilexe.mp3" - let(:doc) { filter %Q(<a href="http://example.com/evil%E2%80%AE3pm.exe">http://example.com/evil\u202E3pm.exe</a>) } + let(:doc) { filter %(<a href="http://example.com/evil%E2%80%AE3pm.exe">http://example.com/evil\u202E3pm.exe</a>) } it_behaves_like 'an external link with rel attribute' @@ -142,7 +142,7 @@ RSpec.describe Banzai::Filter::ExternalLinkFilter, feature_category: :team_plann end it 'does not mangle the link text' do - doc = filter %Q(<a href="http://example.com">One<span>and</span>\u202Eexe.mp3</a>) + doc = filter %(<a href="http://example.com">One<span>and</span>\u202Eexe.mp3</a>) expect(doc.to_html).to include('One<span>and</span>%E2%80%AEexe.mp3</a>') end diff --git a/spec/lib/banzai/filter/image_link_filter_spec.rb b/spec/lib/banzai/filter/image_link_filter_spec.rb index 2d496c447e1..5238f05f4bd 100644 --- a/spec/lib/banzai/filter/image_link_filter_spec.rb +++ b/spec/lib/banzai/filter/image_link_filter_spec.rb @@ -9,8 +9,8 @@ RSpec.describe Banzai::Filter::ImageLinkFilter, feature_category: :team_planning let(:context) { {} } def image(path, alt: nil, data_src: nil) - alt_tag = alt ? %Q{alt="#{alt}"} : "" - data_src_tag = data_src ? %Q{data-src="#{data_src}"} : "" + alt_tag = alt ? %{alt="#{alt}"} : "" + data_src_tag = data_src ? %{data-src="#{data_src}"} : "" %(<img src="#{path}" #{alt_tag} #{data_src_tag} />) end @@ -22,7 +22,7 @@ RSpec.describe Banzai::Filter::ImageLinkFilter, feature_category: :team_planning end it 'does not wrap a duplicate link' do - doc = filter(%Q(<a href="/whatever">#{image(path)}</a>), context) + doc = filter(%(<a href="/whatever">#{image(path)}</a>), context) expect(doc.to_html).to match %r{^<a href="/whatever"><img[^>]*></a>$} end @@ -34,7 +34,7 @@ RSpec.describe Banzai::Filter::ImageLinkFilter, feature_category: :team_planning end it 'works with inline images' do - doc = filter(%Q(<p>test #{image(path)} inline</p>), context) + doc = filter(%(<p>test #{image(path)} inline</p>), context) expect(doc.to_html).to match %r{^<p>test <a[^>]*><img[^>]*></a> inline</p>$} end diff --git a/spec/lib/banzai/filter/references/label_reference_filter_spec.rb b/spec/lib/banzai/filter/references/label_reference_filter_spec.rb index f8d223c6611..91b051d71ec 100644 --- a/spec/lib/banzai/filter/references/label_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/label_reference_filter_spec.rb @@ -344,7 +344,7 @@ RSpec.describe Banzai::Filter::References::LabelReferenceFilter, feature_categor end describe 'referencing a label in a link href' do - let(:reference) { %Q{<a href="#{label.to_reference}">Label</a>} } + let(:reference) { %{<a href="#{label.to_reference}">Label</a>} } it 'links to a valid reference' do doc = reference_filter("See #{reference}") diff --git a/spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb b/spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb index ecd5d1368c9..7caa6efff66 100644 --- a/spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb @@ -132,7 +132,7 @@ RSpec.describe Banzai::Filter::References::MilestoneReferenceFilter, feature_cat shared_examples 'referencing a milestone in a link href' do let(:unquoted_reference) { "#{Milestone.reference_prefix}#{milestone.name}" } - let(:link_reference) { %Q{<a href="#{unquoted_reference}">Milestone</a>} } + let(:link_reference) { %{<a href="#{unquoted_reference}">Milestone</a>} } before do milestone.update!(name: 'gfm') @@ -169,7 +169,7 @@ RSpec.describe Banzai::Filter::References::MilestoneReferenceFilter, feature_cat shared_examples 'linking to a milestone as the entire link' do let(:unquoted_reference) { "#{Milestone.reference_prefix}#{milestone.name}" } let(:link) { urls.milestone_url(milestone) } - let(:link_reference) { %Q{<a href="#{link}">#{link}</a>} } + let(:link_reference) { %{<a href="#{link}">#{link}</a>} } it 'replaces the link text with the milestone reference' do doc = reference_filter("See #{link}") diff --git a/spec/lib/banzai/pipeline/full_pipeline_spec.rb b/spec/lib/banzai/pipeline/full_pipeline_spec.rb index 5d56035f6df..6ef03b58f67 100644 --- a/spec/lib/banzai/pipeline/full_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/full_pipeline_spec.rb @@ -28,7 +28,7 @@ RSpec.describe Banzai::Pipeline::FullPipeline, feature_category: :team_planning end it 'escapes the data-original attribute on a reference' do - markdown = %Q{[">bad things](#{issue.to_reference})} + markdown = %{[">bad things](#{issue.to_reference})} result = described_class.to_html(markdown, project: project) expect(result).to include(%{data-original='\"&gt;bad things'}) end diff --git a/spec/lib/banzai/pipeline/incident_management/timeline_event_pipeline_spec.rb b/spec/lib/banzai/pipeline/incident_management/timeline_event_pipeline_spec.rb index 12a6be6bc18..9e79be4333a 100644 --- a/spec/lib/banzai/pipeline/incident_management/timeline_event_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/incident_management/timeline_event_pipeline_spec.rb @@ -73,7 +73,7 @@ RSpec.describe Banzai::Pipeline::IncidentManagement::TimelineEventPipeline do context 'when markdown contains labels' do let(:label) { create(:label, project: project, title: 'backend') } - let(:markdown) { %Q(~"#{label.name}" ~unknown) } + let(:markdown) { %(~"#{label.name}" ~unknown) } it 'replaces existing label to a link' do # rubocop:disable Layout/LineLength diff --git a/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb b/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb index 8ff0fa3ae1e..ae01939605e 100644 --- a/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb @@ -64,9 +64,9 @@ RSpec.describe Banzai::Pipeline::PlainMarkdownPipeline, feature_category: :team_ describe 'backslash escapes are untouched in code blocks, code spans, autolinks, or raw HTML' do where(:markdown, :expected) do %q(`` \@\! ``) | %q(<code>\@\!</code>) - %q( \@\!) | %Q(<code>\\@\\!\n</code>) - %Q(~~~\n\\@\\!\n~~~) | %Q(<code>\\@\\!\n</code>) - %q($1+\$2$) | %q(<code data-math-style="inline">1+\\$2</code>) + %q( \@\!) | %(<code>\\@\\!\n</code>) + %(~~~\n\\@\\!\n~~~) | %(<code>\\@\\!\n</code>) + %q($1+\$2$) | %q(<code data-math-style="inline">1+\\$2</code>) %q(<http://example.com?find=\@>) | %q(<a href="http://example.com?find=%5C@">http://example.com?find=\@</a>) %q[<a href="/bar\@)">] | %q[<a href="/bar\@)">] end @@ -77,15 +77,15 @@ RSpec.describe Banzai::Pipeline::PlainMarkdownPipeline, feature_category: :team_ end describe 'work in all other contexts, including URLs and link titles, link references, and info strings in fenced code blocks' do - let(:markdown) { %Q(``` foo\\@bar\nfoo\n```) } + let(:markdown) { %(``` foo\\@bar\nfoo\n```) } it 'renders correct html' do - correct_html_included(markdown, %Q(<pre lang="foo@bar"><code>foo\n</code></pre>)) + correct_html_included(markdown, %(<pre lang="foo@bar"><code>foo\n</code></pre>)) end where(:markdown, :expected) do - %q![foo](/bar\@ "\@title")! | %q(<a href="/bar@" title="@title">foo</a>) - %Q![foo]\n\n[foo]: /bar\\@ "\\@title"! | %q(<a href="/bar@" title="@title">foo</a>) + %q![foo](/bar\@ "\@title")! | %q(<a href="/bar@" title="@title">foo</a>) + %![foo]\n\n[foo]: /bar\\@ "\\@title"! | %q(<a href="/bar@" title="@title">foo</a>) end with_them do diff --git a/spec/lib/banzai/reference_parser/issue_parser_spec.rb b/spec/lib/banzai/reference_parser/issue_parser_spec.rb index 2efdb928b6f..072df6a23aa 100644 --- a/spec/lib/banzai/reference_parser/issue_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/issue_parser_spec.rb @@ -136,7 +136,7 @@ RSpec.describe Banzai::ReferenceParser::IssueParser, feature_category: :team_pla end def issue_link(issue) - Nokogiri::HTML.fragment(%Q{<a data-issue="#{issue.id}"></a>}).children[0] + Nokogiri::HTML.fragment(%{<a data-issue="#{issue.id}"></a>}).children[0] end before do diff --git a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb index eead5019217..bab535b67bf 100644 --- a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb @@ -61,7 +61,7 @@ RSpec.describe Banzai::ReferenceParser::MergeRequestParser, feature_category: :c end def merge_request_link(merge_request) - Nokogiri::HTML.fragment(%Q{<a data-project="#{merge_request.project_id}" data-merge-request="#{merge_request.id}"></a>}).children[0] + Nokogiri::HTML.fragment(%{<a data-project="#{merge_request.project_id}" data-merge-request="#{merge_request.id}"></a>}).children[0] end before do diff --git a/spec/lib/gitlab/cache/client_spec.rb b/spec/lib/gitlab/cache/client_spec.rb index 638fed1a905..6543381b86a 100644 --- a/spec/lib/gitlab/cache/client_spec.rb +++ b/spec/lib/gitlab/cache/client_spec.rb @@ -3,52 +3,32 @@ require 'spec_helper' RSpec.describe Gitlab::Cache::Client, feature_category: :source_code_management do - subject(:client) { described_class.new(metadata, backend: backend) } + subject(:client) { described_class.new(metrics, backend: backend) } + let(:metrics) { Gitlab::Cache::Metrics.new(metadata) } let(:backend) { Rails.cache } - let(:metadata) do - Gitlab::Cache::Metadata.new( - cache_identifier: cache_identifier, - feature_category: feature_category, - backing_resource: backing_resource - ) - end let(:cache_identifier) { 'MyClass#cache' } let(:feature_category) { :source_code_management } let(:backing_resource) { :cpu } - let(:metadata_mock) do + let(:metadata) do Gitlab::Cache::Metadata.new( cache_identifier: cache_identifier, - feature_category: feature_category + feature_category: feature_category, + backing_resource: backing_resource ) end - let(:metrics_mock) { Gitlab::Cache::Metrics.new(metadata_mock) } - - describe '.build_with_metadata' do - it 'builds a cache client with metrics support' do - attributes = { - cache_identifier: cache_identifier, - feature_category: feature_category, - backing_resource: backing_resource - } - - instance = described_class.build_with_metadata(**attributes) - - expect(instance).to be_a(described_class) - expect(instance.metadata).to have_attributes(**attributes) - end + let(:labels) do + { + feature_category: :audit_events + } end describe 'Methods', :use_clean_rails_memory_store_caching do let(:expected_key) { 'key' } - before do - allow(Gitlab::Cache::Metrics).to receive(:new).and_return(metrics_mock) - end - describe '#read' do context 'when key does not exist' do it 'returns nil' do @@ -56,9 +36,9 @@ RSpec.describe Gitlab::Cache::Client, feature_category: :source_code_management end it 'increments cache miss' do - expect(metrics_mock).to receive(:increment_cache_miss) + expect(metrics).to receive(:increment_cache_miss).with(labels).and_call_original - client.read('key') + expect(client.read('key', nil, labels)).to be_nil end end @@ -72,9 +52,9 @@ RSpec.describe Gitlab::Cache::Client, feature_category: :source_code_management end it 'increments cache hit' do - expect(metrics_mock).to receive(:increment_cache_hit) + expect(metrics).to receive(:increment_cache_hit).with(labels) - client.read('key') + expect(client.read('key', nil, labels)).to eq('value') end end end @@ -125,13 +105,13 @@ RSpec.describe Gitlab::Cache::Client, feature_category: :source_code_management end it 'increments a cache hit' do - expect(metrics_mock).to receive(:increment_cache_hit) + expect(metrics).to receive(:increment_cache_hit).with(labels) - client.fetch('key') + expect(client.fetch('key', nil, labels)).to eq('value') end it 'does not measure the cache generation time' do - expect(metrics_mock).not_to receive(:observe_cache_generation) + expect(metrics).not_to receive(:observe_cache_generation) client.fetch('key') { 'new-value' } end @@ -145,15 +125,15 @@ RSpec.describe Gitlab::Cache::Client, feature_category: :source_code_management end it 'increments a cache miss' do - expect(metrics_mock).to receive(:increment_cache_miss) + expect(metrics).to receive(:increment_cache_miss).with(labels) - client.fetch('key') + expect(client.fetch('key', nil, labels) { 'value' }).to eq('value') end it 'measures the cache generation time' do - expect(metrics_mock).to receive(:observe_cache_generation) + expect(metrics).to receive(:observe_cache_generation).with(labels).and_call_original - client.fetch('key') { 'value' } + expect(client.fetch('key', nil, labels) { 'value' }).to eq('value') end end end diff --git a/spec/lib/gitlab/cache/metadata_spec.rb b/spec/lib/gitlab/cache/metadata_spec.rb index d2b79fb8b08..29c30d526ad 100644 --- a/spec/lib/gitlab/cache/metadata_spec.rb +++ b/spec/lib/gitlab/cache/metadata_spec.rb @@ -19,11 +19,11 @@ RSpec.describe Gitlab::Cache::Metadata, feature_category: :source_code_managemen context 'when optional arguments are not set' do it 'sets default value for them' do attributes = described_class.new( - cache_identifier: cache_identifier, feature_category: feature_category ) expect(attributes.backing_resource).to eq(:unknown) + expect(attributes.cache_identifier).to be_nil end end diff --git a/spec/lib/gitlab/cache/metrics_spec.rb b/spec/lib/gitlab/cache/metrics_spec.rb index 76ec0dbfa0b..c46533371d3 100644 --- a/spec/lib/gitlab/cache/metrics_spec.rb +++ b/spec/lib/gitlab/cache/metrics_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Cache::Metrics do +RSpec.describe Gitlab::Cache::Metrics, feature_category: :source_code_management do subject(:metrics) { described_class.new(metadata) } let(:metadata) do @@ -23,12 +23,19 @@ RSpec.describe Gitlab::Cache::Metrics do allow(Gitlab::Metrics).to receive(:counter) .with( :redis_hit_miss_operations_total, - 'Hit/miss Redis cache counter' + 'Hit/miss Redis cache counter', + { + cache_identifier: cache_identifier, + feature_category: feature_category, + backing_resource: backing_resource + } ).and_return(counter_mock) end describe '#increment_cache_hit' do - subject { metrics.increment_cache_hit } + subject { metrics.increment_cache_hit(labels) } + + let(:labels) { {} } it 'increments number of hits' do expect(counter_mock) @@ -44,10 +51,31 @@ RSpec.describe Gitlab::Cache::Metrics do subject end + + context 'when labels redefine defaults' do + let(:labels) { { backing_resource: :gitaly } } + + it 'increments number of hits' do + expect(counter_mock) + .to receive(:increment) + .with( + { + backing_resource: :gitaly, + cache_identifier: cache_identifier, + feature_category: feature_category, + cache_hit: true + } + ).once + + subject + end + end end describe '#increment_cache_miss' do - subject { metrics.increment_cache_miss } + subject { metrics.increment_cache_miss(labels) } + + let(:labels) { {} } it 'increments number of misses' do expect(counter_mock) @@ -63,22 +91,40 @@ RSpec.describe Gitlab::Cache::Metrics do subject end + + context 'when labels redefine defaults' do + let(:labels) { { backing_resource: :gitaly } } + + it 'increments number of misses' do + expect(counter_mock) + .to receive(:increment) + .with( + { + backing_resource: :gitaly, + cache_identifier: cache_identifier, + feature_category: feature_category, + cache_hit: false + } + ).once + + subject + end + end end describe '#observe_cache_generation' do subject do - metrics.observe_cache_generation { action } + metrics.observe_cache_generation(labels) { action } end let(:action) { 'action' } let(:histogram_mock) { instance_double(Prometheus::Client::Histogram) } + let(:labels) { {} } before do allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(100.0, 500.0) - end - it 'updates histogram metric' do - expect(Gitlab::Metrics).to receive(:histogram).with( + allow(Gitlab::Metrics).to receive(:histogram).with( :redis_cache_generation_duration_seconds, 'Duration of Redis cache generation', { @@ -88,10 +134,36 @@ RSpec.describe Gitlab::Cache::Metrics do }, [0, 1, 5] ).and_return(histogram_mock) + end - expect(histogram_mock).to receive(:observe).with({}, 400.0) + it 'updates histogram metric' do + expect(histogram_mock).to receive(:observe).with( + { + cache_identifier: cache_identifier, + feature_category: feature_category, + backing_resource: backing_resource + }, + 400.0 + ) is_expected.to eq(action) end + + context 'when labels redefine defaults' do + let(:labels) { { backing_resource: :gitaly } } + + it 'updates histogram metric' do + expect(histogram_mock).to receive(:observe).with( + { + cache_identifier: cache_identifier, + feature_category: feature_category, + backing_resource: :gitaly + }, + 400.0 + ) + + is_expected.to eq(action) + end + end end end diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb index 233dddbdad7..e39c15c8fd7 100644 --- a/spec/lib/gitlab/diff/highlight_spec.rb +++ b/spec/lib/gitlab/diff/highlight_spec.rb @@ -38,19 +38,19 @@ RSpec.describe Gitlab::Diff::Highlight, feature_category: :source_code_managemen end it 'highlights and marks unchanged lines' do - code = %Q{ <span id="LC7" class="line" lang="ruby"> <span class="k">def</span> <span class="nf">popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="kp">nil</span><span class="p">)</span></span>\n} + code = %{ <span id="LC7" class="line" lang="ruby"> <span class="k">def</span> <span class="nf">popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="kp">nil</span><span class="p">)</span></span>\n} expect(subject[2].rich_text).to eq(code) end it 'highlights and marks removed lines' do - code = %Q{-<span id="LC9" class="line" lang="ruby"> <span class="k">raise</span> <span class="s2">"System commands must be given as an array of strings"</span></span>\n} + code = %{-<span id="LC9" class="line" lang="ruby"> <span class="k">raise</span> <span class="s2">"System commands must be given as an array of strings"</span></span>\n} expect(subject[4].rich_text).to eq(code) end it 'highlights and marks added lines' do - code = %Q{+<span id="LC9" class="line" lang="ruby"> <span class="k">raise</span> <span class="no"><span class="idiff left addition">RuntimeError</span></span><span class="p"><span class="idiff addition">,</span></span><span class="idiff right addition"> </span><span class="s2">"System commands must be given as an array of strings"</span></span>\n} + code = %{+<span id="LC9" class="line" lang="ruby"> <span class="k">raise</span> <span class="no"><span class="idiff left addition">RuntimeError</span></span><span class="p"><span class="idiff addition">,</span></span><span class="idiff right addition"> </span><span class="s2">"System commands must be given as an array of strings"</span></span>\n} expect(subject[5].rich_text).to eq(code) end @@ -135,7 +135,7 @@ RSpec.describe Gitlab::Diff::Highlight, feature_category: :source_code_managemen it 'blobs are highlighted as plain text without loading all data' do expect(diff_file.blob).not_to receive(:load_all_data!) - expect(subject[2].rich_text).to eq(%Q{ <span id="LC7" class="line" lang=""> def popen(cmd, path=nil)</span>\n}) + expect(subject[2].rich_text).to eq(%{ <span id="LC7" class="line" lang=""> def popen(cmd, path=nil)</span>\n}) expect(subject[2].rich_text).to be_html_safe end end diff --git a/spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb b/spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb index 73ebee49169..a854adca32b 100644 --- a/spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb +++ b/spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb @@ -28,7 +28,7 @@ RSpec.describe Gitlab::ErrorTracking::StackTraceHighlightDecorator do [11, '<span id="LC1" class="line" lang="ruby"><span class="k">class</span> <span class="nc">HelloWorld</span></span>'], [12, '<span id="LC1" class="line" lang="ruby"> <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">message</span></span>'], [13, '<span id="LC1" class="line" lang="ruby"> <span class="vi">@name</span> <span class="o">=</span> <span class="s1">\'World\'</span></span>'], - [14, %Q[<span id="LC1" class="line" lang="ruby"> <span class="nb">puts</span> <span class="s2">"Hello </span><span class="si">\#{</span><span class="vi">@name</span><span class="si">}</span><span class="s2">"</span></span>]], + [14, %[<span id="LC1" class="line" lang="ruby"> <span class="nb">puts</span> <span class="s2">"Hello </span><span class="si">\#{</span><span class="vi">@name</span><span class="si">}</span><span class="s2">"</span></span>]], [15, '<span id="LC1" class="line" lang="ruby"> <span class="k">end</span></span>'], [16, '<span id="LC1" class="line" lang="ruby"><span class="k">end</span></span>'] ] diff --git a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb index 8bb649e78e0..6de7cab9c42 100644 --- a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb +++ b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb @@ -78,13 +78,13 @@ RSpec.describe Gitlab::Gfm::ReferenceRewriter do context 'label referenced by id' do let(:text) { '#1 and ~123' } - it { is_expected.to eq %Q{#{old_project_ref}#1 and #{old_project_ref}~123} } + it { is_expected.to eq %{#{old_project_ref}#1 and #{old_project_ref}~123} } end context 'label referenced by text' do let(:text) { '#1 and ~"test"' } - it { is_expected.to eq %Q{#{old_project_ref}#1 and #{old_project_ref}~123} } + it { is_expected.to eq %{#{old_project_ref}#1 and #{old_project_ref}~123} } end end @@ -99,13 +99,13 @@ RSpec.describe Gitlab::Gfm::ReferenceRewriter do context 'label referenced by id' do let(:text) { '#1 and ~321' } - it { is_expected.to eq %Q{#{old_project_ref}#1 and #{old_project_ref}~321} } + it { is_expected.to eq %{#{old_project_ref}#1 and #{old_project_ref}~321} } end context 'label referenced by text' do let(:text) { '#1 and ~"group label"' } - it { is_expected.to eq %Q{#{old_project_ref}#1 and #{old_project_ref}~321} } + it { is_expected.to eq %{#{old_project_ref}#1 and #{old_project_ref}~321} } end end end @@ -149,7 +149,7 @@ RSpec.describe Gitlab::Gfm::ReferenceRewriter do let(:text) { 'milestone: %"9.0"' } - it { is_expected.to eq %Q[milestone: #{old_project_ref}%"9.0"] } + it { is_expected.to eq %[milestone: #{old_project_ref}%"9.0"] } end context 'when referring to group milestone' do diff --git a/spec/lib/gitlab/highlight_spec.rb b/spec/lib/gitlab/highlight_spec.rb index d7ae6ed06a4..173131b1d5c 100644 --- a/spec/lib/gitlab/highlight_spec.rb +++ b/spec/lib/gitlab/highlight_spec.rb @@ -34,7 +34,7 @@ RSpec.describe Gitlab::Highlight do end it 'highlights' do - expected = %Q[<span id="LC1" class="line" lang="common_lisp"><span class="p">(</span><span class="nb">make-pathname</span> <span class="ss">:defaults</span> <span class="nv">name</span></span> + expected = %[<span id="LC1" class="line" lang="common_lisp"><span class="p">(</span><span class="nb">make-pathname</span> <span class="ss">:defaults</span> <span class="nv">name</span></span> <span id="LC2" class="line" lang="common_lisp"><span class="ss">:type</span> <span class="s">"assem"</span><span class="p">)</span></span>] expect(described_class.highlight(file_name, content)).to eq(expected) diff --git a/spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb b/spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb index b5ed583b1f1..2e87c582040 100644 --- a/spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb +++ b/spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb @@ -106,7 +106,7 @@ RSpec.describe Gitlab::Pagination::GitalyKeysetPager do context 'when next page could be available' do let(:branches) { [branch1, branch2] } - let(:expected_next_page_link) { %Q(<#{incoming_api_projects_url}?#{query.merge(page_token: branch2.name).to_query}>; rel="next") } + let(:expected_next_page_link) { %(<#{incoming_api_projects_url}?#{query.merge(page_token: branch2.name).to_query}>; rel="next") } it 'uses keyset pagination and adds link headers' do expect(request_context).to receive(:header).with('Link', expected_next_page_link) diff --git a/spec/lib/gitlab/pagination/offset_pagination_spec.rb b/spec/lib/gitlab/pagination/offset_pagination_spec.rb index dc32f471756..836b3cb55d6 100644 --- a/spec/lib/gitlab/pagination/offset_pagination_spec.rb +++ b/spec/lib/gitlab/pagination/offset_pagination_spec.rb @@ -44,9 +44,9 @@ RSpec.describe Gitlab::Pagination::OffsetPagination do expect_header('X-Prev-Page', '') expect_header('Link', anything) do |_key, val| - expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first")) - expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="last")) - expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="next")) + expect(val).to include(%(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first")) + expect(val).to include(%(<#{incoming_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="last")) + expect(val).to include(%(<#{incoming_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="next")) expect(val).not_to include('rel="prev"') end @@ -91,8 +91,8 @@ RSpec.describe Gitlab::Pagination::OffsetPagination do expect_header('X-Prev-Page', '') expect_header('Link', anything) do |_key, val| - expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first")) - expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="next")) + expect(val).to include(%(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first")) + expect(val).to include(%(<#{incoming_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="next")) expect(val).not_to include('rel="last"') expect(val).not_to include('rel="prev"') end @@ -113,8 +113,8 @@ RSpec.describe Gitlab::Pagination::OffsetPagination do expect_header('X-Prev-Page', '') expect_header('Link', anything) do |_key, val| - expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first")) - expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="next")) + expect(val).to include(%(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first")) + expect(val).to include(%(<#{incoming_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="next")) expect(val).not_to include('rel="last"') expect(val).not_to include('rel="prev"') end @@ -242,9 +242,9 @@ RSpec.describe Gitlab::Pagination::OffsetPagination do expect_header('X-Prev-Page', '1') expect_header('Link', anything) do |_key, val| - expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first")) - expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="last")) - expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="prev")) + expect(val).to include(%(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first")) + expect(val).to include(%(<#{incoming_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="last")) + expect(val).to include(%(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="prev")) expect(val).not_to include('rel="next"') end @@ -291,8 +291,8 @@ RSpec.describe Gitlab::Pagination::OffsetPagination do expect_header('X-Prev-Page', '') expect_header('Link', anything) do |_key, val| - expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first")) - expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="last")) + expect(val).to include(%(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first")) + expect(val).to include(%(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="last")) expect(val).not_to include('rel="prev"') expect(val).not_to include('rel="next"') expect(val).not_to include('page=0') diff --git a/spec/lib/gitlab/prometheus/query_variables_spec.rb b/spec/lib/gitlab/prometheus/query_variables_spec.rb index d9cac3e1064..d0947eef2d9 100644 --- a/spec/lib/gitlab/prometheus/query_variables_spec.rb +++ b/spec/lib/gitlab/prometheus/query_variables_spec.rb @@ -20,7 +20,7 @@ RSpec.describe Gitlab::Prometheus::QueryVariables do it do is_expected.to include(environment_filter: - %Q[container_name!="POD",environment="#{slug}"]) + %[container_name!="POD",environment="#{slug}"]) end context 'without deployment platform' do diff --git a/spec/lib/gitlab/reference_extractor_spec.rb b/spec/lib/gitlab/reference_extractor_spec.rb index 62fcb4821fc..37db13b76b9 100644 --- a/spec/lib/gitlab/reference_extractor_spec.rb +++ b/spec/lib/gitlab/reference_extractor_spec.rb @@ -31,7 +31,7 @@ RSpec.describe Gitlab::ReferenceExtractor do project.add_reporter(@u_foo) project.add_reporter(@u_bar) - subject.analyze(%Q{ + subject.analyze(%{ Inline code: `@foo` Code block: diff --git a/spec/lib/gitlab/url_sanitizer_spec.rb b/spec/lib/gitlab/url_sanitizer_spec.rb index c02cbef8328..5f76c1de5b1 100644 --- a/spec/lib/gitlab/url_sanitizer_spec.rb +++ b/spec/lib/gitlab/url_sanitizer_spec.rb @@ -8,7 +8,7 @@ RSpec.describe Gitlab::UrlSanitizer do describe '.sanitize' do def sanitize_url(url) # We want to try with multi-line content because is how error messages are formatted - described_class.sanitize(%Q{ + described_class.sanitize(%{ remote: Not Found fatal: repository `#{url}` not found }) diff --git a/spec/mailers/emails/releases_spec.rb b/spec/mailers/emails/releases_spec.rb index e8ca9533256..4c92762e624 100644 --- a/spec/mailers/emails/releases_spec.rb +++ b/spec/mailers/emails/releases_spec.rb @@ -57,7 +57,7 @@ RSpec.describe Emails::Releases do let(:release) { create(:release, project: project, description: "Attachment: [Test file](#{upload_path})") } it 'renders absolute links' do - is_expected.to have_body_text(%Q(<a href="#{project.web_url}#{upload_path}" data-canonical-src="#{upload_path}" data-link="true" class="gfm">Test file</a>)) + is_expected.to have_body_text(%(<a href="#{project.web_url}#{upload_path}" data-canonical-src="#{upload_path}" data-link="true" class="gfm">Test file</a>)) end end end diff --git a/spec/mailers/emails/service_desk_spec.rb b/spec/mailers/emails/service_desk_spec.rb index 22b910b3dae..8c0efe3f480 100644 --- a/spec/mailers/emails/service_desk_spec.rb +++ b/spec/mailers/emails/service_desk_spec.rb @@ -340,8 +340,8 @@ RSpec.describe Emails::ServiceDesk, feature_category: :service_desk do end end - let_it_be(:expected_html) { %Q(a new comment with <a href="#{project.web_url}#{upload_path}" data-canonical-src="#{upload_path}" data-link="true" class="gfm">#{filename}</a>) } - let_it_be(:expected_template_html) { %Q(some text #{expected_html}) } + let_it_be(:expected_html) { %(a new comment with <a href="#{project.web_url}#{upload_path}" data-canonical-src="#{upload_path}" data-link="true" class="gfm">#{filename}</a>) } + let_it_be(:expected_template_html) { %(some text #{expected_html}) } it_behaves_like 'a service desk notification email' it_behaves_like 'a service desk notification email with template content', 'new_note' @@ -357,7 +357,7 @@ RSpec.describe Emails::ServiceDesk, feature_category: :service_desk do end context 'when upload name is not changed in markdown' do - let_it_be(:expected_template_html) { %Q(some text a new comment with <strong>#{filename}</strong>) } + let_it_be(:expected_template_html) { %(some text a new comment with <strong>#{filename}</strong>) } it_behaves_like 'a service desk notification email', 1 it_behaves_like 'a service desk notification email with template content', 'new_note', 1 @@ -366,9 +366,9 @@ RSpec.describe Emails::ServiceDesk, feature_category: :service_desk do context 'when upload name is changed in markdown' do let_it_be(:upload_name_in_markdown) { 'Custom name' } let_it_be(:note) { create(:note_on_issue, noteable: issue, project: project, note: "a new comment with [#{upload_name_in_markdown}](#{upload_path})") } - let_it_be(:expected_text) { %Q(a new comment with [#{upload_name_in_markdown}](#{upload_path})) } - let_it_be(:expected_html) { %Q(a new comment with <strong>#{upload_name_in_markdown} (#{filename})</strong>) } - let_it_be(:expected_template_html) { %Q(some text #{expected_html}) } + let_it_be(:expected_text) { %(a new comment with [#{upload_name_in_markdown}](#{upload_path})) } + let_it_be(:expected_html) { %(a new comment with <strong>#{upload_name_in_markdown} (#{filename})</strong>) } + let_it_be(:expected_template_html) { %(some text #{expected_html}) } it_behaves_like 'a service desk notification email', 1 it_behaves_like 'a service desk notification email with template content', 'new_note', 1 @@ -392,16 +392,16 @@ RSpec.describe Emails::ServiceDesk, feature_category: :service_desk do let_it_be(:upload_1) { create(:upload, :issuable_upload, :with_file, model: note.project, path: path_1, secret: secret_1) } - let_it_be(:expected_html) { %Q(a new comment with <strong>#{filename}</strong> <strong>#{filename_1}</strong>) } - let_it_be(:expected_template_html) { %Q(some text #{expected_html}) } + let_it_be(:expected_html) { %(a new comment with <strong>#{filename}</strong> <strong>#{filename_1}</strong>) } + let_it_be(:expected_template_html) { %(some text #{expected_html}) } it_behaves_like 'a service desk notification email', 2 it_behaves_like 'a service desk notification email with template content', 'new_note', 2 end context 'when not all uploads processed correct' do - let_it_be(:expected_html) { %Q(a new comment with <strong>#{filename}</strong> <a href="#{project.web_url}#{upload_path_1}" data-canonical-src="#{upload_path_1}" data-link="true" class="gfm">#{filename_1}</a>) } - let_it_be(:expected_template_html) { %Q(some text #{expected_html}) } + let_it_be(:expected_html) { %(a new comment with <strong>#{filename}</strong> <a href="#{project.web_url}#{upload_path_1}" data-canonical-src="#{upload_path_1}" data-link="true" class="gfm">#{filename_1}</a>) } + let_it_be(:expected_template_html) { %(some text #{expected_html}) } it_behaves_like 'a service desk notification email', 1 it_behaves_like 'a service desk notification email with template content', 'new_note', 1 @@ -417,7 +417,7 @@ RSpec.describe Emails::ServiceDesk, feature_category: :service_desk do expect(Gitlab::ErrorTracking).to receive(:track_exception).with(StandardError, project_id: note.project_id) end - let_it_be(:expected_template_html) { %Q(some text a new comment with <a href="#{project.web_url}#{upload_path}" data-canonical-src="#{upload_path}" data-link="true" class="gfm">#{filename}</a>) } + let_it_be(:expected_template_html) { %(some text a new comment with <a href="#{project.web_url}#{upload_path}" data-canonical-src="#{upload_path}" data-link="true" class="gfm">#{filename}</a>) } it_behaves_like 'a service desk notification email with template content', 'new_note' end @@ -430,7 +430,7 @@ RSpec.describe Emails::ServiceDesk, feature_category: :service_desk do expect(Gitlab::ErrorTracking).to receive(:track_exception).with(StandardError, project_id: note.project_id) end - let_it_be(:expected_template_html) { %Q(some text a new comment with <a href="#{project.web_url}#{upload_path}" data-canonical-src="#{upload_path}" data-link="true" class="gfm">#{filename}</a>) } + let_it_be(:expected_template_html) { %(some text a new comment with <a href="#{project.web_url}#{upload_path}" data-canonical-src="#{upload_path}" data-link="true" class="gfm">#{filename}</a>) } it_behaves_like 'a service desk notification email with template content', 'new_note' end diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb index ede96d79656..9c8ac45c405 100644 --- a/spec/models/deployment_spec.rb +++ b/spec/models/deployment_spec.rb @@ -1285,7 +1285,7 @@ RSpec.describe Deployment, feature_category: :continuous_delivery do let(:build_status) { :created } it_behaves_like 'gracefully handling error' do - let(:error_message) { %Q{Status cannot transition via \"create\"} } + let(:error_message) { %{Status cannot transition via \"create\"} } end end @@ -1315,7 +1315,7 @@ RSpec.describe Deployment, feature_category: :continuous_delivery do let(:build_status) { :created } it_behaves_like 'gracefully handling error' do - let(:error_message) { %Q{Status cannot transition via \"create\"} } + let(:error_message) { %{Status cannot transition via \"create\"} } end end @@ -1323,7 +1323,7 @@ RSpec.describe Deployment, feature_category: :continuous_delivery do let(:build_status) { :running } it_behaves_like 'gracefully handling error' do - let(:error_message) { %Q{Status cannot transition via \"run\"} } + let(:error_message) { %{Status cannot transition via \"run\"} } end end diff --git a/spec/models/incident_management/timeline_event_spec.rb b/spec/models/incident_management/timeline_event_spec.rb index 036f5affb87..40adf46e7d5 100644 --- a/spec/models/incident_management/timeline_event_spec.rb +++ b/spec/models/incident_management/timeline_event_spec.rb @@ -76,7 +76,7 @@ RSpec.describe IncidentManagement::TimelineEvent do end let(:expected_note_html) do - %Q(<p>note <strong>bold</strong> <em>italic</em> <code>code</code> #{expected_image_html} #{expected_emoji_html}</p>) + %(<p>note <strong>bold</strong> <em>italic</em> <code>code</code> #{expected_image_html} #{expected_emoji_html}</p>) end # rubocop:enable Layout/LineLength diff --git a/spec/models/integrations/drone_ci_spec.rb b/spec/models/integrations/drone_ci_spec.rb index c46face9702..2cb86fb680a 100644 --- a/spec/models/integrations/drone_ci_spec.rb +++ b/spec/models/integrations/drone_ci_spec.rb @@ -184,7 +184,7 @@ RSpec.describe Integrations::DroneCi, :use_clean_rails_memory_store_caching do "success" => "success" }.each do |drone_status, our_status| it "sets commit status to #{our_status.inspect} when returned status is #{drone_status.inspect}" do - stub_request(body: %Q({"status":"#{drone_status}"})) + stub_request(body: %({"status":"#{drone_status}"})) is_expected.to eq(our_status) end diff --git a/spec/models/integrations/teamcity_spec.rb b/spec/models/integrations/teamcity_spec.rb index e32088a2f79..c4c7202fae0 100644 --- a/spec/models/integrations/teamcity_spec.rb +++ b/spec/models/integrations/teamcity_spec.rb @@ -307,7 +307,7 @@ RSpec.describe Integrations::Teamcity, :use_clean_rails_memory_store_caching do def stub_post_to_build_queue(branch:) teamcity_full_url = "#{teamcity_url}/httpAuth/app/rest/buildQueue" - body ||= %Q(<build branchName=\"#{branch}\"><buildType id=\"foo\"/></build>) + body ||= %(<build branchName=\"#{branch}\"><buildType id=\"foo\"/></build>) auth = %w(mic password) stub_full_request(teamcity_full_url, method: :post).with( @@ -322,7 +322,7 @@ RSpec.describe Integrations::Teamcity, :use_clean_rails_memory_store_caching do def stub_request(status: 200, body: nil, build_status: 'success') auth = %w(mic password) - body ||= %Q({"build":{"status":"#{build_status}","id":"666"}}) + body ||= %({"build":{"status":"#{build_status}","id":"666"}}) stub_full_request(teamcity_full_url).with(basic_auth: auth).to_return( status: status, diff --git a/spec/models/project_label_spec.rb b/spec/models/project_label_spec.rb index ba9ea759c6a..62839f5fb4f 100644 --- a/spec/models/project_label_spec.rb +++ b/spec/models/project_label_spec.rb @@ -107,14 +107,14 @@ RSpec.describe ProjectLabel do context 'using name' do it 'returns cross reference with label name' do expect(label.to_reference(project, format: :name)) - .to eq %Q(#{label.project.full_path}~"#{label.name}") + .to eq %(#{label.project.full_path}~"#{label.name}") end end context 'using id' do it 'returns cross reference with label id' do expect(label.to_reference(project, format: :id)) - .to eq %Q(#{label.project.full_path}~#{label.id}) + .to eq %(#{label.project.full_path}~#{label.id}) end end end diff --git a/spec/presenters/snippet_blob_presenter_spec.rb b/spec/presenters/snippet_blob_presenter_spec.rb index d7f56c30b5e..cdd02241fbf 100644 --- a/spec/presenters/snippet_blob_presenter_spec.rb +++ b/spec/presenters/snippet_blob_presenter_spec.rb @@ -46,7 +46,7 @@ RSpec.describe SnippetBlobPresenter do let(:file) { 'test.ipynb' } it 'returns rich notebook content' do - expect(subject.strip).to eq %Q(<div class="file-content" data-endpoint="#{data_endpoint_url}" data-relative-raw-path="#{data_raw_dir}" id="js-notebook-viewer"></div>) + expect(subject.strip).to eq %(<div class="file-content" data-endpoint="#{data_endpoint_url}" data-relative-raw-path="#{data_raw_dir}" id="js-notebook-viewer"></div>) end end @@ -54,7 +54,7 @@ RSpec.describe SnippetBlobPresenter do let(:file) { 'openapi.yml' } it 'returns rich openapi content' do - expect(subject).to eq %Q(<div class="file-content" data-endpoint="#{data_endpoint_url}" id="js-openapi-viewer"></div>\n) + expect(subject).to eq %(<div class="file-content" data-endpoint="#{data_endpoint_url}" id="js-openapi-viewer"></div>\n) end end diff --git a/spec/requests/api/ci/job_artifacts_spec.rb b/spec/requests/api/ci/job_artifacts_spec.rb index 7cea744cdb9..6f4e7fd66ed 100644 --- a/spec/requests/api/ci/job_artifacts_spec.rb +++ b/spec/requests/api/ci/job_artifacts_spec.rb @@ -541,7 +541,7 @@ RSpec.describe API::Ci::JobArtifacts, feature_category: :build_artifacts do let(:download_headers) do { 'Content-Transfer-Encoding' => 'binary', 'Content-Disposition' => - %Q(attachment; filename="#{job_with_artifacts.artifacts_file.filename}"; filename*=UTF-8''#{job.artifacts_file.filename}) } + %(attachment; filename="#{job_with_artifacts.artifacts_file.filename}"; filename*=UTF-8''#{job.artifacts_file.filename}) } end it { expect(response).to have_gitlab_http_status(:ok) } diff --git a/spec/requests/api/deployments_spec.rb b/spec/requests/api/deployments_spec.rb index d7056adfcb6..82ac2eed83d 100644 --- a/spec/requests/api/deployments_spec.rb +++ b/spec/requests/api/deployments_spec.rb @@ -424,7 +424,7 @@ RSpec.describe API::Deployments, feature_category: :continuous_delivery do ) expect(response).to have_gitlab_http_status(:bad_request) - expect(json_response['message']['status']).to include(%Q{cannot transition via \"run\"}) + expect(json_response['message']['status']).to include(%{cannot transition via \"run\"}) end it 'links merge requests when the deployment status changes to success', :sidekiq_inline do diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb index ed84e3e5f48..ea341703301 100644 --- a/spec/requests/api/files_spec.rb +++ b/spec/requests/api/files_spec.rb @@ -141,11 +141,9 @@ RSpec.describe API::Files, feature_category: :source_code_management do it 'caches sha256 of the content', :use_clean_rails_redis_caching do head api(route(file_path), current_user, **options), params: params - expect(Gitlab::Cache::Client).to receive(:build_with_metadata).with( - cache_identifier: 'API::Files#content_sha', - feature_category: :source_code_management, - backing_resource: :gitaly - ).and_call_original + expect_next_instance_of(Gitlab::Cache::Client) do |instance| + expect(instance).to receive(:fetch).with(anything, nil, { cache_identifier: 'API::Files#content_sha', backing_resource: :gitaly }).and_call_original + end expect(Rails.cache.fetch("blob_content_sha256:#{project.full_path}:#{response.headers['X-Gitlab-Blob-Id']}")) .to eq(content_sha256) diff --git a/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb b/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb index 09e884d9412..c3f818b6627 100644 --- a/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb +++ b/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb @@ -53,7 +53,7 @@ RSpec.describe 'Destroying a Snippet', feature_category: :source_code_management let!(:snippet_gid) { project.to_gid.to_s } it 'returns an error' do - err_message = %Q["#{snippet_gid}" does not represent an instance of Snippet] + err_message = %["#{snippet_gid}" does not represent an instance of Snippet] post_graphql_mutation(mutation, current_user: current_user) diff --git a/spec/requests/api/graphql/project/incident_management/timeline_events_spec.rb b/spec/requests/api/graphql/project/incident_management/timeline_events_spec.rb index 7587b227d9f..dd383226e17 100644 --- a/spec/requests/api/graphql/project/incident_management/timeline_events_spec.rb +++ b/spec/requests/api/graphql/project/incident_management/timeline_events_spec.rb @@ -15,7 +15,7 @@ RSpec.describe 'getting incident timeline events', feature_category: :incident_m let_it_be(:promoted_from_note) { create(:note, project: project, noteable: incident) } let_it_be(:issue_url) { project_issue_url(private_project, issue) } let_it_be(:issue_ref) { "#{private_project.full_path}##{issue.iid}" } - let_it_be(:issue_link) { %Q(<a href="#{issue_url}">#{issue_url}</a>) } + let_it_be(:issue_link) { %(<a href="#{issue_url}">#{issue_url}</a>) } let_it_be(:timeline_event) do create( diff --git a/spec/requests/projects/packages/package_files_controller_spec.rb b/spec/requests/projects/packages/package_files_controller_spec.rb index e5849be9f13..4f1793b831d 100644 --- a/spec/requests/projects/packages/package_files_controller_spec.rb +++ b/spec/requests/projects/packages/package_files_controller_spec.rb @@ -22,7 +22,7 @@ RSpec.describe Projects::Packages::PackageFilesController, feature_category: :pa subject expect(response.headers['Content-Disposition']) - .to eq(%Q(attachment; filename="#{filename}"; filename*=UTF-8''#{filename})) + .to eq(%(attachment; filename="#{filename}"; filename*=UTF-8''#{filename})) end it_behaves_like 'bumping the package last downloaded at field' diff --git a/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb b/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb index 96ff01108c3..4b7ea6b72e5 100644 --- a/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb +++ b/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb @@ -48,35 +48,35 @@ RSpec.describe RuboCop::Cop::Gitlab::MarkUsedFeatureFlags do ].each do |feature_flag_method| context "#{feature_flag_method} method" do context 'a string feature flag' do - include_examples 'sets flag as used', %Q|#{feature_flag_method}("foo")|, 'foo' + include_examples 'sets flag as used', %|#{feature_flag_method}("foo")|, 'foo' end context 'a symbol feature flag' do - include_examples 'sets flag as used', %Q|#{feature_flag_method}(:foo)|, 'foo' + include_examples 'sets flag as used', %|#{feature_flag_method}(:foo)|, 'foo' end context 'an interpolated string feature flag with a string prefix' do - include_examples 'sets flag as used', %Q|#{feature_flag_method}("foo_\#{bar}")|, %w[foo_hello foo_world] + include_examples 'sets flag as used', %|#{feature_flag_method}("foo_\#{bar}")|, %w[foo_hello foo_world] end context 'an interpolated symbol feature flag with a string prefix' do - include_examples 'sets flag as used', %Q|#{feature_flag_method}(:"foo_\#{bar}")|, %w[foo_hello foo_world] + include_examples 'sets flag as used', %|#{feature_flag_method}(:"foo_\#{bar}")|, %w[foo_hello foo_world] end context 'a string with a "/" in it' do - include_examples 'sets flag as used', %Q|#{feature_flag_method}("bar/baz")|, 'bar_baz' + include_examples 'sets flag as used', %|#{feature_flag_method}("bar/baz")|, 'bar_baz' end context 'an interpolated string feature flag with a string prefix and suffix' do - include_examples 'does not set any flags as used', %Q|#{feature_flag_method}(:"foo_\#{bar}_baz")| + include_examples 'does not set any flags as used', %|#{feature_flag_method}(:"foo_\#{bar}_baz")| end context 'a dynamic string feature flag as a variable' do - include_examples 'does not set any flags as used', %Q|#{feature_flag_method}(a_variable, an_arg)| + include_examples 'does not set any flags as used', %|#{feature_flag_method}(a_variable, an_arg)| end context 'an integer feature flag' do - include_examples 'does not set any flags as used', %Q|#{feature_flag_method}(123)| + include_examples 'does not set any flags as used', %|#{feature_flag_method}(123)| end end end @@ -87,31 +87,31 @@ RSpec.describe RuboCop::Cop::Gitlab::MarkUsedFeatureFlags do ].each do |feature_flag_method| context "#{feature_flag_method} method" do context 'a string feature flag' do - include_examples 'sets flag as used', %Q|#{feature_flag_method}("foo")|, 'gitaly_foo' + include_examples 'sets flag as used', %|#{feature_flag_method}("foo")|, 'gitaly_foo' end context 'a symbol feature flag' do - include_examples 'sets flag as used', %Q|#{feature_flag_method}(:foo)|, 'gitaly_foo' + include_examples 'sets flag as used', %|#{feature_flag_method}(:foo)|, 'gitaly_foo' end context 'an interpolated string feature flag with a string prefix' do - include_examples 'sets flag as used', %Q|#{feature_flag_method}("foo_\#{bar}")|, %w[foo_hello foo_world] + include_examples 'sets flag as used', %|#{feature_flag_method}("foo_\#{bar}")|, %w[foo_hello foo_world] end context 'an interpolated symbol feature flag with a string prefix' do - include_examples 'sets flag as used', %Q|#{feature_flag_method}(:"foo_\#{bar}")|, %w[foo_hello foo_world] + include_examples 'sets flag as used', %|#{feature_flag_method}(:"foo_\#{bar}")|, %w[foo_hello foo_world] end context 'an interpolated string feature flag with a string prefix and suffix' do - include_examples 'does not set any flags as used', %Q|#{feature_flag_method}(:"foo_\#{bar}_baz")| + include_examples 'does not set any flags as used', %|#{feature_flag_method}(:"foo_\#{bar}_baz")| end context 'a dynamic string feature flag as a variable' do - include_examples 'does not set any flags as used', %Q|#{feature_flag_method}(a_variable, an_arg)| + include_examples 'does not set any flags as used', %|#{feature_flag_method}(a_variable, an_arg)| end context 'an integer feature flag' do - include_examples 'does not set any flags as used', %Q|#{feature_flag_method}(123)| + include_examples 'does not set any flags as used', %|#{feature_flag_method}(123)| end end end @@ -126,15 +126,15 @@ RSpec.describe RuboCop::Cop::Gitlab::MarkUsedFeatureFlags do end context 'an interpolated string feature flag with a string prefix' do - include_examples 'sets flag as used', %Q|experiment("foo_\#{bar}")|, %w[foo_hello foo_world] + include_examples 'sets flag as used', %|experiment("foo_\#{bar}")|, %w[foo_hello foo_world] end context 'an interpolated symbol feature flag with a string prefix' do - include_examples 'sets flag as used', %Q|experiment(:"foo_\#{bar}")|, %w[foo_hello foo_world] + include_examples 'sets flag as used', %|experiment(:"foo_\#{bar}")|, %w[foo_hello foo_world] end context 'an interpolated string feature flag with a string prefix and suffix' do - include_examples 'does not set any flags as used', %Q|experiment(:"foo_\#{bar}_baz")| + include_examples 'does not set any flags as used', %|experiment(:"foo_\#{bar}_baz")| end context 'a dynamic string feature flag as a variable' do @@ -151,31 +151,31 @@ RSpec.describe RuboCop::Cop::Gitlab::MarkUsedFeatureFlags do ].each do |feature_flag_method| context "#{feature_flag_method} method" do context 'a string feature flag' do - include_examples 'sets flag as used', %Q|#{feature_flag_method}(arg, "baz")|, 'baz' + include_examples 'sets flag as used', %|#{feature_flag_method}(arg, "baz")|, 'baz' end context 'a symbol feature flag' do - include_examples 'sets flag as used', %Q|#{feature_flag_method}(arg, :baz)|, 'baz' + include_examples 'sets flag as used', %|#{feature_flag_method}(arg, :baz)|, 'baz' end context 'an interpolated string feature flag with a string prefix' do - include_examples 'sets flag as used', %Q|#{feature_flag_method}(arg, "foo_\#{bar}")|, %w[foo_hello foo_world] + include_examples 'sets flag as used', %|#{feature_flag_method}(arg, "foo_\#{bar}")|, %w[foo_hello foo_world] end context 'an interpolated symbol feature flag with a string prefix' do - include_examples 'sets flag as used', %Q|#{feature_flag_method}(arg, :"foo_\#{bar}")|, %w[foo_hello foo_world] + include_examples 'sets flag as used', %|#{feature_flag_method}(arg, :"foo_\#{bar}")|, %w[foo_hello foo_world] end context 'an interpolated string feature flag with a string prefix and suffix' do - include_examples 'does not set any flags as used', %Q|#{feature_flag_method}(arg, :"foo_\#{bar}_baz")| + include_examples 'does not set any flags as used', %|#{feature_flag_method}(arg, :"foo_\#{bar}_baz")| end context 'a dynamic string feature flag as a variable' do - include_examples 'does not set any flags as used', %Q|#{feature_flag_method}(a_variable, an_arg)| + include_examples 'does not set any flags as used', %|#{feature_flag_method}(a_variable, an_arg)| end context 'an integer feature flag' do - include_examples 'does not set any flags as used', %Q|#{feature_flag_method}(arg, 123)| + include_examples 'does not set any flags as used', %|#{feature_flag_method}(arg, 123)| end end end diff --git a/spec/services/prometheus/proxy_variable_substitution_service_spec.rb b/spec/services/prometheus/proxy_variable_substitution_service_spec.rb index fbee4b9c7d7..a5395eed1b4 100644 --- a/spec/services/prometheus/proxy_variable_substitution_service_spec.rb +++ b/spec/services/prometheus/proxy_variable_substitution_service_spec.rb @@ -53,7 +53,7 @@ RSpec.describe Prometheus::ProxyVariableSubstitutionService, feature_category: : end it_behaves_like 'success' do - let(:expected_query) { %Q[up{environment="#{environment.slug}"}] } + let(:expected_query) { %[up{environment="#{environment.slug}"}] } end end end diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb index a9ad853b028..62e05129fb2 100644 --- a/spec/support/helpers/graphql_helpers.rb +++ b/spec/support/helpers/graphql_helpers.rb @@ -473,7 +473,7 @@ module GraphqlHelpers end def with_signature(variables, query) - %Q[query(#{variables.map(&:sig).join(', ')}) #{wrap_query(query)}] + %[query(#{variables.map(&:sig).join(', ')}) #{wrap_query(query)}] end def var(type) diff --git a/spec/support/shared_examples/controllers/repository_lfs_file_load_shared_examples.rb b/spec/support/shared_examples/controllers/repository_lfs_file_load_shared_examples.rb index 9cf35325202..ba3b08751da 100644 --- a/spec/support/shared_examples/controllers/repository_lfs_file_load_shared_examples.rb +++ b/spec/support/shared_examples/controllers/repository_lfs_file_load_shared_examples.rb @@ -75,7 +75,7 @@ RSpec.shared_examples 'a controller that can serve LFS files' do |options = {}| file_uri = URI.parse(response.location) params = CGI.parse(file_uri.query) - expect(params["response-content-disposition"].first).to eq(%Q(attachment; filename="#{filename}"; filename*=UTF-8''#{filename})) + expect(params["response-content-disposition"].first).to eq(%(attachment; filename="#{filename}"; filename*=UTF-8''#{filename})) end end end diff --git a/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb b/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb index 337b3f3cbd0..7e3b507c1ba 100644 --- a/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb +++ b/spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb @@ -24,6 +24,6 @@ RSpec.shared_examples 'creating an issue for a thread' do expect(discussion.resolved?).to eq(true) # Issue title inludes MR title - expect(page).to have_content(%Q(Follow-up from "#{merge_request.title}")) + expect(page).to have_content(%(Follow-up from "#{merge_request.title}")) end end diff --git a/spec/support/shared_examples/graphql/label_fields.rb b/spec/support/shared_examples/graphql/label_fields.rb index 030a2feafcd..809c801de62 100644 --- a/spec/support/shared_examples/graphql/label_fields.rb +++ b/spec/support/shared_examples/graphql/label_fields.rb @@ -93,7 +93,7 @@ RSpec.shared_examples 'querying a GraphQL type with labels' do describe 'performance' do def query_for(*labels) selections = labels.map do |label| - %Q[#{label.title.gsub(/:+/, '_')}: label(title: "#{label.title}") { description }] + %[#{label.title.gsub(/:+/, '_')}: label(title: "#{label.title}") { description }] end make_query(selections) diff --git a/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb b/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb index 47655f86558..99d0bc287a3 100644 --- a/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb +++ b/spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb @@ -110,7 +110,7 @@ RSpec.shared_examples 'XSS prevention' do }, 'protocol-based JS injection: Unicode' => { - input: %Q(<a href="\u0001java\u0003script:alert('XSS')">foo</a>), + input: %(<a href="\u0001java\u0003script:alert('XSS')">foo</a>), output: '<a>foo</a>' }, diff --git a/spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb b/spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb index 0e79e32b78a..19581064626 100644 --- a/spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb +++ b/spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb @@ -156,8 +156,8 @@ RSpec.describe ExceedQueryLimitHelpers do expect(test_matcher.count_queries(recorder)).to eq({ 'SELECT "schema_migrations".* FROM "schema_migrations"' => { - %Q[WHERE "schema_migrations"."version" = 'foo\nbar\nbaz' LIMIT 1] => 2, - %Q[WHERE "schema_migrations"."version" = 'foo\nbiz\nbaz' LIMIT 1] => 1 + %[WHERE "schema_migrations"."version" = 'foo\nbar\nbaz' LIMIT 1] => 2, + %[WHERE "schema_migrations"."version" = 'foo\nbiz\nbaz' LIMIT 1] => 1 } }) end diff --git a/spec/views/layouts/_head.html.haml_spec.rb b/spec/views/layouts/_head.html.haml_spec.rb index a44c69748e5..9aec8f2d759 100644 --- a/spec/views/layouts/_head.html.haml_spec.rb +++ b/spec/views/layouts/_head.html.haml_spec.rb @@ -44,13 +44,13 @@ RSpec.describe 'layouts/_head' do it 'adds a link dns-prefetch tag' do render - expect(rendered).to match(%Q(<link href="#{asset_host}" rel="dns-prefetch">)) + expect(rendered).to match(%(<link href="#{asset_host}" rel="dns-prefetch">)) end it 'adds a link preconnect tag' do render - expect(rendered).to match(%Q(<link crossorigin="" href="#{asset_host}" rel="preconnect">)) + expect(rendered).to match(%(<link crossorigin="" href="#{asset_host}" rel="preconnect">)) end end @@ -82,7 +82,7 @@ RSpec.describe 'layouts/_head' do it 'adds a link preconnect tag' do render - expect(rendered).to match(%Q(<link crossorigin="" href="#{snowplow_collector_hostname}" rel="preconnect">)) + expect(rendered).to match(%(<link crossorigin="" href="#{snowplow_collector_hostname}" rel="preconnect">)) end end |