Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-09-13 18:12:17 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-09-13 18:12:17 +0300
commit4597f7fe473d9fa622510f8967620006d4bda64e (patch)
treedafe547a51e57112ad92258f4bf992c014591a88 /spec
parent37a739daec0d7021b2af6ad03c60d37ac3461d88 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/frontend/content_editor/extensions/paste_markdown_spec.js21
-rw-r--r--spec/frontend/cycle_analytics/__snapshots__/total_time_spec.js.snap12
-rw-r--r--spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap4
-rw-r--r--spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap8
-rw-r--r--spec/frontend/design_management/pages/index_spec.js2
-rw-r--r--spec/frontend/locale/sprintf_spec.js18
-rw-r--r--spec/frontend/repository/components/blob_content_viewer_spec.js49
-rw-r--r--spec/frontend/repository/mock_data.js1
-rw-r--r--spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap14
-rw-r--r--spec/frontend/work_items/components/work_item_detail_spec.js4
-rw-r--r--spec/frontend_integration/content_editor/content_editor_integration_spec.js46
-rw-r--r--spec/lib/gitlab/ci/config/entry/root_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/trace/archive_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/variables/helpers_spec.rb89
-rw-r--r--spec/lib/gitlab_edition_spec.rb53
-rw-r--r--spec/mailers/previews_spec.rb44
-rw-r--r--spec/models/ci/job_artifact_spec.rb24
-rw-r--r--spec/services/ci/job_artifacts/create_service_spec.rb12
19 files changed, 295 insertions, 116 deletions
diff --git a/spec/frontend/content_editor/extensions/paste_markdown_spec.js b/spec/frontend/content_editor/extensions/paste_markdown_spec.js
index 53efda6aee2..30e798e8817 100644
--- a/spec/frontend/content_editor/extensions/paste_markdown_spec.js
+++ b/spec/frontend/content_editor/extensions/paste_markdown_spec.js
@@ -5,12 +5,7 @@ import Frontmatter from '~/content_editor/extensions/frontmatter';
import Bold from '~/content_editor/extensions/bold';
import { VARIANT_DANGER } from '~/flash';
import eventHubFactory from '~/helpers/event_hub_factory';
-import {
- ALERT_EVENT,
- LOADING_CONTENT_EVENT,
- LOADING_SUCCESS_EVENT,
- LOADING_ERROR_EVENT,
-} from '~/content_editor/constants';
+import { ALERT_EVENT } from '~/content_editor/constants';
import waitForPromises from 'helpers/wait_for_promises';
import { createTestEditor, createDocBuilder, waitUntilNextDocTransaction } from '../test_utils';
@@ -115,13 +110,6 @@ describe('content_editor/extensions/paste_markdown', () => {
expect(tiptapEditor.state.doc.toJSON()).toEqual(expectedDoc.toJSON());
});
-
- it(`triggers ${LOADING_SUCCESS_EVENT}`, async () => {
- await triggerPasteEventHandlerAndWaitForTransaction(buildClipboardEvent());
-
- expect(eventHub.$emit).toHaveBeenCalledWith(LOADING_CONTENT_EVENT);
- expect(eventHub.$emit).toHaveBeenCalledWith(LOADING_SUCCESS_EVENT);
- });
});
describe('when rendering markdown fails', () => {
@@ -129,13 +117,6 @@ describe('content_editor/extensions/paste_markdown', () => {
renderMarkdown.mockRejectedValueOnce();
});
- it(`triggers ${LOADING_ERROR_EVENT} event`, async () => {
- await triggerPasteEventHandler(buildClipboardEvent());
- await waitForPromises();
-
- expect(eventHub.$emit).toHaveBeenCalledWith(LOADING_ERROR_EVENT);
- });
-
it(`triggers ${ALERT_EVENT} event`, async () => {
await triggerPasteEventHandler(buildClipboardEvent());
await waitForPromises();
diff --git a/spec/frontend/cycle_analytics/__snapshots__/total_time_spec.js.snap b/spec/frontend/cycle_analytics/__snapshots__/total_time_spec.js.snap
index 7f211c1028e..92927ef16ec 100644
--- a/spec/frontend/cycle_analytics/__snapshots__/total_time_spec.js.snap
+++ b/spec/frontend/cycle_analytics/__snapshots__/total_time_spec.js.snap
@@ -1,28 +1,28 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`TotalTime with a blank object should render -- 1`] = `"<span class=\\"total-time\\"> -- </span>"`;
+exports[`TotalTime with a blank object should render -- 1`] = `"<span> -- </span>"`;
exports[`TotalTime with a valid time object with {"days": 3, "mins": 47, "seconds": 3} 1`] = `
-"<span class=\\"total-time\\">
+"<span>
3 <span>days</span></span>"
`;
exports[`TotalTime with a valid time object with {"hours": 7, "mins": 20, "seconds": 10} 1`] = `
-"<span class=\\"total-time\\">
+"<span>
7 <span>hrs</span></span>"
`;
exports[`TotalTime with a valid time object with {"hours": 23, "mins": 10} 1`] = `
-"<span class=\\"total-time\\">
+"<span>
23 <span>hrs</span></span>"
`;
exports[`TotalTime with a valid time object with {"mins": 47, "seconds": 3} 1`] = `
-"<span class=\\"total-time\\">
+"<span>
47 <span>mins</span></span>"
`;
exports[`TotalTime with a valid time object with {"seconds": 35} 1`] = `
-"<span class=\\"total-time\\">
+"<span>
35 <span>s</span></span>"
`;
diff --git a/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap b/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap
index 8fe3e92360a..096d776a7d2 100644
--- a/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap
+++ b/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap
@@ -11,7 +11,7 @@ exports[`Design management list item component when item appears in view after i
exports[`Design management list item component with notes renders item with multiple comments 1`] = `
<router-link-stub
ariacurrentvalue="page"
- class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new"
+ class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new gl-mb-0"
event="click"
tag="a"
to="[object Object]"
@@ -88,7 +88,7 @@ exports[`Design management list item component with notes renders item with mult
exports[`Design management list item component with notes renders item with single comment 1`] = `
<router-link-stub
ariacurrentvalue="page"
- class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new"
+ class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new gl-mb-0"
event="click"
tag="a"
to="[object Object]"
diff --git a/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap b/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap
index 9997f02cd01..8cfe11c9040 100644
--- a/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap
+++ b/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap
@@ -9,9 +9,7 @@ exports[`Design management index page designs renders error 1`] = `
<!---->
- <div
- class="gl-mt-6"
- >
+ <div>
<gl-alert-stub
dismisslabel="Dismiss"
primarybuttonlink=""
@@ -43,9 +41,7 @@ exports[`Design management index page designs renders loading icon 1`] = `
<!---->
- <div
- class="gl-mt-6"
- >
+ <div>
<gl-loading-icon-stub
color="dark"
label="Loading"
diff --git a/spec/frontend/design_management/pages/index_spec.js b/spec/frontend/design_management/pages/index_spec.js
index f90feaadfb0..1033b509419 100644
--- a/spec/frontend/design_management/pages/index_spec.js
+++ b/spec/frontend/design_management/pages/index_spec.js
@@ -254,7 +254,7 @@ describe('Design management index page', () => {
'gl-flex-direction-column',
'col-md-6',
'col-lg-3',
- 'gl-mb-3',
+ 'gl-mt-5',
]);
});
});
diff --git a/spec/frontend/locale/sprintf_spec.js b/spec/frontend/locale/sprintf_spec.js
index 52e903b819f..e0d0e117ea4 100644
--- a/spec/frontend/locale/sprintf_spec.js
+++ b/spec/frontend/locale/sprintf_spec.js
@@ -63,12 +63,26 @@ describe('locale', () => {
it('does not escape parameters for escapeParameters = false', () => {
const input = 'contains %{safeContent}';
const parameters = {
- safeContent: '<strong>bold attempt</strong>',
+ safeContent: '15',
};
const output = sprintf(input, parameters, false);
- expect(output).toBe('contains <strong>bold attempt</strong>');
+ expect(output).toBe('contains 15');
+ });
+
+ describe('replaces duplicated % in input', () => {
+ it('removes duplicated percentage signs', () => {
+ const input = 'contains duplicated %{safeContent}%%';
+
+ const parameters = {
+ safeContent: '15',
+ };
+
+ const output = sprintf(input, parameters, false);
+
+ expect(output).toBe('contains duplicated 15%');
+ });
});
});
});
diff --git a/spec/frontend/repository/components/blob_content_viewer_spec.js b/spec/frontend/repository/components/blob_content_viewer_spec.js
index 0f7cf4e61b2..6ece72c41bb 100644
--- a/spec/frontend/repository/components/blob_content_viewer_spec.js
+++ b/spec/frontend/repository/components/blob_content_viewer_spec.js
@@ -17,7 +17,8 @@ import { loadViewer } from '~/repository/components/blob_viewers';
import DownloadViewer from '~/repository/components/blob_viewers/download_viewer.vue';
import EmptyViewer from '~/repository/components/blob_viewers/empty_viewer.vue';
import SourceViewer from '~/vue_shared/components/source_viewer/source_viewer.vue';
-import blobInfoQuery from '~/repository/queries/blob_info.query.graphql';
+import blobInfoQuery from 'shared_queries/repository/blob_info.query.graphql';
+import projectInfoQuery from '~/repository/queries/project_info.query.graphql';
import userInfoQuery from '~/repository/queries/user_info.query.graphql';
import applicationInfoQuery from '~/repository/queries/application_info.query.graphql';
import CodeIntelligence from '~/code_navigation/components/app.vue';
@@ -45,8 +46,9 @@ jest.mock('~/lib/utils/common_utils');
jest.mock('~/blob/line_highlighter');
let wrapper;
-let mockResolver;
+let blobInfoMockResolver;
let userInfoMockResolver;
+let projectInfoMockResolver;
let applicationInfoMockResolver;
const mockAxios = new MockAdapter(axios);
@@ -74,22 +76,40 @@ const createComponent = async (mockData = {}, mountFn = shallowMount, mockRoute
highlightJs = true,
} = mockData;
- const project = {
+ const blobInfo = {
...projectMock,
+ repository: {
+ empty,
+ blobs: { nodes: [blob] },
+ },
+ };
+
+ const projectInfo = {
+ __typename: 'Project',
+ id: '123',
userPermissions: {
pushCode,
forkProject,
downloadCode,
createMergeRequestIn,
},
- repository: {
- empty,
- blobs: { nodes: [blob] },
+ pathLocks: {
+ nodes: [
+ {
+ id: 'test',
+ path: 'locked_file.js',
+ user: { id: '123', username: 'root' },
+ },
+ ],
},
};
- mockResolver = jest.fn().mockResolvedValue({
- data: { isBinary, project },
+ projectInfoMockResolver = jest.fn().mockResolvedValue({
+ data: { project: projectInfo },
+ });
+
+ blobInfoMockResolver = jest.fn().mockResolvedValue({
+ data: { isBinary, project: blobInfo },
});
userInfoMockResolver = jest.fn().mockResolvedValue({
@@ -101,8 +121,9 @@ const createComponent = async (mockData = {}, mountFn = shallowMount, mockRoute
});
const fakeApollo = createMockApollo([
- [blobInfoQuery, mockResolver],
+ [blobInfoQuery, blobInfoMockResolver],
[userInfoQuery, userInfoMockResolver],
+ [projectInfoQuery, projectInfoMockResolver],
[applicationInfoQuery, applicationInfoMockResolver],
]);
@@ -129,7 +150,7 @@ const createComponent = async (mockData = {}, mountFn = shallowMount, mockRoute
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ project, isBinary });
+ wrapper.setData({ project: blobInfo, isBinary });
await waitForPromises();
};
@@ -504,14 +525,16 @@ describe('Blob content viewer component', () => {
async ({ highlightJs, shouldFetchRawText }) => {
await createComponent({ highlightJs });
- expect(mockResolver).toHaveBeenCalledWith(expect.objectContaining({ shouldFetchRawText }));
+ expect(blobInfoMockResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ shouldFetchRawText }),
+ );
},
);
it('is called with originalBranch value if the prop has a value', async () => {
await createComponent({ inject: { originalBranch: 'some-branch' } });
- expect(mockResolver).toHaveBeenCalledWith(
+ expect(blobInfoMockResolver).toHaveBeenCalledWith(
expect.objectContaining({
ref: 'some-branch',
}),
@@ -521,7 +544,7 @@ describe('Blob content viewer component', () => {
it('is called with ref value if the originalBranch prop has no value', async () => {
await createComponent();
- expect(mockResolver).toHaveBeenCalledWith(
+ expect(blobInfoMockResolver).toHaveBeenCalledWith(
expect.objectContaining({
ref: 'default-ref',
}),
diff --git a/spec/frontend/repository/mock_data.js b/spec/frontend/repository/mock_data.js
index 4db295fe0b7..cda47a5b0a5 100644
--- a/spec/frontend/repository/mock_data.js
+++ b/spec/frontend/repository/mock_data.js
@@ -1,4 +1,5 @@
export const simpleViewerMock = {
+ __typename: 'RepositoryBlob',
id: '1',
name: 'some_file.js',
size: 123,
diff --git a/spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap b/spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap
index 1798ca5ccde..f9d615d4f68 100644
--- a/spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap
+++ b/spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap
@@ -5,7 +5,7 @@ exports[`Upload dropzone component correctly overrides description and drop mess
class="gl-w-full gl-relative"
>
<button
- class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4"
+ class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0"
type="button"
>
<div
@@ -86,7 +86,7 @@ exports[`Upload dropzone component when dragging renders correct template when d
class="gl-w-full gl-relative"
>
<button
- class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4"
+ class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0"
type="button"
>
<div
@@ -171,7 +171,7 @@ exports[`Upload dropzone component when dragging renders correct template when d
class="gl-w-full gl-relative"
>
<button
- class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4"
+ class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0"
type="button"
>
<div
@@ -256,7 +256,7 @@ exports[`Upload dropzone component when dragging renders correct template when d
class="gl-w-full gl-relative"
>
<button
- class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4"
+ class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0"
type="button"
>
<div
@@ -342,7 +342,7 @@ exports[`Upload dropzone component when dragging renders correct template when d
class="gl-w-full gl-relative"
>
<button
- class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4"
+ class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0"
type="button"
>
<div
@@ -428,7 +428,7 @@ exports[`Upload dropzone component when dragging renders correct template when d
class="gl-w-full gl-relative"
>
<button
- class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4"
+ class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0"
type="button"
>
<div
@@ -514,7 +514,7 @@ exports[`Upload dropzone component when no slot provided renders default dropzon
class="gl-w-full gl-relative"
>
<button
- class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4"
+ class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0"
type="button"
>
<div
diff --git a/spec/frontend/work_items/components/work_item_detail_spec.js b/spec/frontend/work_items/components/work_item_detail_spec.js
index 49f7957440d..351a363590c 100644
--- a/spec/frontend/work_items/components/work_item_detail_spec.js
+++ b/spec/frontend/work_items/components/work_item_detail_spec.js
@@ -142,6 +142,10 @@ describe('WorkItemDetail component', () => {
expect(findWorkItemState().exists()).toBe(true);
expect(findWorkItemTitle().exists()).toBe(true);
});
+
+ it('updates the document title', () => {
+ expect(document.title).toEqual('Updated title · Task · test-project-path');
+ });
});
describe('close button', () => {
diff --git a/spec/frontend_integration/content_editor/content_editor_integration_spec.js b/spec/frontend_integration/content_editor/content_editor_integration_spec.js
index 7781a463fd6..c0c6b5e5dc8 100644
--- a/spec/frontend_integration/content_editor/content_editor_integration_spec.js
+++ b/spec/frontend_integration/content_editor/content_editor_integration_spec.js
@@ -27,6 +27,10 @@ describe('content_editor', () => {
await nextTick();
};
+ const mockRenderMarkdownResponse = (response) => {
+ renderMarkdown.mockImplementation((markdown) => (markdown ? response : null));
+ };
+
beforeEach(() => {
renderMarkdown = jest.fn();
});
@@ -34,7 +38,7 @@ describe('content_editor', () => {
describe('when loading initial content', () => {
describe('when the initial content is empty', () => {
it('still hides the loading indicator', async () => {
- renderMarkdown.mockResolvedValue('');
+ mockRenderMarkdownResponse('');
buildWrapper();
@@ -47,9 +51,11 @@ describe('content_editor', () => {
describe('when the initial content is not empty', () => {
const initialContent = '<p><strong>bold text</strong></p>';
beforeEach(async () => {
- renderMarkdown.mockResolvedValue(initialContent);
+ mockRenderMarkdownResponse(initialContent);
- buildWrapper();
+ buildWrapper({
+ markdown: '**bold text**',
+ });
await waitUntilContentIsLoaded();
});
@@ -129,4 +135,38 @@ This reference tag is a mix of letters and numbers [^footnote].
expect(wrapper.findByTestId('table-of-contents').text()).toContain('Heading 1');
expect(wrapper.findByTestId('table-of-contents').text()).toContain('Heading 2');
});
+
+ describe('when pasting content', () => {
+ const buildClipboardData = (data = {}) => ({
+ clipboardData: {
+ getData(mimeType) {
+ return data[mimeType];
+ },
+ types: Object.keys(data),
+ },
+ });
+
+ describe('when the clipboard does not contain text/html data', () => {
+ it('processes the clipboard content as markdown', async () => {
+ const processedMarkdown = '<strong>bold text</strong>';
+
+ buildWrapper();
+
+ await waitUntilContentIsLoaded();
+
+ mockRenderMarkdownResponse(processedMarkdown);
+
+ wrapper.find('[contenteditable]').trigger(
+ 'paste',
+ buildClipboardData({
+ 'text/plain': '**bold text**',
+ }),
+ );
+
+ await waitUntilContentIsLoaded();
+
+ expect(wrapper.find('[contenteditable]').html()).toContain(processedMarkdown);
+ });
+ });
+ });
});
diff --git a/spec/lib/gitlab/ci/config/entry/root_spec.rb b/spec/lib/gitlab/ci/config/entry/root_spec.rb
index 19a4c82dcc1..3d19987a0be 100644
--- a/spec/lib/gitlab/ci/config/entry/root_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/root_spec.rb
@@ -155,7 +155,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: "postgres:9.1" }, { name: "mysql:5.5" }],
cache: [{ key: "k", untracked: true, paths: ["public/"], policy: "pull-push", when: 'on_success' }],
only: { refs: %w(branches tags) },
- job_variables: { 'VAR' => 'job' },
+ job_variables: { 'VAR' => { value: 'job' } },
root_variables_inheritance: true,
after_script: [],
ignore: false,
@@ -215,7 +215,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' }],
- job_variables: { 'VAR' => 'job' },
+ job_variables: { 'VAR' => { value: 'job' } },
root_variables_inheritance: true,
ignore: false,
after_script: ['make clean'],
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
index b6cb07bf119..75f6a773c2d 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -104,8 +104,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it do
is_expected.to include(yaml_variables: [{ key: 'VAR1', value: 'new var 1' },
- { key: 'VAR2', value: 'var 2' },
- { key: 'VAR3', value: 'var 3' }])
+ { key: 'VAR3', value: 'var 3' },
+ { key: 'VAR2', value: 'var 2' }])
end
end
diff --git a/spec/lib/gitlab/ci/trace/archive_spec.rb b/spec/lib/gitlab/ci/trace/archive_spec.rb
index 3ae0e5d1f0e..f91cb03883a 100644
--- a/spec/lib/gitlab/ci/trace/archive_spec.rb
+++ b/spec/lib/gitlab/ci/trace/archive_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Trace::Archive do
context 'with transactional fixtures' do
- let_it_be(:job) { create(:ci_build, :success, :trace_live) }
+ let_it_be_with_reload(:job) { create(:ci_build, :success, :trace_live) }
let_it_be_with_reload(:trace_metadata) { create(:ci_build_trace_metadata, build: job) }
let_it_be(:src_checksum) do
job.trace.read { |stream| Digest::MD5.hexdigest(stream.raw) }
diff --git a/spec/lib/gitlab/ci/variables/helpers_spec.rb b/spec/lib/gitlab/ci/variables/helpers_spec.rb
index ece456ee2d3..fb1e66bd605 100644
--- a/spec/lib/gitlab/ci/variables/helpers_spec.rb
+++ b/spec/lib/gitlab/ci/variables/helpers_spec.rb
@@ -22,14 +22,14 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
subject { described_class.merge_variables(current_variables, new_variables) }
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
context 'when new variables is a hash' do
let(:new_variables) do
{ 'key2' => 'value22', 'key3' => 'value3' }
end
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
end
context 'when new variables is a hash with symbol keys' do
@@ -37,7 +37,7 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
{ key2: 'value22', key3: 'value3' }
end
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
end
context 'when new variables is nil' do
@@ -47,69 +47,58 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
{ key: 'key2', value: 'value2' }]
end
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
end
end
- describe '.transform_to_yaml_variables' do
- let(:variables) do
- { 'key1' => 'value1', 'key2' => 'value2' }
- end
+ describe '.transform_to_array' do
+ subject { described_class.transform_to_array(variables) }
- let(:result) do
- [{ key: 'key1', value: 'value1' },
- { key: 'key2', value: 'value2' }]
- end
-
- subject { described_class.transform_to_yaml_variables(variables) }
-
- it { is_expected.to eq(result) }
-
- context 'when variables is nil' do
- let(:variables) {}
-
- it { is_expected.to eq([]) }
- end
- end
+ context 'when values are strings' do
+ let(:variables) do
+ { 'key1' => 'value1', 'key2' => 'value2' }
+ end
- describe '.transform_from_yaml_variables' do
- let(:variables) do
- [{ key: 'key1', value: 'value1' },
- { key: 'key2', value: 'value2' }]
- end
+ let(:result) do
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value2' }]
+ end
- let(:result) do
- { 'key1' => 'value1', 'key2' => 'value2' }
+ it { is_expected.to match_array(result) }
end
- subject { described_class.transform_from_yaml_variables(variables) }
-
- it { is_expected.to eq(result) }
-
context 'when variables is nil' do
let(:variables) {}
- it { is_expected.to eq({}) }
+ it { is_expected.to match_array([]) }
end
- context 'when variables is a hash' do
+ context 'when values are hashes' do
let(:variables) do
- { key1: 'value1', 'key2' => 'value2' }
+ { 'key1' => { value: 'value1', description: 'var 1' }, 'key2' => { value: 'value2' } }
end
- it { is_expected.to eq(result) }
- end
-
- context 'when variables contain integers and symbols' do
- let(:variables) do
- { key1: 1, key2: :value2 }
+ let(:result) do
+ [{ key: 'key1', value: 'value1', description: 'var 1' },
+ { key: 'key2', value: 'value2' }]
end
- let(:result1) do
- { 'key1' => '1', 'key2' => 'value2' }
- end
+ it { is_expected.to match_array(result) }
+
+ context 'when a value data has `key` as a key' do
+ let(:variables) do
+ { 'key1' => { value: 'value1', key: 'new_key1' }, 'key2' => { value: 'value2' } }
+ end
- it { is_expected.to eq(result1) }
+ let(:result) do
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value2' }]
+ end
+
+ it 'ignores the key set with "key"' do
+ is_expected.to match_array(result)
+ end
+ end
end
end
@@ -134,7 +123,7 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
subject { described_class.inherit_yaml_variables(from: from, to: to, inheritance: inheritance) }
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
context 'when inheritance is false' do
let(:inheritance) { false }
@@ -144,7 +133,7 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
{ key: 'key3', value: 'value3' }]
end
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
end
context 'when inheritance is array' do
@@ -155,7 +144,7 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
{ key: 'key3', value: 'value3' }]
end
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
end
end
end
diff --git a/spec/lib/gitlab_edition_spec.rb b/spec/lib/gitlab_edition_spec.rb
index 0ee63279984..46be1471896 100644
--- a/spec/lib/gitlab_edition_spec.rb
+++ b/spec/lib/gitlab_edition_spec.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'fast_spec_helper'
+require 'rspec-parameterized'
RSpec.describe GitlabEdition do
def remove_instance_variable(ivar)
@@ -27,7 +28,57 @@ RSpec.describe GitlabEdition do
end
end
- describe 'extensions' do
+ describe '.path_glob' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:root) { described_class.root.to_s }
+
+ subject { described_class.path_glob(path) }
+
+ before do
+ allow(described_class).to receive(:jh?).and_return(jh)
+ allow(described_class).to receive(:ee?).and_return(ee)
+ end
+
+ where(:ee, :jh, :path, :expected) do
+ false | false | nil | ''
+ true | false | nil | '{,ee/}'
+ true | true | nil | '{,ee/,jh/}'
+ false | true | nil | '{,ee/,jh/}'
+ false | false | 'app/models' | 'app/models'
+ true | false | 'app/models' | '{,ee/}app/models'
+ true | true | 'app/models' | '{,ee/,jh/}app/models'
+ false | true | 'app/models' | '{,ee/,jh/}app/models'
+ end
+
+ with_them do
+ it { is_expected.to eq("#{root}/#{expected}") }
+ end
+ end
+
+ describe '.extension_path_prefixes' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { described_class.extension_path_prefixes }
+
+ before do
+ allow(described_class).to receive(:jh?).and_return(jh)
+ allow(described_class).to receive(:ee?).and_return(ee)
+ end
+
+ where(:ee, :jh, :expected) do
+ false | false | ''
+ true | false | '{,ee/}'
+ true | true | '{,ee/,jh/}'
+ false | true | '{,ee/,jh/}'
+ end
+
+ with_them do
+ it { is_expected.to eq(expected) }
+ end
+ end
+
+ describe '.extensions' do
context 'when .jh? is true' do
before do
allow(described_class).to receive(:jh?).and_return(true)
diff --git a/spec/mailers/previews_spec.rb b/spec/mailers/previews_spec.rb
new file mode 100644
index 00000000000..14bd56e5d40
--- /dev/null
+++ b/spec/mailers/previews_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Mailer previews' do
+ # Setup needed for email previews
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :repository, :import_failed, group: group, import_last_error: 'some error') }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
+ let_it_be(:milestone) { create(:milestone, project: project) }
+ let_it_be(:issue) { create(:issue, project: project, milestone: milestone) }
+ let_it_be(:remote_mirror) { create(:remote_mirror, project: project) }
+ let_it_be(:member) { create(:project_member, :maintainer, project: project, created_by: user) }
+
+ Gitlab.ee do
+ let_it_be(:epic) { create(:epic, group: group) }
+ end
+
+ let(:expected_kind) { [Mail::Message, ActionMailer::MessageDelivery] }
+
+ let(:pending_failures) do
+ {
+ 'NotifyPreview#note_merge_request_email_for_diff_discussion' =>
+ 'https://gitlab.com/gitlab-org/gitlab/-/issues/372885'
+ }
+ end
+
+ subject { preview.call(email) }
+
+ where(:preview, :email) do
+ ActionMailer::Preview.all.flat_map { |preview| preview.emails.map { |email| [preview, email] } }
+ end
+
+ with_them do
+ it do
+ issue_link = pending_failures["#{preview.name}##{email}"]
+ pending "See #{issue_link}" if issue_link
+
+ is_expected.to be_kind_of(Mail::Message).or(be_kind_of(ActionMailer::MessageDelivery))
+ end
+ end
+end
diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb
index f31edb747bd..1962d232f3d 100644
--- a/spec/models/ci/job_artifact_spec.rb
+++ b/spec/models/ci/job_artifact_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe Ci::JobArtifact do
describe "Associations" do
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:job) }
+ it { is_expected.to validate_presence_of(:job) }
+ it { is_expected.to validate_presence_of(:partition_id) }
end
it { is_expected.to respond_to(:file) }
@@ -758,4 +760,26 @@ RSpec.describe Ci::JobArtifact do
let!(:model) { create(:ci_job_artifact, project: parent) }
end
end
+
+ context 'with partition_id' do
+ let(:job) { build(:ci_build, partition_id: 123) }
+ let(:artifact) { build(:ci_job_artifact, job: job, partition_id: nil) }
+
+ it 'copies the partition_id from job' do
+ expect { artifact.valid? }.to change(artifact, :partition_id).from(nil).to(123)
+ end
+
+ context 'when the job is missing' do
+ let(:artifact) do
+ build(:ci_job_artifact,
+ project: build_stubbed(:project),
+ job: nil,
+ partition_id: nil)
+ end
+
+ it 'does not change the partition_id value' do
+ expect { artifact.valid? }.not_to change(artifact, :partition_id)
+ end
+ end
+ end
end
diff --git a/spec/services/ci/job_artifacts/create_service_spec.rb b/spec/services/ci/job_artifacts/create_service_spec.rb
index 6809b694b22..a2259f9813b 100644
--- a/spec/services/ci/job_artifacts/create_service_spec.rb
+++ b/spec/services/ci/job_artifacts/create_service_spec.rb
@@ -181,6 +181,18 @@ RSpec.describe Ci::JobArtifacts::CreateService do
end
end
+ context 'with job partitioning' do
+ let(:job) { create(:ci_build, project: project, partition_id: 123) }
+
+ it 'sets partition_id on artifacts' do
+ expect { subject }.to change { Ci::JobArtifact.count }
+
+ artifacts_partitions = job.job_artifacts.map(&:partition_id).uniq
+
+ expect(artifacts_partitions).to eq([123])
+ end
+ end
+
shared_examples 'rescues object storage error' do |klass, message, expected_message|
it "handles #{klass}" do
allow_next_instance_of(JobArtifactUploader) do |uploader|