From 87cf0605b5109f62847d7cca96e92f43fadca7d5 Mon Sep 17 00:00:00 2001 From: Doug Stull <dstull@gitlab.com> Date: Mon, 30 Jan 2023 14:24:15 +0000 Subject: [PATCH] Move learn gitlab code to ee - only ever used in ee and never used in foss --- .rubocop_todo/gitlab/doc_url.yml | 2 +- .rubocop_todo/gitlab/strong_memoize_attr.yml | 1 - .../layout/first_hash_element_indentation.yml | 1 - .rubocop_todo/layout/line_length.yml | 1 - .rubocop_todo/rspec/context_wording.yml | 1 - .rubocop_todo/rspec/expect_in_hook.yml | 1 - .../rspec/factory_bot/avoid_create.yml | 3 +- .../rspec/missing_feature_category.yml | 4 - .rubocop_todo/style/if_unless_modifier.yml | 1 - ...orials_continuous_onboarding_experiment.rb | 6 - app/helpers/invite_members_helper.rb | 10 +- app/helpers/learn_gitlab_helper.rb | 106 ------- app/helpers/sidebars_helper.rb | 1 - config/routes/project.rb | 2 - .../included_in_trial_indicator.vue | 0 .../learn_gitlab/components/learn_gitlab.vue | 0 .../components/learn_gitlab_section_card.vue | 0 .../components/learn_gitlab_section_link.vue | 0 .../projects/learn_gitlab/constants/index.js | 0 .../projects/learn_gitlab/index/index.js | 0 .../projects/learn_gitlab_controller.rb | 2 +- ee/app/helpers/ee/invite_members_helper.rb | 10 + ee/app/helpers/ee/learn_gitlab_helper.rb | 59 ---- ee/app/helpers/ee/sidebars_helper.rb | 3 +- .../helpers/projects/learn_gitlab_helper.rb | 131 +++++++++ .../app}/models/onboarding/learn_gitlab.rb | 11 +- .../standard_namespace_create_service.rb | 4 +- .../projects/learn_gitlab/index.html.haml | 3 +- ...nuous_onboarding_getting_started.html.haml | 5 +- .../invite_for_help_continuous_onboarding.yml | 0 .../video_tutorials_continuous_onboarding.yml | 0 ee/config/routes/project.rb | 2 + ee/lib/ee/sidebars/projects/panel.rb | 10 +- .../projects/menus/learn_gitlab_menu.rb | 14 +- .../projects/learn_gitlab_controller_spec.rb | 17 +- .../learn_gitlab_section_card_spec.js.snap | 0 .../__snapshots__/learn_gitlab_spec.js.snap | 0 .../learn_gitlab_section_card_spec.js | 2 +- .../learn_gitlab_section_link_spec.js | 4 +- .../components/learn_gitlab_spec.js | 4 +- .../learn_gitlab_trial_card_spec.js | 2 +- .../learn_gitlab/components/mock_data.js | 0 .../helpers/ee/invite_members_helper_spec.rb | 60 ++++ .../helpers/ee/learn_gitlab_helper_spec.rb | 144 ---------- .../projects/learn_gitlab_helper_spec.rb | 266 ++++++++++++++++++ .../lib/ee/sidebars/projects/panel_spec.rb | 6 + .../projects/menus/learn_gitlab_menu_spec.rb | 17 +- .../models/onboarding/learn_gitlab_spec.rb | 72 +++-- .../standard_namespace_create_service_spec.rb | 4 +- .../nav/sidebar/_project.html.haml_spec.rb | 18 +- ...boarding_getting_started.html.haml_spec.rb | 2 +- .../create_learn_gitlab_worker_spec.rb | 19 +- lib/sidebars/projects/panel.rb | 1 - ...s_continuous_onboarding_experiment_spec.rb | 9 - spec/helpers/invite_members_helper_spec.rb | 52 +--- spec/helpers/learn_gitlab_helper_spec.rb | 162 ----------- spec/support/rspec_order_todo.yml | 4 - .../nav/sidebar/_project.html.haml_spec.rb | 15 +- 58 files changed, 629 insertions(+), 645 deletions(-) delete mode 100644 app/experiments/video_tutorials_continuous_onboarding_experiment.rb delete mode 100644 app/helpers/learn_gitlab_helper.rb rename {app => ee/app}/assets/javascripts/pages/projects/learn_gitlab/components/included_in_trial_indicator.vue (100%) rename {app => ee/app}/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue (100%) rename {app => ee/app}/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue (100%) rename {app => ee/app}/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue (100%) rename {app => ee/app}/assets/javascripts/pages/projects/learn_gitlab/constants/index.js (100%) rename {app => ee/app}/assets/javascripts/pages/projects/learn_gitlab/index/index.js (100%) rename {app => ee/app}/controllers/projects/learn_gitlab_controller.rb (89%) delete mode 100644 ee/app/helpers/ee/learn_gitlab_helper.rb create mode 100644 ee/app/helpers/projects/learn_gitlab_helper.rb rename {app => ee/app}/models/onboarding/learn_gitlab.rb (72%) rename {app => ee/app}/views/projects/learn_gitlab/index.html.haml (71%) rename {config => ee/config}/feature_flags/experiment/invite_for_help_continuous_onboarding.yml (100%) rename {config => ee/config}/feature_flags/experiment/video_tutorials_continuous_onboarding.yml (100%) rename {lib => ee/lib}/sidebars/projects/menus/learn_gitlab_menu.rb (81%) rename {spec => ee/spec}/controllers/projects/learn_gitlab_controller_spec.rb (70%) rename {spec => ee/spec}/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_section_card_spec.js.snap (100%) rename {spec => ee/spec}/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap (100%) rename {spec => ee/spec}/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_card_spec.js (84%) rename {spec => ee/spec}/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js (97%) rename {spec => ee/spec}/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js (94%) rename {spec => ee/spec}/frontend/pages/projects/learn_gitlab/components/learn_gitlab_trial_card_spec.js (71%) rename {spec => ee/spec}/frontend/pages/projects/learn_gitlab/components/mock_data.js (100%) delete mode 100644 ee/spec/helpers/ee/learn_gitlab_helper_spec.rb create mode 100644 ee/spec/helpers/projects/learn_gitlab_helper_spec.rb rename {spec => ee/spec}/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb (77%) rename {spec => ee/spec}/models/onboarding/learn_gitlab_spec.rb (54%) delete mode 100644 spec/experiments/video_tutorials_continuous_onboarding_experiment_spec.rb delete mode 100644 spec/helpers/learn_gitlab_helper_spec.rb diff --git a/.rubocop_todo/gitlab/doc_url.yml b/.rubocop_todo/gitlab/doc_url.yml index 9c781ca64e91..9935af055552 100644 --- a/.rubocop_todo/gitlab/doc_url.yml +++ b/.rubocop_todo/gitlab/doc_url.yml @@ -7,7 +7,7 @@ Gitlab/DocUrl: - 'app/graphql/types/merge_request_type.rb' - 'app/graphql/types/notes/diff_position_input_type.rb' - 'app/graphql/types/query_complexity_type.rb' - - 'app/helpers/learn_gitlab_helper.rb' + - 'ee/app/helpers/projects/learn_gitlab_helper.rb' - 'app/models/integrations/apple_app_store.rb' - 'app/models/integrations/microsoft_teams.rb' - 'app/presenters/dev_ops_report/metric_presenter.rb' diff --git a/.rubocop_todo/gitlab/strong_memoize_attr.yml b/.rubocop_todo/gitlab/strong_memoize_attr.yml index 066f17aabe0d..e0a243aec8e8 100644 --- a/.rubocop_todo/gitlab/strong_memoize_attr.yml +++ b/.rubocop_todo/gitlab/strong_memoize_attr.yml @@ -726,6 +726,5 @@ Gitlab/StrongMemoizeAttr: - 'lib/sidebars/groups/menus/merge_requests_menu.rb' - 'lib/sidebars/projects/menus/analytics_menu.rb' - 'lib/sidebars/projects/menus/issues_menu.rb' - - 'lib/sidebars/projects/menus/learn_gitlab_menu.rb' - 'lib/unnested_in_filters/rewriter.rb' - 'tooling/graphql/docs/helper.rb' diff --git a/.rubocop_todo/layout/first_hash_element_indentation.yml b/.rubocop_todo/layout/first_hash_element_indentation.yml index facc7a58f1a2..ef0e5fbe040d 100644 --- a/.rubocop_todo/layout/first_hash_element_indentation.yml +++ b/.rubocop_todo/layout/first_hash_element_indentation.yml @@ -194,7 +194,6 @@ Layout/FirstHashElementIndentation: - 'spec/frontend/fixtures/autocomplete_sources.rb' - 'spec/graphql/types/ci/detailed_status_type_spec.rb' - 'spec/helpers/groups/observability_helper_spec.rb' - - 'spec/helpers/learn_gitlab_helper_spec.rb' - 'spec/helpers/projects/pages_helper_spec.rb' - 'spec/helpers/routing/pseudonymization_helper_spec.rb' - 'spec/initializers/rack_multipart_patch_spec.rb' diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml index 5e3b05e064d9..b8ef2820dadb 100644 --- a/.rubocop_todo/layout/line_length.yml +++ b/.rubocop_todo/layout/line_length.yml @@ -4041,7 +4041,6 @@ Layout/LineLength: - 'spec/helpers/groups/group_members_helper_spec.rb' - 'spec/helpers/groups_helper_spec.rb' - 'spec/helpers/icons_helper_spec.rb' - - 'spec/helpers/invite_members_helper_spec.rb' - 'spec/helpers/issuables_helper_spec.rb' - 'spec/helpers/issues_helper_spec.rb' - 'spec/helpers/labels_helper_spec.rb' diff --git a/.rubocop_todo/rspec/context_wording.yml b/.rubocop_todo/rspec/context_wording.yml index b55e290f95ad..e710e590a152 100644 --- a/.rubocop_todo/rspec/context_wording.yml +++ b/.rubocop_todo/rspec/context_wording.yml @@ -1525,7 +1525,6 @@ RSpec/ContextWording: - 'spec/helpers/groups_helper_spec.rb' - 'spec/helpers/ide_helper_spec.rb' - 'spec/helpers/integrations_helper_spec.rb' - - 'spec/helpers/invite_members_helper_spec.rb' - 'spec/helpers/jira_connect_helper_spec.rb' - 'spec/helpers/labels_helper_spec.rb' - 'spec/helpers/listbox_helper_spec.rb' diff --git a/.rubocop_todo/rspec/expect_in_hook.yml b/.rubocop_todo/rspec/expect_in_hook.yml index d25c4137c1a2..ae886e6e85e7 100644 --- a/.rubocop_todo/rspec/expect_in_hook.yml +++ b/.rubocop_todo/rspec/expect_in_hook.yml @@ -163,7 +163,6 @@ RSpec/ExpectInHook: - 'spec/graphql/mutations/design_management/move_spec.rb' - 'spec/helpers/commits_helper_spec.rb' - 'spec/helpers/groups_helper_spec.rb' - - 'spec/helpers/invite_members_helper_spec.rb' - 'spec/helpers/projects_helper_spec.rb' - 'spec/helpers/search_helper_spec.rb' - 'spec/helpers/users_helper_spec.rb' diff --git a/.rubocop_todo/rspec/factory_bot/avoid_create.yml b/.rubocop_todo/rspec/factory_bot/avoid_create.yml index 8fb2327f049b..a857841f17ad 100644 --- a/.rubocop_todo/rspec/factory_bot/avoid_create.yml +++ b/.rubocop_todo/rspec/factory_bot/avoid_create.yml @@ -36,7 +36,7 @@ RSpec/FactoryBot/AvoidCreate: - 'ee/spec/helpers/ee/issuables_helper_spec.rb' - 'ee/spec/helpers/ee/issues_helper_spec.rb' - 'ee/spec/helpers/ee/labels_helper_spec.rb' - - 'ee/spec/helpers/ee/learn_gitlab_helper_spec.rb' + - 'ee/spec/helpers/projects/learn_gitlab_helper_spec.rb' - 'ee/spec/helpers/ee/lock_helper_spec.rb' - 'ee/spec/helpers/ee/namespace_user_cap_reached_alert_helper_spec.rb' - 'ee/spec/helpers/ee/namespaces_helper_spec.rb' @@ -305,7 +305,6 @@ RSpec/FactoryBot/AvoidCreate: - 'spec/helpers/keyset_helper_spec.rb' - 'spec/helpers/labels_helper_spec.rb' - 'spec/helpers/lazy_image_tag_helper_spec.rb' - - 'spec/helpers/learn_gitlab_helper_spec.rb' - 'spec/helpers/markup_helper_spec.rb' - 'spec/helpers/members_helper_spec.rb' - 'spec/helpers/merge_requests_helper_spec.rb' diff --git a/.rubocop_todo/rspec/missing_feature_category.yml b/.rubocop_todo/rspec/missing_feature_category.yml index 018e98d123de..8a9367ec2e7d 100644 --- a/.rubocop_todo/rspec/missing_feature_category.yml +++ b/.rubocop_todo/rspec/missing_feature_category.yml @@ -584,7 +584,6 @@ RSpec/MissingFeatureCategory: - 'ee/spec/helpers/ee/invite_members_helper_spec.rb' - 'ee/spec/helpers/ee/issues_helper_spec.rb' - 'ee/spec/helpers/ee/labels_helper_spec.rb' - - 'ee/spec/helpers/ee/learn_gitlab_helper_spec.rb' - 'ee/spec/helpers/ee/lock_helper_spec.rb' - 'ee/spec/helpers/ee/namespace_user_cap_reached_alert_helper_spec.rb' - 'ee/spec/helpers/ee/namespaces_helper_spec.rb' @@ -2583,7 +2582,6 @@ RSpec/MissingFeatureCategory: - 'ee/spec/workers/merge_trains/refresh_worker_spec.rb' - 'ee/spec/workers/namespaces/sync_namespace_name_worker_spec.rb' - 'ee/spec/workers/new_epic_worker_spec.rb' - - 'ee/spec/workers/onboarding/create_learn_gitlab_worker_spec.rb' - 'ee/spec/workers/personal_access_tokens/groups/policy_worker_spec.rb' - 'ee/spec/workers/personal_access_tokens/instance/policy_worker_spec.rb' - 'ee/spec/workers/post_receive_spec.rb' @@ -6051,7 +6049,6 @@ RSpec/MissingFeatureCategory: - 'spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb' - 'spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb' - 'spec/lib/sidebars/projects/menus/issues_menu_spec.rb' - - 'spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb' - 'spec/lib/sidebars/projects/menus/merge_requests_menu_spec.rb' - 'spec/lib/sidebars/projects/menus/monitor_menu_spec.rb' - 'spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb' @@ -6555,7 +6552,6 @@ RSpec/MissingFeatureCategory: - 'spec/models/oauth_access_grant_spec.rb' - 'spec/models/oauth_access_token_spec.rb' - 'spec/models/onboarding/completion_spec.rb' - - 'spec/models/onboarding/learn_gitlab_spec.rb' - 'spec/models/onboarding/progress_spec.rb' - 'spec/models/operations/feature_flag_spec.rb' - 'spec/models/operations/feature_flags/strategy_spec.rb' diff --git a/.rubocop_todo/style/if_unless_modifier.yml b/.rubocop_todo/style/if_unless_modifier.yml index 39f4094d40f3..3794232db319 100644 --- a/.rubocop_todo/style/if_unless_modifier.yml +++ b/.rubocop_todo/style/if_unless_modifier.yml @@ -1065,7 +1065,6 @@ Style/IfUnlessModifier: - 'spec/features/projects/tree/create_file_spec.rb' - 'spec/graphql/mutations/releases/update_spec.rb' - 'spec/helpers/application_settings_helper_spec.rb' - - 'spec/helpers/invite_members_helper_spec.rb' - 'spec/lib/container_registry/gitlab_api_client_spec.rb' - 'spec/lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images_spec.rb' - 'spec/lib/gitlab/config/entry/validators/nested_array_helpers_spec.rb' diff --git a/app/experiments/video_tutorials_continuous_onboarding_experiment.rb b/app/experiments/video_tutorials_continuous_onboarding_experiment.rb deleted file mode 100644 index 2c5790f83d13..000000000000 --- a/app/experiments/video_tutorials_continuous_onboarding_experiment.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -class VideoTutorialsContinuousOnboardingExperiment < ApplicationExperiment - control {} - candidate {} -end diff --git a/app/helpers/invite_members_helper.rb b/app/helpers/invite_members_helper.rb index 6fad13464263..e986b56fde49 100644 --- a/app/helpers/invite_members_helper.rb +++ b/app/helpers/invite_members_helper.rb @@ -45,7 +45,7 @@ def common_invite_modal_dataset(source) full_path: source.full_path } - if show_invite_members_for_task?(source) + if current_user && show_invite_members_for_task?(source) dataset.merge!( tasks_to_be_done_options: tasks_to_be_done_options.to_json, projects: projects_for_source(source).to_json, @@ -71,11 +71,9 @@ def users_filter_data(group) {} end - def show_invite_members_for_task?(source) - return unless current_user - - invite_for_help_continuous_onboarding = source.is_a?(Project) && experiment(:invite_for_help_continuous_onboarding, namespace: source.namespace).assigned.name == 'candidate' - params[:open_modal] == 'invite_members_for_task' || invite_for_help_continuous_onboarding + # Overridden in EE + def show_invite_members_for_task?(_source) + params[:open_modal] == 'invite_members_for_task' end def tasks_to_be_done_options diff --git a/app/helpers/learn_gitlab_helper.rb b/app/helpers/learn_gitlab_helper.rb deleted file mode 100644 index e1241f8b5724..000000000000 --- a/app/helpers/learn_gitlab_helper.rb +++ /dev/null @@ -1,106 +0,0 @@ -# frozen_string_literal: true - -module LearnGitlabHelper - IMAGE_PATH_PLAN = "learn_gitlab/section_plan.svg" - IMAGE_PATH_DEPLOY = "learn_gitlab/section_deploy.svg" - IMAGE_PATH_WORKSPACE = "learn_gitlab/section_workspace.svg" - LICENSE_SCANNING_RUN_URL = 'https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html' - - def learn_gitlab_enabled?(project) - return false unless current_user - - learn_gitlab_onboarding_available?(project) - end - - def learn_gitlab_data(project) - { - actions: onboarding_actions_data(project).to_json, - sections: onboarding_sections_data.to_json, - project: onboarding_project_data(project).to_json - } - end - - def learn_gitlab_onboarding_available?(project) - Onboarding::Progress.onboarding?(project.namespace) && - Onboarding::LearnGitlab.new(current_user).available? - end - - private - - def onboarding_actions_data(project) - attributes = onboarding_progress(project).attributes.symbolize_keys - - action_urls(project).to_h do |action, url| - [ - action, - { - url: url, - completed: attributes[Onboarding::Progress.column_name(action)].present?, - enabled: true - } - ] - end - end - - def onboarding_sections_data - { - workspace: { - svg: image_path(IMAGE_PATH_WORKSPACE) - }, - plan: { - svg: image_path(IMAGE_PATH_PLAN) - }, - deploy: { - svg: image_path(IMAGE_PATH_DEPLOY) - } - } - end - - def onboarding_project_data(project) - { name: project.name } - end - - def action_urls(project) - action_issue_urls.merge( - issue_created: project_issues_path(project), - git_write: project_path(project), - merge_request_created: project_merge_requests_path(project), - user_added: project_members_url(project), - **deploy_section_action_urls(project) - ) - end - - def action_issue_urls - Onboarding::Completion::ACTION_ISSUE_IDS.transform_values do |id| - project_issue_url(learn_gitlab_project, id) - end - end - - def deploy_section_action_urls(project) - experiment( - :security_actions_continuous_onboarding, - namespace: project.namespace, - user: current_user, - sticky_to: current_user - ) do |e| - e.control { { security_scan_enabled: project_security_configuration_path(project) } } - e.candidate do - { - license_scanning_run: LICENSE_SCANNING_RUN_URL, - secure_dependency_scanning_run: project_security_configuration_path(project, anchor: 'dependency-scanning'), - secure_dast_run: project_security_configuration_path(project, anchor: 'dast') - } - end - end.run - end - - def learn_gitlab_project - @learn_gitlab_project ||= Onboarding::LearnGitlab.new(current_user).project - end - - def onboarding_progress(project) - Onboarding::Progress.find_by(namespace: project.namespace) # rubocop: disable CodeReuse/ActiveRecord - end -end - -LearnGitlabHelper.prepend_mod_with('LearnGitlabHelper') diff --git a/app/helpers/sidebars_helper.rb b/app/helpers/sidebars_helper.rb index 9ce68df26a18..5a19ce6149a1 100644 --- a/app/helpers/sidebars_helper.rb +++ b/app/helpers/sidebars_helper.rb @@ -117,7 +117,6 @@ def project_sidebar_context_data(project, user, current_ref, ref_type: nil) { current_user: user, container: project, - learn_gitlab_enabled: learn_gitlab_enabled?(project), current_ref: current_ref, ref_type: ref_type, jira_issues_integration: project_jira_issues_integration?, diff --git a/config/routes/project.rb b/config/routes/project.rb index 4a2f83752495..ceb0671c0343 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -92,8 +92,6 @@ end end - get :learn_gitlab, action: :index, controller: 'learn_gitlab' - namespace :ci do resource :lint, only: [:show, :create] resource :pipeline_editor, only: [:show], controller: :pipeline_editor, path: 'editor' diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/included_in_trial_indicator.vue b/ee/app/assets/javascripts/pages/projects/learn_gitlab/components/included_in_trial_indicator.vue similarity index 100% rename from app/assets/javascripts/pages/projects/learn_gitlab/components/included_in_trial_indicator.vue rename to ee/app/assets/javascripts/pages/projects/learn_gitlab/components/included_in_trial_indicator.vue diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue b/ee/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue similarity index 100% rename from app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue rename to ee/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue b/ee/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue similarity index 100% rename from app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue rename to ee/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue b/ee/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue similarity index 100% rename from app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue rename to ee/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js b/ee/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js similarity index 100% rename from app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js rename to ee/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js b/ee/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js similarity index 100% rename from app/assets/javascripts/pages/projects/learn_gitlab/index/index.js rename to ee/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js diff --git a/app/controllers/projects/learn_gitlab_controller.rb b/ee/app/controllers/projects/learn_gitlab_controller.rb similarity index 89% rename from app/controllers/projects/learn_gitlab_controller.rb rename to ee/app/controllers/projects/learn_gitlab_controller.rb index 0193fcc7be62..acf728a8d12e 100644 --- a/app/controllers/projects/learn_gitlab_controller.rb +++ b/ee/app/controllers/projects/learn_gitlab_controller.rb @@ -15,7 +15,7 @@ def index; end private def verify_learn_gitlab_available! - access_denied! unless helpers.learn_gitlab_enabled?(project) + access_denied! unless Onboarding::LearnGitlab.new(current_user).onboarding_and_available?(project.namespace) end def enable_invite_for_help_continuous_onboarding_experiment diff --git a/ee/app/helpers/ee/invite_members_helper.rb b/ee/app/helpers/ee/invite_members_helper.rb index b23651ef0f12..fba88a77e4e8 100644 --- a/ee/app/helpers/ee/invite_members_helper.rb +++ b/ee/app/helpers/ee/invite_members_helper.rb @@ -56,5 +56,15 @@ def users_filter_data(group) { users_filter: 'saml_provider_id', filter_id: root_group.saml_provider.id } end + + private + + override :show_invite_members_for_task? + def show_invite_members_for_task?(source) + invite_for_help_continuous_onboarding = source.is_a?(Project) && + experiment(:invite_for_help_continuous_onboarding, namespace: source.namespace).assigned.name == 'candidate' + + super || invite_for_help_continuous_onboarding + end end end diff --git a/ee/app/helpers/ee/learn_gitlab_helper.rb b/ee/app/helpers/ee/learn_gitlab_helper.rb deleted file mode 100644 index e2fd41e41f09..000000000000 --- a/ee/app/helpers/ee/learn_gitlab_helper.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: true - -module EE - module LearnGitlabHelper - extend ::Gitlab::Utils::Override - - GITLAB_COM = 'gitlab.com' - ONBOARDING_START_TRIAL = 'onboarding-start-trial' - ONBOARDING_REQUIRE_MR_APPROVALS = 'onboarding-require-merge-approvals' - ONBOARDING_CODE_OWNERS = 'onboarding-code-owners' - - private - - override :action_urls - def action_urls(project) - urls = super(project) - - return urls unless ::Gitlab::CurrentSettings.should_check_namespace_plan? - - trial_items = { - trial_started: project_project_members_path(project), - required_mr_approvals_enabled: help_page_path('ci/pipelines/settings', anchor: 'coverage-check-approval-rule'), - code_owners_enabled: help_page_path('user/project/code_owners', anchor: 'set-up-code-owners') - } - - if can_start_trial?(project) - trial_items = { - trial_started: new_trial_path_with_glm(content: ONBOARDING_START_TRIAL), - required_mr_approvals_enabled: new_trial_path_with_glm(content: ONBOARDING_REQUIRE_MR_APPROVALS), - code_owners_enabled: new_trial_path_with_glm(content: ONBOARDING_CODE_OWNERS) - } - end - - urls.merge(trial_items) - end - - override :onboarding_actions_data - def onboarding_actions_data(project) - action_urls = super(project) - - if ::Gitlab::CurrentSettings.should_check_namespace_plan? && !can_start_trial?(project) - action_urls[:trial_started][:enabled] = false - action_urls[:trial_started][:message] = - s_('LearnGitlab|Contact your administrator to start a free Ultimate trial.') - end - - action_urls - end - - def can_start_trial?(project) - root = project&.root_ancestor - root&.has_free_or_no_subscription? && can?(current_user, :admin_namespace, root) - end - - def new_trial_path_with_glm(content:, source: GITLAB_COM) - new_trial_path({ glm_source: source, glm_content: content }) - end - end -end diff --git a/ee/app/helpers/ee/sidebars_helper.rb b/ee/app/helpers/ee/sidebars_helper.rb index 825588949d3a..db5c645fa077 100644 --- a/ee/app/helpers/ee/sidebars_helper.rb +++ b/ee/app/helpers/ee/sidebars_helper.rb @@ -8,7 +8,8 @@ module SidebarsHelper def project_sidebar_context_data(project, user, current_ref, **args) super.merge({ show_promotions: show_promotions?(user), - show_discover_project_security: show_discover_project_security?(project) + show_discover_project_security: show_discover_project_security?(project), + learn_gitlab_enabled: Onboarding::LearnGitlab.new(user).onboarding_and_available?(project.namespace) }) end diff --git a/ee/app/helpers/projects/learn_gitlab_helper.rb b/ee/app/helpers/projects/learn_gitlab_helper.rb new file mode 100644 index 000000000000..13b684d80f1b --- /dev/null +++ b/ee/app/helpers/projects/learn_gitlab_helper.rb @@ -0,0 +1,131 @@ +# frozen_string_literal: true + +module Projects + module LearnGitlabHelper + IMAGE_PATH_PLAN = "learn_gitlab/section_plan.svg" + IMAGE_PATH_DEPLOY = "learn_gitlab/section_deploy.svg" + IMAGE_PATH_WORKSPACE = "learn_gitlab/section_workspace.svg" + LICENSE_SCANNING_RUN_URL = 'https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html' + GITLAB_COM = 'gitlab.com' + ONBOARDING_START_TRIAL = 'onboarding-start-trial' + ONBOARDING_REQUIRE_MR_APPROVALS = 'onboarding-require-merge-approvals' + ONBOARDING_CODE_OWNERS = 'onboarding-code-owners' + + def learn_gitlab_data(project) + { + actions: onboarding_actions_data(project).to_json, + sections: onboarding_sections_data.to_json, + project: onboarding_project_data(project).to_json + } + end + + def learn_gitlab_onboarding_available?(namespace) + Onboarding::LearnGitlab.new(current_user).onboarding_and_available?(namespace) + end + + private + + def onboarding_actions_data(project) + onboarding_progress = Onboarding::Progress.find_by(namespace: project.namespace) # rubocop: disable CodeReuse/ActiveRecord + attributes = onboarding_progress.attributes.symbolize_keys + + data = action_urls(project).to_h do |action, url| + [ + action, + { + url: url, + completed: attributes[Onboarding::Progress.column_name(action)].present?, + enabled: true + } + ] + end + + if ::Gitlab::CurrentSettings.should_check_namespace_plan? && !can_start_trial?(project) + data[:trial_started][:enabled] = false + data[:trial_started][:message] = + s_('LearnGitlab|Contact your administrator to start a free Ultimate trial.') + end + + data + end + + def can_start_trial?(project) + root = project.root_ancestor + root.has_free_or_no_subscription? && can?(current_user, :admin_namespace, root) + end + + def onboarding_sections_data + { + workspace: { + svg: image_path(IMAGE_PATH_WORKSPACE) + }, + plan: { + svg: image_path(IMAGE_PATH_PLAN) + }, + deploy: { + svg: image_path(IMAGE_PATH_DEPLOY) + } + } + end + + def onboarding_project_data(project) + { name: project.name } + end + + def action_urls(project) + urls = action_issue_urls(project).merge( + issue_created: project_issues_path(project), + git_write: project_path(project), + merge_request_created: project_merge_requests_path(project), + user_added: project_members_url(project), + **deploy_section_action_urls(project) + ) + + return urls unless ::Gitlab::CurrentSettings.should_check_namespace_plan? + + trial_items = { + trial_started: project_project_members_path(project), + required_mr_approvals_enabled: help_page_path('ci/pipelines/settings', anchor: 'coverage-check-approval-rule'), + code_owners_enabled: help_page_path('user/project/code_owners', anchor: 'set-up-code-owners') + } + + if can_start_trial?(project) + trial_items = { + trial_started: new_trial_path_with_glm(content: ONBOARDING_START_TRIAL), + required_mr_approvals_enabled: new_trial_path_with_glm(content: ONBOARDING_REQUIRE_MR_APPROVALS), + code_owners_enabled: new_trial_path_with_glm(content: ONBOARDING_CODE_OWNERS) + } + end + + urls.merge(trial_items) + end + + def new_trial_path_with_glm(content:, source: GITLAB_COM) + new_trial_path({ glm_source: source, glm_content: content }) + end + + def action_issue_urls(project) + Onboarding::Completion::ACTION_ISSUE_IDS.transform_values do |id| + project_issue_url(project, id) + end + end + + def deploy_section_action_urls(project) + experiment( + :security_actions_continuous_onboarding, + namespace: project.namespace, + user: current_user, + sticky_to: current_user + ) do |e| + e.control { { security_scan_enabled: project_security_configuration_path(project) } } + e.candidate do + { + license_scanning_run: LICENSE_SCANNING_RUN_URL, + secure_dependency_scanning_run: project_security_configuration_path(project, anchor: 'dependency-scanning'), + secure_dast_run: project_security_configuration_path(project, anchor: 'dast') + } + end + end.run + end + end +end diff --git a/app/models/onboarding/learn_gitlab.rb b/ee/app/models/onboarding/learn_gitlab.rb similarity index 72% rename from app/models/onboarding/learn_gitlab.rb rename to ee/app/models/onboarding/learn_gitlab.rb index d7a189ed6e28..8b7d0770d749 100644 --- a/app/models/onboarding/learn_gitlab.rb +++ b/ee/app/models/onboarding/learn_gitlab.rb @@ -6,13 +6,16 @@ class LearnGitlab PROJECT_NAME_ULTIMATE_TRIAL = 'Learn GitLab - Ultimate trial' BOARD_NAME = 'GitLab onboarding' LABEL_NAME = 'Novice' + TEMPLATE_NAME = 'learn_gitlab_ultimate.tar.gz' def initialize(current_user) @current_user = current_user end - def available? - project && board && label + def onboarding_and_available?(namespace) + return false unless current_user && project + + Onboarding::Progress.onboarding?(namespace) && available? end def project @@ -34,5 +37,9 @@ def label private attr_reader :current_user + + def available? + project.present? && board.present? && label.present? + end end end diff --git a/ee/app/services/registrations/standard_namespace_create_service.rb b/ee/app/services/registrations/standard_namespace_create_service.rb index 50cd1cb233aa..cd7aad865935 100644 --- a/ee/app/services/registrations/standard_namespace_create_service.rb +++ b/ee/app/services/registrations/standard_namespace_create_service.rb @@ -14,8 +14,6 @@ def execute private - LEARN_GITLAB_ULTIMATE_TEMPLATE = 'learn_gitlab_ultimate.tar.gz' - def new_group? !existing_group_id end @@ -76,7 +74,7 @@ def create_learn_gitlab_project end def learn_gitlab_template_path - Rails.root.join('vendor', 'project_templates', LEARN_GITLAB_ULTIMATE_TEMPLATE) + Rails.root.join('vendor', 'project_templates', Onboarding::LearnGitlab::TEMPLATE_NAME) end def learn_gitlab_project_name diff --git a/app/views/projects/learn_gitlab/index.html.haml b/ee/app/views/projects/learn_gitlab/index.html.haml similarity index 71% rename from app/views/projects/learn_gitlab/index.html.haml rename to ee/app/views/projects/learn_gitlab/index.html.haml index 0e950c26d34d..b5e9ffd000ec 100644 --- a/app/views/projects/learn_gitlab/index.html.haml +++ b/ee/app/views/projects/learn_gitlab/index.html.haml @@ -1,8 +1,7 @@ - breadcrumb_title _("Learn GitLab") - page_title _("Learn GitLab") - add_page_specific_style 'page_bundles/learn_gitlab' -- data = learn_gitlab_data(@project) = render 'projects/invite_members_modal', project: @project -#js-learn-gitlab-app{ data: data } +#js-learn-gitlab-app{ data: learn_gitlab_data(@project) } diff --git a/ee/app/views/registrations/welcome/continuous_onboarding_getting_started.html.haml b/ee/app/views/registrations/welcome/continuous_onboarding_getting_started.html.haml index 913ca8aaccd5..7f110d8e8c5a 100644 --- a/ee/app/views/registrations/welcome/continuous_onboarding_getting_started.html.haml +++ b/ee/app/views/registrations/welcome/continuous_onboarding_getting_started.html.haml @@ -1,6 +1,5 @@ -- return unless project - page_title _('Get started with GitLab') -- unless learn_gitlab_onboarding_available?(project) +- unless learn_gitlab_onboarding_available?(project.namespace) = content_for :meta_tags do %meta{ 'http-equiv': 'refresh', content: '5' } - content_for :page_specific_javascripts do @@ -13,7 +12,7 @@ %h2.gl-text-center.gl-my-5= _('Get started with GitLab') %p.gl-text-center.gl-text-gray-700.gl-mb-7= _('Ready to get started with GitLab? Follow these steps to set up your workspace, plan and commit changes, and deploy your project.') = image_tag 'learn_gitlab/get_started.svg', width: '400', class: 'gl-max-w-full' - - if learn_gitlab_onboarding_available?(project) + - if learn_gitlab_onboarding_available?(project.namespace) %div= link_to s_("LearnGitlab|Ok, let's go"), project_learn_gitlab_path(project), class: 'btn btn-confirm gl-button gl-mt-7 js-get-started-btn', data: { qa_selector: 'confirm_button', track_label: track_label, track_action: "click_ok_lets_go" } - else %p.gl-text-center.gl-text-gray-700.gl-mt-7= s_('LearnGitlab|Creating your onboarding experience...') diff --git a/config/feature_flags/experiment/invite_for_help_continuous_onboarding.yml b/ee/config/feature_flags/experiment/invite_for_help_continuous_onboarding.yml similarity index 100% rename from config/feature_flags/experiment/invite_for_help_continuous_onboarding.yml rename to ee/config/feature_flags/experiment/invite_for_help_continuous_onboarding.yml diff --git a/config/feature_flags/experiment/video_tutorials_continuous_onboarding.yml b/ee/config/feature_flags/experiment/video_tutorials_continuous_onboarding.yml similarity index 100% rename from config/feature_flags/experiment/video_tutorials_continuous_onboarding.yml rename to ee/config/feature_flags/experiment/video_tutorials_continuous_onboarding.yml diff --git a/ee/config/routes/project.rb b/ee/config/routes/project.rb index 2ad17e20fcba..8d7e56068b26 100644 --- a/ee/config/routes/project.rb +++ b/ee/config/routes/project.rb @@ -40,6 +40,8 @@ resources :subscriptions, only: [:create, :destroy] + get :learn_gitlab, action: :index, controller: 'learn_gitlab' + resources :protected_environments, only: [:create, :update, :destroy], constraints: { id: /\d+/ } do collection do get 'search' diff --git a/ee/lib/ee/sidebars/projects/panel.rb b/ee/lib/ee/sidebars/projects/panel.rb index b49161bf366b..c0377e2543ae 100644 --- a/ee/lib/ee/sidebars/projects/panel.rb +++ b/ee/lib/ee/sidebars/projects/panel.rb @@ -10,8 +10,14 @@ module Panel def configure_menus super - insert_menu_before(::Sidebars::Projects::Menus::ProjectInformationMenu, - ::Sidebars::Projects::Menus::TrialWidgetMenu.new(context)) + insert_menu_before( + ::Sidebars::Projects::Menus::ProjectInformationMenu, + ::Sidebars::Projects::Menus::TrialWidgetMenu.new(context) + ) + insert_menu_after( + ::Sidebars::Projects::Menus::ProjectInformationMenu, + ::Sidebars::Projects::Menus::LearnGitlabMenu.new(context) + ) if ::Sidebars::Projects::Menus::IssuesMenu.new(context).show_jira_menu_items? remove_menu(::Sidebars::Projects::Menus::ExternalIssueTrackerMenu) diff --git a/lib/sidebars/projects/menus/learn_gitlab_menu.rb b/ee/lib/sidebars/projects/menus/learn_gitlab_menu.rb similarity index 81% rename from lib/sidebars/projects/menus/learn_gitlab_menu.rb rename to ee/lib/sidebars/projects/menus/learn_gitlab_menu.rb index b6fae2af93d8..e4178292cfee 100644 --- a/lib/sidebars/projects/menus/learn_gitlab_menu.rb +++ b/ee/lib/sidebars/projects/menus/learn_gitlab_menu.rb @@ -28,14 +28,12 @@ def has_pill? override :pill_count def pill_count - strong_memoize(:pill_count) do - percentage = Onboarding::Completion.new( - context.project.namespace, - context.current_user - ).percentage - - "#{percentage}%" - end + percentage = Onboarding::Completion.new( + context.project.namespace, + context.current_user + ).percentage + + "#{percentage}%" end override :extra_nav_link_html_options diff --git a/spec/controllers/projects/learn_gitlab_controller_spec.rb b/ee/spec/controllers/projects/learn_gitlab_controller_spec.rb similarity index 70% rename from spec/controllers/projects/learn_gitlab_controller_spec.rb rename to ee/spec/controllers/projects/learn_gitlab_controller_spec.rb index bcc8fdc0265d..51657bb45e9d 100644 --- a/spec/controllers/projects/learn_gitlab_controller_spec.rb +++ b/ee/spec/controllers/projects/learn_gitlab_controller_spec.rb @@ -5,16 +5,23 @@ RSpec.describe Projects::LearnGitlabController, feature_category: :onboarding do describe 'GET #index' do let_it_be(:user) { create(:user) } + let_it_be(:learn_gitlab_project) do + create(:project, name: Onboarding::LearnGitlab::PROJECT_NAME).tap do |record| + record.add_maintainer(user) + end + end + let_it_be(:project) { create(:project, namespace: create(:group)) } + let_it_be(:board) { create(:board, project: learn_gitlab_project, name: Onboarding::LearnGitlab::BOARD_NAME) } - let(:learn_gitlab_enabled) { true } let(:params) { { namespace_id: project.namespace.to_param, project_id: project } } subject(:action) { get :index, params: params } - before do + before_all do project.namespace.add_owner(user) - allow(controller.helpers).to receive(:learn_gitlab_enabled?).and_return(learn_gitlab_enabled) + create(:label, project: learn_gitlab_project, name: Onboarding::LearnGitlab::LABEL_NAME) + create(:onboarding_progress, namespace: project.namespace) end context 'for unauthenticated user' do @@ -29,7 +36,9 @@ it { is_expected.to render_template(:index) } context 'when learn_gitlab is not available' do - let(:learn_gitlab_enabled) { false } + before do + board.update!(name: 'bogus') + end it { is_expected.to have_gitlab_http_status(:not_found) } end diff --git a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_section_card_spec.js.snap b/ee/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_section_card_spec.js.snap similarity index 100% rename from spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_section_card_spec.js.snap rename to ee/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_section_card_spec.js.snap diff --git a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap b/ee/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap similarity index 100% rename from spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap rename to ee/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap diff --git a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_card_spec.js b/ee/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_card_spec.js similarity index 84% rename from spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_card_spec.js rename to ee/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_card_spec.js index 3a511a009a98..be28aedf166f 100644 --- a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_card_spec.js +++ b/ee/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_card_spec.js @@ -1,5 +1,5 @@ import { shallowMount } from '@vue/test-utils'; -import LearnGitlabSectionCard from '~/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue'; +import LearnGitlabSectionCard from 'ee/pages/projects/learn_gitlab/components/learn_gitlab_section_card.vue'; import { testActions } from './mock_data'; const defaultSection = 'workspace'; diff --git a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js b/ee/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js similarity index 97% rename from spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js rename to ee/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js index 293353083701..c22aa6a955cb 100644 --- a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js +++ b/ee/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js @@ -4,8 +4,8 @@ import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { stubExperiments } from 'helpers/experimentation_helper'; import { mockTracking, triggerEvent, unmockTracking } from 'helpers/tracking_helper'; import eventHub from '~/invite_members/event_hub'; -import LearnGitlabSectionLink from '~/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue'; -import { ACTION_LABELS } from '~/pages/projects/learn_gitlab/constants'; +import LearnGitlabSectionLink from 'ee/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue'; +import { ACTION_LABELS } from 'ee/pages/projects/learn_gitlab/constants'; const defaultAction = 'gitWrite'; const defaultProps = { diff --git a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js b/ee/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js similarity index 94% rename from spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js rename to ee/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js index 0f63c243342c..57414e2e1eac 100644 --- a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js +++ b/ee/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js @@ -1,9 +1,9 @@ import { GlProgressBar, GlAlert } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import Cookies from '~/lib/utils/cookies'; -import LearnGitlab from '~/pages/projects/learn_gitlab/components/learn_gitlab.vue'; +import LearnGitlab from 'ee/pages/projects/learn_gitlab/components/learn_gitlab.vue'; import eventHub from '~/invite_members/event_hub'; -import { INVITE_MODAL_OPEN_COOKIE } from '~/pages/projects/learn_gitlab/constants'; +import { INVITE_MODAL_OPEN_COOKIE } from 'ee/pages/projects/learn_gitlab/constants'; import { testActions, testSections, testProject } from './mock_data'; describe('Learn GitLab', () => { diff --git a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_trial_card_spec.js b/ee/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_trial_card_spec.js similarity index 71% rename from spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_trial_card_spec.js rename to ee/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_trial_card_spec.js index 6ab57e31fed3..7dfc7b6cce59 100644 --- a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_trial_card_spec.js +++ b/ee/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_trial_card_spec.js @@ -1,5 +1,5 @@ import { shallowMount } from '@vue/test-utils'; -import IncludedInTrialIndicator from '~/pages/projects/learn_gitlab/components/included_in_trial_indicator.vue'; +import IncludedInTrialIndicator from 'ee/pages/projects/learn_gitlab/components/included_in_trial_indicator.vue'; describe('Learn GitLab Trial Card', () => { it('renders correctly', () => { diff --git a/spec/frontend/pages/projects/learn_gitlab/components/mock_data.js b/ee/spec/frontend/pages/projects/learn_gitlab/components/mock_data.js similarity index 100% rename from spec/frontend/pages/projects/learn_gitlab/components/mock_data.js rename to ee/spec/frontend/pages/projects/learn_gitlab/components/mock_data.js diff --git a/ee/spec/helpers/ee/invite_members_helper_spec.rb b/ee/spec/helpers/ee/invite_members_helper_spec.rb index 0ce4c14f49ec..ff0912232b57 100644 --- a/ee/spec/helpers/ee/invite_members_helper_spec.rb +++ b/ee/spec/helpers/ee/invite_members_helper_spec.rb @@ -133,6 +133,66 @@ end end end + + context 'with tasks_to_be_done' do + using RSpec::Parameterized::TableSyntax + + let_it_be(:project) { create(:project) } + let_it_be(:group) { create(:group, projects: [project]) } + let_it_be(:developer) { create(:user, developer_projects: [project]) } + + subject(:output) { helper.common_invite_modal_dataset(source) } + + shared_examples_for 'including the tasks to be done attributes' do + it 'includes the tasks to be done attributes when expected' do + if expected? + result = [ + { value: :code, text: 'Create/import code into a project (repository)' }, + { value: :ci, text: 'Set up CI/CD pipelines to build, test, deploy, and monitor code' }, + { value: :issues, text: 'Create/import issues (tickets) to collaborate on ideas and plan work' } + ].to_json + + expect(output[:tasks_to_be_done_options]).to eq(result) + expect(output[:projects]).to eq([{ id: project.id, title: project.title }].to_json) + expect(output[:new_project_path]) + .to eq(source.is_a?(Project) ? '' : new_project_path(namespace_id: group.id)) + else + expect(output[:tasks_to_be_done_options]).to be_nil + expect(output[:projects]).to be_nil + expect(output[:new_project_path]).to be_nil + end + end + end + + context 'with the invite_for_help_continuous_onboarding experiment' do + where(:invite_continuous_onboarding?, :logged_in?, :expected?) do + true | true | true + true | false | false + false | true | false + false | false | false + end + + with_them do + before do + allow(helper).to receive(:current_user).and_return(developer) if logged_in? + stub_experiments(invite_for_help_continuous_onboarding: :candidate) if invite_continuous_onboarding? + end + + context 'when the source is a project' do + let(:source) { project } + + it_behaves_like 'including the tasks to be done attributes' + end + + context 'when the source is a group' do + let(:source) { group } + let(:expected?) { false } + + it_behaves_like 'including the tasks to be done attributes' + end + end + end + end end describe '#users_filter_data' do diff --git a/ee/spec/helpers/ee/learn_gitlab_helper_spec.rb b/ee/spec/helpers/ee/learn_gitlab_helper_spec.rb deleted file mode 100644 index 994bb472a2a1..000000000000 --- a/ee/spec/helpers/ee/learn_gitlab_helper_spec.rb +++ /dev/null @@ -1,144 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe LearnGitlabHelper do - include Devise::Test::ControllerHelpers - - let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, name: Onboarding::LearnGitlab::PROJECT_NAME, namespace: user.namespace) } - let_it_be(:namespace) { project.namespace } - let(:disabled_message) { s_('LearnGitlab|Contact your administrator to start a free Ultimate trial.') } - - before do - allow_next_instance_of(Onboarding::LearnGitlab) do |learn_gitlab| - allow(learn_gitlab).to receive(:project).and_return(project) - end - - Onboarding::Progress.onboard(namespace) - sign_in(user) - end - - describe '#learn_gitlab_data' do - subject(:onboarding_actions_data) do - Gitlab::Json.parse(helper.learn_gitlab_data(project)[:actions]).deep_symbolize_keys - end - - context 'when in the new action URLs experiment' do - context 'for trial- and subscription-related actions' do - context 'when namespace plans are not enabled' do - before do - stub_application_setting(check_namespace_plan: false) - end - - it 'provides the default URLs' do - expect(onboarding_actions_data).to include( - trial_started: a_hash_including( - url: a_string_matching(%r{#{namespace.path}/learn_gitlab/-/issues/2}) - ), - code_owners_enabled: a_hash_including( - url: a_string_matching(%r{#{namespace.path}/learn_gitlab/-/issues/10}) - ), - required_mr_approvals_enabled: a_hash_including( - url: a_string_matching(%r{#{namespace.path}/learn_gitlab/-/issues/11}) - ) - ) - end - end - - context 'when namespace plans are enabled' do - before do - stub_application_setting(check_namespace_plan: true) - end - - context 'when namespace has free or no subscription' do - before do - allow(namespace).to receive(:has_free_or_no_subscription?).and_return(true) - end - - it 'provides URLs to start a trial to namespace admins' do - allow(helper).to receive(:can?).with(user, :admin_namespace, namespace).and_return(true) - expect(onboarding_actions_data).to include( - trial_started: a_hash_including( - url: new_trial_path(glm_source: 'gitlab.com', glm_content: 'onboarding-start-trial'), - enabled: true - ), - code_owners_enabled: a_hash_including( - url: new_trial_path(glm_source: 'gitlab.com', glm_content: 'onboarding-code-owners'), - enabled: true - ), - required_mr_approvals_enabled: a_hash_including( - url: new_trial_path(glm_source: 'gitlab.com', glm_content: 'onboarding-require-merge-approvals'), - enabled: true - ) - ) - end - - it 'provides URLs to Gitlab docs to namespace non-admins' do - allow(helper).to receive(:can?).with(user, :admin_namespace, namespace).and_return(false) - expect(onboarding_actions_data).to include( - trial_started: a_hash_including( - url: project_project_members_path(project), - enabled: false, - message: disabled_message - ), - code_owners_enabled: a_hash_including( - url: help_page_path('user/project/code_owners', anchor: 'set-up-code-owners'), - enabled: true - ), - required_mr_approvals_enabled: a_hash_including( - url: help_page_path('ci/pipelines/settings', anchor: 'coverage-check-approval-rule'), - enabled: true - ) - ) - end - end - - context 'when namespace has paid subscription' do - before do - allow(namespace).to receive(:has_free_or_no_subscription?).and_return(false) - end - - it 'provides URLs to Gitlab docs to namespace admins' do - allow(helper).to receive(:can?).with(user, :admin_namespace, namespace).and_return(true) - expect(onboarding_actions_data).to include( - trial_started: a_hash_including( - url: project_project_members_path(project), - enabled: false, - message: disabled_message - ), - code_owners_enabled: a_hash_including( - url: help_page_path('user/project/code_owners', anchor: 'set-up-code-owners'), - enabled: true - ), - required_mr_approvals_enabled: a_hash_including( - url: help_page_path('ci/pipelines/settings', anchor: 'coverage-check-approval-rule'), - enabled: true - ) - ) - end - - it 'provides URLs to Gitlab docs to namespace non-admins' do - allow(helper).to receive(:can?).with(user, :admin_namespace, namespace).and_return(false) - expect(onboarding_actions_data).to include( - trial_started: a_hash_including( - url: project_project_members_path(project), - enabled: false, - message: disabled_message - ), - code_owners_enabled: a_hash_including( - url: help_page_path('user/project/code_owners', anchor: 'set-up-code-owners'), - enabled: true - ), - required_mr_approvals_enabled: a_hash_including( - url: help_page_path('ci/pipelines/settings', anchor: 'coverage-check-approval-rule'), - enabled: true - ) - ) - end - end - end - end - end - end -end diff --git a/ee/spec/helpers/projects/learn_gitlab_helper_spec.rb b/ee/spec/helpers/projects/learn_gitlab_helper_spec.rb new file mode 100644 index 000000000000..04e4ef8bd50a --- /dev/null +++ b/ee/spec/helpers/projects/learn_gitlab_helper_spec.rb @@ -0,0 +1,266 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::LearnGitlabHelper, feature_category: :onboarding do + let_it_be(:user) { create(:user) } + + before do + allow(helper).to receive(:current_user).and_return(user) + end + + describe '#learn_gitlab_data' do + let_it_be(:namespace) { create(:group) } + let_it_be(:project) { build_stubbed(:project, name: Onboarding::LearnGitlab::PROJECT_NAME, namespace: namespace) } + let(:onboarding_actions_data) { Gitlab::Json.parse(learn_gitlab_data[:actions]).deep_symbolize_keys } + let(:onboarding_sections_data) { Gitlab::Json.parse(learn_gitlab_data[:sections]).deep_symbolize_keys } + let(:onboarding_project_data) { Gitlab::Json.parse(learn_gitlab_data[:project]).deep_symbolize_keys } + + before do + Onboarding::Progress.onboard(namespace) + Onboarding::Progress.register(namespace, :git_write) + end + + subject(:learn_gitlab_data) { helper.learn_gitlab_data(project) } + + shared_examples 'has all data' do + it 'has all actions' do + expected_keys = [ + :issue_created, + :git_write, + :pipeline_created, + :merge_request_created, + :user_added, + :trial_started, + :required_mr_approvals_enabled, + :code_owners_enabled, + :security_scan_enabled + ] + + expect(onboarding_actions_data.keys).to contain_exactly(*expected_keys) + end + + it 'has all section data', :aggregate_failures do + expect(onboarding_sections_data.keys).to contain_exactly(:deploy, :plan, :workspace) + expect(onboarding_sections_data.values.map(&:keys)).to match_array([[:svg]] * 3) + end + + it 'has all project data', :aggregate_failures do + expect(onboarding_project_data.keys).to contain_exactly(:name) + expect(onboarding_project_data.values).to match_array([project.name]) + end + end + + it_behaves_like 'has all data' + + it 'sets correct completion statuses' do + result = { + issue_created: a_hash_including(completed: false), + git_write: a_hash_including(completed: true), + pipeline_created: a_hash_including(completed: false), + merge_request_created: a_hash_including(completed: false), + user_added: a_hash_including(completed: false), + trial_started: a_hash_including(completed: false), + required_mr_approvals_enabled: a_hash_including(completed: false), + code_owners_enabled: a_hash_including(completed: false), + security_scan_enabled: a_hash_including(completed: false) + } + + expect(onboarding_actions_data).to match(result) + end + + context 'with security_actions_continuous_onboarding experiment' do + let(:base_paths) do + { + trial_started: a_hash_including(url: %r{/learn_gitlab/-/issues/2\z}), + pipeline_created: a_hash_including(url: %r{/learn_gitlab/-/issues/7\z}), + code_owners_enabled: a_hash_including(url: %r{/learn_gitlab/-/issues/10\z}), + required_mr_approvals_enabled: a_hash_including(url: %r{/learn_gitlab/-/issues/11\z}), + issue_created: a_hash_including(url: %r{/learn_gitlab/-/issues\z}), + git_write: a_hash_including(url: %r{/learn_gitlab\z}), + user_added: a_hash_including(url: %r{/learn_gitlab/-/project_members\z}), + merge_request_created: a_hash_including(url: %r{/learn_gitlab/-/merge_requests\z}) + } + end + + context 'when control' do + before do + stub_experiments(security_actions_continuous_onboarding: :control) + end + + it 'sets correct paths' do + result = base_paths.merge( + security_scan_enabled: a_hash_including( + url: %r{/learn_gitlab/-/security/configuration\z} + ) + ) + + expect(onboarding_actions_data).to match(result) + end + end + + context 'when candidate' do + before do + stub_experiments(security_actions_continuous_onboarding: :candidate) + end + + it 'sets correct paths' do + result = base_paths.merge( + license_scanning_run: a_hash_including( + url: described_class::LICENSE_SCANNING_RUN_URL + ), + secure_dependency_scanning_run: a_hash_including( + url: project_security_configuration_path(project, anchor: 'dependency-scanning') + ), + secure_dast_run: a_hash_including( + url: project_security_configuration_path(project, anchor: 'dast') + ) + ) + + expect(onboarding_actions_data).to match(result) + end + end + end + + context 'for trial- and subscription-related actions' do + let(:disabled_message) { s_('LearnGitlab|Contact your administrator to start a free Ultimate trial.') } + + context 'when namespace plans are not enabled' do + before do + stub_application_setting(check_namespace_plan: false) + end + + it 'provides the default URLs' do + result = { + trial_started: a_hash_including( + url: a_string_matching(%r{#{namespace.path}/learn_gitlab/-/issues/2}) + ), + code_owners_enabled: a_hash_including( + url: a_string_matching(%r{#{namespace.path}/learn_gitlab/-/issues/10}) + ), + required_mr_approvals_enabled: a_hash_including( + url: a_string_matching(%r{#{namespace.path}/learn_gitlab/-/issues/11}) + ) + } + + expect(onboarding_actions_data).to include(result) + end + end + + context 'when namespace plans are enabled' do + before do + stub_application_setting(check_namespace_plan: true) + end + + context 'when namespace has free or no subscription' do + before do + allow(namespace).to receive(:has_free_or_no_subscription?).and_return(true) + end + + it 'provides URLs to start a trial to namespace admins' do + namespace.add_owner(user) + result = { + trial_started: a_hash_including( + url: new_trial_path(glm_source: 'gitlab.com', glm_content: 'onboarding-start-trial'), + enabled: true + ), + code_owners_enabled: a_hash_including( + url: new_trial_path(glm_source: 'gitlab.com', glm_content: 'onboarding-code-owners'), + enabled: true + ), + required_mr_approvals_enabled: a_hash_including( + url: new_trial_path(glm_source: 'gitlab.com', glm_content: 'onboarding-require-merge-approvals'), + enabled: true + ) + } + + expect(onboarding_actions_data).to include(result) + end + + it 'provides URLs to Gitlab docs to namespace non-admins' do + result = { + trial_started: a_hash_including( + url: project_project_members_path(project), + enabled: false, + message: disabled_message + ), + code_owners_enabled: a_hash_including( + url: help_page_path('user/project/code_owners', anchor: 'set-up-code-owners'), + enabled: true + ), + required_mr_approvals_enabled: a_hash_including( + url: help_page_path('ci/pipelines/settings', anchor: 'coverage-check-approval-rule'), + enabled: true + ) + } + + expect(onboarding_actions_data).to include(result) + end + end + + context 'when namespace has paid subscription' do + before do + allow(namespace).to receive(:has_free_or_no_subscription?).and_return(false) + end + + it 'provides URLs to Gitlab docs to namespace admins' do + namespace.add_owner(user) + result = { + trial_started: a_hash_including( + url: project_project_members_path(project), + enabled: false, + message: disabled_message + ), + code_owners_enabled: a_hash_including( + url: help_page_path('user/project/code_owners', anchor: 'set-up-code-owners'), + enabled: true + ), + required_mr_approvals_enabled: a_hash_including( + url: help_page_path('ci/pipelines/settings', anchor: 'coverage-check-approval-rule'), + enabled: true + ) + } + + expect(onboarding_actions_data).to include(result) + end + + it 'provides URLs to Gitlab docs to namespace non-admins' do + result = { + trial_started: a_hash_including( + url: project_project_members_path(project), + enabled: false, + message: disabled_message + ), + code_owners_enabled: a_hash_including( + url: help_page_path('user/project/code_owners', anchor: 'set-up-code-owners'), + enabled: true + ), + required_mr_approvals_enabled: a_hash_including( + url: help_page_path('ci/pipelines/settings', anchor: 'coverage-check-approval-rule'), + enabled: true + ) + } + + expect(onboarding_actions_data).to include(result) + end + end + end + end + end + + describe '#learn_gitlab_onboarding_available?' do + let(:namespace) { build(:group) } + + it 'is not available' do + expect(helper.learn_gitlab_onboarding_available?(namespace)).to eq(false) + end + + it 'is available' do + allow_next_instance_of(Onboarding::LearnGitlab, user) do |instance| + allow(instance).to receive(:onboarding_and_available?).with(namespace).and_return(true) + end + + expect(helper.learn_gitlab_onboarding_available?(namespace)).to eq(true) + end + end +end diff --git a/ee/spec/lib/ee/sidebars/projects/panel_spec.rb b/ee/spec/lib/ee/sidebars/projects/panel_spec.rb index 4ac5f0e0bb14..35ce79095338 100644 --- a/ee/spec/lib/ee/sidebars/projects/panel_spec.rb +++ b/ee/spec/lib/ee/sidebars/projects/panel_spec.rb @@ -37,6 +37,12 @@ def contains_external_issue_tracker_menu? end end + context 'with learn gitlab menu' do + it 'contains the menu' do + expect(contains_menu?(Sidebars::Projects::Menus::LearnGitlabMenu)).to be(true) + end + end + def contains_menu?(menu) panel.instance_variable_get(:@menus).any? { |i| i.is_a?(menu) } end diff --git a/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb b/ee/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb similarity index 77% rename from spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb rename to ee/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb index 4ae29f28f3a9..6efadc6e0252 100644 --- a/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb +++ b/ee/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb @@ -2,10 +2,9 @@ require 'spec_helper' -RSpec.describe Sidebars::Projects::Menus::LearnGitlabMenu do - let_it_be(:project) { build(:project) } - let_it_be(:learn_gitlab_enabled) { true } - +RSpec.describe Sidebars::Projects::Menus::LearnGitlabMenu, feature_category: :onboarding do + let(:project) { build(:project) } + let(:learn_gitlab_enabled) { true } let(:context) do Sidebars::Projects::Context.new( current_user: nil, @@ -21,7 +20,7 @@ end describe '#nav_link_html_options' do - let_it_be(:data_tracking) do + let(:data_tracking) do { class: 'home', data: { @@ -36,13 +35,13 @@ end describe '#render?' do - context 'when learn gitlab experiment is enabled' do + context 'when learn gitlab is enabled' do it 'returns true' do expect(subject.render?).to eq true end end - context 'when learn gitlab experiment is disabled' do + context 'when learn gitlab is disabled' do let(:learn_gitlab_enabled) { false } it 'returns false' do @@ -52,13 +51,13 @@ end describe '#has_pill?' do - context 'when learn gitlab experiment is enabled' do + context 'when learn gitlab is enabled' do it 'returns true' do expect(subject.has_pill?).to eq true end end - context 'when learn gitlab experiment is disabled' do + context 'when learn gitlab is disabled' do let(:learn_gitlab_enabled) { false } it 'returns false' do diff --git a/spec/models/onboarding/learn_gitlab_spec.rb b/ee/spec/models/onboarding/learn_gitlab_spec.rb similarity index 54% rename from spec/models/onboarding/learn_gitlab_spec.rb rename to ee/spec/models/onboarding/learn_gitlab_spec.rb index 5e3e1f9c304e..25c26cf00acc 100644 --- a/spec/models/onboarding/learn_gitlab_spec.rb +++ b/ee/spec/models/onboarding/learn_gitlab_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Onboarding::LearnGitlab do +RSpec.describe Onboarding::LearnGitlab, feature_category: :onboarding do let_it_be(:current_user) { create(:user) } let_it_be(:learn_gitlab_project) { create(:project, name: described_class::PROJECT_NAME) } let_it_be(:learn_gitlab_board) { create(:board, project: learn_gitlab_project, name: described_class::BOARD_NAME) } @@ -12,35 +12,6 @@ learn_gitlab_project.add_developer(current_user) end - describe '#available?' do - using RSpec::Parameterized::TableSyntax - - where(:project, :board, :label, :expected_result) do - nil | nil | nil | nil - nil | nil | true | nil - nil | true | nil | nil - nil | true | true | nil - true | nil | nil | nil - true | nil | true | nil - true | true | nil | nil - true | true | true | true - end - - with_them do - before do - allow_next_instance_of(described_class) do |learn_gitlab| - allow(learn_gitlab).to receive(:project).and_return(project) - allow(learn_gitlab).to receive(:board).and_return(board) - allow(learn_gitlab).to receive(:label).and_return(label) - end - end - - subject { described_class.new(current_user).available? } - - it { is_expected.to be expected_result } - end - end - describe '#project' do subject { described_class.new(current_user).project } @@ -66,4 +37,45 @@ it { is_expected.to eq learn_gitlab_label } end + + describe '#onboarding_and_available?' do + using RSpec::Parameterized::TableSyntax + + let(:namespace) { build(:namespace) } + + where(:current_user, :project, :available, :onboarding, :expected_result) do + nil | nil | false | false | false + true | nil | false | false | false + true | true | false | false | false + true | true | true | false | false + true | true | true | true | true + nil | nil | false | true | false + nil | nil | true | true | false + nil | nil | true | false | false + nil | true | true | true | false + nil | true | true | false | false + nil | true | false | false | false + nil | true | false | true | false + true | nil | true | true | false + true | true | false | true | false + true | nil | true | false | false + true | nil | false | true | false + end + + with_them do + before do + allow_next_instance_of(described_class) do |learn_gitlab| + allow(learn_gitlab).to receive(:project).and_return(project) + allow(learn_gitlab).to receive(:available?).and_return(available) + allow(learn_gitlab).to receive(:current_user).and_return(current_user) + end + + allow(Onboarding::Progress).to receive(:onboarding?).with(namespace).and_return(onboarding) + end + + subject { described_class.new(current_user).onboarding_and_available?(namespace) } + + it { is_expected.to be expected_result } + end + end end diff --git a/ee/spec/services/registrations/standard_namespace_create_service_spec.rb b/ee/spec/services/registrations/standard_namespace_create_service_spec.rb index e0ca4d83f2c4..672d846be12a 100644 --- a/ee/spec/services/registrations/standard_namespace_create_service_spec.rb +++ b/ee/spec/services/registrations/standard_namespace_create_service_spec.rb @@ -173,8 +173,8 @@ context 'with learn gitlab project', :sidekiq_inline do where(:trial, :project_name, :template) do - 'false' | 'Learn GitLab' | described_class::LEARN_GITLAB_ULTIMATE_TEMPLATE - 'true' | 'Learn GitLab - Ultimate trial' | described_class::LEARN_GITLAB_ULTIMATE_TEMPLATE + 'false' | 'Learn GitLab' | Onboarding::LearnGitlab::TEMPLATE_NAME + 'true' | 'Learn GitLab - Ultimate trial' | Onboarding::LearnGitlab::TEMPLATE_NAME end with_them do diff --git a/ee/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/ee/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb index 556364548293..80e590b2ff5e 100644 --- a/ee/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb +++ b/ee/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'layouts/nav/sidebar/_project' do +RSpec.describe 'layouts/nav/sidebar/_project', feature_category: :navigation do let_it_be_with_refind(:project) { create(:project, :repository) } let_it_be(:user) { project.first_owner } @@ -13,6 +13,22 @@ allow(view).to receive(:current_ref).and_return('master') end + describe 'Learn GitLab' do + it 'has a link to the learn GitLab' do + allow(view).to receive(:current_user).and_return(user) + allow_next_instance_of(Onboarding::LearnGitlab, user) do |instance| + allow(instance).to receive(:onboarding_and_available?).with(project.namespace).and_return(true) + end + allow_next_instance_of(Onboarding::Completion) do |onboarding| + expect(onboarding).to receive(:percentage).and_return(20) + end + + render + + expect(rendered).to have_link('Learn GitLab', href: project_learn_gitlab_path(project)) + end + end + describe 'Repository' do describe 'Files' do it 'has a link to the project file locks path' do diff --git a/ee/spec/views/registrations/welcome/continuous_onboarding_getting_started.html.haml_spec.rb b/ee/spec/views/registrations/welcome/continuous_onboarding_getting_started.html.haml_spec.rb index c2b9e7e3d424..eaf11088dec0 100644 --- a/ee/spec/views/registrations/welcome/continuous_onboarding_getting_started.html.haml_spec.rb +++ b/ee/spec/views/registrations/welcome/continuous_onboarding_getting_started.html.haml_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'registrations/welcome/continuous_onboarding_getting_started' do +RSpec.describe 'registrations/welcome/continuous_onboarding_getting_started', feature_category: :onboarding do describe 'project import state' do let_it_be(:project) { create(:project) } diff --git a/ee/spec/workers/onboarding/create_learn_gitlab_worker_spec.rb b/ee/spec/workers/onboarding/create_learn_gitlab_worker_spec.rb index bfbbace23451..1c17ad7a3849 100644 --- a/ee/spec/workers/onboarding/create_learn_gitlab_worker_spec.rb +++ b/ee/spec/workers/onboarding/create_learn_gitlab_worker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Onboarding::CreateLearnGitlabWorker, type: :worker do +RSpec.describe Onboarding::CreateLearnGitlabWorker, type: :worker, feature_category: :onboarding do include AfterNextHelpers let_it_be(:namespace) { create(:namespace) } @@ -47,5 +47,22 @@ perform end end + + context 'when learn gitlab project already exists' do + let(:logger) { described_class.new.send(:logger) } + let(:project_name) { Onboarding::LearnGitlab::PROJECT_NAME } + + before do + create(:project, name: project_name, namespace: namespace) + end + + it 'invokes Projects::GitlabProjectsImportService' do + expect(File).not_to receive(:open).with(template_path) + expect_next(::Projects::GitlabProjectsImportService).not_to receive(:execute) + expect(logger).not_to receive(:error) + + perform + end + end end end diff --git a/lib/sidebars/projects/panel.rb b/lib/sidebars/projects/panel.rb index 8ae8f931aab1..9d0f5eb87bd7 100644 --- a/lib/sidebars/projects/panel.rb +++ b/lib/sidebars/projects/panel.rb @@ -19,7 +19,6 @@ def aria_label def add_menus add_menu(Sidebars::Projects::Menus::ProjectInformationMenu.new(context)) - add_menu(Sidebars::Projects::Menus::LearnGitlabMenu.new(context)) add_menu(Sidebars::Projects::Menus::RepositoryMenu.new(context)) add_menu(Sidebars::Projects::Menus::IssuesMenu.new(context)) add_menu(Sidebars::Projects::Menus::ExternalIssueTrackerMenu.new(context)) diff --git a/spec/experiments/video_tutorials_continuous_onboarding_experiment_spec.rb b/spec/experiments/video_tutorials_continuous_onboarding_experiment_spec.rb deleted file mode 100644 index 596791308a40..000000000000 --- a/spec/experiments/video_tutorials_continuous_onboarding_experiment_spec.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe VideoTutorialsContinuousOnboardingExperiment do - it "defines a control and candidate" do - expect(subject.behaviors.keys).to match_array(%w[control candidate]) - end -end diff --git a/spec/helpers/invite_members_helper_spec.rb b/spec/helpers/invite_members_helper_spec.rb index 48e94ec7e980..abf8b65dc1ec 100644 --- a/spec/helpers/invite_members_helper_spec.rb +++ b/spec/helpers/invite_members_helper_spec.rb @@ -36,7 +36,8 @@ end it 'provides the correct attributes' do - expect(helper.common_invite_group_modal_data(group, GroupMember, 'false')).to include({ groups_filter: 'descendant_groups', parent_id: group.id }) + expect(helper.common_invite_group_modal_data(group, GroupMember, 'false')) + .to include({ groups_filter: 'descendant_groups', parent_id: group.id }) end end @@ -46,7 +47,8 @@ end it 'does not return filter attributes' do - expect(helper.common_invite_group_modal_data(project.group, ProjectMember, 'true').keys).not_to include(:groups_filter, :parent_id) + expect(helper.common_invite_group_modal_data(project.group, ProjectMember, 'true').keys) + .not_to include(:groups_filter, :parent_id) end end end @@ -64,7 +66,7 @@ expect(helper.common_invite_modal_dataset(project)).to include(attributes) end - context 'tasks_to_be_done' do + context 'with tasks_to_be_done' do using RSpec::Parameterized::TableSyntax subject(:output) { helper.common_invite_modal_dataset(source) } @@ -79,9 +81,7 @@ { value: :issues, text: 'Create/import issues (tickets) to collaborate on ideas and plan work' } ].to_json ) - expect(output[:projects]).to eq( - [{ id: project.id, title: project.title }].to_json - ) + expect(output[:projects]).to eq([{ id: project.id, title: project.title }].to_json) expect(output[:new_project_path]).to eq( source.is_a?(Project) ? '' : new_project_path(namespace_id: group.id) ) @@ -93,8 +93,8 @@ end end - context 'inviting members for tasks' do - where(:open_modal_param_present?, :logged_in?, :expected?) do + context 'when inviting members for tasks' do + where(:open_modal_param?, :logged_in?, :expected?) do true | true | true true | false | false false | true | false @@ -104,7 +104,7 @@ with_them do before do allow(helper).to receive(:current_user).and_return(developer) if logged_in? - allow(helper).to receive(:params).and_return({ open_modal: 'invite_members_for_task' }) if open_modal_param_present? + allow(helper).to receive(:params).and_return({ open_modal: 'invite_members_for_task' }) if open_modal_param? end context 'when the source is a project' do @@ -120,36 +120,6 @@ end end end - - context 'the invite_for_help_continuous_onboarding experiment' do - where(:invite_for_help_continuous_onboarding?, :logged_in?, :expected?) do - true | true | true - true | false | false - false | true | false - false | false | false - end - - with_them do - before do - allow(helper).to receive(:current_user).and_return(developer) if logged_in? - stub_experiments(invite_for_help_continuous_onboarding: :candidate) if invite_for_help_continuous_onboarding? - end - - context 'when the source is a project' do - let_it_be(:source) { project } - - it_behaves_like 'including the tasks to be done attributes' - end - - context 'when the source is a group' do - let_it_be(:source) { group } - - let(:expected?) { false } - - it_behaves_like 'including the tasks to be done attributes' - end - end - end end end @@ -172,11 +142,9 @@ end context 'when the user can not manage project members' do - before do + it 'returns false' do expect(helper).to receive(:can?).with(owner, :admin_project_member, project).and_return(false) - end - it 'returns false' do expect(helper.can_invite_members_for_project?(project)).to eq false end end diff --git a/spec/helpers/learn_gitlab_helper_spec.rb b/spec/helpers/learn_gitlab_helper_spec.rb deleted file mode 100644 index 0ec1434e4962..000000000000 --- a/spec/helpers/learn_gitlab_helper_spec.rb +++ /dev/null @@ -1,162 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe LearnGitlabHelper, feature_category: :onboarding do - include AfterNextHelpers - include Devise::Test::ControllerHelpers - - let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, name: Onboarding::LearnGitlab::PROJECT_NAME, namespace: user.namespace) } - let_it_be(:namespace) { project.namespace } - - before do - allow_next_instance_of(Onboarding::LearnGitlab) do |learn_gitlab| - allow(learn_gitlab).to receive(:project).and_return(project) - end - - Onboarding::Progress.onboard(namespace) - Onboarding::Progress.register(namespace, :git_write) - end - - describe '#learn_gitlab_enabled?' do - using RSpec::Parameterized::TableSyntax - - let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, namespace: user.namespace) } - - let(:params) { { namespace_id: project.namespace.to_param, project_id: project } } - - subject { helper.learn_gitlab_enabled?(project) } - - where(:onboarding, :learn_gitlab_available, :result) do - true | true | true - true | false | false - false | true | false - end - - with_them do - before do - allow(Onboarding::Progress).to receive(:onboarding?).with(project.namespace).and_return(onboarding) - allow_next(Onboarding::LearnGitlab, user).to receive(:available?).and_return(learn_gitlab_available) - end - - context 'when signed in' do - before do - sign_in(user) - end - - it { is_expected.to eq(result) } - end - end - - context 'when not signed in' do - it { is_expected.to eq(false) } - end - end - - describe '#learn_gitlab_data' do - subject(:learn_gitlab_data) { helper.learn_gitlab_data(project) } - - let(:onboarding_actions_data) { Gitlab::Json.parse(learn_gitlab_data[:actions]).deep_symbolize_keys } - let(:onboarding_sections_data) { Gitlab::Json.parse(learn_gitlab_data[:sections]).deep_symbolize_keys } - let(:onboarding_project_data) { Gitlab::Json.parse(learn_gitlab_data[:project]).deep_symbolize_keys } - - shared_examples 'has all data' do - it 'has all actions' do - expected_keys = [ - :issue_created, - :git_write, - :pipeline_created, - :merge_request_created, - :user_added, - :trial_started, - :required_mr_approvals_enabled, - :code_owners_enabled, - :security_scan_enabled - ] - - expect(onboarding_actions_data.keys).to contain_exactly(*expected_keys) - end - - it 'has all section data', :aggregate_failures do - expect(onboarding_sections_data.keys).to contain_exactly(:deploy, :plan, :workspace) - expect(onboarding_sections_data.values.map(&:keys)).to match_array([[:svg]] * 3) - end - - it 'has all project data', :aggregate_failures do - expect(onboarding_project_data.keys).to contain_exactly(:name) - expect(onboarding_project_data.values).to match_array([project.name]) - end - end - - it_behaves_like 'has all data' - - it 'sets correct completion statuses' do - expect(onboarding_actions_data).to match({ - issue_created: a_hash_including(completed: false), - git_write: a_hash_including(completed: true), - pipeline_created: a_hash_including(completed: false), - merge_request_created: a_hash_including(completed: false), - user_added: a_hash_including(completed: false), - trial_started: a_hash_including(completed: false), - required_mr_approvals_enabled: a_hash_including(completed: false), - code_owners_enabled: a_hash_including(completed: false), - security_scan_enabled: a_hash_including(completed: false) - }) - end - - describe 'security_actions_continuous_onboarding experiment' do - let(:base_paths) do - { - trial_started: a_hash_including(url: %r{/learn_gitlab/-/issues/2\z}), - pipeline_created: a_hash_including(url: %r{/learn_gitlab/-/issues/7\z}), - code_owners_enabled: a_hash_including(url: %r{/learn_gitlab/-/issues/10\z}), - required_mr_approvals_enabled: a_hash_including(url: %r{/learn_gitlab/-/issues/11\z}), - issue_created: a_hash_including(url: %r{/learn_gitlab/-/issues\z}), - git_write: a_hash_including(url: %r{/learn_gitlab\z}), - user_added: a_hash_including(url: %r{/learn_gitlab/-/project_members\z}), - merge_request_created: a_hash_including(url: %r{/learn_gitlab/-/merge_requests\z}) - } - end - - context 'when control' do - before do - stub_experiments(security_actions_continuous_onboarding: :control) - end - - it 'sets correct paths' do - expect(onboarding_actions_data).to match( - base_paths.merge( - security_scan_enabled: a_hash_including( - url: %r{/learn_gitlab/-/security/configuration\z} - ) - ) - ) - end - end - - context 'when candidate' do - before do - stub_experiments(security_actions_continuous_onboarding: :candidate) - end - - it 'sets correct paths' do - expect(onboarding_actions_data).to match( - base_paths.merge( - license_scanning_run: a_hash_including( - url: described_class::LICENSE_SCANNING_RUN_URL - ), - secure_dependency_scanning_run: a_hash_including( - url: project_security_configuration_path(project, anchor: 'dependency-scanning') - ), - secure_dast_run: a_hash_including( - url: project_security_configuration_path(project, anchor: 'dast') - ) - ) - ) - end - end - end - end -end diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml index e50b08d8fbeb..420a704e20cd 100644 --- a/spec/support/rspec_order_todo.yml +++ b/spec/support/rspec_order_todo.yml @@ -966,11 +966,9 @@ - './ee/spec/helpers/ee/groups/settings_helper_spec.rb' - './ee/spec/helpers/ee/hooks_helper_spec.rb' - './ee/spec/helpers/ee/integrations_helper_spec.rb' -- './ee/spec/helpers/ee/invite_members_helper_spec.rb' - './ee/spec/helpers/ee/issuables_helper_spec.rb' - './ee/spec/helpers/ee/issues_helper_spec.rb' - './ee/spec/helpers/ee/labels_helper_spec.rb' -- './ee/spec/helpers/ee/learn_gitlab_helper_spec.rb' - './ee/spec/helpers/ee/lock_helper_spec.rb' - './ee/spec/helpers/ee/namespaces_helper_spec.rb' - './ee/spec/helpers/ee/namespace_user_cap_reached_alert_helper_spec.rb' @@ -3633,7 +3631,6 @@ - './spec/experiments/ios_specific_templates_experiment_spec.rb' - './spec/experiments/require_verification_for_namespace_creation_experiment_spec.rb' - './spec/experiments/security_reports_mr_widget_prompt_experiment_spec.rb' -- './spec/experiments/video_tutorials_continuous_onboarding_experiment_spec.rb' - './spec/features/abuse_report_spec.rb' - './spec/features/action_cable_logging_spec.rb' - './spec/features/admin/admin_abuse_reports_spec.rb' @@ -5160,7 +5157,6 @@ - './spec/helpers/import_helper_spec.rb' - './spec/helpers/instance_configuration_helper_spec.rb' - './spec/helpers/integrations_helper_spec.rb' -- './spec/helpers/invite_members_helper_spec.rb' - './spec/helpers/issuables_description_templates_helper_spec.rb' - './spec/helpers/issuables_helper_spec.rb' - './spec/helpers/issues_helper_spec.rb' diff --git a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb index 4de2c011b93a..82584155de5e 100644 --- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb +++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'layouts/nav/sidebar/_project' do +RSpec.describe 'layouts/nav/sidebar/_project', feature_category: :navigation do let_it_be_with_reload(:project) { create(:project, :repository) } let(:user) { project.first_owner } @@ -67,19 +67,6 @@ end end - describe 'Learn GitLab' do - it 'has a link to the learn GitLab' do - allow(view).to receive(:learn_gitlab_enabled?).and_return(true) - allow_next_instance_of(Onboarding::Completion) do |onboarding| - expect(onboarding).to receive(:percentage).and_return(20) - end - - render - - expect(rendered).to have_link('Learn GitLab', href: project_learn_gitlab_path(project)) - end - end - describe 'Repository' do it 'has a link to the project tree path' do render -- GitLab