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
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-05-25 21:08:15 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-05-25 21:08:15 +0300
commit28b119a4b47d3a41c4879aab651221b85289bc69 (patch)
tree5482e008b585e7170a54f7e67e0e62bdb091b7f5 /spec/frontend
parent4dc41ac252c0bfefb9bc55a8627262cc76c69d5e (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/blob/csv/csv_viewer_spec.js10
-rw-r--r--spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap191
-rw-r--r--spec/frontend/clusters/components/remove_cluster_confirmation_spec.js22
-rw-r--r--spec/frontend/content_editor/remark_markdown_processing_spec.js44
-rw-r--r--spec/frontend/content_editor/services/markdown_serializer_spec.js4
-rw-r--r--spec/frontend/custom_metrics/components/custom_metrics_form_spec.js2
-rw-r--r--spec/frontend/diffs/components/commit_item_spec.js2
-rw-r--r--spec/frontend/fixtures/integrations.rb (renamed from spec/frontend/fixtures/services.rb)6
-rw-r--r--spec/frontend/fixtures/prometheus_integration.rb (renamed from spec/frontend/fixtures/prometheus_service.rb)6
-rw-r--r--spec/frontend/lib/utils/users_cache_spec.js27
-rw-r--r--spec/frontend/members/components/table/members_table_spec.js9
-rw-r--r--spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap2
-rw-r--r--spec/frontend/notes/components/comment_form_spec.js8
-rw-r--r--spec/frontend/notes/components/notes_app_spec.js2
-rw-r--r--spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js2
-rw-r--r--spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js3
-rw-r--r--spec/frontend/prometheus_metrics/custom_metrics_spec.js4
-rw-r--r--spec/frontend/prometheus_metrics/prometheus_metrics_spec.js2
-rw-r--r--spec/frontend/repository/components/new_directory_modal_spec.js2
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js2
-rw-r--r--spec/frontend/user_popovers_spec.js135
-rw-r--r--spec/frontend/vue_shared/components/ci_icon_spec.js48
-rw-r--r--spec/frontend/vue_shared/components/papa_parse_alert_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js10
24 files changed, 282 insertions, 265 deletions
diff --git a/spec/frontend/blob/csv/csv_viewer_spec.js b/spec/frontend/blob/csv/csv_viewer_spec.js
index ff96193a20c..9364f76da5e 100644
--- a/spec/frontend/blob/csv/csv_viewer_spec.js
+++ b/spec/frontend/blob/csv/csv_viewer_spec.js
@@ -44,7 +44,7 @@ describe('app/assets/javascripts/blob/csv/csv_viewer.vue', () => {
describe('when the CSV contains errors', () => {
it('should render alert with correct props', async () => {
createComponent({ csv: brokenCsv });
- await nextTick;
+ await nextTick();
expect(findAlert().props()).toMatchObject({
papaParseErrors: [{ code: 'UndetectableDelimiter' }],
@@ -55,14 +55,14 @@ describe('app/assets/javascripts/blob/csv/csv_viewer.vue', () => {
describe('when the CSV contains no errors', () => {
it('should not render alert', async () => {
createComponent();
- await nextTick;
+ await nextTick();
expect(findAlert().exists()).toBe(false);
});
it('renders the CSV table with the correct attributes', async () => {
createComponent();
- await nextTick;
+ await nextTick();
expect(findCsvTable().attributes()).toMatchObject({
'empty-text': 'No CSV data to display.',
@@ -72,7 +72,7 @@ describe('app/assets/javascripts/blob/csv/csv_viewer.vue', () => {
it('renders the CSV table with the correct content', async () => {
createComponent({ mountFunction: mount });
- await nextTick;
+ await nextTick();
expect(getAllByRole(wrapper.element, 'row', { name: /One/i })).toHaveLength(1);
expect(getAllByRole(wrapper.element, 'row', { name: /Two/i })).toHaveLength(1);
@@ -93,7 +93,7 @@ describe('app/assets/javascripts/blob/csv/csv_viewer.vue', () => {
skipEmptyLines: true,
complete: expect.any(Function),
});
- await nextTick;
+ await nextTick();
expect(wrapper.vm.items).toEqual(validCsv.split(','));
});
});
diff --git a/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap b/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap
index 42d81900911..46ee123a12d 100644
--- a/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap
+++ b/spec/frontend/clusters/components/__snapshots__/remove_cluster_confirmation_spec.js.snap
@@ -1,167 +1,44 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Remove cluster confirmation modal renders splitbutton with modal included 1`] = `
+exports[`Remove cluster confirmation modal renders buttons with modal included 1`] = `
<div
- class="gl-display-flex gl-justify-content-end"
+ class="gl-display-flex"
>
- <div
- class="dropdown b-dropdown gl-new-dropdown btn-group"
- menu-class="dropdown-menu-large"
+ <button
+ class="btn gl-mr-3 btn-danger btn-md gl-button"
+ data-testid="remove-integration-and-resources-button"
+ type="button"
>
- <button
- class="btn btn-danger btn-md gl-button split-content-button"
- type="button"
+ <!---->
+
+ <!---->
+
+ <span
+ class="gl-button-text"
>
- <!---->
-
- <!---->
-
- <span
- class="gl-new-dropdown-button-text"
- >
- Remove integration and resources
- </span>
-
- <!---->
- </button>
- <button
- aria-expanded="false"
- aria-haspopup="true"
- class="btn dropdown-toggle btn-danger btn-md gl-button gl-dropdown-toggle dropdown-toggle-split"
- type="button"
- >
- <span
- class="sr-only"
- >
- Toggle dropdown
- </span>
- </button>
- <ul
- class="dropdown-menu dropdown-menu-large"
- role="menu"
- tabindex="-1"
+
+ Remove integration and resources
+
+ </span>
+ </button>
+
+ <button
+ class="btn btn-danger btn-md gl-button btn-danger-secondary"
+ data-testid="remove-integration-button"
+ type="button"
+ >
+ <!---->
+
+ <!---->
+
+ <span
+ class="gl-button-text"
>
- <div
- class="gl-new-dropdown-inner"
- >
- <!---->
-
- <!---->
-
- <div
- class="gl-new-dropdown-contents"
- >
- <!---->
-
- <li
- class="gl-new-dropdown-item"
- role="presentation"
- >
- <button
- class="dropdown-item"
- role="menuitem"
- type="button"
- >
- <svg
- aria-hidden="true"
- class="gl-icon s16 gl-new-dropdown-item-check-icon gl-mt-3 gl-align-self-start"
- data-testid="dropdown-item-checkbox"
- role="img"
- >
- <use
- href="#mobile-issue-close"
- />
- </svg>
-
- <!---->
-
- <!---->
-
- <div
- class="gl-new-dropdown-item-text-wrapper"
- >
- <p
- class="gl-new-dropdown-item-text-primary"
- >
- <strong>
- Remove integration and resources
- </strong>
-
- <div>
- Deletes all GitLab resources attached to this cluster during removal
- </div>
- </p>
-
- <!---->
- </div>
-
- <!---->
- </button>
- </li>
-
- <li
- class="gl-new-dropdown-divider"
- role="presentation"
- >
- <hr
- aria-orientation="horizontal"
- class="dropdown-divider"
- role="separator"
- />
- </li>
- <li
- class="gl-new-dropdown-item"
- role="presentation"
- >
- <button
- class="dropdown-item"
- role="menuitem"
- type="button"
- >
- <svg
- aria-hidden="true"
- class="gl-icon s16 gl-new-dropdown-item-check-icon gl-visibility-hidden gl-mt-3 gl-align-self-start"
- data-testid="dropdown-item-checkbox"
- role="img"
- >
- <use
- href="#mobile-issue-close"
- />
- </svg>
-
- <!---->
-
- <!---->
-
- <div
- class="gl-new-dropdown-item-text-wrapper"
- >
- <p
- class="gl-new-dropdown-item-text-primary"
- >
- <strong>
- Remove integration
- </strong>
-
- <div>
- Removes cluster from project but keeps associated resources
- </div>
- </p>
-
- <!---->
- </div>
-
- <!---->
- </button>
- </li>
-
- <!---->
- </div>
-
- <!---->
- </div>
- </ul>
- </div>
+
+ Remove integration
+
+ </span>
+ </button>
<!---->
</div>
diff --git a/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js b/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js
index 173fefe6167..53683af893a 100644
--- a/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js
+++ b/spec/frontend/clusters/components/remove_cluster_confirmation_spec.js
@@ -3,7 +3,6 @@ import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { stubComponent } from 'helpers/stub_component';
import RemoveClusterConfirmation from '~/clusters/components/remove_cluster_confirmation.vue';
-import SplitButton from '~/vue_shared/components/split_button.vue';
describe('Remove cluster confirmation modal', () => {
let wrapper;
@@ -24,14 +23,17 @@ describe('Remove cluster confirmation modal', () => {
wrapper = null;
});
- it('renders splitbutton with modal included', () => {
+ it('renders buttons with modal included', () => {
createComponent();
expect(wrapper.element).toMatchSnapshot();
});
- describe('split button dropdown', () => {
+ describe('two buttons', () => {
const findModal = () => wrapper.findComponent(GlModal);
- const findSplitButton = () => wrapper.findComponent(SplitButton);
+ const findRemoveIntegrationButton = () =>
+ wrapper.find('[data-testid="remove-integration-button"]');
+ const findRemoveIntegrationAndResourcesButton = () =>
+ wrapper.find('[data-testid="remove-integration-and-resources-button"]');
beforeEach(() => {
createComponent({
@@ -41,8 +43,8 @@ describe('Remove cluster confirmation modal', () => {
jest.spyOn(findModal().vm, 'show').mockReturnValue();
});
- it('opens modal with "cleanup" option', async () => {
- findSplitButton().vm.$emit('remove-cluster-and-cleanup');
+ it('open modal with "cleanup" option', async () => {
+ findRemoveIntegrationAndResourcesButton().trigger('click');
await nextTick();
@@ -53,8 +55,8 @@ describe('Remove cluster confirmation modal', () => {
);
});
- it('opens modal without "cleanup" option', async () => {
- findSplitButton().vm.$emit('remove-cluster');
+ it('open modal without "cleanup" option', async () => {
+ findRemoveIntegrationButton().trigger('click');
await nextTick();
@@ -71,8 +73,8 @@ describe('Remove cluster confirmation modal', () => {
});
it('renders regular button instead', () => {
- expect(findSplitButton().exists()).toBe(false);
- expect(wrapper.find('[data-testid="btnRemove"]').exists()).toBe(true);
+ expect(findRemoveIntegrationAndResourcesButton().exists()).toBe(false);
+ expect(findRemoveIntegrationButton().exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/content_editor/remark_markdown_processing_spec.js b/spec/frontend/content_editor/remark_markdown_processing_spec.js
index eeabcf0fe4c..06f109f8603 100644
--- a/spec/frontend/content_editor/remark_markdown_processing_spec.js
+++ b/spec/frontend/content_editor/remark_markdown_processing_spec.js
@@ -13,6 +13,7 @@ import ListItem from '~/content_editor/extensions/list_item';
import OrderedList from '~/content_editor/extensions/ordered_list';
import Paragraph from '~/content_editor/extensions/paragraph';
import Sourcemap from '~/content_editor/extensions/sourcemap';
+import Strike from '~/content_editor/extensions/strike';
import remarkMarkdownDeserializer from '~/content_editor/services/remark_markdown_deserializer';
import markdownSerializer from '~/content_editor/services/markdown_serializer';
@@ -34,6 +35,7 @@ const tiptapEditor = createTestEditor({
ListItem,
OrderedList,
Sourcemap,
+ Strike,
],
});
@@ -54,6 +56,7 @@ const {
link,
listItem,
orderedList,
+ strike,
},
} = createDocBuilder({
tiptapEditor,
@@ -72,6 +75,7 @@ const {
listItem: { nodeType: ListItem.name },
orderedList: { nodeType: OrderedList.name },
paragraph: { nodeType: Paragraph.name },
+ strike: { nodeType: Strike.name },
},
});
@@ -566,10 +570,50 @@ const fn = () => 'GitLab';
),
),
},
+ {
+ markdown: '~~Strikedthrough text~~',
+ expectedDoc: doc(
+ paragraph(
+ sourceAttrs('0:23', '~~Strikedthrough text~~'),
+ strike(sourceAttrs('0:23', '~~Strikedthrough text~~'), 'Strikedthrough text'),
+ ),
+ ),
+ },
+ {
+ markdown: '<del>Strikedthrough text</del>',
+ expectedDoc: doc(
+ paragraph(
+ sourceAttrs('0:30', '<del>Strikedthrough text</del>'),
+ strike(sourceAttrs('0:30', '<del>Strikedthrough text</del>'), 'Strikedthrough text'),
+ ),
+ ),
+ },
+ {
+ markdown: '<strike>Strikedthrough text</strike>',
+ expectedDoc: doc(
+ paragraph(
+ sourceAttrs('0:36', '<strike>Strikedthrough text</strike>'),
+ strike(
+ sourceAttrs('0:36', '<strike>Strikedthrough text</strike>'),
+ 'Strikedthrough text',
+ ),
+ ),
+ ),
+ },
+ {
+ markdown: '<s>Strikedthrough text</s>',
+ expectedDoc: doc(
+ paragraph(
+ sourceAttrs('0:26', '<s>Strikedthrough text</s>'),
+ strike(sourceAttrs('0:26', '<s>Strikedthrough text</s>'), 'Strikedthrough text'),
+ ),
+ ),
+ },
])('processes %s correctly', async ({ markdown, expectedDoc }) => {
const trimmed = markdown.trim();
const document = await deserialize(trimmed);
+ expect(expectedDoc).not.toBeFalsy();
expect(document.toJSON()).toEqual(expectedDoc.toJSON());
expect(serialize(document)).toEqual(trimmed);
});
diff --git a/spec/frontend/content_editor/services/markdown_serializer_spec.js b/spec/frontend/content_editor/services/markdown_serializer_spec.js
index 25b7483f234..10625d481ce 100644
--- a/spec/frontend/content_editor/services/markdown_serializer_spec.js
+++ b/spec/frontend/content_editor/services/markdown_serializer_spec.js
@@ -1176,6 +1176,10 @@ Oranges are orange [^1]
${'link'} | ${'<a href="https://gitlab.com">link</a>'} | ${'<a href="https://gitlab.com">link modified</a>'}
${'code'} | ${'`code`'} | ${'`code modified`'}
${'code'} | ${'<code>code</code>'} | ${'<code>code modified</code>'}
+ ${'strike'} | ${'~~striked~~'} | ${'~~striked modified~~'}
+ ${'strike'} | ${'<del>striked</del>'} | ${'<del>striked modified</del>'}
+ ${'strike'} | ${'<strike>striked</strike>'} | ${'<strike>striked modified</strike>'}
+ ${'strike'} | ${'<s>striked</s>'} | ${'<s>striked modified</s>'}
`(
'preserves original $mark syntax when sourceMarkdown is available',
async ({ content, modifiedContent }) => {
diff --git a/spec/frontend/custom_metrics/components/custom_metrics_form_spec.js b/spec/frontend/custom_metrics/components/custom_metrics_form_spec.js
index 384d6699150..af56b94f90b 100644
--- a/spec/frontend/custom_metrics/components/custom_metrics_form_spec.js
+++ b/spec/frontend/custom_metrics/components/custom_metrics_form_spec.js
@@ -18,7 +18,7 @@ describe('CustomMetricsForm', () => {
wrapper = shallowMount(CustomMetricsForm, {
propsData: {
customMetricsPath: '',
- editProjectServicePath: '',
+ editIntegrationPath: '',
metricPersisted,
validateQueryPath: '',
formData,
diff --git a/spec/frontend/diffs/components/commit_item_spec.js b/spec/frontend/diffs/components/commit_item_spec.js
index eee17e118a0..e52c5abbc7b 100644
--- a/spec/frontend/diffs/components/commit_item_spec.js
+++ b/spec/frontend/diffs/components/commit_item_spec.js
@@ -6,8 +6,6 @@ import Component from '~/diffs/components/commit_item.vue';
import { getTimeago } from '~/lib/utils/datetime_utility';
import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
-jest.mock('~/user_popovers');
-
const TEST_AUTHOR_NAME = 'test';
const TEST_AUTHOR_EMAIL = 'test+test@gitlab.com';
const TEST_AUTHOR_GRAVATAR = `${TEST_HOST}/avatar/test?s=40`;
diff --git a/spec/frontend/fixtures/services.rb b/spec/frontend/fixtures/integrations.rb
index f0bb8fb962f..1bafb0bfe78 100644
--- a/spec/frontend/fixtures/services.rb
+++ b/spec/frontend/fixtures/integrations.rb
@@ -2,11 +2,11 @@
require 'spec_helper'
-RSpec.describe Projects::ServicesController, '(JavaScript fixtures)', type: :controller do
+RSpec.describe Projects::Settings::IntegrationsController, '(JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
- let(:project) { create(:project_empty_repo, namespace: namespace, path: 'services-project') }
+ let(:project) { create(:project_empty_repo, namespace: namespace, path: 'integrations-project') }
let!(:service) { create(:custom_issue_tracker_integration, project: project) }
let(:user) { project.first_owner }
@@ -20,7 +20,7 @@ RSpec.describe Projects::ServicesController, '(JavaScript fixtures)', type: :con
remove_repository(project)
end
- it 'services/edit_service.html' do
+ it 'settings/integrations/edit.html' do
get :edit, params: {
namespace_id: namespace,
project_id: project,
diff --git a/spec/frontend/fixtures/prometheus_service.rb b/spec/frontend/fixtures/prometheus_integration.rb
index aed73dc1096..883dbb929a2 100644
--- a/spec/frontend/fixtures/prometheus_service.rb
+++ b/spec/frontend/fixtures/prometheus_integration.rb
@@ -2,11 +2,11 @@
require 'spec_helper'
-RSpec.describe Projects::ServicesController, '(JavaScript fixtures)', type: :controller do
+RSpec.describe Projects::Settings::IntegrationsController, '(JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
- let(:project) { create(:project_empty_repo, namespace: namespace, path: 'services-project') }
+ let(:project) { create(:project_empty_repo, namespace: namespace, path: 'integrations-project') }
let!(:integration) { create(:prometheus_integration, project: project) }
let(:user) { project.first_owner }
@@ -20,7 +20,7 @@ RSpec.describe Projects::ServicesController, '(JavaScript fixtures)', type: :con
remove_repository(project)
end
- it 'services/prometheus/prometheus_service.html' do
+ it 'integrations/prometheus/prometheus_integration.html' do
get :edit, params: {
namespace_id: namespace,
project_id: project,
diff --git a/spec/frontend/lib/utils/users_cache_spec.js b/spec/frontend/lib/utils/users_cache_spec.js
index d35ba20f570..5a55874b5fa 100644
--- a/spec/frontend/lib/utils/users_cache_spec.js
+++ b/spec/frontend/lib/utils/users_cache_spec.js
@@ -154,8 +154,8 @@ describe('UsersCache', () => {
};
const user = await UsersCache.retrieveById(dummyUserId);
- expect(user).toBe(dummyUser);
- expect(UsersCache.internalStorage[dummyUserId]).toBe(dummyUser);
+ expect(user).toEqual(dummyUser);
+ expect(UsersCache.internalStorage[dummyUserId]).toEqual(dummyUser);
});
it('returns undefined if Ajax call fails and cache is empty', async () => {
@@ -180,6 +180,29 @@ describe('UsersCache', () => {
const user = await UsersCache.retrieveById(dummyUserId);
expect(user).toBe(dummyUser);
});
+
+ it('does not clobber existing cached values', async () => {
+ UsersCache.internalStorage[dummyUserId] = {
+ status: dummyUserStatus,
+ };
+
+ apiSpy = (id) => {
+ expect(id).toBe(dummyUserId);
+
+ return Promise.resolve({
+ data: dummyUser,
+ });
+ };
+
+ const user = await UsersCache.retrieveById(dummyUserId);
+ const expectedUser = {
+ status: dummyUserStatus,
+ ...dummyUser,
+ };
+
+ expect(user).toEqual(expectedUser);
+ expect(UsersCache.internalStorage[dummyUserId]).toEqual(expectedUser);
+ });
});
describe('retrieveStatusById', () => {
diff --git a/spec/frontend/members/components/table/members_table_spec.js b/spec/frontend/members/components/table/members_table_spec.js
index 298a01e4f4d..c02f483dac9 100644
--- a/spec/frontend/members/components/table/members_table_spec.js
+++ b/spec/frontend/members/components/table/members_table_spec.js
@@ -21,7 +21,6 @@ import {
BADGE_LABELS_PENDING_OWNER_APPROVAL,
TAB_QUERY_PARAM_VALUES,
} from '~/members/constants';
-import * as initUserPopovers from '~/user_popovers';
import {
member as memberMock,
directMember,
@@ -257,14 +256,6 @@ describe('MembersTable', () => {
});
});
- it('initializes user popovers when mounted', () => {
- const initUserPopoversMock = jest.spyOn(initUserPopovers, 'default');
-
- createComponent();
-
- expect(initUserPopoversMock).toHaveBeenCalled();
- });
-
it('adds QA selector to table', () => {
createComponent();
diff --git a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
index a93035cc53a..a9f37f90561 100644
--- a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
+++ b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
@@ -151,7 +151,7 @@ exports[`Dashboard template matches the default snapshot 1`] = `
emptynodatasvgpath="/images/illustrations/monitoring/no_data.svg"
emptyunabletoconnectsvgpath="/images/illustrations/monitoring/unable_to_connect.svg"
selectedstate="gettingStarted"
- settingspath="/monitoring/monitor-project/-/integrations/prometheus/edit"
+ settingspath="/monitoring/monitor-project/-/settings/integrations/prometheus/edit"
/>
</div>
`;
diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js
index ba5d4d27e55..df41aad2981 100644
--- a/spec/frontend/notes/components/comment_form_spec.js
+++ b/spec/frontend/notes/components/comment_form_spec.js
@@ -487,8 +487,8 @@ describe('issue_comment_form component', () => {
await findCloseReopenButton().trigger('click');
- await nextTick;
- await nextTick;
+ await nextTick();
+ await nextTick();
expect(createFlash).toHaveBeenCalledWith({
message: `Something went wrong while closing the ${type}. Please try again later.`,
@@ -523,8 +523,8 @@ describe('issue_comment_form component', () => {
await findCloseReopenButton().trigger('click');
- await nextTick;
- await nextTick;
+ await nextTick();
+ await nextTick();
expect(createFlash).toHaveBeenCalledWith({
message: `Something went wrong while reopening the ${type}. Please try again later.`,
diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js
index 413ee815906..e018523472b 100644
--- a/spec/frontend/notes/components/notes_app_spec.js
+++ b/spec/frontend/notes/components/notes_app_spec.js
@@ -19,8 +19,6 @@ import '~/behaviors/markdown/render_gfm';
import OrderedLayout from '~/vue_shared/components/ordered_layout.vue';
import * as mockData from '../mock_data';
-jest.mock('~/user_popovers', () => jest.fn());
-
setTestTimeout(1000);
const TYPE_COMMENT_FORM = 'comment-form';
diff --git a/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js b/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js
index ae5404f2d13..d5b4b3c22d8 100644
--- a/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js
+++ b/spec/frontend/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js
@@ -190,7 +190,7 @@ describe('Interval Pattern Input Component', () => {
findCustomInput().setValue(newValue);
- await nextTick;
+ await nextTick();
expect(findSelectedRadioKey()).toBe(customKey);
});
diff --git a/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js b/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js
index 6d0e99ff63e..b574b217180 100644
--- a/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js
+++ b/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js
@@ -55,6 +55,8 @@ describe('Pipelines stage component', () => {
const findDropdownToggle = () => wrapper.find('button.dropdown-toggle');
const findDropdownMenu = () =>
wrapper.find('[data-testid="mini-pipeline-graph-dropdown-menu-list"]');
+ const findDropdownMenuTitle = () =>
+ wrapper.find('[data-testid="pipeline-stage-dropdown-menu-title"]');
const findMergeTrainWarning = () => wrapper.find('[data-testid="warning-message-merge-trains"]');
const openStageDropdown = () => {
@@ -97,6 +99,7 @@ describe('Pipelines stage component', () => {
it('should render the received data and emit `clickedDropdown` event', async () => {
expect(findDropdownMenu().text()).toContain(stageReply.latest_statuses[0].name);
+ expect(findDropdownMenuTitle().text()).toContain(stageReply.name);
expect(eventHub.$emit).toHaveBeenCalledWith('clickedDropdown');
});
diff --git a/spec/frontend/prometheus_metrics/custom_metrics_spec.js b/spec/frontend/prometheus_metrics/custom_metrics_spec.js
index 473327bf5e1..fc906194059 100644
--- a/spec/frontend/prometheus_metrics/custom_metrics_spec.js
+++ b/spec/frontend/prometheus_metrics/custom_metrics_spec.js
@@ -6,9 +6,9 @@ import CustomMetrics from '~/prometheus_metrics/custom_metrics';
import { metrics1 as metrics } from './mock_data';
describe('PrometheusMetrics', () => {
- const FIXTURE = 'services/prometheus/prometheus_service.html';
+ const FIXTURE = 'integrations/prometheus/prometheus_integration.html';
const customMetricsEndpoint =
- 'http://test.host/frontend-fixtures/services-project/prometheus/metrics';
+ 'http://test.host/frontend-fixtures/integrations-project/prometheus/metrics';
let mock;
beforeEach(() => {
diff --git a/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js b/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
index 1151c0b3769..0df2aad5882 100644
--- a/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
+++ b/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
@@ -7,7 +7,7 @@ import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
import { metrics2 as metrics, missingVarMetrics } from './mock_data';
describe('PrometheusMetrics', () => {
- const FIXTURE = 'services/prometheus/prometheus_service.html';
+ const FIXTURE = 'integrations/prometheus/prometheus_integration.html';
beforeEach(() => {
loadHTMLFixture(FIXTURE);
diff --git a/spec/frontend/repository/components/new_directory_modal_spec.js b/spec/frontend/repository/components/new_directory_modal_spec.js
index fe7f024e3ea..e1c50d63851 100644
--- a/spec/frontend/repository/components/new_directory_modal_spec.js
+++ b/spec/frontend/repository/components/new_directory_modal_spec.js
@@ -67,7 +67,7 @@ describe('NewDirectoryModal', () => {
await findBranchName().vm.$emit('input', branchName);
await findCommitMessage().vm.$emit('input', commitMessage);
await findMrToggle().vm.$emit('change', createNewMr);
- await nextTick;
+ await nextTick();
};
const submitForm = async () => {
diff --git a/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js
index c870bbecd76..724fba62479 100644
--- a/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js
+++ b/spec/frontend/sidebar/components/assignees/sidebar_editable_item_spec.js
@@ -72,7 +72,7 @@ describe('boards sidebar remove issue', () => {
createComponent({ canUpdate: true, slots });
findEditButton().vm.$emit('click');
- await nextTick;
+ await nextTick();
expect(findCollapsed().isVisible()).toBe(false);
expect(findExpanded().isVisible()).toBe(true);
diff --git a/spec/frontend/user_popovers_spec.js b/spec/frontend/user_popovers_spec.js
index fa598716645..2c3db36d7e6 100644
--- a/spec/frontend/user_popovers_spec.js
+++ b/spec/frontend/user_popovers_spec.js
@@ -26,12 +26,13 @@ describe('User Popovers', () => {
return link;
};
+ const findPopovers = () => {
+ return Array.from(document.querySelectorAll('[data-testid="user-popover"]'));
+ };
const dummyUser = { name: 'root', username: 'root', is_followed: false };
const dummyUserStatus = { message: 'active' };
- let popovers;
-
const triggerEvent = (eventName, el) => {
const event = new MouseEvent(eventName, {
bubbles: true,
@@ -54,56 +55,73 @@ describe('User Popovers', () => {
.mockImplementation((userId) => userStatusCacheSpy(userId));
jest.spyOn(UsersCache, 'updateById');
- popovers = initUserPopovers(document.querySelectorAll(selector));
+ initUserPopovers((popoverInstance) => {
+ const mountingRoot = document.createElement('div');
+ document.body.appendChild(mountingRoot);
+ popoverInstance.$mount(mountingRoot);
+ });
});
afterEach(() => {
resetHTMLFixture();
});
- it('initializes a popover for each user link with a user id', () => {
- const linksWithUsers = findFixtureLinks();
+ describe('shows a placeholder popover on hover', () => {
+ let linksWithUsers;
+ beforeEach(() => {
+ linksWithUsers = findFixtureLinks();
+ linksWithUsers.forEach((el) => {
+ triggerEvent('mouseover', el);
+ });
+ });
- expect(linksWithUsers.length).toBe(popovers.length);
- });
+ it('for initial links', () => {
+ expect(findPopovers().length).toBe(linksWithUsers.length);
+ });
- it('adds popovers to user links added to the DOM tree after the initial call', async () => {
- document.body.appendChild(createUserLink());
- document.body.appendChild(createUserLink());
+ it('for elements added after initial load', async () => {
+ const addedLinks = [createUserLink(), createUserLink()];
+ addedLinks.forEach((link) => {
+ document.body.appendChild(link);
+ });
- const linksWithUsers = findFixtureLinks();
+ jest.runOnlyPendingTimers();
- expect(linksWithUsers.length).toBe(popovers.length + 2);
+ addedLinks.forEach((link) => {
+ triggerEvent('mouseover', link);
+ });
+
+ expect(findPopovers().length).toBe(linksWithUsers.length + addedLinks.length);
+ });
});
- it('does not initialize the user popovers twice for the same element', () => {
- const newPopovers = initUserPopovers(document.querySelectorAll(selector));
- const samePopovers = popovers.every((popover, index) => newPopovers[index] === popover);
+ it('does not initialize the user popovers twice for the same element', async () => {
+ const [firstUserLink] = findFixtureLinks();
+ triggerEvent('mouseover', firstUserLink);
+ jest.runOnlyPendingTimers();
+ triggerEvent('mouseleave', firstUserLink);
+ jest.runOnlyPendingTimers();
+ triggerEvent('mouseover', firstUserLink);
+ jest.runOnlyPendingTimers();
- expect(samePopovers).toBe(true);
+ expect(findPopovers().length).toBe(1);
});
- describe('when user link emits mouseenter event', () => {
+ describe('when user link emits mouseenter event with empty user cache', () => {
let userLink;
beforeEach(() => {
UsersCache.retrieveById.mockReset();
- userLink = document.querySelector(selector);
-
- triggerEvent('mouseenter', userLink);
- });
+ [userLink] = findFixtureLinks();
- it('removes title attribute from user links', () => {
- expect(userLink.getAttribute('title')).toBeFalsy();
- expect(userLink.dataset.originalTitle).toBeFalsy();
+ triggerEvent('mouseover', userLink);
});
- it('populates popovers with preloaded user data', () => {
+ it('populates popover with preloaded user data', () => {
const { name, userId, username } = userLink.dataset;
- const [firstPopover] = popovers;
- expect(firstPopover.$props.user).toEqual(
+ expect(userLink.user).toEqual(
expect.objectContaining({
name,
userId,
@@ -111,6 +129,21 @@ describe('User Popovers', () => {
}),
);
});
+ });
+
+ describe('when user link emits mouseenter event', () => {
+ let userLink;
+
+ beforeEach(() => {
+ [userLink] = findFixtureLinks();
+
+ triggerEvent('mouseover', userLink);
+ });
+
+ it('removes title attribute from user links', () => {
+ expect(userLink.getAttribute('title')).toBeFalsy();
+ expect(userLink.dataset.originalTitle).toBeFalsy();
+ });
it('fetches user info and status from the user cache', () => {
const { userId } = userLink.dataset;
@@ -118,42 +151,38 @@ describe('User Popovers', () => {
expect(UsersCache.retrieveById).toHaveBeenCalledWith(userId);
expect(UsersCache.retrieveStatusById).toHaveBeenCalledWith(userId);
});
- });
-
- it('removes aria-describedby attribute from the user link on mouseleave', () => {
- const userLink = document.querySelector(selector);
- userLink.setAttribute('aria-describedby', 'popover');
- triggerEvent('mouseleave', userLink);
+ it('removes aria-describedby attribute from the user link on mouseleave', () => {
+ userLink.setAttribute('aria-describedby', 'popover');
+ triggerEvent('mouseleave', userLink);
- expect(userLink.getAttribute('aria-describedby')).toBe(null);
- });
-
- it('updates toggle follow button and `UsersCache` when toggle follow button is clicked', async () => {
- const [firstPopover] = popovers;
- const withinFirstPopover = within(firstPopover.$el);
- const findFollowButton = () => withinFirstPopover.queryByRole('button', { name: 'Follow' });
- const findUnfollowButton = () => withinFirstPopover.queryByRole('button', { name: 'Unfollow' });
+ expect(userLink.getAttribute('aria-describedby')).toBe(null);
+ });
- const userLink = document.querySelector(selector);
- triggerEvent('mouseenter', userLink);
+ it('updates toggle follow button and `UsersCache` when toggle follow button is clicked', async () => {
+ const [firstPopover] = findPopovers();
+ const withinFirstPopover = within(firstPopover);
+ const findFollowButton = () => withinFirstPopover.queryByRole('button', { name: 'Follow' });
+ const findUnfollowButton = () =>
+ withinFirstPopover.queryByRole('button', { name: 'Unfollow' });
- await waitForPromises();
+ jest.runOnlyPendingTimers();
- const { userId } = document.querySelector(selector).dataset;
+ const { userId } = document.querySelector(selector).dataset;
- triggerEvent('click', findFollowButton());
+ triggerEvent('click', findFollowButton());
- await waitForPromises();
+ await waitForPromises();
- expect(findUnfollowButton()).not.toBe(null);
- expect(UsersCache.updateById).toHaveBeenCalledWith(userId, { is_followed: true });
+ expect(findUnfollowButton()).not.toBe(null);
+ expect(UsersCache.updateById).toHaveBeenCalledWith(userId, { is_followed: true });
- triggerEvent('click', findUnfollowButton());
+ triggerEvent('click', findUnfollowButton());
- await waitForPromises();
+ await waitForPromises();
- expect(findFollowButton()).not.toBe(null);
- expect(UsersCache.updateById).toHaveBeenCalledWith(userId, { is_followed: false });
+ expect(findFollowButton()).not.toBe(null);
+ expect(UsersCache.updateById).toHaveBeenCalledWith(userId, { is_followed: false });
+ });
});
});
diff --git a/spec/frontend/vue_shared/components/ci_icon_spec.js b/spec/frontend/vue_shared/components/ci_icon_spec.js
index 6d52db7ae65..1b502f9587c 100644
--- a/spec/frontend/vue_shared/components/ci_icon_spec.js
+++ b/spec/frontend/vue_shared/components/ci_icon_spec.js
@@ -5,6 +5,8 @@ import ciIcon from '~/vue_shared/components/ci_icon.vue';
describe('CI Icon component', () => {
let wrapper;
+ const findIconWrapper = () => wrapper.find('[data-testid="ci-icon-wrapper"]');
+
afterEach(() => {
wrapper.destroy();
wrapper = null;
@@ -23,6 +25,52 @@ describe('CI Icon component', () => {
expect(wrapper.find(GlIcon).exists()).toBe(true);
});
+ describe('active icons', () => {
+ it.each`
+ isActive | cssClass
+ ${true} | ${'active'}
+ ${false} | ${'active'}
+ `('active should be $isActive', ({ isActive, cssClass }) => {
+ wrapper = shallowMount(ciIcon, {
+ propsData: {
+ status: {
+ icon: 'status_success',
+ },
+ isActive,
+ },
+ });
+
+ if (isActive) {
+ expect(findIconWrapper().classes()).toContain(cssClass);
+ } else {
+ expect(findIconWrapper().classes()).not.toContain(cssClass);
+ }
+ });
+ });
+
+ describe('interactive icons', () => {
+ it.each`
+ isInteractive | cssClass
+ ${true} | ${'interactive'}
+ ${false} | ${'interactive'}
+ `('interactive should be $isInteractive', ({ isInteractive, cssClass }) => {
+ wrapper = shallowMount(ciIcon, {
+ propsData: {
+ status: {
+ icon: 'status_success',
+ },
+ isInteractive,
+ },
+ });
+
+ if (isInteractive) {
+ expect(findIconWrapper().classes()).toContain(cssClass);
+ } else {
+ expect(findIconWrapper().classes()).not.toContain(cssClass);
+ }
+ });
+ });
+
describe('rendering a status', () => {
it.each`
icon | group | cssClass
diff --git a/spec/frontend/vue_shared/components/papa_parse_alert_spec.js b/spec/frontend/vue_shared/components/papa_parse_alert_spec.js
index 9be2de17d01..ff4febd647e 100644
--- a/spec/frontend/vue_shared/components/papa_parse_alert_spec.js
+++ b/spec/frontend/vue_shared/components/papa_parse_alert_spec.js
@@ -22,7 +22,7 @@ describe('app/assets/javascripts/vue_shared/components/papa_parse_alert.vue', ()
it('should render alert with correct props', async () => {
createComponent({ errorMessages: [{ code: 'MissingQuotes' }] });
- await nextTick;
+ await nextTick();
expect(findAlert().props()).toMatchObject({
variant: 'danger',
@@ -37,7 +37,7 @@ describe('app/assets/javascripts/vue_shared/components/papa_parse_alert.vue', ()
createComponent({
errorMessages: [{ code: 'NotDefined', message: 'Error code is undefined' }],
});
- await nextTick;
+ await nextTick();
expect(findAlert().text()).toContain('Error code is undefined');
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js
index 31819d0e2f7..d5ea1a5acd1 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js
@@ -152,13 +152,13 @@ describe('LabelsSelectRoot', () => {
it('renders `dropdown-value-collapsed` component when `allowLabelCreate` prop is `true`', async () => {
createComponent();
- await nextTick;
+ await nextTick();
expect(wrapper.find(DropdownValueCollapsed).exists()).toBe(true);
});
it('renders `dropdown-title` component', async () => {
createComponent();
- await nextTick;
+ await nextTick();
expect(wrapper.find(DropdownTitle).exists()).toBe(true);
});
@@ -166,7 +166,7 @@ describe('LabelsSelectRoot', () => {
createComponent(mockConfig, {
default: 'None',
});
- await nextTick;
+ await nextTick();
const valueComp = wrapper.find(DropdownValue);
@@ -177,14 +177,14 @@ describe('LabelsSelectRoot', () => {
it('renders `dropdown-button` component when `showDropdownButton` prop is `true`', async () => {
createComponent();
wrapper.vm.$store.dispatch('toggleDropdownButton');
- await nextTick;
+ await nextTick();
expect(wrapper.find(DropdownButton).exists()).toBe(true);
});
it('renders `dropdown-contents` component when `showDropdownButton` & `showDropdownContents` prop is `true`', async () => {
createComponent();
wrapper.vm.$store.dispatch('toggleDropdownContents');
- await nextTick;
+ await nextTick();
expect(wrapper.find(DropdownContents).exists()).toBe(true);
});