Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
2b349d9a94
commit
97cdd36a0b
30 changed files with 291 additions and 141 deletions
|
@ -1,4 +1,8 @@
|
|||
<!-- The first four sections: "Problem to solve", "Intended users", "User experience goal", and "Proposal", are strongly recommended, while the rest of the sections can be filled out during the problem validation or breakdown phase. However, keep in mind that providing complete and relevant information early helps our product team validate the problem and start working on a solution. -->
|
||||
<!-- The first section "Release notes" is required if you want to have your release post blog MR auto generated. Currently piloting, details can be found in this issue: https://gitlab.com/gitlab-com/Product/-/issues/1392 and this video: https://www.youtube.com/watch?v=rfn9ebgTwKg The next four sections: "Problem to solve", "Intended users", "User experience goal", and "Proposal", are strongly recommended in your first draft, while the rest of the sections can be filled out during the problem validation or breakdown phase. However, keep in mind that providing complete and relevant information early helps our product team validate the problem and start working on a solution. -->
|
||||
|
||||
### Release notes
|
||||
|
||||
<!-- What is the problem and solution you're proposing? This content sets the overall vision for the feature and serves as the release notes that will populate in various places, including the [release post blog](https://about.gitlab.com/releases/categories/releases/) and [Gitlab project releases](https://gitlab.com/gitlab-org/gitlab/-/releases). " -->
|
||||
|
||||
### Problem to solve
|
||||
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
<script>
|
||||
import { GlFormInputGroup, GlDeprecatedButton, GlIcon } from '@gitlab/ui';
|
||||
import { __ } from '~/locale';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlFormInputGroup,
|
||||
GlDeprecatedButton,
|
||||
GlIcon,
|
||||
},
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
optionValues: [
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
{ name: __('Embed'), value: `<script src='${this.url}.js'><\/script>` },
|
||||
{ name: __('Share'), value: this.url },
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<gl-form-input-group
|
||||
id="embeddable-text"
|
||||
:predefined-options="optionValues"
|
||||
readonly
|
||||
select-on-click
|
||||
>
|
||||
<template #append>
|
||||
<gl-deprecated-button new-style data-clipboard-target="#embeddable-text">
|
||||
<gl-icon name="copy-to-clipboard" :title="__('Copy')" />
|
||||
</gl-deprecated-button>
|
||||
</template>
|
||||
</gl-form-input-group>
|
||||
</template>
|
|
@ -3,14 +3,14 @@
|
|||
* Renders a prevent auto-stop button.
|
||||
* Used in environments table.
|
||||
*/
|
||||
import { GlDeprecatedButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
|
||||
import { GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
|
||||
import { __ } from '~/locale';
|
||||
import eventHub from '../event_hub';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlIcon,
|
||||
GlDeprecatedButton,
|
||||
GlButton,
|
||||
},
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
|
@ -30,12 +30,7 @@ export default {
|
|||
};
|
||||
</script>
|
||||
<template>
|
||||
<gl-deprecated-button
|
||||
v-gl-tooltip
|
||||
:title="$options.title"
|
||||
:aria-label="$options.title"
|
||||
@click="onPinClick"
|
||||
>
|
||||
<gl-button v-gl-tooltip :title="$options.title" :aria-label="$options.title" @click="onPinClick">
|
||||
<gl-icon name="thumbtack" />
|
||||
</gl-deprecated-button>
|
||||
</gl-button>
|
||||
</template>
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
GlSprintf,
|
||||
} from '@gitlab/ui';
|
||||
import { s__, __ } from '~/locale';
|
||||
import Api from '~/api';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { redirectTo } from '~/lib/utils/url_utility';
|
||||
import { VARIABLE_TYPE, FILE_TYPE } from '../constants';
|
||||
|
||||
|
@ -145,13 +145,17 @@ export default {
|
|||
({ key, value }) => key !== '' && value !== '',
|
||||
);
|
||||
|
||||
return Api.createPipeline(this.projectId, {
|
||||
ref: this.refValue,
|
||||
variables: filteredVariables,
|
||||
})
|
||||
.then(({ data }) => redirectTo(data.web_url))
|
||||
return axios
|
||||
.post(this.pipelinesPath, {
|
||||
ref: this.refValue,
|
||||
variables: filteredVariables,
|
||||
})
|
||||
.then(({ data }) => {
|
||||
redirectTo(`${this.pipelinesPath}/${data.id}`);
|
||||
})
|
||||
.catch(err => {
|
||||
this.error = err.response.data.message.base;
|
||||
const [message] = err.response.data.base;
|
||||
this.error = message;
|
||||
});
|
||||
},
|
||||
},
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
<script>
|
||||
import { escape as esc } from 'lodash';
|
||||
import {
|
||||
GlButton,
|
||||
GlDropdown,
|
||||
GlDropdownHeader,
|
||||
GlDropdownText,
|
||||
GlFormInputGroup,
|
||||
GlTooltipDirective,
|
||||
} from '@gitlab/ui';
|
||||
import { __ } from '~/locale';
|
||||
|
||||
const MSG_EMBED = __('Embed');
|
||||
const MSG_SHARE = __('Share');
|
||||
const MSG_COPY = __('Copy');
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlButton,
|
||||
GlDropdown,
|
||||
GlDropdownHeader,
|
||||
GlDropdownText,
|
||||
GlFormInputGroup,
|
||||
},
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
},
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
sections() {
|
||||
return [
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
{ name: MSG_EMBED, value: `<script src="${esc(this.url)}.js"><\/script>` },
|
||||
{ name: MSG_SHARE, value: this.url },
|
||||
];
|
||||
},
|
||||
},
|
||||
MSG_EMBED,
|
||||
MSG_COPY,
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<gl-dropdown
|
||||
right
|
||||
:text="$options.MSG_EMBED"
|
||||
menu-class="gl-px-1! gl-pb-5! gl-dropdown-menu-wide"
|
||||
>
|
||||
<template v-for="{ name, value } in sections">
|
||||
<gl-dropdown-header :key="`header_${name}`" data-testid="header">{{
|
||||
name
|
||||
}}</gl-dropdown-header>
|
||||
<gl-dropdown-text
|
||||
:key="`input_${name}`"
|
||||
tag="div"
|
||||
class="gl-dropdown-text-py-0 gl-dropdown-text-block"
|
||||
data-testid="input"
|
||||
>
|
||||
<gl-form-input-group :value="value" readonly select-on-click>
|
||||
<template #append>
|
||||
<gl-button
|
||||
v-gl-tooltip.hover
|
||||
:title="$options.MSG_COPY"
|
||||
:data-clipboard-text="value"
|
||||
icon="copy-to-clipboard"
|
||||
/>
|
||||
</template>
|
||||
</gl-form-input-group>
|
||||
</gl-dropdown-text>
|
||||
</template>
|
||||
</gl-dropdown>
|
||||
</template>
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { GlLoadingIcon } from '@gitlab/ui';
|
||||
import BlobEmbeddable from '~/blob/components/blob_embeddable.vue';
|
||||
import EmbedDropdown from './embed_dropdown.vue';
|
||||
import SnippetHeader from './snippet_header.vue';
|
||||
import SnippetTitle from './snippet_title.vue';
|
||||
import SnippetBlob from './snippet_blob_view.vue';
|
||||
|
@ -13,7 +13,7 @@ import { SNIPPET_MARK_VIEW_APP_START } from '~/performance_constants';
|
|||
|
||||
export default {
|
||||
components: {
|
||||
BlobEmbeddable,
|
||||
EmbedDropdown,
|
||||
SnippetHeader,
|
||||
SnippetTitle,
|
||||
GlLoadingIcon,
|
||||
|
@ -46,7 +46,7 @@ export default {
|
|||
<snippet-header :snippet="snippet" />
|
||||
<snippet-title :snippet="snippet" />
|
||||
<div class="gl-display-flex gl-justify-content-end gl-mb-5">
|
||||
<blob-embeddable v-if="embeddable" class="gl-flex-fill-1" :url="snippet.webUrl" />
|
||||
<embed-dropdown v-if="embeddable" :url="snippet.webUrl" />
|
||||
<clone-dropdown-button
|
||||
v-if="canBeCloned"
|
||||
class="gl-ml-3"
|
||||
|
|
|
@ -1104,3 +1104,28 @@ header.header-content .dropdown-menu.frequent-items-dropdown-menu {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This class won't be needed once we can directly add utility classes to the child
|
||||
// https://github.com/bootstrap-vue/bootstrap-vue/issues/5669
|
||||
.gl-dropdown-text-py-0 {
|
||||
.b-dropdown-text {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// This class won't be needed once we can directly add utility classes to the child
|
||||
// https://github.com/bootstrap-vue/bootstrap-vue/issues/5669
|
||||
.gl-dropdown-text-block {
|
||||
.b-dropdown-text {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
// This class won't be needed once we can add a prop for this in the GitLab UI component
|
||||
// https://gitlab.com/gitlab-org/gitlab-ui/-/issues/966
|
||||
.gl-new-dropdown {
|
||||
.gl-dropdown-menu-wide {
|
||||
width: $gl-dropdown-width-wide;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Migrate environments pin button
|
||||
merge_request: 38891
|
||||
author: George Tsiolis
|
||||
type: changed
|
5
changelogs/unreleased/220803-embed-dropdown-snippets.yml
Normal file
5
changelogs/unreleased/220803-embed-dropdown-snippets.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Use dropdown for embed in snippets
|
||||
merge_request: 39885
|
||||
author:
|
||||
type: changed
|
|
@ -1,7 +1,7 @@
|
|||
# End-to-end testing Best Practices
|
||||
|
||||
NOTE: **Note:**
|
||||
This is an tailored extension of the Best Practices [found in the testing guide](../best_practices.md).
|
||||
This is a tailored extension of the Best Practices [found in the testing guide](../best_practices.md).
|
||||
|
||||
## Prefer API over UI
|
||||
|
||||
|
@ -166,3 +166,26 @@ end
|
|||
NOTE: **Note:**
|
||||
A few exceptions for using a `ProjectPush` would be when your test calls for testing SSH integration or
|
||||
using the Git CLI.
|
||||
|
||||
## Preferred method to blur elements
|
||||
|
||||
To blur an element, the preferred method is to click another element that does not alter the test state.
|
||||
If there's a mask that blocks the page elements, such as may occur with some dropdowns,
|
||||
use WebDriver's native mouse events to simulate a click event on the coordinates of an element. Use the following method: `click_element_coordinates`.
|
||||
|
||||
Avoid clicking the `body` for blurring elements such as inputs and dropdowns because it clicks the center of the viewport.
|
||||
This action can also unintentionally click other elements, altering the test state and causing it to fail.
|
||||
|
||||
```ruby
|
||||
# Clicking another element to blur an input
|
||||
def add_issue_to_epic(issue_url)
|
||||
find_element(:issue_actions_split_button).find('button', text: 'Add an issue').click
|
||||
fill_element :add_issue_input, issue_url
|
||||
# Clicking the title blurs the input
|
||||
click_element :title
|
||||
click_element :add_issue_button
|
||||
end
|
||||
|
||||
# Using native mouse click events in the case of a mask/overlay
|
||||
click_element_coordinates(:title)
|
||||
```
|
||||
|
|
|
@ -22,7 +22,7 @@ module QA
|
|||
push_commit('Initial commit')
|
||||
end
|
||||
|
||||
it 'closes via pushing a commit' do
|
||||
it 'closes via pushing a commit', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/423' do
|
||||
push_commit("Closes ##{issue_id}", false)
|
||||
|
||||
Support::Retrier.retry_until(max_duration: 10, sleep_interval: 1) do
|
||||
|
|
|
@ -19,7 +19,7 @@ module QA
|
|||
Flow::Login.sign_in
|
||||
end
|
||||
|
||||
it 'is received by a user for project invitation' do
|
||||
it 'is received by a user for project invitation', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/676' do
|
||||
Flow::Project.add_member(project: project, username: user.username)
|
||||
|
||||
expect(page).to have_content(/@#{user.username}(\n| )?Given access/)
|
||||
|
|
|
@ -27,7 +27,7 @@ module QA
|
|||
end.visit!
|
||||
end
|
||||
|
||||
it 'mentions a user in a comment' do
|
||||
it 'mentions a user in a comment', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/452' do
|
||||
Page::Project::Issue::Show.perform do |show|
|
||||
show.select_all_activities_filter
|
||||
show.comment("cc-ing you here @#{user.username}")
|
||||
|
|
|
@ -17,7 +17,7 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
it 'collapses and expands reply for comments in an issue' do
|
||||
it 'collapses and expands reply for comments in an issue', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/434' do
|
||||
Page::Project::Issue::Show.perform do |show|
|
||||
one_reply = "1 reply"
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ module QA
|
|||
Resource::Issue.fabricate_via_api!.visit!
|
||||
end
|
||||
|
||||
it 'comments on an issue and edits the comment' do
|
||||
it 'comments on an issue and edits the comment', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/450' do
|
||||
Page::Project::Issue::Show.perform do |show|
|
||||
first_version_of_comment = 'First version of the comment'
|
||||
second_version_of_comment = 'Second version of the comment'
|
||||
|
|
|
@ -9,7 +9,7 @@ module QA
|
|||
Flow::Login.sign_in
|
||||
end
|
||||
|
||||
it 'creates an issue', :reliable do
|
||||
it 'creates an issue', :reliable, status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/432' do
|
||||
issue = Resource::Issue.fabricate_via_browser_ui!
|
||||
|
||||
Page::Project::Menu.perform(&:click_issues)
|
||||
|
@ -19,7 +19,7 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
it 'closes an issue', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/225303', type: :bug } do
|
||||
it 'closes an issue', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/225303', type: :bug }, status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/852' do
|
||||
closed_issue.visit!
|
||||
|
||||
Page::Project::Issue::Show.perform do |issue_page|
|
||||
|
@ -48,7 +48,7 @@ module QA
|
|||
Resource::Issue.fabricate_via_api!.visit!
|
||||
end
|
||||
|
||||
it 'comments on an issue with an attachment' do
|
||||
it 'comments on an issue with an attachment', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/393' do
|
||||
Page::Project::Issue::Show.perform do |show|
|
||||
show.comment('See attached banana for scale', attachment: file_to_attach)
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ module QA
|
|||
Page::Project::Menu.perform(&:click_issues)
|
||||
end
|
||||
|
||||
it 'successfully exports issues list as CSV' do
|
||||
it 'successfully exports issues list as CSV', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/764' do
|
||||
Page::Project::Issue::Index.perform do |index|
|
||||
index.click_export_as_csv_button
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ module QA
|
|||
Resource::Issue.fabricate_via_api!.visit!
|
||||
end
|
||||
|
||||
it 'filters comments and activities in an issue' do
|
||||
it 'filters comments and activities in an issue', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/425' do
|
||||
Page::Project::Issue::Show.perform do |show|
|
||||
my_own_comment = "My own comment"
|
||||
made_the_issue_confidential = "made the issue confidential"
|
||||
|
|
|
@ -13,7 +13,7 @@ module QA
|
|||
end.project.visit!
|
||||
end
|
||||
|
||||
it 'shows issue suggestions when creating a new issue' do
|
||||
it 'shows issue suggestions when creating a new issue', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/412' do
|
||||
Page::Project::Show.perform(&:go_to_new_issue)
|
||||
Page::Project::Issue::New.perform do |new_page|
|
||||
new_page.fill_title("issue")
|
||||
|
|
|
@ -14,7 +14,7 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
it 'imports issues from Jira' do
|
||||
it 'imports issues from Jira', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/896' do
|
||||
set_up_jira_integration
|
||||
import_jira_issues
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ module QA
|
|||
end.visit!
|
||||
end
|
||||
|
||||
it 'mentions another user in an issue' do
|
||||
it 'mentions another user in an issue', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/446' do
|
||||
Page::Project::Issue::Show.perform do |show|
|
||||
at_username = "@#{user.username}"
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module QA
|
|||
Flow::Login.sign_in
|
||||
end
|
||||
|
||||
it 'focuses on issue board' do
|
||||
it 'focuses on issue board', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/820' do
|
||||
project.visit!
|
||||
|
||||
Page::Project::Menu.perform(&:go_to_boards)
|
||||
|
|
|
@ -14,7 +14,7 @@ module QA
|
|||
Flow::Login.sign_in
|
||||
end
|
||||
|
||||
it 'creates a group milestone' do
|
||||
it 'creates a group milestone', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/922' do
|
||||
group_milestone = Resource::GroupMilestone.fabricate_via_browser_ui! do |milestone|
|
||||
milestone.title = title
|
||||
milestone.description = description
|
||||
|
|
|
@ -14,7 +14,7 @@ module QA
|
|||
Flow::Login.sign_in
|
||||
end
|
||||
|
||||
it 'creates a project milestone' do
|
||||
it 'creates a project milestone', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/901' do
|
||||
project_milestone = Resource::ProjectMilestone.fabricate_via_browser_ui! do |milestone|
|
||||
milestone.title = title
|
||||
milestone.description = description
|
||||
|
|
|
@ -25,7 +25,7 @@ module QA
|
|||
Flow::Login.sign_in
|
||||
end
|
||||
|
||||
it 'relates and unrelates one issue to/from another' do
|
||||
it 'relates and unrelates one issue to/from another', status_issue: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/541' do
|
||||
issue_1.visit!
|
||||
|
||||
Page::Project::Issue::Show.perform do |show|
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlFormInputGroup } from '@gitlab/ui';
|
||||
import BlobEmbeddable from '~/blob/components/blob_embeddable.vue';
|
||||
|
||||
describe('Blob Embeddable', () => {
|
||||
let wrapper;
|
||||
const url = 'https://foo.bar';
|
||||
|
||||
function createComponent() {
|
||||
wrapper = shallowMount(BlobEmbeddable, {
|
||||
propsData: {
|
||||
url,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
it('renders gl-form-input-group component', () => {
|
||||
expect(wrapper.find(GlFormInputGroup).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('makes up optionValues based on the url prop', () => {
|
||||
expect(wrapper.vm.optionValues).toEqual([
|
||||
{ name: 'Embed', value: expect.stringContaining(`${url}.js`) },
|
||||
{ name: 'Share', value: url },
|
||||
]);
|
||||
});
|
||||
});
|
|
@ -1,5 +1,5 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlDeprecatedButton, GlIcon } from '@gitlab/ui';
|
||||
import { GlButton, GlIcon } from '@gitlab/ui';
|
||||
import eventHub from '~/environments/event_hub';
|
||||
import PinComponent from '~/environments/components/environment_pin.vue';
|
||||
|
||||
|
@ -36,7 +36,7 @@ describe('Pin Component', () => {
|
|||
|
||||
it('should emit onPinClick when clicked', () => {
|
||||
const eventHubSpy = jest.spyOn(eventHub, '$emit');
|
||||
const button = wrapper.find(GlDeprecatedButton);
|
||||
const button = wrapper.find(GlButton);
|
||||
|
||||
button.vm.$emit('click');
|
||||
|
||||
|
|
|
@ -1,11 +1,22 @@
|
|||
import { mount, shallowMount } from '@vue/test-utils';
|
||||
import { GlNewDropdown, GlNewDropdownItem, GlForm } from '@gitlab/ui';
|
||||
import Api from '~/api';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import PipelineNewForm from '~/pipeline_new/components/pipeline_new_form.vue';
|
||||
import { mockRefs, mockParams, mockPostParams, mockProjectId } from '../mock_data';
|
||||
import { redirectTo } from '~/lib/utils/url_utility';
|
||||
|
||||
jest.mock('~/lib/utils/url_utility', () => ({
|
||||
redirectTo: jest.fn(),
|
||||
}));
|
||||
|
||||
const pipelinesPath = '/root/project/-/pipleines';
|
||||
const postResponse = { id: 1 };
|
||||
|
||||
describe('Pipeline New Form', () => {
|
||||
let wrapper;
|
||||
let mock;
|
||||
|
||||
const dummySubmitEvent = {
|
||||
preventDefault() {},
|
||||
|
@ -17,12 +28,13 @@ describe('Pipeline New Form', () => {
|
|||
const findVariableRows = () => wrapper.findAll('[data-testid="ci-variable-row"]');
|
||||
const findRemoveIcons = () => wrapper.findAll('[data-testid="remove-ci-variable-row"]');
|
||||
const findKeyInputs = () => wrapper.findAll('[data-testid="pipeline-form-ci-variable-key"]');
|
||||
const getExpectedPostParams = () => JSON.parse(mock.history.post[0].data);
|
||||
|
||||
const createComponent = (term = '', props = {}, method = shallowMount) => {
|
||||
wrapper = method(PipelineNewForm, {
|
||||
propsData: {
|
||||
projectId: mockProjectId,
|
||||
pipelinesPath: '',
|
||||
pipelinesPath,
|
||||
refs: mockRefs,
|
||||
defaultBranch: 'master',
|
||||
settingsLink: '',
|
||||
|
@ -37,24 +49,28 @@ describe('Pipeline New Form', () => {
|
|||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(Api, 'createPipeline').mockResolvedValue({ data: { web_url: '/' } });
|
||||
mock = new MockAdapter(axios);
|
||||
|
||||
mock.onPost(pipelinesPath).reply(200, postResponse);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
|
||||
mock.restore();
|
||||
});
|
||||
|
||||
describe('Dropdown with branches and tags', () => {
|
||||
it('displays dropdown with all branches and tags', () => {
|
||||
createComponent();
|
||||
expect(findDropdownItems().length).toBe(mockRefs.length);
|
||||
expect(findDropdownItems()).toHaveLength(mockRefs.length);
|
||||
});
|
||||
|
||||
it('when user enters search term the list is filtered', () => {
|
||||
createComponent('master');
|
||||
|
||||
expect(findDropdownItems().length).toBe(1);
|
||||
expect(findDropdownItems()).toHaveLength(1);
|
||||
expect(
|
||||
findDropdownItems()
|
||||
.at(0)
|
||||
|
@ -67,42 +83,45 @@ describe('Pipeline New Form', () => {
|
|||
beforeEach(() => {
|
||||
createComponent('', mockParams, mount);
|
||||
});
|
||||
it('displays the correct values for the provided query params', () => {
|
||||
it('displays the correct values for the provided query params', async () => {
|
||||
expect(findDropdown().props('text')).toBe('tag-1');
|
||||
|
||||
return wrapper.vm.$nextTick().then(() => {
|
||||
expect(findVariableRows().length).toBe(3);
|
||||
});
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(findVariableRows()).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('does not display remove icon for last row', () => {
|
||||
expect(findRemoveIcons().length).toBe(2);
|
||||
expect(findRemoveIcons()).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('removes ci variable row on remove icon button click', () => {
|
||||
it('removes ci variable row on remove icon button click', async () => {
|
||||
findRemoveIcons()
|
||||
.at(1)
|
||||
.trigger('click');
|
||||
|
||||
return wrapper.vm.$nextTick().then(() => {
|
||||
expect(findVariableRows().length).toBe(2);
|
||||
});
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(findVariableRows()).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('creates a pipeline on submit', () => {
|
||||
it('creates a pipeline on submit', async () => {
|
||||
findForm().vm.$emit('submit', dummySubmitEvent);
|
||||
|
||||
expect(Api.createPipeline).toHaveBeenCalledWith(mockProjectId, mockPostParams);
|
||||
await waitForPromises();
|
||||
|
||||
expect(getExpectedPostParams()).toEqual(mockPostParams);
|
||||
expect(redirectTo).toHaveBeenCalledWith(`${pipelinesPath}/${postResponse.id}`);
|
||||
});
|
||||
|
||||
it('creates blank variable on input change event', () => {
|
||||
it('creates blank variable on input change event', async () => {
|
||||
findKeyInputs()
|
||||
.at(2)
|
||||
.trigger('change');
|
||||
|
||||
return wrapper.vm.$nextTick().then(() => {
|
||||
expect(findVariableRows().length).toBe(4);
|
||||
});
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(findVariableRows()).toHaveLength(4);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
70
spec/frontend/snippets/components/embed_dropdown_spec.js
Normal file
70
spec/frontend/snippets/components/embed_dropdown_spec.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
import { escape as esc } from 'lodash';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import { GlFormInputGroup } from '@gitlab/ui';
|
||||
import { TEST_HOST } from 'helpers/test_constants';
|
||||
import EmbedDropdown from '~/snippets/components/embed_dropdown.vue';
|
||||
|
||||
const TEST_URL = `${TEST_HOST}/test/no">'xss`;
|
||||
|
||||
describe('snippets/components/embed_dropdown', () => {
|
||||
let wrapper;
|
||||
|
||||
const createComponent = () => {
|
||||
wrapper = mount(EmbedDropdown, {
|
||||
propsData: {
|
||||
url: TEST_URL,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
});
|
||||
|
||||
const findSectionsData = () => {
|
||||
const sections = [];
|
||||
let current = {};
|
||||
|
||||
wrapper.findAll('[data-testid="header"],[data-testid="input"]').wrappers.forEach(x => {
|
||||
const type = x.attributes('data-testid');
|
||||
|
||||
if (type === 'header') {
|
||||
current = {
|
||||
header: x.text(),
|
||||
};
|
||||
|
||||
sections.push(current);
|
||||
} else {
|
||||
const value = x.find(GlFormInputGroup).props('value');
|
||||
const copyValue = x.find('button[title="Copy"]').attributes('data-clipboard-text');
|
||||
|
||||
Object.assign(current, {
|
||||
value,
|
||||
copyValue,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return sections;
|
||||
};
|
||||
|
||||
it('renders dropdown items', () => {
|
||||
createComponent();
|
||||
|
||||
const embedValue = `<script src="${esc(TEST_URL)}.js"></script>`;
|
||||
|
||||
expect(findSectionsData()).toEqual([
|
||||
{
|
||||
header: 'Embed',
|
||||
value: embedValue,
|
||||
copyValue: embedValue,
|
||||
},
|
||||
{
|
||||
header: 'Share',
|
||||
value: TEST_URL,
|
||||
copyValue: TEST_URL,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
|
@ -2,7 +2,7 @@ import { GlLoadingIcon } from '@gitlab/ui';
|
|||
import { Blob, BinaryBlob } from 'jest/blob/components/mock_data';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import SnippetApp from '~/snippets/components/show.vue';
|
||||
import BlobEmbeddable from '~/blob/components/blob_embeddable.vue';
|
||||
import EmbedDropdown from '~/snippets/components/embed_dropdown.vue';
|
||||
import SnippetHeader from '~/snippets/components/snippet_header.vue';
|
||||
import SnippetTitle from '~/snippets/components/snippet_title.vue';
|
||||
import SnippetBlob from '~/snippets/components/snippet_blob_view.vue';
|
||||
|
@ -57,7 +57,7 @@ describe('Snippet view app', () => {
|
|||
expect(wrapper.find(SnippetTitle).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders embeddable component if visibility allows', () => {
|
||||
it('renders embed dropdown component if visibility allows', () => {
|
||||
createComponent({
|
||||
data: {
|
||||
snippet: {
|
||||
|
@ -66,7 +66,7 @@ describe('Snippet view app', () => {
|
|||
},
|
||||
},
|
||||
});
|
||||
expect(wrapper.contains(BlobEmbeddable)).toBe(true);
|
||||
expect(wrapper.contains(EmbedDropdown)).toBe(true);
|
||||
});
|
||||
|
||||
it('renders correct snippet-blob components', () => {
|
||||
|
@ -88,7 +88,7 @@ describe('Snippet view app', () => {
|
|||
${SNIPPET_VISIBILITY_PRIVATE} | ${'not render'} | ${false}
|
||||
${'foo'} | ${'not render'} | ${false}
|
||||
${SNIPPET_VISIBILITY_PUBLIC} | ${'render'} | ${true}
|
||||
`('does $condition blob-embeddable by default', ({ visibilityLevel, isRendered }) => {
|
||||
`('does $condition embed-dropdown by default', ({ visibilityLevel, isRendered }) => {
|
||||
createComponent({
|
||||
data: {
|
||||
snippet: {
|
||||
|
@ -97,7 +97,7 @@ describe('Snippet view app', () => {
|
|||
},
|
||||
},
|
||||
});
|
||||
expect(wrapper.contains(BlobEmbeddable)).toBe(isRendered);
|
||||
expect(wrapper.contains(EmbedDropdown)).toBe(isRendered);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue