Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-08-25 21:10:30 +00:00
parent 2b349d9a94
commit 97cdd36a0b
30 changed files with 291 additions and 141 deletions

View file

@ -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

View file

@ -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>

View file

@ -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>

View file

@ -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;
});
},
},

View file

@ -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>

View file

@ -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"

View file

@ -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;
}
}

View file

@ -0,0 +1,5 @@
---
title: Migrate environments pin button
merge_request: 38891
author: George Tsiolis
type: changed

View file

@ -0,0 +1,5 @@
---
title: Use dropdown for embed in snippets
merge_request: 39885
author:
type: changed

View file

@ -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)
```

View file

@ -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

View file

@ -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/)

View file

@ -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}")

View file

@ -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"

View file

@ -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'

View file

@ -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)

View file

@ -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

View file

@ -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"

View file

@ -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")

View file

@ -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

View file

@ -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}"

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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|

View file

@ -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 },
]);
});
});

View file

@ -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');

View file

@ -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);
});
});
});

View 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,
},
]);
});
});

View file

@ -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);
});
});