Commit af2798f7 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 80486a9c 4579fd7d
...@@ -4,7 +4,7 @@ import IssueCardInnerDeprecated from './issue_card_inner_deprecated.vue'; ...@@ -4,7 +4,7 @@ import IssueCardInnerDeprecated from './issue_card_inner_deprecated.vue';
import boardsStore from '../stores/boards_store'; import boardsStore from '../stores/boards_store';
export default { export default {
name: 'BoardsIssueCard', name: 'BoardCardLayout',
components: { components: {
IssueCardInner: gon.features?.graphqlBoardLists ? IssueCardInner : IssueCardInnerDeprecated, IssueCardInner: gon.features?.graphqlBoardLists ? IssueCardInner : IssueCardInnerDeprecated,
}, },
...@@ -81,7 +81,7 @@ export default { ...@@ -81,7 +81,7 @@ export default {
:data-issue-iid="issue.iid" :data-issue-iid="issue.iid"
:data-issue-path="issue.referencePath" :data-issue-path="issue.referencePath"
data-testid="board_card" data-testid="board_card"
class="board-card p-3 rounded" class="board-card gl-p-5 gl-rounded-base"
@mousedown="mouseDown" @mousedown="mouseDown"
@mousemove="mouseMove" @mousemove="mouseMove"
@mouseup="showIssue($event)" @mouseup="showIssue($event)"
......
...@@ -17,15 +17,21 @@ export class CiSchemaExtension extends EditorLiteExtension { ...@@ -17,15 +17,21 @@ export class CiSchemaExtension extends EditorLiteExtension {
* @param {String?} opts.ref - Current ref. Defaults to master * @param {String?} opts.ref - Current ref. Defaults to master
*/ */
registerCiSchema({ projectNamespace, projectPath, ref = 'master' } = {}) { registerCiSchema({ projectNamespace, projectPath, ref = 'master' } = {}) {
const ciSchemaUri = Api.buildUrl(Api.projectFileSchemaPath) const ciSchemaPath = Api.buildUrl(Api.projectFileSchemaPath)
.replace(':namespace_path', projectNamespace) .replace(':namespace_path', projectNamespace)
.replace(':project_path', projectPath) .replace(':project_path', projectPath)
.replace(':ref', ref) .replace(':ref', ref)
.replace(':filename', EXTENSION_CI_SCHEMA_FILE_NAME_MATCH); .replace(':filename', EXTENSION_CI_SCHEMA_FILE_NAME_MATCH);
// In order for workers loaded from `data://` as the
// ones loaded by monaco editor, we use absolute URLs
// to fetch schema files, hence the `gon.gitlab_url`
// reference. This prevents error:
// "Failed to execute 'fetch' on 'WorkerGlobalScope'"
const absoluteSchemaUrl = gon.gitlab_url + ciSchemaPath;
const modelFileName = this.getModel().uri.path.split('/').pop(); const modelFileName = this.getModel().uri.path.split('/').pop();
registerSchema({ registerSchema({
uri: ciSchemaUri, uri: absoluteSchemaUrl,
fileMatch: [modelFileName], fileMatch: [modelFileName],
}); });
} }
......
...@@ -3,6 +3,7 @@ import { GlAlert, GlLoadingIcon, GlTabs, GlTab } from '@gitlab/ui'; ...@@ -3,6 +3,7 @@ import { GlAlert, GlLoadingIcon, GlTabs, GlTab } from '@gitlab/ui';
import { __, s__, sprintf } from '~/locale'; import { __, s__, sprintf } from '~/locale';
import { mergeUrlParams, redirectTo } from '~/lib/utils/url_utility'; import { mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import httpStatusCodes from '~/lib/utils/http_status';
import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue'; import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
import CiLint from './components/lint/ci_lint.vue'; import CiLint from './components/lint/ci_lint.vue';
...@@ -23,7 +24,6 @@ const COMMIT_FAILURE = 'COMMIT_FAILURE'; ...@@ -23,7 +24,6 @@ const COMMIT_FAILURE = 'COMMIT_FAILURE';
const COMMIT_SUCCESS = 'COMMIT_SUCCESS'; const COMMIT_SUCCESS = 'COMMIT_SUCCESS';
const DEFAULT_FAILURE = 'DEFAULT_FAILURE'; const DEFAULT_FAILURE = 'DEFAULT_FAILURE';
const LOAD_FAILURE_NO_FILE = 'LOAD_FAILURE_NO_FILE'; const LOAD_FAILURE_NO_FILE = 'LOAD_FAILURE_NO_FILE';
const LOAD_FAILURE_NO_REF = 'LOAD_FAILURE_NO_REF';
const LOAD_FAILURE_UNKNOWN = 'LOAD_FAILURE_UNKNOWN'; const LOAD_FAILURE_UNKNOWN = 'LOAD_FAILURE_UNKNOWN';
export default { export default {
...@@ -125,6 +125,9 @@ export default { ...@@ -125,6 +125,9 @@ export default {
isBlobContentLoading() { isBlobContentLoading() {
return this.$apollo.queries.content.loading; return this.$apollo.queries.content.loading;
}, },
isBlobContentError() {
return this.failureType === LOAD_FAILURE_NO_FILE || this.failureType === LOAD_FAILURE_UNKNOWN;
},
isCiConfigDataLoading() { isCiConfigDataLoading() {
return this.$apollo.queries.ciConfigData.loading; return this.$apollo.queries.ciConfigData.loading;
}, },
...@@ -144,14 +147,11 @@ export default { ...@@ -144,14 +147,11 @@ export default {
}, },
failure() { failure() {
switch (this.failureType) { switch (this.failureType) {
case LOAD_FAILURE_NO_REF:
return {
text: this.$options.alertTexts[LOAD_FAILURE_NO_REF],
variant: 'danger',
};
case LOAD_FAILURE_NO_FILE: case LOAD_FAILURE_NO_FILE:
return { return {
text: this.$options.alertTexts[LOAD_FAILURE_NO_FILE], text: sprintf(this.$options.alertTexts[LOAD_FAILURE_NO_FILE], {
filePath: this.ciConfigPath,
}),
variant: 'danger', variant: 'danger',
}; };
case LOAD_FAILURE_UNKNOWN: case LOAD_FAILURE_UNKNOWN:
...@@ -182,9 +182,8 @@ export default { ...@@ -182,9 +182,8 @@ export default {
[COMMIT_FAILURE]: s__('Pipelines|The GitLab CI configuration could not be updated.'), [COMMIT_FAILURE]: s__('Pipelines|The GitLab CI configuration could not be updated.'),
[COMMIT_SUCCESS]: __('Your changes have been successfully committed.'), [COMMIT_SUCCESS]: __('Your changes have been successfully committed.'),
[DEFAULT_FAILURE]: __('Something went wrong on our end.'), [DEFAULT_FAILURE]: __('Something went wrong on our end.'),
[LOAD_FAILURE_NO_FILE]: s__('Pipelines|No CI file found in this repository, please add one.'), [LOAD_FAILURE_NO_FILE]: s__(
[LOAD_FAILURE_NO_REF]: s__( 'Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again.',
'Pipelines|Repository does not have a default branch, please set one.',
), ),
[LOAD_FAILURE_UNKNOWN]: s__('Pipelines|The CI configuration was not loaded, please try again.'), [LOAD_FAILURE_UNKNOWN]: s__('Pipelines|The CI configuration was not loaded, please try again.'),
}, },
...@@ -193,12 +192,13 @@ export default { ...@@ -193,12 +192,13 @@ export default {
const { networkError } = error; const { networkError } = error;
const { response } = networkError; const { response } = networkError;
if (response?.status === 404) { // 404 for missing CI file
// 404 for missing CI file // 400 for blank projects with no repository
if (
response?.status === httpStatusCodes.NOT_FOUND ||
response?.status === httpStatusCodes.BAD_REQUEST
) {
this.reportFailure(LOAD_FAILURE_NO_FILE); this.reportFailure(LOAD_FAILURE_NO_FILE);
} else if (response?.status === 400) {
// 400 for a missing ref when no default branch is set
this.reportFailure(LOAD_FAILURE_NO_REF);
} else { } else {
this.reportFailure(LOAD_FAILURE_UNKNOWN); this.reportFailure(LOAD_FAILURE_UNKNOWN);
} }
...@@ -299,9 +299,9 @@ export default { ...@@ -299,9 +299,9 @@ export default {
<li v-for="reason in failureReasons" :key="reason">{{ reason }}</li> <li v-for="reason in failureReasons" :key="reason">{{ reason }}</li>
</ul> </ul>
</gl-alert> </gl-alert>
<div class="gl-mt-4"> <gl-loading-icon v-if="isBlobContentLoading" size="lg" class="gl-m-3" />
<gl-loading-icon v-if="isBlobContentLoading" size="lg" class="gl-m-3" /> <div v-else-if="!isBlobContentError" class="gl-mt-4">
<div v-else class="file-editor gl-mb-3"> <div class="file-editor gl-mb-3">
<div class="info-well gl-display-none gl-display-sm-block"> <div class="info-well gl-display-none gl-display-sm-block">
<validation-segment <validation-segment
class="well-segment" class="well-segment"
......
...@@ -32,13 +32,17 @@ ...@@ -32,13 +32,17 @@
.rotations-modal { .rotations-modal {
.gl-card { .gl-card {
min-width: 75%; min-width: 75%;
width: fit-content;
@include gl-bg-gray-10;
} }
&.gl-modal .modal-md { &.gl-modal .modal-md {
max-width: 640px; max-width: 640px;
} }
// TODO: move to gitlab/ui utilities
// https://gitlab.com/gitlab-org/gitlab/-/issues/297502
.gl-w-fit-content {
width: fit-content;
}
} }
//// Copied from roadmaps.scss - adapted for on-call schedules //// Copied from roadmaps.scss - adapted for on-call schedules
......
...@@ -208,7 +208,7 @@ export default { ...@@ -208,7 +208,7 @@ export default {
<gl-dropdown <gl-dropdown
data-testid="rotation-start-time" data-testid="rotation-start-time"
:text="format24HourTimeStringFromInt(form.startsAt.time)" :text="format24HourTimeStringFromInt(form.startsAt.time)"
class="gl-w-12 gl-pl-3" class="gl-px-3"
> >
<gl-dropdown-item <gl-dropdown-item
v-for="time in $options.HOURS_IN_DAY" v-for="time in $options.HOURS_IN_DAY"
...@@ -220,99 +220,117 @@ export default { ...@@ -220,99 +220,117 @@ export default {
<span class="gl-white-space-nowrap"> {{ format24HourTimeStringFromInt(time) }}</span> <span class="gl-white-space-nowrap"> {{ format24HourTimeStringFromInt(time) }}</span>
</gl-dropdown-item> </gl-dropdown-item>
</gl-dropdown> </gl-dropdown>
<span class="gl-pl-5"> {{ schedule.timezone }} </span> <span> {{ schedule.timezone }} </span>
</div> </div>
</gl-form-group> </gl-form-group>
</div> </div>
<div class="gl-w-fit-content">
<gl-toggle
v-model="endDateEnabled"
:label="$options.i18n.fields.endsOn.enableToggle"
label-position="left"
class="gl-mb-5"
/>
<gl-toggle <gl-card
v-model="endDateEnabled" v-if="endDateEnabled"
:label="$options.i18n.fields.endsOn.enableToggle" data-testid="rotation-ends-on"
label-position="left" class="gl-border-gray-400 gl-bg-gray-10 gl-w-fit-content"
class="gl-mb-5"
/>
<gl-card v-if="endDateEnabled" data-testid="rotation-ends-on">
<gl-form-group
:label="$options.i18n.fields.endsOn.title"
label-size="sm"
:invalid-feedback="$options.i18n.fields.endsOn.error"
> >
<div class="gl-display-flex gl-align-items-center"> <gl-form-group
<gl-datepicker :label="$options.i18n.fields.endsOn.title"
class="gl-mr-3" label-size="sm"
@input="$emit('update-rotation-form', { type: 'endsOn.date', value: $event })" :invalid-feedback="$options.i18n.fields.endsOn.error"
/> class="gl-mb-0"
<span> {{ __('at') }} </span> >
<gl-dropdown <div class="gl-display-flex gl-align-items-center">
data-testid="rotation-end-time" <gl-datepicker
:text="format24HourTimeStringFromInt(form.endsOn.time)" class="gl-mr-3"
class="gl-w-12 gl-pl-3" @input="$emit('update-rotation-form', { type: 'endsOn.date', value: $event })"
> />
<gl-dropdown-item <span> {{ __('at') }} </span>
v-for="time in $options.HOURS_IN_DAY" <gl-dropdown
:key="time" data-testid="rotation-end-time"
:is-checked="form.endsOn.time === time" :text="format24HourTimeStringFromInt(form.endsOn.time)"
is-check-item class="gl-px-3"
@click="$emit('update-rotation-form', { type: 'endsOn.time', value: time })"
> >
<span class="gl-white-space-nowrap"> {{ format24HourTimeStringFromInt(time) }}</span> <gl-dropdown-item
</gl-dropdown-item> v-for="time in $options.HOURS_IN_DAY"
</gl-dropdown> :key="time"
<div class="gl-mx-5">{{ schedule.timezone }}</div> :is-checked="form.endsOn.time === time"
</div> is-check-item
</gl-form-group> @click="$emit('update-rotation-form', { type: 'endsOn.time', value: time })"
</gl-card> >
<span class="gl-white-space-nowrap">
{{ format24HourTimeStringFromInt(time) }}</span
>
</gl-dropdown-item>
</gl-dropdown>
<span>{{ schedule.timezone }}</span>
</div>
</gl-form-group>
</gl-card>
<gl-toggle <gl-toggle
v-model="restrictToTimeEnabled" v-model="restrictToTimeEnabled"
data-testid="restricted-to-toggle" data-testid="restricted-to-toggle"
:label="$options.i18n.fields.restrictToTime.enableToggle" :label="$options.i18n.fields.restrictToTime.enableToggle"
label-position="left" label-position="left"
class="gl-my-5" class="gl-mt-5"
/> />
<gl-card v-if="restrictToTimeEnabled" data-testid="restricted-to-time"> <gl-card
<gl-form-group v-if="restrictToTimeEnabled"
:label="$options.i18n.fields.restrictToTime.title" data-testid="restricted-to-time"
label-size="sm" class="gl-mt-5 gl-border-gray-400 gl-bg-gray-10"
:invalid-feedback="$options.i18n.fields.endsOn.error"
> >
<div class="gl-display-flex gl-align-items-center"> <gl-form-group
<span> {{ __('From') }} </span> :label="$options.i18n.fields.restrictToTime.title"
<gl-dropdown label-size="sm"
data-testid="restricted-from" :invalid-feedback="$options.i18n.fields.endsOn.error"
:text="format24HourTimeStringFromInt(form.restrictedTo.from)" class="gl-mb-0"
class="gl-px-3" >
> <div class="gl-display-flex gl-align-items-center">
<gl-dropdown-item <span> {{ __('From') }} </span>
v-for="time in $options.HOURS_IN_DAY" <gl-dropdown
:key="time" data-testid="restricted-from"
:is-checked="form.restrictedTo.from === time" :text="format24HourTimeStringFromInt(form.restrictedTo.from)"
is-check-item class="gl-px-3"
@click="$emit('update-rotation-form', { type: 'restrictedTo.from', value: time })"
> >
<span class="gl-white-space-nowrap"> {{ format24HourTimeStringFromInt(time) }}</span> <gl-dropdown-item
</gl-dropdown-item> v-for="time in $options.HOURS_IN_DAY"
</gl-dropdown> :key="time"
<span> {{ __('To') }} </span> :is-checked="form.restrictedTo.from === time"
<gl-dropdown is-check-item
data-testid="restricted-to" @click="$emit('update-rotation-form', { type: 'restrictedTo.from', value: time })"
:text="format24HourTimeStringFromInt(form.restrictedTo.to)" >
class="gl-px-3" <span class="gl-white-space-nowrap">
> {{ format24HourTimeStringFromInt(time) }}</span
<gl-dropdown-item >
v-for="time in $options.HOURS_IN_DAY" </gl-dropdown-item>
:key="time" </gl-dropdown>
:is-checked="form.restrictedTo.to === time" <span> {{ __('To') }} </span>
is-check-item <gl-dropdown
@click="$emit('update-rotation-form', { type: 'restrictedTo.to', value: time })" data-testid="restricted-to"
:text="format24HourTimeStringFromInt(form.restrictedTo.to)"
class="gl-px-3"
> >
<span class="gl-white-space-nowrap"> {{ format24HourTimeStringFromInt(time) }}</span> <gl-dropdown-item
</gl-dropdown-item> v-for="time in $options.HOURS_IN_DAY"
</gl-dropdown> :key="time"
</div> :is-checked="form.restrictedTo.to === time"
</gl-form-group> is-check-item
</gl-card> @click="$emit('update-rotation-form', { type: 'restrictedTo.to', value: time })"
>
<span class="gl-white-space-nowrap">
{{ format24HourTimeStringFromInt(time) }}</span
>
</gl-dropdown-item>
</gl-dropdown>
<span>{{ schedule.timezone }} </span>
</div>
</gl-form-group>
</gl-card>
</div>
</gl-form> </gl-form>
</template> </template>
...@@ -266,7 +266,7 @@ RSpec.describe 'Epic show', :js do ...@@ -266,7 +266,7 @@ RSpec.describe 'Epic show', :js do
end end
end end
describe 'epic actions' do describe 'epic actions', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297505' do
shared_examples 'epic closed' do |selector| shared_examples 'epic closed' do |selector|
it 'can close an epic' do it 'can close an epic' do
expect(find('.status-box')).to have_content 'Open' expect(find('.status-box')).to have_content 'Open'
......
...@@ -20790,9 +20790,6 @@ msgstr "" ...@@ -20790,9 +20790,6 @@ msgstr ""
msgid "Pipelines|More Information" msgid "Pipelines|More Information"
msgstr "" msgstr ""
msgid "Pipelines|No CI file found in this repository, please add one."
msgstr ""
msgid "Pipelines|No triggers have been created yet. Add one using the form above." msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr "" msgstr ""
...@@ -20805,9 +20802,6 @@ msgstr "" ...@@ -20805,9 +20802,6 @@ msgstr ""
msgid "Pipelines|Project cache successfully reset." msgid "Pipelines|Project cache successfully reset."
msgstr "" msgstr ""
msgid "Pipelines|Repository does not have a default branch, please set one."
msgstr ""
msgid "Pipelines|Revoke" msgid "Pipelines|Revoke"
msgstr "" msgstr ""
...@@ -20829,6 +20823,9 @@ msgstr "" ...@@ -20829,6 +20823,9 @@ msgstr ""
msgid "Pipelines|There are currently no pipelines." msgid "Pipelines|There are currently no pipelines."
msgstr "" msgstr ""
msgid "Pipelines|There is no %{filePath} file in this repository, please add one and visit the Pipeline Editor again."
msgstr ""
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team." msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "" msgstr ""
......
...@@ -41,7 +41,7 @@ RSpec.describe 'issue state', :js do ...@@ -41,7 +41,7 @@ RSpec.describe 'issue state', :js do
end end
end end
describe 'when open' do describe 'when open', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297348' do
context 'when clicking the top `Close issue` button', :aggregate_failures do context 'when clicking the top `Close issue` button', :aggregate_failures do
let(:open_issue) { create(:issue, project: project) } let(:open_issue) { create(:issue, project: project) }
...@@ -63,7 +63,7 @@ RSpec.describe 'issue state', :js do ...@@ -63,7 +63,7 @@ RSpec.describe 'issue state', :js do
end end
end end
describe 'when closed' do describe 'when closed', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/297201' do
context 'when clicking the top `Reopen issue` button', :aggregate_failures do context 'when clicking the top `Reopen issue` button', :aggregate_failures do
let(:closed_issue) { create(:issue, project: project, state: 'closed') } let(:closed_issue) { create(:issue, project: project, state: 'closed') }
......
import { languages } from 'monaco-editor'; import { languages } from 'monaco-editor';
import { TEST_HOST } from 'helpers/test_constants';
import EditorLite from '~/editor/editor_lite'; import EditorLite from '~/editor/editor_lite';
import { CiSchemaExtension } from '~/editor/extensions/editor_ci_schema_ext'; import { CiSchemaExtension } from '~/editor/extensions/editor_ci_schema_ext';
import { EXTENSION_CI_SCHEMA_FILE_NAME_MATCH } from '~/editor/constants'; import { EXTENSION_CI_SCHEMA_FILE_NAME_MATCH } from '~/editor/constants';
...@@ -9,6 +10,7 @@ describe('~/editor/editor_ci_config_ext', () => { ...@@ -9,6 +10,7 @@ describe('~/editor/editor_ci_config_ext', () => {
let editor; let editor;
let instance; let instance;
let editorEl; let editorEl;
let originalGitlabUrl;
const createMockEditor = ({ blobPath = defaultBlobPath } = {}) => { const createMockEditor = ({ blobPath = defaultBlobPath } = {}) => {
setFixtures('<div id="editor"></div>'); setFixtures('<div id="editor"></div>');
...@@ -22,6 +24,15 @@ describe('~/editor/editor_ci_config_ext', () => { ...@@ -22,6 +24,15 @@ describe('~/editor/editor_ci_config_ext', () => {
instance.use(new CiSchemaExtension()); instance.use(new CiSchemaExtension());
}; };
beforeAll(() => {
originalGitlabUrl = gon.gitlab_url;
gon.gitlab_url = TEST_HOST;
});
afterAll(() => {
gon.gitlab_url = originalGitlabUrl;
});
beforeEach(() => { beforeEach(() => {
createMockEditor(); createMockEditor();
}); });
...@@ -73,7 +84,7 @@ describe('~/editor/editor_ci_config_ext', () => { ...@@ -73,7 +84,7 @@ describe('~/editor/editor_ci_config_ext', () => {
}); });
expect(getConfiguredYmlSchema()).toEqual({ expect(getConfiguredYmlSchema()).toEqual({
uri: `/${mockProjectNamespace}/${mockProjectPath}/-/schema/${mockRef}/${EXTENSION_CI_SCHEMA_FILE_NAME_MATCH}`, uri: `${TEST_HOST}/${mockProjectNamespace}/${mockProjectPath}/-/schema/${mockRef}/${EXTENSION_CI_SCHEMA_FILE_NAME_MATCH}`,
fileMatch: [defaultBlobPath], fileMatch: [defaultBlobPath],
}); });
}); });
...@@ -87,7 +98,7 @@ describe('~/editor/editor_ci_config_ext', () => { ...@@ -87,7 +98,7 @@ describe('~/editor/editor_ci_config_ext', () => {
}); });
expect(getConfiguredYmlSchema()).toEqual({ expect(getConfiguredYmlSchema()).toEqual({
uri: `/${mockProjectNamespace}/${mockProjectPath}/-/schema/master/${EXTENSION_CI_SCHEMA_FILE_NAME_MATCH}`, uri: `${TEST_HOST}/${mockProjectNamespace}/${mockProjectPath}/-/schema/master/${EXTENSION_CI_SCHEMA_FILE_NAME_MATCH}`,
fileMatch: ['another-ci-filename.yml'], fileMatch: ['another-ci-filename.yml'],
}); });
}); });
......
...@@ -5,6 +5,7 @@ import waitForPromises from 'helpers/wait_for_promises'; ...@@ -5,6 +5,7 @@ import waitForPromises from 'helpers/wait_for_promises';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import createMockApollo from 'jest/helpers/mock_apollo_helper'; import createMockApollo from 'jest/helpers/mock_apollo_helper';
import httpStatusCodes from '~/lib/utils/http_status';
import { objectToQuery, redirectTo, refreshCurrentPage } from '~/lib/utils/url_utility'; import { objectToQuery, redirectTo, refreshCurrentPage } from '~/lib/utils/url_utility';
import { import {
mockCiConfigPath, mockCiConfigPath,
...@@ -414,58 +415,81 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => { ...@@ -414,58 +415,81 @@ describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
mockCiConfigData.mockResolvedValue(mockCiConfigQueryResponse); mockCiConfigData.mockResolvedValue(mockCiConfigQueryResponse);
}); });
it('no error is shown when data is set', async () => { describe('when file exists', () => {
createComponentWithApollo(); beforeEach(async () => {
createComponentWithApollo();
await waitForPromises(); await waitForPromises();
});
expect(findAlert().exists()).toBe(false); it('shows editor and commit form', () => {
expect(findEditorLite().attributes('value')).toBe(mockCiYml); expect(findEditorLite().exists()).toBe(true);
}); expect(findTextEditor().exists()).toBe(true);
});
it('ci config query is called with correct variables', async () => { it('no error is shown when data is set', async () => {
createComponentWithApollo(); expect(findAlert().exists()).toBe(false);
expect(findEditorLite().attributes('value')).toBe(mockCiYml);
});
await waitForPromises(); it('ci config query is called with correct variables', async () => {
createComponentWithApollo();
expect(mockCiConfigData).toHaveBeenCalledWith({ await waitForPromises();
content: mockCiYml,
projectPath: mockProjectFullPath, expect(mockCiConfigData).toHaveBeenCalledWith({
content: mockCiYml,
projectPath: mockProjectFullPath,
});
}); });
}); });
it('shows a 404 error message', async () => { describe('when no file exists', () => {
mockBlobContentData.mockRejectedValueOnce({ const expectedAlertMsg =
response: { 'There is no .gitlab-ci.yml file in this repository, please add one and visit the Pipeline Editor again.';
status: 404,
}, it('does not show editor or commit form', async () => {
mockBlobContentData.mockRejectedValueOnce(new Error('My error!'));
createComponentWithApollo();
await waitForPromises();
expect(findEditorLite().exists()).toBe(false);
expect(findTextEditor().exists()).toBe(false);
}); });
createComponentWithApollo();
await waitForPromises(); it('shows a 404 error message', async () => {
mockBlobContentData.mockRejectedValueOnce({
response: {
status: httpStatusCodes.NOT_FOUND,
},
});
createComponentWithApollo();
expect(findAlert().text()).toBe('No CI file found in this repository, please add one.'); await waitForPromises();
});
it('shows a 400 error message', async () => { expect(findAlert().text()).toBe(expectedAlertMsg);
mockBlobContentData.mockRejectedValueOnce({
response: {
status: 400,
},
}); });
createComponentWithApollo();
await waitForPromises(); it('shows a 400 error message', async () => {
mockBlobContentData.mockRejectedValueOnce({
response: {
status: httpStatusCodes.BAD_REQUEST,
},
});
createComponentWithApollo();
expect(findAlert().text()).toBe('Repository does not have a default branch, please set one.'); await waitForPromises();
});
it('shows a unkown error message', async () => { expect(findAlert().text()).toBe(expectedAlertMsg);
mockBlobContentData.mockRejectedValueOnce(new Error('My error!')); });
createComponentWithApollo();
await waitForPromises(); it('shows a unkown error message', async () => {
mockBlobContentData.mockRejectedValueOnce(new Error('My error!'));
createComponentWithApollo();
await waitForPromises();
expect(findAlert().text()).toBe('The CI configuration was not loaded, please try again.'); expect(findAlert().text()).toBe('The CI configuration was not loaded, please try again.');
});
}); });
}); });
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment