Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
4d3bbc4990
commit
87543246d9
|
@ -4,10 +4,6 @@ GraphQL/OrderedArguments:
|
|||
- app/graphql/resolvers/base_issues_resolver.rb
|
||||
- app/graphql/resolvers/design_management/designs_resolver.rb
|
||||
- app/graphql/resolvers/design_management/version/design_at_version_resolver.rb
|
||||
- app/graphql/resolvers/merge_requests_resolver.rb
|
||||
- app/graphql/resolvers/paginated_tree_resolver.rb
|
||||
- app/graphql/resolvers/tree_resolver.rb
|
||||
- app/graphql/resolvers/users/groups_resolver.rb
|
||||
- app/graphql/types/commit_action_type.rb
|
||||
- app/graphql/types/diff_paths_input_type.rb
|
||||
- app/graphql/types/issues/negated_issue_filter_input_type.rb
|
||||
|
|
|
@ -5,7 +5,6 @@ import { __ } from '../../../locale';
|
|||
export default class PayloadPreviewer {
|
||||
constructor(trigger) {
|
||||
this.trigger = trigger;
|
||||
this.container = document.querySelector(trigger.dataset.payloadSelector);
|
||||
this.isVisible = false;
|
||||
this.isInserted = false;
|
||||
}
|
||||
|
@ -23,21 +22,27 @@ export default class PayloadPreviewer {
|
|||
});
|
||||
}
|
||||
|
||||
getContainer() {
|
||||
return document.querySelector(this.trigger.dataset.payloadSelector);
|
||||
}
|
||||
|
||||
requestPayload() {
|
||||
if (this.isInserted) return this.showPayload();
|
||||
|
||||
this.spinner.classList.add('d-inline-flex');
|
||||
this.spinner.classList.add('gl-display-inline-flex');
|
||||
|
||||
const container = this.getContainer();
|
||||
|
||||
return axios
|
||||
.get(this.container.dataset.endpoint, {
|
||||
.get(container.dataset.endpoint, {
|
||||
responseType: 'text',
|
||||
})
|
||||
.then(({ data }) => {
|
||||
this.spinner.classList.remove('d-inline-flex');
|
||||
this.spinner.classList.remove('gl-display-inline-flex');
|
||||
this.insertPayload(data);
|
||||
})
|
||||
.catch(() => {
|
||||
this.spinner.classList.remove('d-inline-flex');
|
||||
this.spinner.classList.remove('gl-display-inline-flex');
|
||||
createFlash({
|
||||
message: __('Error fetching payload data.'),
|
||||
});
|
||||
|
@ -46,19 +51,19 @@ export default class PayloadPreviewer {
|
|||
|
||||
hidePayload() {
|
||||
this.isVisible = false;
|
||||
this.container.classList.add('d-none');
|
||||
this.getContainer().classList.add('gl-display-none');
|
||||
this.text.textContent = __('Preview payload');
|
||||
}
|
||||
|
||||
showPayload() {
|
||||
this.isVisible = true;
|
||||
this.container.classList.remove('d-none');
|
||||
this.getContainer().classList.remove('gl-display-none');
|
||||
this.text.textContent = __('Hide payload');
|
||||
}
|
||||
|
||||
insertPayload(data) {
|
||||
this.isInserted = true;
|
||||
this.container.innerHTML = data;
|
||||
this.getContainer().innerHTML = data;
|
||||
this.showPayload();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ class Projects::GroupLinksController < Projects::ApplicationController
|
|||
|
||||
if group_link.expires?
|
||||
render json: {
|
||||
expires_in: helpers.distance_of_time_in_words_to_now(group_link.expires_at),
|
||||
expires_in: helpers.time_ago_with_tooltip(group_link.expires_at),
|
||||
expires_soon: group_link.expires_soon?
|
||||
}
|
||||
else
|
||||
|
|
|
@ -55,6 +55,13 @@ module Resolvers
|
|||
required: false,
|
||||
description: 'Limit result to draft merge requests.'
|
||||
|
||||
argument :created_after, Types::TimeType,
|
||||
required: false,
|
||||
description: 'Merge requests created after this timestamp.'
|
||||
argument :created_before, Types::TimeType,
|
||||
required: false,
|
||||
description: 'Merge requests created before this timestamp.'
|
||||
|
||||
argument :labels, [GraphQL::Types::String],
|
||||
required: false,
|
||||
as: :label_name,
|
||||
|
@ -72,12 +79,6 @@ module Resolvers
|
|||
description: 'Sort merge requests by this criteria.',
|
||||
required: false,
|
||||
default_value: :created_desc
|
||||
argument :created_after, Types::TimeType,
|
||||
required: false,
|
||||
description: 'Merge requests created after this timestamp.'
|
||||
argument :created_before, Types::TimeType,
|
||||
required: false,
|
||||
description: 'Merge requests created before this timestamp.'
|
||||
|
||||
negated do
|
||||
argument :labels, [GraphQL::Types::String],
|
||||
|
|
|
@ -11,14 +11,14 @@ module Resolvers
|
|||
required: false,
|
||||
default_value: '', # root of the repository
|
||||
description: 'Path to get the tree for. Default value is the root of the repository.'
|
||||
argument :ref, GraphQL::Types::String,
|
||||
required: false,
|
||||
default_value: :head,
|
||||
description: 'Commit ref to get the tree for. Default value is HEAD.'
|
||||
argument :recursive, GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
default_value: false,
|
||||
description: 'Used to get a recursive tree. Default is false.'
|
||||
argument :ref, GraphQL::Types::String,
|
||||
required: false,
|
||||
default_value: :head,
|
||||
description: 'Commit ref to get the tree for. Default value is HEAD.'
|
||||
|
||||
alias_method :repository, :object
|
||||
|
||||
|
|
|
@ -10,14 +10,14 @@ module Resolvers
|
|||
required: false,
|
||||
default_value: '',
|
||||
description: 'Path to get the tree for. Default value is the root of the repository.'
|
||||
argument :ref, GraphQL::Types::String,
|
||||
required: false,
|
||||
default_value: :head,
|
||||
description: 'Commit ref to get the tree for. Default value is HEAD.'
|
||||
argument :recursive, GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
default_value: false,
|
||||
description: 'Used to get a recursive tree. Default is false.'
|
||||
argument :ref, GraphQL::Types::String,
|
||||
required: false,
|
||||
default_value: :head,
|
||||
description: 'Commit ref to get the tree for. Default value is HEAD.'
|
||||
|
||||
alias_method :repository, :object
|
||||
|
||||
|
|
|
@ -11,13 +11,13 @@ module Resolvers
|
|||
authorize :read_user_groups
|
||||
authorizes_object!
|
||||
|
||||
argument :search, GraphQL::Types::String,
|
||||
required: false,
|
||||
description: 'Search by group name or path.'
|
||||
argument :permission_scope,
|
||||
::Types::PermissionTypes::GroupEnum,
|
||||
required: false,
|
||||
description: 'Filter by permissions the user has on groups.'
|
||||
argument :search, GraphQL::Types::String,
|
||||
required: false,
|
||||
description: 'Search by group name or path.'
|
||||
|
||||
before_connection_authorization do |nodes, current_user|
|
||||
Preloaders::GroupPolicyPreloader.new(nodes, current_user).execute
|
||||
|
|
|
@ -180,6 +180,7 @@ class Member < ApplicationRecord
|
|||
|
||||
scope :on_project_and_ancestors, ->(project) { where(source: [project] + project.ancestors) }
|
||||
|
||||
before_validation :set_member_namespace_id, on: :create
|
||||
before_validation :generate_invite_token, on: :create, if: -> (member) { member.invite_email.present? && !member.invite_accepted_at? }
|
||||
|
||||
after_create :send_invite, if: :invite?, unless: :importing?
|
||||
|
@ -380,6 +381,12 @@ class Member < ApplicationRecord
|
|||
|
||||
private
|
||||
|
||||
# TODO: https://gitlab.com/groups/gitlab-org/-/epics/7054
|
||||
# temporary until we can we properly remove the source columns
|
||||
def set_member_namespace_id
|
||||
self.member_namespace_id = self.source_id
|
||||
end
|
||||
|
||||
def access_level_inclusion
|
||||
return if access_level.in?(Gitlab::Access.all_values)
|
||||
|
||||
|
|
|
@ -118,6 +118,13 @@ class ProjectMember < Member
|
|||
# rubocop:enable CodeReuse/ServiceClass
|
||||
end
|
||||
|
||||
# TODO: https://gitlab.com/groups/gitlab-org/-/epics/7054
|
||||
# temporary until we can we properly remove the source columns
|
||||
override :set_member_namespace_id
|
||||
def set_member_namespace_id
|
||||
self.member_namespace_id = project&.project_namespace_id
|
||||
end
|
||||
|
||||
def send_invite
|
||||
run_after_commit_or_now { notification_service.invite_project_member(self, @raw_invite_token) }
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@ class StateNote < SyntheticNote
|
|||
def note_text(html: false)
|
||||
if event.state == 'closed'
|
||||
if event.close_after_error_tracking_resolve
|
||||
return 'resolved the corresponding error and closed the issue.'
|
||||
return 'resolved the corresponding error and closed the issue'
|
||||
end
|
||||
|
||||
if event.close_auto_resolve_prometheus_alert
|
||||
return 'automatically closed this issue because the alert resolved.'
|
||||
return 'automatically closed this incident because the alert resolved'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ module Issues
|
|||
return if alert.resolved?
|
||||
|
||||
if alert.resolve
|
||||
SystemNotes::AlertManagementService.new(noteable: alert, project: alert.project, author: current_user).closed_alert_issue(issue)
|
||||
SystemNoteService.change_alert_status(alert, current_user, " by closing incident #{issue.to_reference(project)}")
|
||||
else
|
||||
Gitlab::AppLogger.warn(
|
||||
message: 'Cannot resolve an associated Alert Management alert',
|
||||
|
@ -97,7 +97,7 @@ module Issues
|
|||
|
||||
status = issue.incident_management_issuable_escalation_status || issue.build_incident_management_issuable_escalation_status
|
||||
|
||||
SystemNoteService.resolve_incident_status(issue, current_user) if status.resolve
|
||||
SystemNoteService.change_incident_status(issue, current_user, ' by closing the incident') if status.resolve
|
||||
end
|
||||
|
||||
def store_first_mentioned_in_commit_at(issue, merge_request, max_commit_lookup: 100)
|
||||
|
|
|
@ -47,8 +47,7 @@ module Projects
|
|||
end
|
||||
|
||||
def save_all!
|
||||
if save_exporters
|
||||
Gitlab::ImportExport::Saver.save(exportable: project, shared: shared)
|
||||
if save_exporters && save_export_archive
|
||||
notify_success
|
||||
else
|
||||
notify_error!
|
||||
|
@ -59,6 +58,10 @@ module Projects
|
|||
exporters.all?(&:save)
|
||||
end
|
||||
|
||||
def save_export_archive
|
||||
Gitlab::ImportExport::Saver.save(exportable: project, shared: shared)
|
||||
end
|
||||
|
||||
def exporters
|
||||
[
|
||||
version_saver, avatar_saver, project_tree_saver, uploads_saver,
|
||||
|
|
|
@ -335,10 +335,6 @@ module SystemNoteService
|
|||
::SystemNotes::IncidentService.new(noteable: incident, project: incident.project, author: author).change_incident_severity
|
||||
end
|
||||
|
||||
def resolve_incident_status(incident, author)
|
||||
::SystemNotes::IncidentService.new(noteable: incident, project: incident.project, author: author).resolve_incident_status
|
||||
end
|
||||
|
||||
def change_incident_status(incident, author, reason = nil)
|
||||
::SystemNotes::IncidentService.new(noteable: incident, project: incident.project, author: author).change_incident_status(reason)
|
||||
end
|
||||
|
|
|
@ -40,30 +40,15 @@ module SystemNotes
|
|||
#
|
||||
# Example Note text:
|
||||
#
|
||||
# "created issue #17 for this alert"
|
||||
# "created incident #17 for this alert"
|
||||
#
|
||||
# Returns the created Note object
|
||||
def new_alert_issue(issue)
|
||||
body = "created issue #{issue.to_reference(project)} for this alert"
|
||||
body = "created incident #{issue.to_reference(project)} for this alert"
|
||||
|
||||
create_note(NoteSummary.new(noteable, project, author, body, action: 'alert_issue_added'))
|
||||
end
|
||||
|
||||
# Called when an AlertManagement::Alert is resolved due to the associated issue being closed
|
||||
#
|
||||
# issue - Issue object.
|
||||
#
|
||||
# Example Note text:
|
||||
#
|
||||
# "changed the status to Resolved by closing issue #17"
|
||||
#
|
||||
# Returns the created Note object
|
||||
def closed_alert_issue(issue)
|
||||
body = "changed the status to **Resolved** by closing issue #{issue.to_reference(project)}"
|
||||
|
||||
create_note(NoteSummary.new(noteable, project, author, body, action: 'status'))
|
||||
end
|
||||
|
||||
# Called when an alert is resolved due to received resolving alert payload
|
||||
#
|
||||
# alert - AlertManagement::Alert object.
|
||||
|
|
|
@ -26,12 +26,6 @@ module SystemNotes
|
|||
end
|
||||
end
|
||||
|
||||
def resolve_incident_status
|
||||
body = 'changed the status to **Resolved** by closing the incident'
|
||||
|
||||
create_note(NoteSummary.new(noteable, project, author, body, action: 'status'))
|
||||
end
|
||||
|
||||
# Called when the status of an IncidentManagement::IssuableEscalationStatus has changed
|
||||
#
|
||||
# reason - String.
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
|
||||
%button.gl-button.btn.btn-default.js-payload-preview-trigger{ type: 'button', data: { payload_selector: ".#{payload_class}" } }
|
||||
.gl-spinner.js-spinner.gl-display-none.gl-mr-2
|
||||
.js-text.d-inline= _('Preview payload')
|
||||
%pre.service-data-payload-container.js-syntax-highlight.code.highlight.mt-2.d-none{ class: payload_class, data: { endpoint: usage_data_admin_application_settings_path(format: :html) } }
|
||||
.js-text.gl-display-inline= _('Preview payload')
|
||||
%pre.service-data-payload-container.js-syntax-highlight.code.highlight.gl-mt-2.gl-display-none{ class: payload_class, data: { endpoint: usage_data_admin_application_settings_path(format: :html) } }
|
||||
- else
|
||||
= _('Service ping is disabled in your configuration file, and cannot be enabled through this form.')
|
||||
- deactivating_service_ping_path = help_page_path('development/service_ping/index.md', anchor: 'disable-service-ping-using-the-configuration-file')
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
.content-wrapper.content-wrapper-margin{ class: "#{@content_wrapper_class}" }
|
||||
.mobile-overlay
|
||||
= render_if_exists 'layouts/header/verification_reminder'
|
||||
= yield :group_invite_members_banner
|
||||
.alert-wrapper.gl-force-block-formatting-context
|
||||
= render 'shared/outdated_browser'
|
||||
= render_if_exists "layouts/header/licensed_user_count_threshold"
|
||||
|
@ -21,6 +20,7 @@
|
|||
= render_if_exists "shared/namespace_user_cap_reached_alert"
|
||||
= render_if_exists "shared/new_user_signups_cap_reached_alert"
|
||||
= yield :page_level_alert
|
||||
= yield :group_invite_members_banner
|
||||
- unless @hide_breadcrumbs
|
||||
= render "layouts/nav/breadcrumbs"
|
||||
%div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
- name: "`started` iterations API field" # The name of the feature to be deprecated
|
||||
announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
|
||||
announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
|
||||
removal_date: "2022-05-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
breaking_change: true # If this deprecation is a breaking change, set this value to true
|
||||
body: | # Do not modify this line, instead modify the lines below.
|
||||
The `started` field in the [iterations API](https://docs.gitlab.com/ee/api/iterations.html#list-project-iterations) is being deprecated and will be removed in GitLab 15.0. This field is being replaced with the `current` field (already available) which aligns with the naming for other time-based entities, such as milestones.
|
||||
# The following items are not published on the docs page, but may be used in the future.
|
||||
stage: plan
|
||||
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
|
||||
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334018
|
||||
documentation_url: # (optional) This is a link to the current documentation page
|
||||
image_url: # (optional) This is a link to a thumbnail image depicting the feature
|
||||
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
|
|
@ -85,10 +85,9 @@ To remove a metric:
|
|||
1. Verify that removing the metric from the Service Ping payload does not cause
|
||||
errors in [Version App](https://gitlab.com/gitlab-services/version-gitlab-com)
|
||||
when the updated payload is collected and processed. Version App collects
|
||||
and persists all Service Ping reports. To do that you can modify
|
||||
[fixtures](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/spec/support/usage_data_helpers.rb#L540)
|
||||
used to test
|
||||
[`UsageDataController#create`](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/3760ef28/spec/controllers/usage_data_controller_spec.rb#L75)
|
||||
and persists all Service Ping reports. To verify Service Ping processing in your local development environment, follow this [guide](https://www.youtube.com/watch?v=FS5emplabRU).
|
||||
Alternatively, you can modify [fixtures](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/spec/support/usage_data_helpers.rb#L540)
|
||||
used to test the [`UsageDataController#create`](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/3760ef28/spec/controllers/usage_data_controller_spec.rb#L75)
|
||||
endpoint, and assure that test suite does not fail when metric that you wish to remove is not included into test payload.
|
||||
|
||||
1. Create an issue in the
|
||||
|
|
|
@ -716,3 +716,15 @@ Support for `fixup!` is now considered deprecated, and will be
|
|||
removed in GitLab 15.0.
|
||||
|
||||
**Planned removal milestone: 15.0 (2022-06-22)**
|
||||
|
||||
### `started` iterations API field
|
||||
|
||||
WARNING:
|
||||
This feature will be changed or removed in 15.0
|
||||
as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
|
||||
Before updating GitLab, review the details carefully to determine if you need to make any
|
||||
changes to your code, settings, or workflow.
|
||||
|
||||
The `started` field in the [iterations API](https://docs.gitlab.com/ee/api/iterations.html#list-project-iterations) is being deprecated and will be removed in GitLab 15.0. This field is being replaced with the `current` field (already available) which aligns with the naming for other time-based entities, such as milestones.
|
||||
|
||||
**Planned removal milestone: 15.0 (2022-05-22)**
|
||||
|
|
|
@ -54,6 +54,8 @@ module Gitlab
|
|||
File.open(archive_file) { |file| upload.export_file = file }
|
||||
|
||||
upload.save!
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def error_message
|
||||
|
|
|
@ -9,9 +9,7 @@ module QA
|
|||
|
||||
attribute :id
|
||||
attribute :project do
|
||||
Project.fabricate! do |project|
|
||||
project.initialize_with_readme = true
|
||||
end
|
||||
Project.fabricate!
|
||||
end
|
||||
attribute :token do
|
||||
Page::Project::Settings::AccessTokens.perform(&:created_access_token)
|
||||
|
|
|
@ -4,7 +4,9 @@ module QA
|
|||
RSpec.describe 'Manage' do
|
||||
describe 'Project access token' do
|
||||
before(:all) do
|
||||
@project_access_token = QA::Resource::ProjectAccessToken.fabricate_via_api!
|
||||
@project_access_token = QA::Resource::ProjectAccessToken.fabricate_via_api! do |pat|
|
||||
pat.project = Resource::ReusableProject.fabricate_via_api!
|
||||
end
|
||||
|
||||
@user_api_client = Runtime::API::Client.new(:gitlab, personal_access_token: @project_access_token.token)
|
||||
end
|
||||
|
@ -76,11 +78,6 @@ module QA
|
|||
@different_project.remove_via_api!
|
||||
end
|
||||
end
|
||||
|
||||
after(:all) do
|
||||
@project_access_token.remove_via_api!
|
||||
@project_access_token.project.remove_via_api!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,12 +11,7 @@ module QA
|
|||
let(:title) { "MR push options test #{SecureRandom.hex(8)}" }
|
||||
let(:commit_message) { 'Add README.md' }
|
||||
|
||||
let(:project) do
|
||||
Resource::Project.fabricate_via_api! do |project|
|
||||
project.name = 'merge-request-push-options'
|
||||
project.initialize_with_readme = true
|
||||
end
|
||||
end
|
||||
let(:project) { Resource::ReusableProject.fabricate_via_api! }
|
||||
|
||||
def create_new_mr_via_push
|
||||
Resource::Repository::ProjectPush.fabricate! do |push|
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
require 'fast_spec_helper'
|
||||
require 'rspec-parameterized'
|
||||
|
||||
require_relative '../../support/stub_settings_source'
|
||||
require_relative '../../../sidekiq_cluster/cli'
|
||||
|
||||
RSpec.describe Gitlab::SidekiqCluster::CLI, stubbing_settings_source: true do # rubocop:disable RSpec/FilePath
|
||||
RSpec.describe Gitlab::SidekiqCluster::CLI, stub_settings_source: true do # rubocop:disable RSpec/FilePath
|
||||
let(:cli) { described_class.new('/dev/null') }
|
||||
let(:timeout) { Gitlab::SidekiqCluster::DEFAULT_SOFT_TIMEOUT_SECONDS }
|
||||
let(:default_options) do
|
||||
|
|
|
@ -178,7 +178,7 @@ RSpec.describe Projects::GroupLinksController do
|
|||
|
||||
context 'when `expires_at` is set' do
|
||||
it 'returns correct json response' do
|
||||
expect(json_response).to eq({ "expires_in" => "about 1 month", "expires_soon" => false })
|
||||
expect(json_response).to eq({ "expires_in" => controller.helpers.time_ago_with_tooltip(expiry_date), "expires_soon" => false })
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -528,7 +528,7 @@ RSpec.describe 'Admin updates settings' do
|
|||
expect(find_field('Allow access to members of the following group').value).to be_nil
|
||||
end
|
||||
|
||||
it 'loads usage ping payload on click', :js do
|
||||
it 'loads togglable usage ping payload on click', :js do
|
||||
stub_usage_data_connections
|
||||
stub_database_flavor_check
|
||||
|
||||
|
@ -544,6 +544,10 @@ RSpec.describe 'Admin updates settings' do
|
|||
expect(page).to have_selector '.js-service-ping-payload'
|
||||
expect(page).to have_button 'Hide payload'
|
||||
expect(page).to have_content expected_payload_content
|
||||
|
||||
click_button('Hide payload')
|
||||
|
||||
expect(page).not_to have_content expected_payload_content
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import MockAdapter from 'axios-mock-adapter';
|
||||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import { DUMMY_IMAGE_URL, TEST_HOST } from 'helpers/test_constants';
|
||||
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
|
||||
import BadgeForm from '~/badges/components/badge_form.vue';
|
||||
|
@ -74,7 +74,7 @@ describe('BadgeForm component', () => {
|
|||
expect(feedbackElement).toBeVisible();
|
||||
};
|
||||
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
jest.spyOn(vm, submitAction).mockReturnValue(Promise.resolve());
|
||||
store.replaceState({
|
||||
...store.state,
|
||||
|
@ -83,14 +83,10 @@ describe('BadgeForm component', () => {
|
|||
isSaving: false,
|
||||
});
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
setValue(nameSelector, 'TestBadge');
|
||||
setValue(linkUrlSelector, `${TEST_HOST}/link/url`);
|
||||
setValue(imageUrlSelector, `${window.location.origin}${DUMMY_IMAGE_URL}`);
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
await nextTick();
|
||||
setValue(nameSelector, 'TestBadge');
|
||||
setValue(linkUrlSelector, `${TEST_HOST}/link/url`);
|
||||
setValue(imageUrlSelector, `${window.location.origin}${DUMMY_IMAGE_URL}`);
|
||||
});
|
||||
|
||||
it('returns immediately if imageUrl is empty', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
|
||||
import BadgeListRow from '~/badges/components/badge_list_row.vue';
|
||||
import { GROUP_BADGE, PROJECT_BADGE } from '~/badges/constants';
|
||||
|
@ -73,25 +73,21 @@ describe('BadgeListRow component', () => {
|
|||
expect(vm.editBadge).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls updateBadgeInModal and shows modal when clicking then delete button', (done) => {
|
||||
it('calls updateBadgeInModal and shows modal when clicking then delete button', async () => {
|
||||
jest.spyOn(vm, 'updateBadgeInModal').mockImplementation(() => {});
|
||||
|
||||
const deleteButton = vm.$el.querySelector('.table-button-footer button:last-of-type');
|
||||
deleteButton.click();
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
expect(vm.updateBadgeInModal).toHaveBeenCalled();
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
await nextTick();
|
||||
expect(vm.updateBadgeInModal).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('for a group badge', () => {
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
badge.kind = GROUP_BADGE;
|
||||
|
||||
Vue.nextTick().then(done).catch(done.fail);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('renders the badge kind', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
|
||||
import BadgeList from '~/badges/components/badge_list.vue';
|
||||
import { GROUP_BADGE, PROJECT_BADGE } from '~/badges/constants';
|
||||
|
@ -48,46 +48,34 @@ describe('BadgeList component', () => {
|
|||
expect(rows).toHaveLength(numberOfDummyBadges);
|
||||
});
|
||||
|
||||
it('renders a message if no badges exist', (done) => {
|
||||
it('renders a message if no badges exist', async () => {
|
||||
store.state.badges = [];
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
expect(vm.$el.innerText).toMatch('This project has no badges');
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
await nextTick();
|
||||
expect(vm.$el.innerText).toMatch('This project has no badges');
|
||||
});
|
||||
|
||||
it('shows a loading icon when loading', (done) => {
|
||||
it('shows a loading icon when loading', async () => {
|
||||
store.state.isLoading = true;
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
const loadingIcon = vm.$el.querySelector('.gl-spinner');
|
||||
await nextTick();
|
||||
const loadingIcon = vm.$el.querySelector('.gl-spinner');
|
||||
|
||||
expect(loadingIcon).toBeVisible();
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
expect(loadingIcon).toBeVisible();
|
||||
});
|
||||
|
||||
describe('for group badges', () => {
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
store.state.kind = GROUP_BADGE;
|
||||
|
||||
Vue.nextTick().then(done).catch(done.fail);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('renders a message if no badges exist', (done) => {
|
||||
it('renders a message if no badges exist', async () => {
|
||||
store.state.badges = [];
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
expect(vm.$el.innerText).toMatch('This group has no badges');
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
await nextTick();
|
||||
expect(vm.$el.innerText).toMatch('This group has no badges');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import mountComponent from 'helpers/vue_mount_component_helper';
|
||||
import { DUMMY_IMAGE_URL, TEST_HOST } from 'spec/test_constants';
|
||||
import Badge from '~/badges/components/badge.vue';
|
||||
|
@ -27,7 +27,7 @@ describe('Badge component', () => {
|
|||
badgeImage.addEventListener('load', resolve);
|
||||
// Manually dispatch load event as it is not triggered
|
||||
badgeImage.dispatchEvent(new Event('load'));
|
||||
}).then(() => Vue.nextTick());
|
||||
}).then(() => nextTick());
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -36,34 +36,25 @@ describe('Badge component', () => {
|
|||
|
||||
describe('watchers', () => {
|
||||
describe('imageUrl', () => {
|
||||
it('sets isLoading and resets numRetries and hasError', (done) => {
|
||||
it('sets isLoading and resets numRetries and hasError', async () => {
|
||||
const props = { ...dummyProps };
|
||||
createComponent(props)
|
||||
.then(() => {
|
||||
expect(vm.isLoading).toBe(false);
|
||||
vm.hasError = true;
|
||||
vm.numRetries = 42;
|
||||
await createComponent(props);
|
||||
expect(vm.isLoading).toBe(false);
|
||||
vm.hasError = true;
|
||||
vm.numRetries = 42;
|
||||
|
||||
vm.imageUrl = `${props.imageUrl}#something/else`;
|
||||
|
||||
return Vue.nextTick();
|
||||
})
|
||||
.then(() => {
|
||||
expect(vm.isLoading).toBe(true);
|
||||
expect(vm.numRetries).toBe(0);
|
||||
expect(vm.hasError).toBe(false);
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
vm.imageUrl = `${props.imageUrl}#something/else`;
|
||||
await nextTick();
|
||||
expect(vm.isLoading).toBe(true);
|
||||
expect(vm.numRetries).toBe(0);
|
||||
expect(vm.hasError).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('methods', () => {
|
||||
beforeEach((done) => {
|
||||
createComponent({ ...dummyProps })
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
beforeEach(async () => {
|
||||
await createComponent({ ...dummyProps });
|
||||
});
|
||||
|
||||
it('onError resets isLoading and sets hasError', () => {
|
||||
|
@ -116,37 +107,29 @@ describe('Badge component', () => {
|
|||
expect(vm.$el.querySelector('.btn-group')).toBeHidden();
|
||||
});
|
||||
|
||||
it('shows a loading icon when loading', (done) => {
|
||||
it('shows a loading icon when loading', async () => {
|
||||
vm.isLoading = true;
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
const { badgeImage, loadingIcon, reloadButton } = findElements();
|
||||
await nextTick();
|
||||
const { badgeImage, loadingIcon, reloadButton } = findElements();
|
||||
|
||||
expect(badgeImage).toBeHidden();
|
||||
expect(loadingIcon).toBeVisible();
|
||||
expect(reloadButton).toBeHidden();
|
||||
expect(vm.$el.querySelector('.btn-group')).toBeHidden();
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
expect(badgeImage).toBeHidden();
|
||||
expect(loadingIcon).toBeVisible();
|
||||
expect(reloadButton).toBeHidden();
|
||||
expect(vm.$el.querySelector('.btn-group')).toBeHidden();
|
||||
});
|
||||
|
||||
it('shows an error and reload button if loading failed', (done) => {
|
||||
it('shows an error and reload button if loading failed', async () => {
|
||||
vm.hasError = true;
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
const { badgeImage, loadingIcon, reloadButton } = findElements();
|
||||
await nextTick();
|
||||
const { badgeImage, loadingIcon, reloadButton } = findElements();
|
||||
|
||||
expect(badgeImage).toBeHidden();
|
||||
expect(loadingIcon).toBeHidden();
|
||||
expect(reloadButton).toBeVisible();
|
||||
expect(reloadButton).toHaveSpriteIcon('retry');
|
||||
expect(vm.$el.innerText.trim()).toBe('No badge image');
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
expect(badgeImage).toBeHidden();
|
||||
expect(loadingIcon).toBeHidden();
|
||||
expect(reloadButton).toBeVisible();
|
||||
expect(reloadButton).toHaveSpriteIcon('retry');
|
||||
expect(vm.$el.innerText.trim()).toBe('No badge image');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import PreviewDropdown from '~/batch_comments/components/preview_dropdown.vue';
|
||||
|
@ -49,7 +49,7 @@ describe('Batch comments preview dropdown', () => {
|
|||
|
||||
wrapper.findByTestId('preview-item').vm.$emit('click');
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(setCurrentFileHash).toHaveBeenCalledWith(expect.anything(), 'hash');
|
||||
expect(scrollToDraft).toHaveBeenCalledWith(expect.anything(), { id: 1, file_hash: 'hash' });
|
||||
|
@ -63,7 +63,7 @@ describe('Batch comments preview dropdown', () => {
|
|||
|
||||
wrapper.findByTestId('preview-item').vm.$emit('click');
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(scrollToDraft).toHaveBeenCalledWith(expect.anything(), { id: 1 });
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
import { TEST_HOST } from 'helpers/test_constants';
|
||||
import initConfirmModal from '~/confirm_modal';
|
||||
|
||||
|
@ -92,10 +92,9 @@ describe('ConfirmModal', () => {
|
|||
});
|
||||
|
||||
describe('Cancel Button', () => {
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
findModalCancelButton(findModal()).click();
|
||||
|
||||
return Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('closes the modal', () => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { GlFormCheckbox } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
|
||||
import EksClusterConfigurationForm from '~/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue';
|
||||
|
@ -223,108 +223,98 @@ describe('EksClusterConfigurationForm', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('sets isLoadingRoles to RoleDropdown loading property', () => {
|
||||
it('sets isLoadingRoles to RoleDropdown loading property', async () => {
|
||||
rolesState.isLoadingItems = true;
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(findRoleDropdown().props('loading')).toBe(rolesState.isLoadingItems);
|
||||
});
|
||||
await nextTick();
|
||||
expect(findRoleDropdown().props('loading')).toBe(rolesState.isLoadingItems);
|
||||
});
|
||||
|
||||
it('sets roles to RoleDropdown items property', () => {
|
||||
expect(findRoleDropdown().props('items')).toBe(rolesState.items);
|
||||
});
|
||||
|
||||
it('sets RoleDropdown hasErrors to true when loading roles failed', () => {
|
||||
it('sets RoleDropdown hasErrors to true when loading roles failed', async () => {
|
||||
rolesState.loadingItemsError = new Error();
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(findRoleDropdown().props('hasErrors')).toEqual(true);
|
||||
});
|
||||
await nextTick();
|
||||
expect(findRoleDropdown().props('hasErrors')).toEqual(true);
|
||||
});
|
||||
|
||||
it('disables KeyPairDropdown when no region is selected', () => {
|
||||
expect(findKeyPairDropdown().props('disabled')).toBe(true);
|
||||
});
|
||||
|
||||
it('enables KeyPairDropdown when no region is selected', () => {
|
||||
it('enables KeyPairDropdown when no region is selected', async () => {
|
||||
state.selectedRegion = { name: 'west-1 ' };
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(findKeyPairDropdown().props('disabled')).toBe(false);
|
||||
});
|
||||
await nextTick();
|
||||
expect(findKeyPairDropdown().props('disabled')).toBe(false);
|
||||
});
|
||||
|
||||
it('sets isLoadingKeyPairs to KeyPairDropdown loading property', () => {
|
||||
it('sets isLoadingKeyPairs to KeyPairDropdown loading property', async () => {
|
||||
keyPairsState.isLoadingItems = true;
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(findKeyPairDropdown().props('loading')).toBe(keyPairsState.isLoadingItems);
|
||||
});
|
||||
await nextTick();
|
||||
expect(findKeyPairDropdown().props('loading')).toBe(keyPairsState.isLoadingItems);
|
||||
});
|
||||
|
||||
it('sets keyPairs to KeyPairDropdown items property', () => {
|
||||
expect(findKeyPairDropdown().props('items')).toBe(keyPairsState.items);
|
||||
});
|
||||
|
||||
it('sets KeyPairDropdown hasErrors to true when loading key pairs fails', () => {
|
||||
it('sets KeyPairDropdown hasErrors to true when loading key pairs fails', async () => {
|
||||
keyPairsState.loadingItemsError = new Error();
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(findKeyPairDropdown().props('hasErrors')).toEqual(true);
|
||||
});
|
||||
await nextTick();
|
||||
expect(findKeyPairDropdown().props('hasErrors')).toEqual(true);
|
||||
});
|
||||
|
||||
it('disables VpcDropdown when no region is selected', () => {
|
||||
expect(findVpcDropdown().props('disabled')).toBe(true);
|
||||
});
|
||||
|
||||
it('enables VpcDropdown when no region is selected', () => {
|
||||
it('enables VpcDropdown when no region is selected', async () => {
|
||||
state.selectedRegion = { name: 'west-1 ' };
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(findVpcDropdown().props('disabled')).toBe(false);
|
||||
});
|
||||
await nextTick();
|
||||
expect(findVpcDropdown().props('disabled')).toBe(false);
|
||||
});
|
||||
|
||||
it('sets isLoadingVpcs to VpcDropdown loading property', () => {
|
||||
it('sets isLoadingVpcs to VpcDropdown loading property', async () => {
|
||||
vpcsState.isLoadingItems = true;
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(findVpcDropdown().props('loading')).toBe(vpcsState.isLoadingItems);
|
||||
});
|
||||
await nextTick();
|
||||
expect(findVpcDropdown().props('loading')).toBe(vpcsState.isLoadingItems);
|
||||
});
|
||||
|
||||
it('sets vpcs to VpcDropdown items property', () => {
|
||||
expect(findVpcDropdown().props('items')).toBe(vpcsState.items);
|
||||
});
|
||||
|
||||
it('sets VpcDropdown hasErrors to true when loading vpcs fails', () => {
|
||||
it('sets VpcDropdown hasErrors to true when loading vpcs fails', async () => {
|
||||
vpcsState.loadingItemsError = new Error();
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(findVpcDropdown().props('hasErrors')).toEqual(true);
|
||||
});
|
||||
await nextTick();
|
||||
expect(findVpcDropdown().props('hasErrors')).toEqual(true);
|
||||
});
|
||||
|
||||
it('disables SubnetDropdown when no vpc is selected', () => {
|
||||
expect(findSubnetDropdown().props('disabled')).toBe(true);
|
||||
});
|
||||
|
||||
it('enables SubnetDropdown when a vpc is selected', () => {
|
||||
it('enables SubnetDropdown when a vpc is selected', async () => {
|
||||
state.selectedVpc = { name: 'vpc-1 ' };
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(findSubnetDropdown().props('disabled')).toBe(false);
|
||||
});
|
||||
await nextTick();
|
||||
expect(findSubnetDropdown().props('disabled')).toBe(false);
|
||||
});
|
||||
|
||||
it('sets isLoadingSubnets to SubnetDropdown loading property', () => {
|
||||
it('sets isLoadingSubnets to SubnetDropdown loading property', async () => {
|
||||
subnetsState.isLoadingItems = true;
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(findSubnetDropdown().props('loading')).toBe(subnetsState.isLoadingItems);
|
||||
});
|
||||
await nextTick();
|
||||
expect(findSubnetDropdown().props('loading')).toBe(subnetsState.isLoadingItems);
|
||||
});
|
||||
|
||||
it('sets subnets to SubnetDropdown items property', () => {
|
||||
|
@ -360,32 +350,29 @@ describe('EksClusterConfigurationForm', () => {
|
|||
expect(findSecurityGroupDropdown().props('disabled')).toBe(true);
|
||||
});
|
||||
|
||||
it('enables SecurityGroupDropdown when a vpc is selected', () => {
|
||||
it('enables SecurityGroupDropdown when a vpc is selected', async () => {
|
||||
state.selectedVpc = { name: 'vpc-1 ' };
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(findSecurityGroupDropdown().props('disabled')).toBe(false);
|
||||
});
|
||||
await nextTick();
|
||||
expect(findSecurityGroupDropdown().props('disabled')).toBe(false);
|
||||
});
|
||||
|
||||
it('sets isLoadingSecurityGroups to SecurityGroupDropdown loading property', () => {
|
||||
it('sets isLoadingSecurityGroups to SecurityGroupDropdown loading property', async () => {
|
||||
securityGroupsState.isLoadingItems = true;
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(findSecurityGroupDropdown().props('loading')).toBe(securityGroupsState.isLoadingItems);
|
||||
});
|
||||
await nextTick();
|
||||
expect(findSecurityGroupDropdown().props('loading')).toBe(securityGroupsState.isLoadingItems);
|
||||
});
|
||||
|
||||
it('sets securityGroups to SecurityGroupDropdown items property', () => {
|
||||
expect(findSecurityGroupDropdown().props('items')).toBe(securityGroupsState.items);
|
||||
});
|
||||
|
||||
it('sets SecurityGroupDropdown hasErrors to true when loading security groups fails', () => {
|
||||
it('sets SecurityGroupDropdown hasErrors to true when loading security groups fails', async () => {
|
||||
securityGroupsState.loadingItemsError = new Error();
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(findSecurityGroupDropdown().props('hasErrors')).toEqual(true);
|
||||
});
|
||||
await nextTick();
|
||||
expect(findSecurityGroupDropdown().props('hasErrors')).toEqual(true);
|
||||
});
|
||||
|
||||
it('dispatches setClusterName when cluster name input changes', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
|
||||
import groupFolderComponent from '~/groups/components/group_folder.vue';
|
||||
import groupItemComponent from '~/groups/components/group_item.vue';
|
||||
|
@ -18,13 +18,13 @@ const createComponent = (groups = mockGroups, parentGroup = mockParentGroupItem)
|
|||
describe('GroupFolderComponent', () => {
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
Vue.component('GroupItem', groupItemComponent);
|
||||
|
||||
vm = createComponent();
|
||||
vm.$mount();
|
||||
|
||||
return Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
|
||||
import commitSidebarList from '~/ide/components/commit_sidebar/list.vue';
|
||||
import { createStore } from '~/ide/stores';
|
||||
|
@ -31,12 +31,11 @@ describe('Multi-file editor commit sidebar list', () => {
|
|||
});
|
||||
|
||||
describe('with a list of files', () => {
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
const f = file('file name');
|
||||
f.changed = true;
|
||||
vm.fileList.push(f);
|
||||
|
||||
Vue.nextTick(done);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('renders list', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
|
||||
import radioGroup from '~/ide/components/commit_sidebar/radio_group.vue';
|
||||
import { createStore } from '~/ide/stores';
|
||||
|
@ -7,7 +7,7 @@ describe('IDE commit sidebar radio group', () => {
|
|||
let vm;
|
||||
let store;
|
||||
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
store = createStore();
|
||||
|
||||
const Component = Vue.extend(radioGroup);
|
||||
|
@ -22,7 +22,7 @@ describe('IDE commit sidebar radio group', () => {
|
|||
|
||||
vm.$mount();
|
||||
|
||||
Vue.nextTick(done);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -33,7 +33,7 @@ describe('IDE commit sidebar radio group', () => {
|
|||
expect(vm.$el.textContent).toContain('test');
|
||||
});
|
||||
|
||||
it('uses slot if label is not present', (done) => {
|
||||
it('uses slot if label is not present', async () => {
|
||||
vm.$destroy();
|
||||
|
||||
vm = new Vue({
|
||||
|
@ -47,25 +47,19 @@ describe('IDE commit sidebar radio group', () => {
|
|||
|
||||
vm.$mount();
|
||||
|
||||
Vue.nextTick(() => {
|
||||
expect(vm.$el.textContent).toContain('Testing slot');
|
||||
|
||||
done();
|
||||
});
|
||||
await nextTick();
|
||||
expect(vm.$el.textContent).toContain('Testing slot');
|
||||
});
|
||||
|
||||
it('updates store when changing radio button', (done) => {
|
||||
it('updates store when changing radio button', async () => {
|
||||
vm.$el.querySelector('input').dispatchEvent(new Event('change'));
|
||||
|
||||
Vue.nextTick(() => {
|
||||
expect(store.state.commit.commitAction).toBe('1');
|
||||
|
||||
done();
|
||||
});
|
||||
await nextTick();
|
||||
expect(store.state.commit.commitAction).toBe('1');
|
||||
});
|
||||
|
||||
describe('with input', () => {
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
vm.$destroy();
|
||||
|
||||
const Component = Vue.extend(radioGroup);
|
||||
|
@ -82,32 +76,27 @@ describe('IDE commit sidebar radio group', () => {
|
|||
|
||||
vm.$mount();
|
||||
|
||||
Vue.nextTick(done);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('renders input box when commitAction matches value', () => {
|
||||
expect(vm.$el.querySelector('.form-control')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('hides input when commitAction doesnt match value', (done) => {
|
||||
it('hides input when commitAction doesnt match value', async () => {
|
||||
store.state.commit.commitAction = '2';
|
||||
|
||||
Vue.nextTick(() => {
|
||||
expect(vm.$el.querySelector('.form-control')).toBeNull();
|
||||
done();
|
||||
});
|
||||
await nextTick();
|
||||
expect(vm.$el.querySelector('.form-control')).toBeNull();
|
||||
});
|
||||
|
||||
it('updates branch name in store on input', (done) => {
|
||||
it('updates branch name in store on input', async () => {
|
||||
const input = vm.$el.querySelector('.form-control');
|
||||
input.value = 'testing-123';
|
||||
input.dispatchEvent(new Event('input'));
|
||||
|
||||
Vue.nextTick(() => {
|
||||
expect(store.state.commit.newBranchName).toBe('testing-123');
|
||||
|
||||
done();
|
||||
});
|
||||
await nextTick();
|
||||
expect(store.state.commit.newBranchName).toBe('testing-123');
|
||||
});
|
||||
|
||||
it('renders newBranchName if present', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
|
||||
import successMessage from '~/ide/components/commit_sidebar/success_message.vue';
|
||||
import { createStore } from '~/ide/stores';
|
||||
|
@ -23,13 +23,10 @@ describe('IDE commit panel successful commit state', () => {
|
|||
vm.$destroy();
|
||||
});
|
||||
|
||||
it('renders last commit message when it exists', (done) => {
|
||||
it('renders last commit message when it exists', async () => {
|
||||
vm.$store.state.lastCommitMsg = 'testing commit message';
|
||||
|
||||
Vue.nextTick(() => {
|
||||
expect(vm.$el.textContent).toContain('testing commit message');
|
||||
|
||||
done();
|
||||
});
|
||||
await nextTick();
|
||||
expect(vm.$el.textContent).toContain('testing commit message');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import MockAdapter from 'axios-mock-adapter';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
import eventHub from '~/ide/eventhub';
|
||||
import { createRouter } from '~/ide/ide_router';
|
||||
import service from '~/ide/services';
|
||||
|
@ -68,7 +68,7 @@ describe('IDE store file actions', () => {
|
|||
|
||||
return store
|
||||
.dispatch('closeFile', localFile)
|
||||
.then(Vue.nextTick)
|
||||
.then(nextTick)
|
||||
.then(() => {
|
||||
expect(store.state.openFiles.length).toBe(0);
|
||||
expect(store.state.changedFiles.length).toBe(1);
|
||||
|
@ -83,7 +83,7 @@ describe('IDE store file actions', () => {
|
|||
|
||||
return store
|
||||
.dispatch('closeFile', localFile)
|
||||
.then(Vue.nextTick)
|
||||
.then(nextTick)
|
||||
.then(() => {
|
||||
expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/main/-/newOpenFile/');
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { GlIcon } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
|
||||
import { mockMilestone } from 'jest/boards/mock_data';
|
||||
import IssueMilestone from '~/issuable/components/issue_milestone.vue';
|
||||
|
@ -19,12 +19,12 @@ describe('IssueMilestoneComponent', () => {
|
|||
let wrapper;
|
||||
let vm;
|
||||
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
wrapper = createComponent();
|
||||
|
||||
({ vm } = wrapper);
|
||||
|
||||
Vue.nextTick(done);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -37,7 +37,7 @@ describe('IssueMilestoneComponent', () => {
|
|||
wrapper.setProps({
|
||||
milestone: { ...mockMilestone, start_date: '' },
|
||||
});
|
||||
await wrapper.vm.$nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.isMilestoneStarted).toBe(false);
|
||||
});
|
||||
|
@ -46,7 +46,7 @@ describe('IssueMilestoneComponent', () => {
|
|||
await wrapper.setProps({
|
||||
milestone: { ...mockMilestone, start_date: '1990-07-22' },
|
||||
});
|
||||
await wrapper.vm.$nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.isMilestoneStarted).toBe(true);
|
||||
});
|
||||
|
@ -57,7 +57,7 @@ describe('IssueMilestoneComponent', () => {
|
|||
wrapper.setProps({
|
||||
milestone: { ...mockMilestone, due_date: '' },
|
||||
});
|
||||
await wrapper.vm.$nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.isMilestonePastDue).toBe(false);
|
||||
});
|
||||
|
@ -80,7 +80,7 @@ describe('IssueMilestoneComponent', () => {
|
|||
wrapper.setProps({
|
||||
milestone: { ...mockMilestone, due_date: '' },
|
||||
});
|
||||
await wrapper.vm.$nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.milestoneDatesAbsolute).toBe('(January 1, 2018)');
|
||||
});
|
||||
|
@ -89,7 +89,7 @@ describe('IssueMilestoneComponent', () => {
|
|||
wrapper.setProps({
|
||||
milestone: { ...mockMilestone, start_date: '', due_date: '' },
|
||||
});
|
||||
await wrapper.vm.$nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.milestoneDatesAbsolute).toBe('');
|
||||
});
|
||||
|
@ -100,7 +100,7 @@ describe('IssueMilestoneComponent', () => {
|
|||
wrapper.setProps({
|
||||
milestone: { ...mockMilestone, due_date: `${new Date().getFullYear() + 10}-01-01` },
|
||||
});
|
||||
await wrapper.vm.$nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.milestoneDatesHuman).toContain('years remaining');
|
||||
});
|
||||
|
@ -109,7 +109,7 @@ describe('IssueMilestoneComponent', () => {
|
|||
wrapper.setProps({
|
||||
milestone: { ...mockMilestone, start_date: '1990-07-22', due_date: '' },
|
||||
});
|
||||
await wrapper.vm.$nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.milestoneDatesHuman).toContain('Started');
|
||||
});
|
||||
|
@ -122,7 +122,7 @@ describe('IssueMilestoneComponent', () => {
|
|||
due_date: '',
|
||||
},
|
||||
});
|
||||
await wrapper.vm.$nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.milestoneDatesHuman).toContain('Starts');
|
||||
});
|
||||
|
@ -131,7 +131,7 @@ describe('IssueMilestoneComponent', () => {
|
|||
wrapper.setProps({
|
||||
milestone: { ...mockMilestone, start_date: '', due_date: '' },
|
||||
});
|
||||
await wrapper.vm.$nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.milestoneDatesHuman).toBe('');
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { GlAlert, GlLabel } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
import JiraIssuesImportStatus from '~/issues/list/components/jira_issues_import_status_app.vue';
|
||||
|
||||
describe('JiraIssuesImportStatus', () => {
|
||||
|
@ -100,7 +100,7 @@ describe('JiraIssuesImportStatus', () => {
|
|||
});
|
||||
|
||||
describe('alert message', () => {
|
||||
it('is hidden when dismissed', () => {
|
||||
it('is hidden when dismissed', async () => {
|
||||
wrapper = mountComponent({
|
||||
shouldShowInProgressAlert: true,
|
||||
});
|
||||
|
@ -109,9 +109,8 @@ describe('JiraIssuesImportStatus', () => {
|
|||
|
||||
findAlert().vm.$emit('dismiss');
|
||||
|
||||
return Vue.nextTick(() => {
|
||||
expect(wrapper.find(GlAlert).exists()).toBe(false);
|
||||
});
|
||||
await nextTick();
|
||||
expect(wrapper.find(GlAlert).exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import titleComponent from '~/issues/show/components/title.vue';
|
||||
import eventHub from '~/issues/show/event_hub';
|
||||
import Store from '~/issues/show/stores';
|
||||
|
@ -29,36 +29,33 @@ describe('Title component', () => {
|
|||
expect(vm.$el.querySelector('.title').innerHTML.trim()).toBe('Testing <img>');
|
||||
});
|
||||
|
||||
it('updates page title when changing titleHtml', () => {
|
||||
it('updates page title when changing titleHtml', async () => {
|
||||
const spy = jest.spyOn(vm, 'setPageTitle');
|
||||
vm.titleHtml = 'test';
|
||||
|
||||
return vm.$nextTick().then(() => {
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
await nextTick();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('animates title changes', () => {
|
||||
it('animates title changes', async () => {
|
||||
vm.titleHtml = 'test';
|
||||
return vm
|
||||
.$nextTick()
|
||||
.then(() => {
|
||||
expect(vm.$el.querySelector('.title').classList).toContain('issue-realtime-pre-pulse');
|
||||
jest.runAllTimers();
|
||||
return vm.$nextTick();
|
||||
})
|
||||
.then(() => {
|
||||
expect(vm.$el.querySelector('.title').classList).toContain('issue-realtime-trigger-pulse');
|
||||
});
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(vm.$el.querySelector('.title').classList).toContain('issue-realtime-pre-pulse');
|
||||
jest.runAllTimers();
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(vm.$el.querySelector('.title').classList).toContain('issue-realtime-trigger-pulse');
|
||||
});
|
||||
|
||||
it('updates page title after changing title', () => {
|
||||
it('updates page title after changing title', async () => {
|
||||
vm.titleHtml = 'changed';
|
||||
vm.titleText = 'changed';
|
||||
|
||||
return vm.$nextTick().then(() => {
|
||||
expect(document.querySelector('title').textContent.trim()).toContain('changed');
|
||||
});
|
||||
await nextTick();
|
||||
expect(document.querySelector('title').textContent.trim()).toContain('changed');
|
||||
});
|
||||
|
||||
describe('inline edit button', () => {
|
||||
|
@ -80,16 +77,15 @@ describe('Title component', () => {
|
|||
expect(vm.$el.querySelector('.btn-edit')).toBeDefined();
|
||||
});
|
||||
|
||||
it('should trigger open.form event when clicked', () => {
|
||||
it('should trigger open.form event when clicked', async () => {
|
||||
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
|
||||
vm.showInlineEditButton = true;
|
||||
vm.canUpdate = true;
|
||||
|
||||
Vue.nextTick(() => {
|
||||
vm.$el.querySelector('.btn-edit').click();
|
||||
await nextTick();
|
||||
vm.$el.querySelector('.btn-edit').click();
|
||||
|
||||
expect(eventHub.$emit).toHaveBeenCalledWith('open.form');
|
||||
});
|
||||
expect(eventHub.$emit).toHaveBeenCalledWith('open.form');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
import JiraImportApp from '~/jira_import/components/jira_import_app.vue';
|
||||
import JiraImportForm from '~/jira_import/components/jira_import_form.vue';
|
||||
import JiraImportProgress from '~/jira_import/components/jira_import_progress.vue';
|
||||
|
@ -230,7 +230,7 @@ describe('JiraImportApp', () => {
|
|||
|
||||
getFormComponent().vm.$emit('error', 'There was an error');
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(getAlert().exists()).toBe(true);
|
||||
});
|
||||
|
@ -248,7 +248,7 @@ describe('JiraImportApp', () => {
|
|||
|
||||
getAlert().vm.$emit('dismiss');
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(getAlert().exists()).toBe(false);
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { mount, createWrapper } from '@vue/test-utils';
|
||||
import AxiosMockAdapter from 'axios-mock-adapter';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
import { TEST_HOST } from 'spec/test_constants';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
|
||||
|
@ -76,15 +76,14 @@ describe('noteActions', () => {
|
|||
expect(findUserAccessRoleBadgeText(1)).toBe(props.accessLevel);
|
||||
});
|
||||
|
||||
it('should render contributor badge', () => {
|
||||
it('should render contributor badge', async () => {
|
||||
wrapper.setProps({
|
||||
accessLevel: null,
|
||||
isContributor: true,
|
||||
});
|
||||
|
||||
return wrapper.vm.$nextTick().then(() => {
|
||||
expect(findUserAccessRoleBadgeText(1)).toBe('Contributor');
|
||||
});
|
||||
await nextTick();
|
||||
expect(findUserAccessRoleBadgeText(1)).toBe('Contributor');
|
||||
});
|
||||
|
||||
it('should render emoji link', () => {
|
||||
|
@ -105,7 +104,7 @@ describe('noteActions', () => {
|
|||
expect(wrapper.find('.js-btn-copy-note-link').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should not show copy link action when `noteUrl` prop is empty', (done) => {
|
||||
it('should not show copy link action when `noteUrl` prop is empty', async () => {
|
||||
wrapper.setProps({
|
||||
...props,
|
||||
author: {
|
||||
|
@ -119,30 +118,23 @@ describe('noteActions', () => {
|
|||
noteUrl: '',
|
||||
});
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
expect(wrapper.find('.js-btn-copy-note-link').exists()).toBe(false);
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
await nextTick();
|
||||
expect(wrapper.find('.js-btn-copy-note-link').exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('should be possible to delete comment', () => {
|
||||
expect(wrapper.find('.js-note-delete').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('closes tooltip when dropdown opens', (done) => {
|
||||
it('closes tooltip when dropdown opens', async () => {
|
||||
wrapper.find('.more-actions-toggle').trigger('click');
|
||||
|
||||
const rootWrapper = createWrapper(wrapper.vm.$root);
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
const emitted = Object.keys(rootWrapper.emitted());
|
||||
|
||||
expect(emitted).toEqual([BV_HIDE_TOOLTIP]);
|
||||
done();
|
||||
})
|
||||
.catch(done.fail);
|
||||
await nextTick();
|
||||
const emitted = Object.keys(rootWrapper.emitted());
|
||||
|
||||
expect(emitted).toEqual([BV_HIDE_TOOLTIP]);
|
||||
});
|
||||
|
||||
it('should not be possible to assign or unassign the comment author in a merge request', () => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
|
||||
import { suggestionCommitMessage } from '~/diffs/store/getters';
|
||||
|
@ -46,9 +46,9 @@ describe('issue_note_body component', () => {
|
|||
});
|
||||
|
||||
describe('isEditing', () => {
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
vm.isEditing = true;
|
||||
Vue.nextTick(done);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('renders edit form', () => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { mount, shallowMount } from '@vue/test-utils';
|
||||
import AxiosMockAdapter from 'axios-mock-adapter';
|
||||
import $ from 'jquery';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
import setWindowLocation from 'helpers/set_window_location_helper';
|
||||
import { setTestTimeout } from 'helpers/timeout';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
|
@ -294,24 +294,22 @@ describe('note_app', () => {
|
|||
return waitForDiscussionsRequest();
|
||||
});
|
||||
|
||||
it('should render markdown docs url', () => {
|
||||
it('should render markdown docs url', async () => {
|
||||
wrapper.find('.js-note-edit').trigger('click');
|
||||
const { markdownDocsPath } = mockData.notesDataMock;
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(wrapper.find(`.edit-note a[href="${markdownDocsPath}"]`).text().trim()).toEqual(
|
||||
'Markdown is supported',
|
||||
);
|
||||
});
|
||||
await nextTick();
|
||||
expect(wrapper.find(`.edit-note a[href="${markdownDocsPath}"]`).text().trim()).toEqual(
|
||||
'Markdown is supported',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not render quick actions docs url', () => {
|
||||
it('should not render quick actions docs url', async () => {
|
||||
wrapper.find('.js-note-edit').trigger('click');
|
||||
const { quickActionsDocsPath } = mockData.notesDataMock;
|
||||
|
||||
return wrapper.vm.$nextTick().then(() => {
|
||||
expect(wrapper.find(`.edit-note a[href="${quickActionsDocsPath}"]`).exists()).toBe(false);
|
||||
});
|
||||
await nextTick();
|
||||
expect(wrapper.find(`.edit-note a[href="${quickActionsDocsPath}"]`).exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import { merge } from 'lodash';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
|
||||
import { TEST_HOST } from 'helpers/test_constants';
|
||||
import deleteAccountModal from '~/profile/account/components/delete_account_modal.vue';
|
||||
|
@ -56,7 +56,7 @@ describe('DeleteAccountModal component', () => {
|
|||
const findModal = () => wrapper.find(GlModalStub);
|
||||
|
||||
describe('with password confirmation', () => {
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
createWrapper({
|
||||
propsData: {
|
||||
confirmWithPassword: true,
|
||||
|
@ -65,48 +65,40 @@ describe('DeleteAccountModal component', () => {
|
|||
|
||||
vm.isOpen = true;
|
||||
|
||||
Vue.nextTick().then(done).catch(done.fail);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('does not accept empty password', (done) => {
|
||||
it('does not accept empty password', async () => {
|
||||
const { form, input } = findElements();
|
||||
jest.spyOn(form, 'submit').mockImplementation(() => {});
|
||||
input.value = '';
|
||||
input.dispatchEvent(new Event('input'));
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
expect(vm.enteredPassword).toBe(input.value);
|
||||
expect(findModal().attributes('ok-disabled')).toBe('true');
|
||||
findModal().vm.$emit('primary');
|
||||
await nextTick();
|
||||
expect(vm.enteredPassword).toBe(input.value);
|
||||
expect(findModal().attributes('ok-disabled')).toBe('true');
|
||||
findModal().vm.$emit('primary');
|
||||
|
||||
expect(form.submit).not.toHaveBeenCalled();
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
expect(form.submit).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('submits form with password', (done) => {
|
||||
it('submits form with password', async () => {
|
||||
const { form, input } = findElements();
|
||||
jest.spyOn(form, 'submit').mockImplementation(() => {});
|
||||
input.value = 'anything';
|
||||
input.dispatchEvent(new Event('input'));
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
expect(vm.enteredPassword).toBe(input.value);
|
||||
expect(findModal().attributes('ok-disabled')).toBeUndefined();
|
||||
findModal().vm.$emit('primary');
|
||||
await nextTick();
|
||||
expect(vm.enteredPassword).toBe(input.value);
|
||||
expect(findModal().attributes('ok-disabled')).toBeUndefined();
|
||||
findModal().vm.$emit('primary');
|
||||
|
||||
expect(form.submit).toHaveBeenCalled();
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
expect(form.submit).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('with username confirmation', () => {
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
createWrapper({
|
||||
propsData: {
|
||||
confirmWithPassword: false,
|
||||
|
@ -115,43 +107,35 @@ describe('DeleteAccountModal component', () => {
|
|||
|
||||
vm.isOpen = true;
|
||||
|
||||
Vue.nextTick().then(done).catch(done.fail);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('does not accept wrong username', (done) => {
|
||||
it('does not accept wrong username', async () => {
|
||||
const { form, input } = findElements();
|
||||
jest.spyOn(form, 'submit').mockImplementation(() => {});
|
||||
input.value = 'this is wrong';
|
||||
input.dispatchEvent(new Event('input'));
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
expect(vm.enteredUsername).toBe(input.value);
|
||||
expect(findModal().attributes('ok-disabled')).toBe('true');
|
||||
findModal().vm.$emit('primary');
|
||||
await nextTick();
|
||||
expect(vm.enteredUsername).toBe(input.value);
|
||||
expect(findModal().attributes('ok-disabled')).toBe('true');
|
||||
findModal().vm.$emit('primary');
|
||||
|
||||
expect(form.submit).not.toHaveBeenCalled();
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
expect(form.submit).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('submits form with correct username', (done) => {
|
||||
it('submits form with correct username', async () => {
|
||||
const { form, input } = findElements();
|
||||
jest.spyOn(form, 'submit').mockImplementation(() => {});
|
||||
input.value = username;
|
||||
input.dispatchEvent(new Event('input'));
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
expect(vm.enteredUsername).toBe(input.value);
|
||||
expect(findModal().attributes('ok-disabled')).toBeUndefined();
|
||||
findModal().vm.$emit('primary');
|
||||
await nextTick();
|
||||
expect(vm.enteredUsername).toBe(input.value);
|
||||
expect(findModal().attributes('ok-disabled')).toBeUndefined();
|
||||
findModal().vm.$emit('primary');
|
||||
|
||||
expect(form.submit).toHaveBeenCalled();
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
expect(form.submit).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import mountComponent, { mountComponentWithSlots } from 'helpers/vue_mount_component_helper';
|
||||
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||
import reportSection from '~/reports/components/report_section.vue';
|
||||
|
@ -71,16 +71,12 @@ describe('Report section', () => {
|
|||
const issues = hasIssues ? 'has issues' : 'has no issues';
|
||||
const open = alwaysOpen ? 'is always open' : 'is not always open';
|
||||
|
||||
it(`is ${isCollapsible}, if the report ${issues} and ${open}`, (done) => {
|
||||
it(`is ${isCollapsible}, if the report ${issues} and ${open}`, async () => {
|
||||
vm.hasIssues = hasIssues;
|
||||
vm.alwaysOpen = alwaysOpen;
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
expect(vm.isCollapsible).toBe(isCollapsible);
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
await nextTick();
|
||||
expect(vm.isCollapsible).toBe(isCollapsible);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -97,16 +93,12 @@ describe('Report section', () => {
|
|||
const issues = isCollapsed ? 'is collapsed' : 'is not collapsed';
|
||||
const open = alwaysOpen ? 'is always open' : 'is not always open';
|
||||
|
||||
it(`is ${isExpanded}, if the report ${issues} and ${open}`, (done) => {
|
||||
it(`is ${isExpanded}, if the report ${issues} and ${open}`, async () => {
|
||||
vm.isCollapsed = isCollapsed;
|
||||
vm.alwaysOpen = alwaysOpen;
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
expect(vm.isExpanded).toBe(isExpanded);
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
await nextTick();
|
||||
expect(vm.isExpanded).toBe(isExpanded);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -148,79 +140,55 @@ describe('Report section', () => {
|
|||
describe('toggleCollapsed', () => {
|
||||
const hiddenCss = { display: 'none' };
|
||||
|
||||
it('toggles issues', (done) => {
|
||||
it('toggles issues', async () => {
|
||||
vm.$el.querySelector('button').click();
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
expect(vm.$el.querySelector('.js-report-section-container')).not.toHaveCss(hiddenCss);
|
||||
expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Collapse');
|
||||
await nextTick();
|
||||
expect(vm.$el.querySelector('.js-report-section-container')).not.toHaveCss(hiddenCss);
|
||||
expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Collapse');
|
||||
|
||||
vm.$el.querySelector('button').click();
|
||||
})
|
||||
.then(Vue.nextTick)
|
||||
.then(() => {
|
||||
expect(vm.$el.querySelector('.js-report-section-container')).toHaveCss(hiddenCss);
|
||||
expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Expand');
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
vm.$el.querySelector('button').click();
|
||||
|
||||
await nextTick();
|
||||
expect(vm.$el.querySelector('.js-report-section-container')).toHaveCss(hiddenCss);
|
||||
expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Expand');
|
||||
});
|
||||
|
||||
it('is always expanded, if always-open is set to true', (done) => {
|
||||
it('is always expanded, if always-open is set to true', async () => {
|
||||
vm.alwaysOpen = true;
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
expect(vm.$el.querySelector('.js-report-section-container')).not.toHaveCss(hiddenCss);
|
||||
expect(vm.$el.querySelector('button')).toBeNull();
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
await nextTick();
|
||||
expect(vm.$el.querySelector('.js-report-section-container')).not.toHaveCss(hiddenCss);
|
||||
expect(vm.$el.querySelector('button')).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('snowplow events', () => {
|
||||
it('does emit an event on issue toggle if the shouldEmitToggleEvent prop does exist', (done) => {
|
||||
it('does emit an event on issue toggle if the shouldEmitToggleEvent prop does exist', async () => {
|
||||
createComponent({ hasIssues: true, shouldEmitToggleEvent: true });
|
||||
|
||||
expect(wrapper.emitted().toggleEvent).toBeUndefined();
|
||||
|
||||
findCollapseButton().trigger('click');
|
||||
return wrapper.vm
|
||||
.$nextTick()
|
||||
.then(() => {
|
||||
expect(wrapper.emitted().toggleEvent).toHaveLength(1);
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
await nextTick();
|
||||
expect(wrapper.emitted().toggleEvent).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('does not emit an event on issue toggle if the shouldEmitToggleEvent prop does not exist', (done) => {
|
||||
it('does not emit an event on issue toggle if the shouldEmitToggleEvent prop does not exist', async () => {
|
||||
createComponent({ hasIssues: true });
|
||||
|
||||
expect(wrapper.emitted().toggleEvent).toBeUndefined();
|
||||
|
||||
findCollapseButton().trigger('click');
|
||||
return wrapper.vm
|
||||
.$nextTick()
|
||||
.then(() => {
|
||||
expect(wrapper.emitted().toggleEvent).toBeUndefined();
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
await nextTick();
|
||||
expect(wrapper.emitted().toggleEvent).toBeUndefined();
|
||||
});
|
||||
|
||||
it('does not emit an event if always-open is set to true', (done) => {
|
||||
it('does not emit an event if always-open is set to true', async () => {
|
||||
createComponent({ alwaysOpen: true, hasIssues: true, shouldEmitToggleEvent: true });
|
||||
|
||||
wrapper.vm
|
||||
.$nextTick()
|
||||
.then(() => {
|
||||
expect(wrapper.emitted().toggleEvent).toBeUndefined();
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
await nextTick();
|
||||
expect(wrapper.emitted().toggleEvent).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { GlLoadingIcon } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
import Participants from '~/sidebar/components/participants/participants.vue';
|
||||
|
||||
const PARTICIPANT = {
|
||||
|
@ -77,7 +77,7 @@ describe('Participants', () => {
|
|||
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('when only showing visible participants, shows an avatar only for each participant under the limit', () => {
|
||||
it('when only showing visible participants, shows an avatar only for each participant under the limit', async () => {
|
||||
const numberOfLessParticipants = 2;
|
||||
wrapper = mountComponent({
|
||||
loading: false,
|
||||
|
@ -91,12 +91,11 @@ describe('Participants', () => {
|
|||
isShowingMoreParticipants: false,
|
||||
});
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(wrapper.findAll('.participants-author')).toHaveLength(numberOfLessParticipants);
|
||||
});
|
||||
await nextTick();
|
||||
expect(wrapper.findAll('.participants-author')).toHaveLength(numberOfLessParticipants);
|
||||
});
|
||||
|
||||
it('when only showing all participants, each has an avatar', () => {
|
||||
it('when only showing all participants, each has an avatar', async () => {
|
||||
wrapper = mountComponent({
|
||||
loading: false,
|
||||
participants: PARTICIPANT_LIST,
|
||||
|
@ -109,9 +108,8 @@ describe('Participants', () => {
|
|||
isShowingMoreParticipants: true,
|
||||
});
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(wrapper.findAll('.participants-author')).toHaveLength(PARTICIPANT_LIST.length);
|
||||
});
|
||||
await nextTick();
|
||||
expect(wrapper.findAll('.participants-author')).toHaveLength(PARTICIPANT_LIST.length);
|
||||
});
|
||||
|
||||
it('does not have more participants link when they can all be shown', () => {
|
||||
|
@ -126,7 +124,7 @@ describe('Participants', () => {
|
|||
expect(getMoreParticipantsButton().exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('when too many participants, has more participants link to show more', () => {
|
||||
it('when too many participants, has more participants link to show more', async () => {
|
||||
wrapper = mountComponent({
|
||||
loading: false,
|
||||
participants: PARTICIPANT_LIST,
|
||||
|
@ -139,12 +137,11 @@ describe('Participants', () => {
|
|||
isShowingMoreParticipants: false,
|
||||
});
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(getMoreParticipantsButton().text()).toBe('+ 1 more');
|
||||
});
|
||||
await nextTick();
|
||||
expect(getMoreParticipantsButton().text()).toBe('+ 1 more');
|
||||
});
|
||||
|
||||
it('when too many participants and already showing them, has more participants link to show less', () => {
|
||||
it('when too many participants and already showing them, has more participants link to show less', async () => {
|
||||
wrapper = mountComponent({
|
||||
loading: false,
|
||||
participants: PARTICIPANT_LIST,
|
||||
|
@ -157,9 +154,8 @@ describe('Participants', () => {
|
|||
isShowingMoreParticipants: true,
|
||||
});
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
expect(getMoreParticipantsButton().text()).toBe('- show less');
|
||||
});
|
||||
await nextTick();
|
||||
expect(getMoreParticipantsButton().text()).toBe('- show less');
|
||||
});
|
||||
|
||||
it('clicking more participants link emits event', () => {
|
||||
|
@ -176,7 +172,7 @@ describe('Participants', () => {
|
|||
expect(wrapper.vm.isShowingMoreParticipants).toBe(true);
|
||||
});
|
||||
|
||||
it('clicking on participants icon emits `toggleSidebar` event', () => {
|
||||
it('clicking on participants icon emits `toggleSidebar` event', async () => {
|
||||
wrapper = mountComponent({
|
||||
loading: false,
|
||||
participants: PARTICIPANT_LIST,
|
||||
|
@ -187,11 +183,9 @@ describe('Participants', () => {
|
|||
|
||||
wrapper.find('.sidebar-collapsed-icon').trigger('click');
|
||||
|
||||
return Vue.nextTick(() => {
|
||||
expect(spy).toHaveBeenCalledWith('toggleSidebar');
|
||||
|
||||
spy.mockRestore();
|
||||
});
|
||||
await nextTick();
|
||||
expect(spy).toHaveBeenCalledWith('toggleSidebar');
|
||||
spy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
|
||||
import { within } from '@testing-library/dom';
|
||||
import { mount, createWrapper } from '@vue/test-utils';
|
||||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import Api from '~/api';
|
||||
|
@ -82,7 +82,7 @@ describe('~/user_lists/components/user_lists.vue', () => {
|
|||
|
||||
factory();
|
||||
await waitForPromises();
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
emptyState = wrapper.findComponent(GlEmptyState);
|
||||
});
|
||||
|
@ -130,7 +130,7 @@ describe('~/user_lists/components/user_lists.vue', () => {
|
|||
|
||||
factory();
|
||||
jest.spyOn(store, 'dispatch');
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
table = wrapper.findComponent(UserListsTable);
|
||||
});
|
||||
|
||||
|
@ -171,7 +171,7 @@ describe('~/user_lists/components/user_lists.vue', () => {
|
|||
Api.fetchFeatureFlagUserLists.mockRejectedValue();
|
||||
factory();
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('should render error state', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
import { setHTMLFixture } from 'helpers/fixtures';
|
||||
import { TEST_HOST } from 'helpers/test_constants';
|
||||
import initVueAlerts from '~/vue_alerts';
|
||||
|
@ -75,10 +75,9 @@ describe('VueAlerts', () => {
|
|||
});
|
||||
|
||||
describe('when dismissed', () => {
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
findAlertDismiss(findAlerts()[0]).click();
|
||||
|
||||
return Vue.nextTick();
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('hides the alert', () => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import axios from 'axios';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import MemoryUsage from '~/vue_merge_request_widget/components/deployment/memory_usage.vue';
|
||||
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
|
||||
|
||||
|
@ -184,7 +184,7 @@ describe('MemoryUsage', () => {
|
|||
vm.hasMetrics = false;
|
||||
vm.loadFailed = false;
|
||||
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
expect(el.querySelector('.js-usage-info.usage-info-loading')).toBeDefined();
|
||||
|
||||
expect(el.querySelector('.js-usage-info .usage-info-load-spinner')).toBeDefined();
|
||||
|
@ -203,7 +203,7 @@ describe('MemoryUsage', () => {
|
|||
vm.loadFailed = false;
|
||||
vm.memoryMetrics = metricsMockData.metrics.memory_values[0].values;
|
||||
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
expect(el.querySelector('.memory-graph-container')).toBeDefined();
|
||||
expect(el.querySelector('.js-usage-info').innerText).toContain(messages.hasMetrics);
|
||||
done();
|
||||
|
@ -215,7 +215,7 @@ describe('MemoryUsage', () => {
|
|||
vm.hasMetrics = false;
|
||||
vm.loadFailed = true;
|
||||
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
expect(el.querySelector('.js-usage-info.usage-info-failed')).toBeDefined();
|
||||
|
||||
expect(el.querySelector('.js-usage-info').innerText).toContain(messages.loadFailed);
|
||||
|
@ -228,7 +228,7 @@ describe('MemoryUsage', () => {
|
|||
vm.hasMetrics = false;
|
||||
vm.loadFailed = false;
|
||||
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
expect(el.querySelector('.js-usage-info.usage-info-unavailable')).toBeDefined();
|
||||
|
||||
expect(el.querySelector('.js-usage-info').innerText).toContain(messages.metricsUnavailable);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { getByRole } from '@testing-library/dom';
|
||||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import mountComponent from 'helpers/vue_mount_component_helper';
|
||||
import { OPEN_REVERT_MODAL, OPEN_CHERRY_PICK_MODAL } from '~/projects/commit/constants';
|
||||
import modalEventHub from '~/projects/commit/event_hub';
|
||||
|
@ -200,7 +200,7 @@ describe('MRWidgetMerged', () => {
|
|||
it('hides button to copy commit SHA if SHA does not exist', (done) => {
|
||||
vm.mr.mergeCommitSha = null;
|
||||
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
expect(selectors.copyMergeShaButton).toBe(null);
|
||||
expect(vm.$el.querySelector('.mr-info-list').innerText).not.toContain('with');
|
||||
done();
|
||||
|
@ -216,7 +216,7 @@ describe('MRWidgetMerged', () => {
|
|||
it('should not show source branch deleted text', (done) => {
|
||||
vm.mr.sourceBranchRemoved = false;
|
||||
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
expect(vm.$el.innerText).not.toContain('The source branch has been deleted');
|
||||
done();
|
||||
});
|
||||
|
@ -226,7 +226,7 @@ describe('MRWidgetMerged', () => {
|
|||
vm.mr.isRemovingSourceBranch = true;
|
||||
vm.mr.sourceBranchRemoved = false;
|
||||
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
expect(vm.$el.innerText).toContain('The source branch is being deleted');
|
||||
expect(vm.$el.innerText).not.toContain('The source branch has been deleted');
|
||||
done();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import NothingToMerge from '~/vue_merge_request_widget/components/states/nothing_to_merge.vue';
|
||||
|
||||
describe('NothingToMerge', () => {
|
||||
|
@ -20,7 +20,7 @@ describe('NothingToMerge', () => {
|
|||
|
||||
it('should not show new blob link if there is no link available', () => {
|
||||
vm.mr.newBlobPath = null;
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
expect(vm.$el.querySelector('[data-testid="createFileButton"]')).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
import { GlSprintf } from '@gitlab/ui';
|
||||
import simplePoll from '~/lib/utils/simple_poll';
|
||||
import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit.vue';
|
||||
|
@ -196,7 +196,7 @@ describe('ReadyToMerge', () => {
|
|||
// eslint-disable-next-line no-restricted-syntax
|
||||
wrapper.setData({ isMergingImmediately: true });
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.mergeButtonText).toEqual('Merge in progress');
|
||||
});
|
||||
|
@ -266,7 +266,7 @@ describe('ReadyToMerge', () => {
|
|||
// eslint-disable-next-line no-restricted-syntax
|
||||
wrapper.setData({ isMakingRequest: true });
|
||||
|
||||
await Vue.nextTick();
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.isMergeButtonDisabled).toBe(true);
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import WorkInProgress from '~/vue_merge_request_widget/components/states/work_in_progress.vue';
|
||||
import toast from '~/vue_shared/plugins/global_toast';
|
||||
import eventHub from '~/vue_merge_request_widget/event_hub';
|
||||
|
@ -94,7 +94,7 @@ describe('Wip', () => {
|
|||
it('should not show removeWIP button is user cannot update MR', (done) => {
|
||||
vm.mr.removeWIPPath = '';
|
||||
|
||||
Vue.nextTick(() => {
|
||||
nextTick(() => {
|
||||
expect(el.querySelector('.js-remove-draft')).toEqual(null);
|
||||
done();
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
import ExpandButton from '~/vue_shared/components/expand_button.vue';
|
||||
|
||||
const text = {
|
||||
|
@ -66,9 +66,9 @@ describe('Expand button', () => {
|
|||
});
|
||||
|
||||
describe('on click', () => {
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
expanderPrependEl().trigger('click');
|
||||
Vue.nextTick(done);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -85,7 +85,7 @@ describe('Expand button', () => {
|
|||
});
|
||||
|
||||
describe('when short text is provided', () => {
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
factory({
|
||||
slots: {
|
||||
expanded: `<p>${text.expanded}</p>`,
|
||||
|
@ -94,7 +94,7 @@ describe('Expand button', () => {
|
|||
});
|
||||
|
||||
expanderPrependEl().trigger('click');
|
||||
Vue.nextTick(done);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('only renders expanded text', () => {
|
||||
|
@ -110,31 +110,29 @@ describe('Expand button', () => {
|
|||
});
|
||||
|
||||
describe('append button', () => {
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
expanderPrependEl().trigger('click');
|
||||
Vue.nextTick(done);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('clicking hides itself and shows prepend', () => {
|
||||
it('clicking hides itself and shows prepend', async () => {
|
||||
expect(expanderAppendEl().isVisible()).toBe(true);
|
||||
expanderAppendEl().trigger('click');
|
||||
|
||||
return wrapper.vm.$nextTick().then(() => {
|
||||
expect(expanderPrependEl().isVisible()).toBe(true);
|
||||
});
|
||||
await nextTick();
|
||||
expect(expanderPrependEl().isVisible()).toBe(true);
|
||||
});
|
||||
|
||||
it('clicking hides expanded text', () => {
|
||||
it('clicking hides expanded text', async () => {
|
||||
expect(wrapper.find(ExpandButton).text().trim()).toBe(text.expanded);
|
||||
expanderAppendEl().trigger('click');
|
||||
|
||||
return wrapper.vm.$nextTick().then(() => {
|
||||
expect(wrapper.find(ExpandButton).text().trim()).not.toBe(text.expanded);
|
||||
});
|
||||
await nextTick();
|
||||
expect(wrapper.find(ExpandButton).text().trim()).not.toBe(text.expanded);
|
||||
});
|
||||
|
||||
describe('when short text is provided', () => {
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
factory({
|
||||
slots: {
|
||||
expanded: `<p>${text.expanded}</p>`,
|
||||
|
@ -143,16 +141,15 @@ describe('Expand button', () => {
|
|||
});
|
||||
|
||||
expanderPrependEl().trigger('click');
|
||||
Vue.nextTick(done);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('clicking reveals short text', () => {
|
||||
it('clicking reveals short text', async () => {
|
||||
expect(wrapper.find(ExpandButton).text().trim()).toBe(text.expanded);
|
||||
expanderAppendEl().trigger('click');
|
||||
|
||||
return wrapper.vm.$nextTick().then(() => {
|
||||
expect(wrapper.find(ExpandButton).text().trim()).toBe(text.short);
|
||||
});
|
||||
await nextTick();
|
||||
expect(wrapper.find(ExpandButton).text().trim()).toBe(text.short);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import mountComponent from 'helpers/vue_mount_component_helper';
|
||||
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
|
||||
|
||||
|
@ -17,38 +17,34 @@ describe('GlCountdown', () => {
|
|||
});
|
||||
|
||||
describe('when there is time remaining', () => {
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
vm = mountComponent(Component, {
|
||||
endDateString: '2000-01-01T01:02:03Z',
|
||||
});
|
||||
|
||||
Vue.nextTick().then(done).catch(done.fail);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('displays remaining time', () => {
|
||||
expect(vm.$el.textContent).toContain('01:02:03');
|
||||
});
|
||||
|
||||
it('updates remaining time', (done) => {
|
||||
it('updates remaining time', async () => {
|
||||
now = '2000-01-01T00:00:01Z';
|
||||
jest.advanceTimersByTime(1000);
|
||||
|
||||
Vue.nextTick()
|
||||
.then(() => {
|
||||
expect(vm.$el.textContent).toContain('01:02:02');
|
||||
done();
|
||||
})
|
||||
.catch(done.fail);
|
||||
await nextTick();
|
||||
expect(vm.$el.textContent).toContain('01:02:02');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there is no time remaining', () => {
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
vm = mountComponent(Component, {
|
||||
endDateString: '1900-01-01T00:00:00Z',
|
||||
});
|
||||
|
||||
Vue.nextTick().then(done).catch(done.fail);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('displays 00:00:00', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Vue from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import SuggestionsComponent from '~/vue_shared/components/markdown/suggestions.vue';
|
||||
|
||||
const MOCK_DATA = {
|
||||
|
@ -51,7 +51,7 @@ describe('Suggestion component', () => {
|
|||
let vm;
|
||||
let diffTable;
|
||||
|
||||
beforeEach((done) => {
|
||||
beforeEach(async () => {
|
||||
const Component = Vue.extend(SuggestionsComponent);
|
||||
|
||||
vm = new Component({
|
||||
|
@ -62,7 +62,7 @@ describe('Suggestion component', () => {
|
|||
|
||||
jest.spyOn(vm, 'renderSuggestions').mockImplementation(() => {});
|
||||
vm.renderSuggestions();
|
||||
Vue.nextTick(done);
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
describe('mounted', () => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import $ from 'jquery';
|
||||
import Vue from 'vue';
|
||||
import { nextTick } from 'vue';
|
||||
import ResizableChartContainer from '~/vue_shared/components/resizable_chart/resizable_chart_container.vue';
|
||||
|
||||
jest.mock('~/lib/utils/common_utils', () => ({
|
||||
|
@ -35,7 +35,7 @@ describe('Resizable Chart Container', () => {
|
|||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('updates the slot width and height props', () => {
|
||||
it('updates the slot width and height props', async () => {
|
||||
const width = 1920;
|
||||
const height = 1080;
|
||||
|
||||
|
@ -44,13 +44,12 @@ describe('Resizable Chart Container', () => {
|
|||
|
||||
$(document).trigger('content.resize');
|
||||
|
||||
return Vue.nextTick().then(() => {
|
||||
const widthNode = wrapper.find('.slot > .width');
|
||||
const heightNode = wrapper.find('.slot > .height');
|
||||
await nextTick();
|
||||
const widthNode = wrapper.find('.slot > .width');
|
||||
const heightNode = wrapper.find('.slot > .height');
|
||||
|
||||
expect(parseInt(widthNode.text(), 10)).toEqual(width);
|
||||
expect(parseInt(heightNode.text(), 10)).toEqual(height);
|
||||
});
|
||||
expect(parseInt(widthNode.text(), 10)).toEqual(width);
|
||||
expect(parseInt(heightNode.text(), 10)).toEqual(height);
|
||||
});
|
||||
|
||||
it('calls onResize on manual resize', () => {
|
||||
|
|
|
@ -894,4 +894,15 @@ RSpec.describe Member do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#set_member_namespace_id' do
|
||||
let(:group) { create(:group) }
|
||||
let(:member) { create(:group_member, group: group) }
|
||||
|
||||
describe 'on create' do
|
||||
it 'sets the member_namespace_id' do
|
||||
expect(member.member_namespace_id).to eq group.id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -257,4 +257,15 @@ RSpec.describe ProjectMember do
|
|||
it_behaves_like 'calls AuthorizedProjectUpdate::UserRefreshFromReplicaWorker with a delay to update project authorizations'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#set_member_namespace_id' do
|
||||
let(:project) { create(:project) }
|
||||
let(:member) { create(:project_member, project: project) }
|
||||
|
||||
context 'on create' do
|
||||
it 'sets the member_namespace_id' do
|
||||
expect(member.member_namespace_id).to eq project.project_namespace_id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -55,7 +55,7 @@ RSpec.describe StateNote do
|
|||
it 'contains the expected values' do
|
||||
expect(subject.author).to eq(author)
|
||||
expect(subject.created_at).to eq(event.created_at)
|
||||
expect(subject.note).to eq('resolved the corresponding error and closed the issue.')
|
||||
expect(subject.note).to eq('resolved the corresponding error and closed the issue')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -65,7 +65,7 @@ RSpec.describe StateNote do
|
|||
it 'contains the expected values' do
|
||||
expect(subject.author).to eq(author)
|
||||
expect(subject.created_at).to eq(event.created_at)
|
||||
expect(subject.note).to eq('automatically closed this issue because the alert resolved.')
|
||||
expect(subject.note).to eq('automatically closed this incident because the alert resolved')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -118,7 +118,7 @@ RSpec.describe Issues::CloseService do
|
|||
expect { service.execute(issue) }.to change { issue.notes.count }.by(1)
|
||||
|
||||
new_note = issue.notes.last
|
||||
expect(new_note.note).to eq('changed the status to **Resolved** by closing the incident')
|
||||
expect(new_note.note).to eq('changed the incident status to **Resolved** by closing the incident')
|
||||
expect(new_note.author).to eq(user)
|
||||
end
|
||||
|
||||
|
@ -334,8 +334,12 @@ RSpec.describe Issues::CloseService do
|
|||
let!(:alert) { create(:alert_management_alert, issue: issue, project: project) }
|
||||
|
||||
it 'resolves an alert and sends a system note' do
|
||||
expect_next_instance_of(SystemNotes::AlertManagementService) do |notes_service|
|
||||
expect(notes_service).to receive(:closed_alert_issue).with(issue)
|
||||
expect_any_instance_of(SystemNoteService) do |notes_service|
|
||||
expect(notes_service).to receive(:change_alert_status).with(
|
||||
alert,
|
||||
current_user,
|
||||
" by closing issue #{issue.to_reference(project)}"
|
||||
)
|
||||
end
|
||||
|
||||
close_issue
|
||||
|
|
|
@ -93,11 +93,23 @@ RSpec.describe Projects::ImportExport::ExportService do
|
|||
end
|
||||
|
||||
it 'saves the project in the file system' do
|
||||
expect(Gitlab::ImportExport::Saver).to receive(:save).with(exportable: project, shared: shared)
|
||||
expect(Gitlab::ImportExport::Saver).to receive(:save).with(exportable: project, shared: shared).and_return(true)
|
||||
|
||||
service.execute
|
||||
end
|
||||
|
||||
context 'when the upload fails' do
|
||||
before do
|
||||
expect(Gitlab::ImportExport::Saver).to receive(:save).with(exportable: project, shared: shared).and_return(false)
|
||||
end
|
||||
|
||||
it 'notifies the user of an error' do
|
||||
expect(service).to receive(:notify_error).and_call_original
|
||||
|
||||
expect { service.execute }.to raise_error(Gitlab::ImportExport::Error)
|
||||
end
|
||||
end
|
||||
|
||||
it 'calls the after export strategy' do
|
||||
expect(after_export_strategy).to receive(:execute)
|
||||
|
||||
|
@ -107,6 +119,7 @@ RSpec.describe Projects::ImportExport::ExportService do
|
|||
context 'when after export strategy fails' do
|
||||
before do
|
||||
allow(after_export_strategy).to receive(:execute).and_return(false)
|
||||
expect(Gitlab::ImportExport::Saver).to receive(:save).with(exportable: project, shared: shared).and_return(true)
|
||||
end
|
||||
|
||||
after do
|
||||
|
|
|
@ -632,18 +632,6 @@ RSpec.describe SystemNoteService do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.resolve_incident_status' do
|
||||
let(:incident) { build(:incident, :closed) }
|
||||
|
||||
it 'calls IncidentService' do
|
||||
expect_next_instance_of(SystemNotes::IncidentService) do |service|
|
||||
expect(service).to receive(:resolve_incident_status)
|
||||
end
|
||||
|
||||
described_class.resolve_incident_status(incident, author)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.change_incident_status' do
|
||||
let(:incident) { instance_double('Issue', project: project) }
|
||||
|
||||
|
|
|
@ -54,21 +54,7 @@ RSpec.describe ::SystemNotes::AlertManagementService do
|
|||
end
|
||||
|
||||
it 'has the appropriate message' do
|
||||
expect(subject.note).to eq("created issue #{issue.to_reference(project)} for this alert")
|
||||
end
|
||||
end
|
||||
|
||||
describe '#closed_alert_issue' do
|
||||
let_it_be(:issue) { noteable.issue }
|
||||
|
||||
subject { described_class.new(noteable: noteable, project: project, author: author).closed_alert_issue(issue) }
|
||||
|
||||
it_behaves_like 'a system note' do
|
||||
let(:action) { 'status' }
|
||||
end
|
||||
|
||||
it 'has the appropriate message' do
|
||||
expect(subject.note).to eq("changed the status to **Resolved** by closing issue #{issue.to_reference(project)}")
|
||||
expect(subject.note).to eq("created incident #{issue.to_reference(project)} for this alert")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -57,16 +57,6 @@ RSpec.describe ::SystemNotes::IncidentService do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#resolve_incident_status' do
|
||||
subject(:resolve_incident_status) { described_class.new(noteable: noteable, project: project, author: author).resolve_incident_status }
|
||||
|
||||
it 'creates a new note about resolved incident', :aggregate_failures do
|
||||
expect { resolve_incident_status }.to change { noteable.notes.count }.by(1)
|
||||
|
||||
expect(noteable.notes.last.note).to eq('changed the status to **Resolved** by closing the incident')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#change_incident_status' do
|
||||
let_it_be(:escalation_status) { create(:incident_management_issuable_escalation_status, issue: noteable) }
|
||||
|
||||
|
|
|
@ -462,14 +462,6 @@ RSpec.configure do |config|
|
|||
$stdout = STDOUT
|
||||
end
|
||||
|
||||
config.around(:each, stubbing_settings_source: true) do |example|
|
||||
original_instance = ::Settings.instance_variable_get(:@instance)
|
||||
|
||||
example.run
|
||||
|
||||
::Settings.instance_variable_set(:@instance, original_instance)
|
||||
end
|
||||
|
||||
config.disable_monkey_patching!
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.around(:each, stub_settings_source: true) do |example|
|
||||
original_instance = ::Settings.instance_variable_get(:@instance)
|
||||
|
||||
example.run
|
||||
|
||||
::Settings.instance_variable_set(:@instance, original_instance)
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue