summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/create_cluster/init_create_cluster.js20
-rw-r--r--app/controllers/clusters/clusters_controller.rb9
-rw-r--r--app/services/projects/container_repository/cleanup_tags_service.rb4
-rw-r--r--app/services/projects/container_repository/delete_tags_service.rb34
-rw-r--r--app/views/admin/application_settings/integrations.html.haml2
-rw-r--r--app/views/clusters/clusters/gcp/_new.html.haml2
-rw-r--r--app/views/clusters/clusters/gcp/_signin_with_google_button.html.haml4
-rw-r--r--app/views/clusters/clusters/new.html.haml14
-rw-r--r--changelogs/unreleased/22392-remove-eks-cluster-feature-flag.yml5
-rw-r--r--doc/user/project/clusters/add_remove_clusters.md24
-rw-r--r--locale/gitlab.pot6
-rw-r--r--spec/controllers/admin/clusters_controller_spec.rb26
-rw-r--r--spec/controllers/groups/clusters_controller_spec.rb20
-rw-r--r--spec/controllers/projects/clusters_controller_spec.rb20
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb29
-rw-r--r--spec/features/projects/clusters_spec.rb33
-rw-r--r--spec/javascripts/diffs/components/settings_dropdown_spec.js10
-rw-r--r--spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js60
-rw-r--r--spec/javascripts/frequent_items/components/frequent_items_search_input_spec.js18
-rw-r--r--spec/javascripts/jobs/components/manual_variables_form_spec.js26
-rw-r--r--spec/javascripts/monitoring/charts/column_spec.js8
-rw-r--r--spec/javascripts/monitoring/charts/empty_chart_spec.js8
-rw-r--r--spec/javascripts/monitoring/charts/single_stat_spec.js8
-rw-r--r--spec/javascripts/monitoring/components/dashboard_spec.js56
-rw-r--r--spec/javascripts/monitoring/components/graph_group_spec.js38
-rw-r--r--spec/javascripts/notes/components/note_actions/reply_button_spec.js9
-rw-r--r--spec/javascripts/notes/components/note_actions_spec.js2
-rw-r--r--spec/javascripts/notes/components/note_form_spec.js2
-rw-r--r--spec/javascripts/notes/components/noteable_discussion_spec.js5
-rw-r--r--spec/javascripts/notes/components/noteable_note_spec.js2
-rw-r--r--spec/javascripts/related_merge_requests/components/related_merge_requests_spec.js2
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js5
-rw-r--r--spec/javascripts/vue_shared/components/pagination/graphql_pagination_spec.js8
33 files changed, 206 insertions, 313 deletions
diff --git a/app/assets/javascripts/create_cluster/init_create_cluster.js b/app/assets/javascripts/create_cluster/init_create_cluster.js
index 7c984582fd8..2b09771d772 100644
--- a/app/assets/javascripts/create_cluster/init_create_cluster.js
+++ b/app/assets/javascripts/create_cluster/init_create_cluster.js
@@ -6,7 +6,7 @@ const newClusterViews = [':clusters:new', ':clusters:create_gcp', ':clusters:cre
const isProjectLevelCluster = page => page.startsWith('project:clusters');
-export default (document, gon) => {
+export default document => {
const { page } = document.body.dataset;
const isNewClusterView = newClusterViews.some(view => page.endsWith(view));
@@ -19,17 +19,15 @@ export default (document, gon) => {
initGkeDropdowns();
- if (gon.features.createEksClusters) {
- import(/* webpackChunkName: 'eks_cluster' */ '~/create_cluster/eks_cluster')
- .then(({ default: initCreateEKSCluster }) => {
- const el = document.querySelector('.js-create-eks-cluster-form-container');
+ import(/* webpackChunkName: 'eks_cluster' */ '~/create_cluster/eks_cluster')
+ .then(({ default: initCreateEKSCluster }) => {
+ const el = document.querySelector('.js-create-eks-cluster-form-container');
- if (el) {
- initCreateEKSCluster(el);
- }
- })
- .catch(() => {});
- }
+ if (el) {
+ initCreateEKSCluster(el);
+ }
+ })
+ .catch(() => {});
if (isProjectLevelCluster(page)) {
initGkeNamespace();
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb
index 9da8ad229fe..0295f36732c 100644
--- a/app/controllers/clusters/clusters_controller.rb
+++ b/app/controllers/clusters/clusters_controller.rb
@@ -12,9 +12,6 @@ class Clusters::ClustersController < Clusters::BaseController
before_action :authorize_update_cluster!, only: [:update]
before_action :authorize_admin_cluster!, only: [:destroy, :clear_cache]
before_action :update_applications_status, only: [:cluster_status]
- before_action only: [:new, :create_gcp] do
- push_frontend_feature_flag(:create_eks_clusters)
- end
before_action only: [:show] do
push_frontend_feature_flag(:enable_cluster_application_elastic_stack)
push_frontend_feature_flag(:enable_cluster_application_crossplane)
@@ -42,8 +39,6 @@ class Clusters::ClustersController < Clusters::BaseController
end
def new
- return unless Feature.enabled?(:create_eks_clusters)
-
if params[:provider] == 'aws'
@aws_role = current_user.aws_role || Aws::Role.new
@aws_role.ensure_role_external_id!
@@ -113,6 +108,7 @@ class Clusters::ClustersController < Clusters::BaseController
generate_gcp_authorize_url
validate_gcp_token
user_cluster
+ params[:provider] = 'gcp'
render :new, locals: { active_tab: 'create' }
end
@@ -277,8 +273,7 @@ class Clusters::ClustersController < Clusters::BaseController
end
def generate_gcp_authorize_url
- params = Feature.enabled?(:create_eks_clusters) ? { provider: :gke } : {}
- state = generate_session_key_redirect(clusterable.new_path(params).to_s)
+ state = generate_session_key_redirect(clusterable.new_path(provider: :gcp).to_s)
@authorize_url = GoogleApi::CloudPlatform::Client.new(
nil, callback_google_api_auth_url,
diff --git a/app/services/projects/container_repository/cleanup_tags_service.rb b/app/services/projects/container_repository/cleanup_tags_service.rb
index 1b880a7aab1..b995df12e56 100644
--- a/app/services/projects/container_repository/cleanup_tags_service.rb
+++ b/app/services/projects/container_repository/cleanup_tags_service.rb
@@ -26,13 +26,13 @@ module Projects
def delete_tags(tags_to_delete, tags_by_digest)
deleted_digests = group_by_digest(tags_to_delete).select do |digest, tags|
- delete_tag_digest(digest, tags, tags_by_digest[digest])
+ delete_tag_digest(tags, tags_by_digest[digest])
end
deleted_digests.values.flatten
end
- def delete_tag_digest(digest, tags, other_tags)
+ def delete_tag_digest(tags, other_tags)
# Issue: https://gitlab.com/gitlab-org/gitlab-foss/issues/21405
# we have to remove all tags due
# to Docker Distribution bug unable
diff --git a/app/services/projects/container_repository/delete_tags_service.rb b/app/services/projects/container_repository/delete_tags_service.rb
index 48bd9394dc5..af58d3780b0 100644
--- a/app/services/projects/container_repository/delete_tags_service.rb
+++ b/app/services/projects/container_repository/delete_tags_service.rb
@@ -24,32 +24,36 @@ module Projects
dummy_manifest = container_repository.client.generate_empty_manifest(container_repository.path)
return error('could not generate manifest') if dummy_manifest.nil?
- # update the manifests of the tags with the new dummy image
- deleted_tags = []
- tag_digests = []
+ deleted_tags = replace_tag_manifests(container_repository, dummy_manifest, tag_names)
+
+ # Deletes the dummy image
+ # All created tag digests are the same since they all have the same dummy image.
+ # a single delete is sufficient to remove all tags with it
+ if deleted_tags.any? && container_repository.delete_tag_by_digest(deleted_tags.values.first)
+ success(deleted: deleted_tags.keys)
+ else
+ error('could not delete tags')
+ end
+ end
+
+ # update the manifests of the tags with the new dummy image
+ def replace_tag_manifests(container_repository, dummy_manifest, tag_names)
+ deleted_tags = {}
tag_names.each do |name|
digest = container_repository.client.put_tag(container_repository.path, name, dummy_manifest)
next unless digest
- deleted_tags << name
- tag_digests << digest
+ deleted_tags[name] = digest
end
# make sure the digests are the same (it should always be)
- tag_digests.uniq!
+ digests = deleted_tags.values.uniq
# rubocop: disable CodeReuse/ActiveRecord
- Gitlab::Sentry.track_exception(ArgumentError.new('multiple tag digests')) if tag_digests.many?
+ Gitlab::Sentry.track_exception(ArgumentError.new('multiple tag digests')) if digests.many?
- # Deletes the dummy image
- # All created tag digests are the same since they all have the same dummy image.
- # a single delete is sufficient to remove all tags with it
- if tag_digests.any? && container_repository.delete_tag_by_digest(tag_digests.first)
- success(deleted: deleted_tags)
- else
- error('could not delete tags')
- end
+ deleted_tags
end
end
end
diff --git a/app/views/admin/application_settings/integrations.html.haml b/app/views/admin/application_settings/integrations.html.haml
index 0aa833e49a8..c6318c9bb2f 100644
--- a/app/views/admin/application_settings/integrations.html.haml
+++ b/app/views/admin/application_settings/integrations.html.haml
@@ -8,5 +8,5 @@
= render_if_exists 'admin/application_settings/slack'
= render 'admin/application_settings/third_party_offers'
= render 'admin/application_settings/snowplow'
-= render 'admin/application_settings/eks' if Feature.enabled?(:create_eks_clusters)
+= render 'admin/application_settings/eks'
diff --git a/app/views/clusters/clusters/gcp/_new.html.haml b/app/views/clusters/clusters/gcp/_new.html.haml
index 3d47f4bf2c3..6c3a230fb93 100644
--- a/app/views/clusters/clusters/gcp/_new.html.haml
+++ b/app/views/clusters/clusters/gcp/_new.html.haml
@@ -1,7 +1,5 @@
= render 'clusters/clusters/gcp/header'
- if @valid_gcp_token
= render 'clusters/clusters/gcp/form'
-- elsif @authorize_url
- = render 'clusters/clusters/gcp/signin_with_google_button'
- else
= render 'clusters/clusters/gcp/gcp_not_configured'
diff --git a/app/views/clusters/clusters/gcp/_signin_with_google_button.html.haml b/app/views/clusters/clusters/gcp/_signin_with_google_button.html.haml
deleted file mode 100644
index 65cfa6552b1..00000000000
--- a/app/views/clusters/clusters/gcp/_signin_with_google_button.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-.signin-with-google
- - create_account_link = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: 'https://accounts.google.com/SignUpWithoutGmail?service=cloudconsole&continue=https%3A%2F%2Fconsole.cloud.google.com%2Ffreetrial%3Futm_campaign%3D2018_cpanel%26utm_source%3Dgitlab%26utm_medium%3Dreferral' }
- = link_to(image_tag('auth_buttons/signin_with_google.png', width: '191px', alt: _('Sign in with Google')), @authorize_url)
- = s_('or %{link_start}create a new Google account%{link_end}').html_safe % { link_start: create_account_link, link_end: '</a>'.html_safe }
diff --git a/app/views/clusters/clusters/new.html.haml b/app/views/clusters/clusters/new.html.haml
index cb8cbe4e6f2..629585d82cd 100644
--- a/app/views/clusters/clusters/new.html.haml
+++ b/app/views/clusters/clusters/new.html.haml
@@ -1,6 +1,5 @@
- breadcrumb_title _('Kubernetes')
- page_title _('Kubernetes Cluster')
-- create_eks_enabled = Feature.enabled?(:create_eks_clusters)
- active_tab = local_assigns.fetch(:active_tab, 'create')
= javascript_include_tag 'https://apis.google.com/js/api.js'
@@ -14,21 +13,14 @@
%li.nav-item{ role: 'presentation' }
%a.nav-link{ href: '#create-cluster-pane', id: 'create-cluster-tab', class: active_when(active_tab == 'create'), data: { toggle: 'tab' }, role: 'tab' }
%span
- - if create_eks_enabled
- = create_new_cluster_label(provider: params[:provider])
- - else
- = create_new_cluster_label(provider: 'gcp')
+ = create_new_cluster_label(provider: params[:provider])
%li.nav-item{ role: 'presentation' }
%a.nav-link{ href: '#add-cluster-pane', id: 'add-cluster-tab', class: active_when(active_tab == 'add'), data: { toggle: 'tab' }, role: 'tab' }
%span Add existing cluster
.tab-content.gitlab-tab-content
- - if create_eks_enabled
- .tab-pane{ id: 'create-cluster-pane', class: active_when(active_tab == 'create'), role: 'tabpanel' }
- = render new_cluster_partial(provider: params[:provider])
- - else
- .tab-pane{ id: 'create-cluster-pane', class: active_when(active_tab == 'create'), role: 'tabpanel' }
- = render new_cluster_partial(provider: 'gcp')
+ .tab-pane{ id: 'create-cluster-pane', class: active_when(active_tab == 'create'), role: 'tabpanel' }
+ = render new_cluster_partial(provider: params[:provider])
.tab-pane{ id: 'add-cluster-pane', class: active_when(active_tab == 'add'), role: 'tabpanel' }
= render 'clusters/clusters/user/header'
diff --git a/changelogs/unreleased/22392-remove-eks-cluster-feature-flag.yml b/changelogs/unreleased/22392-remove-eks-cluster-feature-flag.yml
new file mode 100644
index 00000000000..07dbd072cc2
--- /dev/null
+++ b/changelogs/unreleased/22392-remove-eks-cluster-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Enable creating Amazon EKS clusters from GitLab
+merge_request: 20333
+author:
+type: added
diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md
index ad5a0c2273b..a1f437b6e54 100644
--- a/doc/user/project/clusters/add_remove_clusters.md
+++ b/doc/user/project/clusters/add_remove_clusters.md
@@ -211,33 +211,9 @@ GitLab supports:
Before creating your first cluster on Amazon EKS with GitLab's integration,
make sure the following requirements are met:
-- Self-managed GitLab instances have the `create_eks_clusters` feature flag enabled.
- An [Amazon Web Services](https://aws.amazon.com/) account is set up and you are able to log in.
- You have permissions to manage IAM resources.
-##### Enable the `create_eks_clusters` feature flag **(CORE ONLY)**
-
-Self-managed instances must have the feature flag `create_eks_clusters` enabled to create
-EKS clusters. To enable EKS cluster creation, ask a GitLab administrator with Rails console access
-to run the following command:
-
-```ruby
-Feature.enable(:create_eks_clusters)
-```
-
-To have it enabled for a specific project only, ask a GitLab administrator to run the following
-command using a Rails console:
-
-```ruby
-Feature.enable(:create_eks_clusters, Project.find_by_full_path('my_group/my_project'))
-```
-
-To have this feature disabled, ask a GitLab administrator to run the following command:
-
-```ruby
-Feature.disable(:create_eks_clusters)
-```
-
##### Additional requirements for self-managed instances
If you are using a self-managed GitLab instance, GitLab must first
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 525d441b1fc..f36318676aa 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -15948,9 +15948,6 @@ msgstr ""
msgid "Sign in via 2FA code"
msgstr ""
-msgid "Sign in with Google"
-msgstr ""
-
msgid "Sign in with Single Sign-On"
msgstr ""
@@ -21263,9 +21260,6 @@ msgstr ""
msgid "opened %{timeAgoString} by %{user}"
msgstr ""
-msgid "or %{link_start}create a new Google account%{link_end}"
-msgstr ""
-
msgid "out of %d total test"
msgid_plural "out of %d total tests"
msgstr[0] ""
diff --git a/spec/controllers/admin/clusters_controller_spec.rb b/spec/controllers/admin/clusters_controller_spec.rb
index 326d0808092..4184c7e611a 100644
--- a/spec/controllers/admin/clusters_controller_spec.rb
+++ b/spec/controllers/admin/clusters_controller_spec.rb
@@ -84,29 +84,11 @@ describe Admin::ClustersController do
GoogleApi::CloudPlatform::Client.session_key_for_redirect_uri(key)
end
- before do
- stub_feature_flags(create_eks_clusters: false)
- allow(SecureRandom).to receive(:hex).and_return(key)
- end
-
- it 'has authorize_url' do
- get_new
-
- expect(assigns(:authorize_url)).to include(key)
- expect(session[session_key_for_redirect_uri]).to eq(new_admin_cluster_path)
- end
-
- context 'when create_eks_clusters feature flag is enabled' do
- before do
- stub_feature_flags(create_eks_clusters: true)
- end
-
- context 'when selected provider is gke and no valid gcp token exists' do
- it 'redirects to gcp authorize_url' do
- get_new
+ context 'when selected provider is gke and no valid gcp token exists' do
+ it 'redirects to gcp authorize_url' do
+ get_new
- expect(response).to redirect_to(assigns(:authorize_url))
- end
+ expect(response).to redirect_to(assigns(:authorize_url))
end
end
end
diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb
index d1669c84e3e..d47122f051e 100644
--- a/spec/controllers/groups/clusters_controller_spec.rb
+++ b/spec/controllers/groups/clusters_controller_spec.rb
@@ -97,29 +97,15 @@ describe Groups::ClustersController do
end
before do
- stub_feature_flags(create_eks_clusters: false)
allow(SecureRandom).to receive(:hex).and_return(key)
end
- it 'has authorize_url' do
+ it 'redirects to gcp authorize_url' do
go
expect(assigns(:authorize_url)).to include(key)
- expect(session[session_key_for_redirect_uri]).to eq(new_group_cluster_path(group))
- end
-
- context 'when create_eks_clusters feature flag is enabled' do
- before do
- stub_feature_flags(create_eks_clusters: true)
- end
-
- context 'when selected provider is gke and no valid gcp token exists' do
- it 'redirects to gcp authorize_url' do
- go
-
- expect(response).to redirect_to(assigns(:authorize_url))
- end
- end
+ expect(session[session_key_for_redirect_uri]).to eq(new_group_cluster_path(group, provider: :gcp))
+ expect(response).to redirect_to(assigns(:authorize_url))
end
end
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index 9c21b472c15..5efac44615f 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -95,29 +95,15 @@ describe Projects::ClustersController do
end
before do
- stub_feature_flags(create_eks_clusters: false)
allow(SecureRandom).to receive(:hex).and_return(key)
end
- it 'has authorize_url' do
+ it 'redirects to gcp authorize_url' do
go
expect(assigns(:authorize_url)).to include(key)
- expect(session[session_key_for_redirect_uri]).to eq(new_project_cluster_path(project))
- end
-
- context 'when create_eks_clusters feature flag is enabled' do
- before do
- stub_feature_flags(create_eks_clusters: true)
- end
-
- context 'when selected provider is gke and no valid gcp token exists' do
- it 'redirects to gcp authorize_url' do
- go
-
- expect(response).to redirect_to(assigns(:authorize_url))
- end
- end
+ expect(session[session_key_for_redirect_uri]).to eq(new_project_cluster_path(project, provider: :gcp))
+ expect(response).to redirect_to(assigns(:authorize_url))
end
end
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index bdc946a9c98..9e1b4c5c45f 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -18,8 +18,6 @@ describe 'Gcp Cluster', :js do
let(:project_id) { 'test-project-1234' }
before do
- stub_feature_flags(create_eks_clusters: false)
-
allow_any_instance_of(Projects::ClustersController)
.to receive(:token_in_session).and_return('token')
allow_any_instance_of(Projects::ClustersController)
@@ -31,7 +29,8 @@ describe 'Gcp Cluster', :js do
visit project_clusters_path(project)
click_link 'Add Kubernetes cluster'
- click_link 'Create new Cluster on GKE'
+ click_link 'Create new Cluster'
+ click_link 'Google GKE'
end
context 'when user filled form with valid parameters' do
@@ -147,21 +146,6 @@ describe 'Gcp Cluster', :js do
end
end
- context 'when user has not signed with Google' do
- before do
- stub_feature_flags(create_eks_clusters: false)
- visit project_clusters_path(project)
-
- click_link 'Add Kubernetes cluster'
- click_link 'Create new Cluster on GKE'
- end
-
- it 'user sees a login page' do
- expect(page).to have_css('.signin-with-google')
- expect(page).to have_link('Google account')
- end
- end
-
context 'when a user cannot edit the environment scope' do
before do
visit project_clusters_path(project)
@@ -177,7 +161,6 @@ describe 'Gcp Cluster', :js do
context 'when user has not dismissed GCP signup offer' do
before do
- stub_feature_flags(create_eks_clusters: false)
visit project_clusters_path(project)
end
@@ -190,18 +173,10 @@ describe 'Gcp Cluster', :js do
expect(page).to have_css('.gcp-signup-offer')
end
-
- it 'user sees offer on cluster GCP login page' do
- click_link 'Add Kubernetes cluster'
- click_link 'Create new Cluster on GKE'
-
- expect(page).to have_css('.gcp-signup-offer')
- end
end
context 'when user has dismissed GCP signup offer' do
before do
- stub_feature_flags(create_eks_clusters: false)
visit project_clusters_path(project)
end
diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb
index 67d14d0a58a..9b02991cd53 100644
--- a/spec/features/projects/clusters_spec.rb
+++ b/spec/features/projects/clusters_spec.rb
@@ -49,41 +49,20 @@ describe 'Clusters', :js do
end
end
- context 'when user has not signed in Google' do
+ context 'user visits create cluster page' do
before do
- stub_feature_flags(create_eks_clusters: false)
visit project_clusters_path(project)
click_link 'Add Kubernetes cluster'
- click_link 'Create new Cluster on GKE'
+ click_link 'Create new Cluster'
end
- it 'user sees a login page' do
- expect(page).to have_css('.signin-with-google')
- expect(page).to have_link('Google account')
+ it 'user sees a link to create a GKE cluster' do
+ expect(page).to have_link('Google GKE')
end
- end
-
- context 'when create_eks_clusters feature flag is enabled' do
- before do
- stub_feature_flags(create_eks_clusters: true)
- end
-
- context 'when user access create cluster page' do
- before do
- visit project_clusters_path(project)
- click_link 'Add Kubernetes cluster'
- click_link 'Create new Cluster'
- end
-
- it 'user sees a link to create a GKE cluster' do
- expect(page).to have_link('Google GKE')
- end
-
- it 'user sees a link to create an EKS cluster' do
- expect(page).to have_link('Amazon EKS')
- end
+ it 'user sees a link to create an EKS cluster' do
+ expect(page).to have_link('Amazon EKS')
end
end
end
diff --git a/spec/javascripts/diffs/components/settings_dropdown_spec.js b/spec/javascripts/diffs/components/settings_dropdown_spec.js
index 5031846cff0..6c08474ffd2 100644
--- a/spec/javascripts/diffs/components/settings_dropdown_spec.js
+++ b/spec/javascripts/diffs/components/settings_dropdown_spec.js
@@ -4,15 +4,14 @@ import diffModule from '~/diffs/store/modules';
import SettingsDropdown from '~/diffs/components/settings_dropdown.vue';
import { PARALLEL_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE } from '~/diffs/constants';
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
describe('Diff settiings dropdown component', () => {
let vm;
let actions;
function createComponent(extendStore = () => {}) {
- const localVue = createLocalVue();
-
- localVue.use(Vuex);
-
const store = new Vuex.Store({
modules: {
diffs: {
@@ -26,9 +25,10 @@ describe('Diff settiings dropdown component', () => {
extendStore(store);
- vm = mount(SettingsDropdown, {
+ vm = mount(localVue.extend(SettingsDropdown), {
localVue,
store,
+ sync: false,
});
}
diff --git a/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js b/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js
index dce8e3be148..27c79b9c34c 100644
--- a/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js
+++ b/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js
@@ -1,53 +1,51 @@
-import Vue from 'vue';
import frequentItemsListItemComponent from '~/frequent_items/components/frequent_items_list_item.vue';
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import { trimText } from 'spec/helpers/text_helper';
import { mockProject } from '../mock_data'; // can also use 'mockGroup', but not useful to test here
-const createComponent = () => {
- const Component = Vue.extend(frequentItemsListItemComponent);
-
- return shallowMount(Component, {
- propsData: {
- itemId: mockProject.id,
- itemName: mockProject.name,
- namespace: mockProject.namespace,
- webUrl: mockProject.webUrl,
- avatarUrl: mockProject.avatarUrl,
- },
- });
-};
+const localVue = createLocalVue();
describe('FrequentItemsListItemComponent', () => {
let wrapper;
- let vm;
-
- beforeEach(() => {
- wrapper = createComponent();
- ({ vm } = wrapper);
- });
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(localVue.extend(frequentItemsListItemComponent), {
+ propsData: {
+ itemId: mockProject.id,
+ itemName: mockProject.name,
+ namespace: mockProject.namespace,
+ webUrl: mockProject.webUrl,
+ avatarUrl: mockProject.avatarUrl,
+ ...props,
+ },
+ sync: false,
+ localVue,
+ });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
+ wrapper = null;
});
describe('computed', () => {
describe('hasAvatar', () => {
it('should return `true` or `false` if whether avatar is present or not', () => {
- wrapper.setProps({ avatarUrl: 'path/to/avatar.png' });
+ createComponent({ avatarUrl: 'path/to/avatar.png' });
- expect(vm.hasAvatar).toBe(true);
+ expect(wrapper.vm.hasAvatar).toBe(true);
+ });
- wrapper.setProps({ avatarUrl: null });
+ it('should return `false` if avatar is not present', () => {
+ createComponent({ avatarUrl: null });
- expect(vm.hasAvatar).toBe(false);
+ expect(wrapper.vm.hasAvatar).toBe(false);
});
});
describe('highlightedItemName', () => {
it('should enclose part of project name in <b> & </b> which matches with `matcher` prop', () => {
- wrapper.setProps({ matcher: 'lab' });
+ createComponent({ matcher: 'lab' });
expect(wrapper.find('.js-frequent-items-item-title').html()).toContain(
'<b>L</b><b>a</b><b>b</b>',
@@ -55,7 +53,7 @@ describe('FrequentItemsListItemComponent', () => {
});
it('should return project name as it is if `matcher` is not available', () => {
- wrapper.setProps({ matcher: null });
+ createComponent({ matcher: null });
expect(trimText(wrapper.find('.js-frequent-items-item-title').text())).toBe(
mockProject.name,
@@ -65,13 +63,13 @@ describe('FrequentItemsListItemComponent', () => {
describe('truncatedNamespace', () => {
it('should truncate project name from namespace string', () => {
- wrapper.setProps({ namespace: 'platform / nokia-3310' });
+ createComponent({ namespace: 'platform / nokia-3310' });
expect(trimText(wrapper.find('.js-frequent-items-item-namespace').text())).toBe('platform');
});
it('should truncate namespace string from the middle if it includes more than two groups in path', () => {
- wrapper.setProps({
+ createComponent({
namespace: 'platform / hardware / broadcom / Wifi Group / Mobile Chipset / nokia-3310',
});
@@ -84,6 +82,8 @@ describe('FrequentItemsListItemComponent', () => {
describe('template', () => {
it('should render component element', () => {
+ createComponent();
+
expect(wrapper.classes()).toContain('frequent-items-list-item-container');
expect(wrapper.findAll('a').length).toBe(1);
expect(wrapper.findAll('.frequent-items-item-avatar-container').length).toBe(1);
diff --git a/spec/javascripts/frequent_items/components/frequent_items_search_input_spec.js b/spec/javascripts/frequent_items/components/frequent_items_search_input_spec.js
index ddbbc5c2d29..c548c16c022 100644
--- a/spec/javascripts/frequent_items/components/frequent_items_search_input_spec.js
+++ b/spec/javascripts/frequent_items/components/frequent_items_search_input_spec.js
@@ -1,13 +1,15 @@
-import Vue from 'vue';
import searchComponent from '~/frequent_items/components/frequent_items_search_input.vue';
import eventHub from '~/frequent_items/event_hub';
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
-const createComponent = (namespace = 'projects') => {
- const Component = Vue.extend(searchComponent);
+const localVue = createLocalVue();
- return shallowMount(Component, { propsData: { namespace } });
-};
+const createComponent = (namespace = 'projects') =>
+ shallowMount(localVue.extend(searchComponent), {
+ propsData: { namespace },
+ localVue,
+ sync: false,
+ });
describe('FrequentItemsSearchInputComponent', () => {
let wrapper;
@@ -40,7 +42,7 @@ describe('FrequentItemsSearchInputComponent', () => {
spyOn(eventHub, '$on');
const vmX = createComponent().vm;
- Vue.nextTick(() => {
+ localVue.nextTick(() => {
expect(eventHub.$on).toHaveBeenCalledWith(
`${vmX.namespace}-dropdownOpen`,
jasmine.any(Function),
@@ -58,7 +60,7 @@ describe('FrequentItemsSearchInputComponent', () => {
vmX.$mount();
vmX.$destroy();
- Vue.nextTick(() => {
+ localVue.nextTick(() => {
expect(eventHub.$off).toHaveBeenCalledWith(
`${vmX.namespace}-dropdownOpen`,
jasmine.any(Function),
diff --git a/spec/javascripts/jobs/components/manual_variables_form_spec.js b/spec/javascripts/jobs/components/manual_variables_form_spec.js
index 093aa905185..1f2bf8674c1 100644
--- a/spec/javascripts/jobs/components/manual_variables_form_spec.js
+++ b/spec/javascripts/jobs/components/manual_variables_form_spec.js
@@ -1,9 +1,12 @@
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlButton } from '@gitlab/ui';
import Form from '~/jobs/components/manual_variables_form.vue';
+const localVue = createLocalVue();
+
describe('Manual Variables Form', () => {
let wrapper;
+
const requiredProps = {
action: {
path: '/play',
@@ -14,8 +17,10 @@ describe('Manual Variables Form', () => {
};
const factory = (props = {}) => {
- wrapper = shallowMount(Form, {
+ wrapper = shallowMount(localVue.extend(Form), {
propsData: props,
+ localVue,
+ sync: false,
});
};
@@ -23,8 +28,15 @@ describe('Manual Variables Form', () => {
factory(requiredProps);
});
- afterEach(() => {
- wrapper.destroy();
+ afterEach(done => {
+ // The component has a `nextTick` callback after some events so we need
+ // to wait for those to finish before destroying.
+ setImmediate(() => {
+ wrapper.destroy();
+ wrapper = null;
+
+ done();
+ });
});
it('renders empty form with correct placeholders', () => {
@@ -71,7 +83,7 @@ describe('Manual Variables Form', () => {
});
describe('when deleting a variable', () => {
- it('removes the variable row', () => {
+ beforeEach(done => {
wrapper.vm.variables = [
{
key: 'new key',
@@ -80,6 +92,10 @@ describe('Manual Variables Form', () => {
},
];
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('removes the variable row', () => {
wrapper.find(GlButton).vm.$emit('click');
expect(wrapper.vm.variables.length).toBe(0);
diff --git a/spec/javascripts/monitoring/charts/column_spec.js b/spec/javascripts/monitoring/charts/column_spec.js
index d8ac68b9484..27b3d435f08 100644
--- a/spec/javascripts/monitoring/charts/column_spec.js
+++ b/spec/javascripts/monitoring/charts/column_spec.js
@@ -1,12 +1,14 @@
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlColumnChart } from '@gitlab/ui/dist/charts';
import ColumnChart from '~/monitoring/components/charts/column.vue';
+const localVue = createLocalVue();
+
describe('Column component', () => {
let columnChart;
beforeEach(() => {
- columnChart = shallowMount(ColumnChart, {
+ columnChart = shallowMount(localVue.extend(ColumnChart), {
propsData: {
graphData: {
queries: [
@@ -28,6 +30,8 @@ describe('Column component', () => {
},
containerWidth: 100,
},
+ sync: false,
+ localVue,
});
});
diff --git a/spec/javascripts/monitoring/charts/empty_chart_spec.js b/spec/javascripts/monitoring/charts/empty_chart_spec.js
index bbfca27dc5a..06822126b59 100644
--- a/spec/javascripts/monitoring/charts/empty_chart_spec.js
+++ b/spec/javascripts/monitoring/charts/empty_chart_spec.js
@@ -1,15 +1,19 @@
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import EmptyChart from '~/monitoring/components/charts/empty_chart.vue';
+const localVue = createLocalVue();
+
describe('Empty Chart component', () => {
let emptyChart;
const graphTitle = 'Memory Usage';
beforeEach(() => {
- emptyChart = shallowMount(EmptyChart, {
+ emptyChart = shallowMount(localVue.extend(EmptyChart), {
propsData: {
graphTitle,
},
+ sync: false,
+ localVue,
});
});
diff --git a/spec/javascripts/monitoring/charts/single_stat_spec.js b/spec/javascripts/monitoring/charts/single_stat_spec.js
index 127a4a7955a..6adca0b0eed 100644
--- a/spec/javascripts/monitoring/charts/single_stat_spec.js
+++ b/spec/javascripts/monitoring/charts/single_stat_spec.js
@@ -1,15 +1,19 @@
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import SingleStatChart from '~/monitoring/components/charts/single_stat.vue';
import { graphDataPrometheusQuery } from '../mock_data';
+const localVue = createLocalVue();
+
describe('Single Stat Chart component', () => {
let singleStatChart;
beforeEach(() => {
- singleStatChart = shallowMount(SingleStatChart, {
+ singleStatChart = shallowMount(localVue.extend(SingleStatChart), {
propsData: {
graphData: graphDataPrometheusQuery,
},
+ sync: false,
+ localVue,
});
});
diff --git a/spec/javascripts/monitoring/components/dashboard_spec.js b/spec/javascripts/monitoring/components/dashboard_spec.js
index 0f20171726c..3529a3d72ba 100644
--- a/spec/javascripts/monitoring/components/dashboard_spec.js
+++ b/spec/javascripts/monitoring/components/dashboard_spec.js
@@ -72,6 +72,17 @@ describe('Dashboard', () => {
let mock;
let store;
let component;
+ let wrapper;
+
+ const createComponentWrapper = (props = {}, options = {}) => {
+ wrapper = shallowMount(localVue.extend(DashboardComponent), {
+ localVue,
+ sync: false,
+ propsData: { ...propsData, ...props },
+ store,
+ ...options,
+ });
+ };
beforeEach(() => {
setFixtures(`
@@ -81,13 +92,16 @@ describe('Dashboard', () => {
store = createStore();
mock = new MockAdapter(axios);
- DashboardComponent = Vue.extend(Dashboard);
+ DashboardComponent = localVue.extend(Dashboard);
});
afterEach(() => {
if (component) {
component.$destroy();
}
+ if (wrapper) {
+ wrapper.destroy();
+ }
mock.restore();
});
@@ -123,15 +137,8 @@ describe('Dashboard', () => {
});
describe('cluster health', () => {
- let wrapper;
-
beforeEach(done => {
- wrapper = shallowMount(DashboardComponent, {
- localVue,
- sync: false,
- propsData: { ...propsData, hasMetrics: true },
- store,
- });
+ createComponentWrapper({ hasMetrics: true });
// all_dashboards is not defined in health dashboards
wrapper.vm.$store.commit(`monitoringDashboard/${types.SET_ALL_DASHBOARDS}`, undefined);
@@ -383,7 +390,6 @@ describe('Dashboard', () => {
});
describe('drag and drop function', () => {
- let wrapper;
let expectedPanelCount; // also called metrics, naming to be improved: https://gitlab.com/gitlab-org/gitlab/issues/31565
const findDraggables = () => wrapper.findAll(VueDraggable);
@@ -400,13 +406,7 @@ describe('Dashboard', () => {
});
beforeEach(done => {
- wrapper = shallowMount(DashboardComponent, {
- localVue,
- sync: false,
- propsData: { ...propsData, hasMetrics: true },
- store,
- attachToDocument: true,
- });
+ createComponentWrapper({ hasMetrics: true }, { attachToDocument: true });
setupComponentStore(wrapper.vm);
@@ -417,6 +417,10 @@ describe('Dashboard', () => {
wrapper.destroy();
});
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
it('wraps vuedraggable', () => {
expect(findDraggablePanels().exists()).toBe(true);
expect(findDraggablePanels().length).toEqual(expectedPanelCount);
@@ -502,7 +506,6 @@ describe('Dashboard', () => {
// https://gitlab.com/gitlab-org/gitlab-ce/issues/66922
// eslint-disable-next-line jasmine/no-disabled-tests
xdescribe('link to chart', () => {
- let wrapper;
const currentDashboard = 'TEST_DASHBOARD';
localVue.use(GlToast);
const link = () => wrapper.find('.js-chart-link');
@@ -511,13 +514,7 @@ describe('Dashboard', () => {
beforeEach(done => {
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
- wrapper = shallowMount(DashboardComponent, {
- localVue,
- sync: false,
- attachToDocument: true,
- propsData: { ...propsData, hasMetrics: true, currentDashboard },
- store,
- });
+ createComponentWrapper({ hasMetrics: true, currentDashboard }, { attachToDocument: true });
setTimeout(done);
});
@@ -614,19 +611,12 @@ describe('Dashboard', () => {
});
describe('dashboard edit link', () => {
- let wrapper;
const findEditLink = () => wrapper.find('.js-edit-link');
beforeEach(done => {
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
- wrapper = shallowMount(DashboardComponent, {
- localVue,
- sync: false,
- attachToDocument: true,
- propsData: { ...propsData, hasMetrics: true },
- store,
- });
+ createComponentWrapper({ hasMetrics: true }, { attachToDocument: true });
wrapper.vm.$store.commit(
`monitoringDashboard/${types.SET_ALL_DASHBOARDS}`,
diff --git a/spec/javascripts/monitoring/components/graph_group_spec.js b/spec/javascripts/monitoring/components/graph_group_spec.js
index 7bcab9116e9..04371091ca8 100644
--- a/spec/javascripts/monitoring/components/graph_group_spec.js
+++ b/spec/javascripts/monitoring/components/graph_group_spec.js
@@ -1,22 +1,31 @@
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import GraphGroup from '~/monitoring/components/graph_group.vue';
+const localVue = createLocalVue();
+
describe('Graph group component', () => {
let graphGroup;
+
const findPrometheusGroup = () => graphGroup.find('.prometheus-graph-group');
const findPrometheusPanel = () => graphGroup.find('.prometheus-panel');
+ const createComponent = propsData => {
+ graphGroup = shallowMount(localVue.extend(GraphGroup), {
+ propsData,
+ sync: false,
+ localVue,
+ });
+ };
+
afterEach(() => {
graphGroup.destroy();
});
describe('When groups can be collapsed', () => {
beforeEach(() => {
- graphGroup = shallowMount(GraphGroup, {
- propsData: {
- name: 'panel',
- collapseGroup: true,
- },
+ createComponent({
+ name: 'panel',
+ collapseGroup: true,
});
});
@@ -33,12 +42,10 @@ describe('Graph group component', () => {
describe('When groups can not be collapsed', () => {
beforeEach(() => {
- graphGroup = shallowMount(GraphGroup, {
- propsData: {
- name: 'panel',
- collapseGroup: true,
- showPanels: false,
- },
+ createComponent({
+ name: 'panel',
+ collapseGroup: true,
+ showPanels: false,
});
});
@@ -49,12 +56,7 @@ describe('Graph group component', () => {
describe('When collapseGroup prop is updated', () => {
beforeEach(() => {
- graphGroup = shallowMount(GraphGroup, {
- propsData: {
- name: 'panel',
- collapseGroup: false,
- },
- });
+ createComponent({ name: 'panel', collapseGroup: false });
});
it('previously collapsed group should respond to the prop change', done => {
diff --git a/spec/javascripts/notes/components/note_actions/reply_button_spec.js b/spec/javascripts/notes/components/note_actions/reply_button_spec.js
index 003773d07ea..aa39ab15833 100644
--- a/spec/javascripts/notes/components/note_actions/reply_button_spec.js
+++ b/spec/javascripts/notes/components/note_actions/reply_button_spec.js
@@ -2,15 +2,14 @@ import Vuex from 'vuex';
import { createLocalVue, mount } from '@vue/test-utils';
import ReplyButton from '~/notes/components/note_actions/reply_button.vue';
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
describe('ReplyButton', () => {
let wrapper;
beforeEach(() => {
- const localVue = createLocalVue();
-
- localVue.use(Vuex);
-
- wrapper = mount(ReplyButton, {
+ wrapper = mount(localVue.extend(ReplyButton), {
sync: false,
localVue,
});
diff --git a/spec/javascripts/notes/components/note_actions_spec.js b/spec/javascripts/notes/components/note_actions_spec.js
index 1f2c07385a7..3439873168c 100644
--- a/spec/javascripts/notes/components/note_actions_spec.js
+++ b/spec/javascripts/notes/components/note_actions_spec.js
@@ -12,7 +12,7 @@ describe('noteActions', () => {
const shallowMountNoteActions = propsData => {
const localVue = createLocalVue();
- return shallowMount(noteActions, {
+ return shallowMount(localVue.extend(noteActions), {
store,
propsData,
localVue,
diff --git a/spec/javascripts/notes/components/note_form_spec.js b/spec/javascripts/notes/components/note_form_spec.js
index 96aa7824cec..35283e14dc5 100644
--- a/spec/javascripts/notes/components/note_form_spec.js
+++ b/spec/javascripts/notes/components/note_form_spec.js
@@ -14,7 +14,7 @@ describe('issue_note_form component', () => {
const createComponentWrapper = () => {
const localVue = createLocalVue();
- return shallowMount(NoteForm, {
+ return shallowMount(localVue.extend(NoteForm), {
store,
propsData: props,
// see https://gitlab.com/gitlab-org/gitlab-foss/issues/56317 for the following
diff --git a/spec/javascripts/notes/components/noteable_discussion_spec.js b/spec/javascripts/notes/components/noteable_discussion_spec.js
index ea1ed3da112..5e359759afc 100644
--- a/spec/javascripts/notes/components/noteable_discussion_spec.js
+++ b/spec/javascripts/notes/components/noteable_discussion_spec.js
@@ -10,6 +10,8 @@ import mockDiffFile from '../../diffs/mock_data/diff_file';
const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json';
+const localVue = createLocalVue();
+
describe('noteable_discussion component', () => {
let store;
let wrapper;
@@ -22,8 +24,7 @@ describe('noteable_discussion component', () => {
store.dispatch('setNoteableData', noteableDataMock);
store.dispatch('setNotesData', notesDataMock);
- const localVue = createLocalVue();
- wrapper = mount(noteableDiscussion, {
+ wrapper = mount(localVue.extend(noteableDiscussion), {
store,
propsData: { discussion: discussionMock },
localVue,
diff --git a/spec/javascripts/notes/components/noteable_note_spec.js b/spec/javascripts/notes/components/noteable_note_spec.js
index 9420713ceca..72a13afe498 100644
--- a/spec/javascripts/notes/components/noteable_note_spec.js
+++ b/spec/javascripts/notes/components/noteable_note_spec.js
@@ -18,7 +18,7 @@ describe('issue_note', () => {
store.dispatch('setNotesData', notesDataMock);
const localVue = createLocalVue();
- wrapper = shallowMount(issueNote, {
+ wrapper = shallowMount(localVue.extend(issueNote), {
store,
propsData: {
note,
diff --git a/spec/javascripts/related_merge_requests/components/related_merge_requests_spec.js b/spec/javascripts/related_merge_requests/components/related_merge_requests_spec.js
index 29760f79c3c..cf3ab4d4a68 100644
--- a/spec/javascripts/related_merge_requests/components/related_merge_requests_spec.js
+++ b/spec/javascripts/related_merge_requests/components/related_merge_requests_spec.js
@@ -20,7 +20,7 @@ describe('RelatedMergeRequests', () => {
mock = new MockAdapter(axios);
mock.onGet(`${API_ENDPOINT}?per_page=100`).reply(200, mockData, { 'x-total': 2 });
- wrapper = mount(RelatedMergeRequests, {
+ wrapper = mount(localVue.extend(RelatedMergeRequests), {
localVue,
sync: false,
store: createStore(),
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
index 6cdf60f3535..703b889cd5d 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
@@ -4,18 +4,19 @@ import MrWidgetPipeline from '~/vue_merge_request_widget/components/mr_widget_pi
import ArtifactsApp from '~/vue_merge_request_widget/components/artifacts_list_app.vue';
import { mockStore } from '../mock_data';
+const localVue = createLocalVue();
+
describe('MrWidgetPipelineContainer', () => {
let wrapper;
const factory = (props = {}) => {
- const localVue = createLocalVue();
-
wrapper = mount(localVue.extend(MrWidgetPipelineContainer), {
propsData: {
mr: Object.assign({}, mockStore),
...props,
},
localVue,
+ sync: false,
});
};
diff --git a/spec/javascripts/vue_shared/components/pagination/graphql_pagination_spec.js b/spec/javascripts/vue_shared/components/pagination/graphql_pagination_spec.js
index 7445da6cdee..204c0decfd8 100644
--- a/spec/javascripts/vue_shared/components/pagination/graphql_pagination_spec.js
+++ b/spec/javascripts/vue_shared/components/pagination/graphql_pagination_spec.js
@@ -1,14 +1,18 @@
-import { shallowMount } from '@vue/test-utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import GraphqlPagination from '~/vue_shared/components/pagination/graphql_pagination.vue';
+const localVue = createLocalVue();
+
describe('Graphql Pagination component', () => {
let wrapper;
function factory({ hasNextPage = true, hasPreviousPage = true }) {
- wrapper = shallowMount(GraphqlPagination, {
+ wrapper = shallowMount(localVue.extend(GraphqlPagination), {
propsData: {
hasNextPage,
hasPreviousPage,
},
+ sync: false,
+ localVue,
});
}