diff options
51 files changed, 420 insertions, 291 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 0bcc88f64d3..428bc196899 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -42f8c9df6f29d8983c0f976b352129ec91499667 +04496625daa52aaa82fe4140d898258e7e6fda22 diff --git a/app/assets/stylesheets/framework/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar.scss index 48252762546..745d469e3e8 100644 --- a/app/assets/stylesheets/framework/contextual_sidebar.scss +++ b/app/assets/stylesheets/framework/contextual_sidebar.scss @@ -436,11 +436,7 @@ padding: 6px 16px; margin: 0 0 0 -15px; height: 46px; - - i { - font-size: 20px; - color: $gl-text-color-secondary; - } + color: $gl-text-color; @include media-breakpoint-down(sm) { display: flex; diff --git a/app/finders/merge_requests_finder.rb b/app/finders/merge_requests_finder.rb index 87c190bdc45..9f9e2afa7fe 100644 --- a/app/finders/merge_requests_finder.rb +++ b/app/finders/merge_requests_finder.rb @@ -57,7 +57,7 @@ class MergeRequestsFinder < IssuableFinder end def params_class - MergeRequestsFinder::Params + MergeRequestsFinder.const_get(:Params, false) # rubocop: disable CodeReuse/Finder end def filter_items(_items) diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index efe5789e49a..e9128252eb2 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -389,12 +389,8 @@ module Ci end after_transition any => [:skipped, :canceled] do |build, transition| - if Feature.enabled?(:cd_skipped_deployment_status, build.project) - if transition.to_name == :skipped - build.deployment&.skip - else - build.deployment&.cancel - end + if transition.to_name == :skipped + build.deployment&.skip else build.deployment&.cancel end diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 02ea8948419..6f7b377ee52 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -28,7 +28,7 @@ class Namespace < ApplicationRecord has_many :runner_namespaces, inverse_of: :namespace, class_name: 'Ci::RunnerNamespace' has_many :runners, through: :runner_namespaces, source: :runner, class_name: 'Ci::Runner' - has_many :namespace_onboarding_actions + has_one :onboarding_progress # This should _not_ be `inverse_of: :namespace`, because that would also set # `user.namespace` when this user creates a group with themselves as `owner`. diff --git a/app/models/namespace_onboarding_action.rb b/app/models/namespace_onboarding_action.rb deleted file mode 100644 index 2b0d6cad02d..00000000000 --- a/app/models/namespace_onboarding_action.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -class NamespaceOnboardingAction < ApplicationRecord - belongs_to :namespace, optional: false - - validates :action, presence: true - - ACTIONS = { - subscription_created: 1, - git_write: 2, - merge_request_created: 3, - git_read: 4, - pipeline_created: 5, - user_added: 6 - }.freeze - - # The monitoring window prevents the recording of a namespace_onboarding_action if a namespace is created before this - # time span. We are not interested in older namspaces, because the purpose of this table is to monitor and act on the - # progress of newly created namespaces or namespaces that already have at least one recorded action. - MONITORING_WINDOW = 90.days - - enum action: ACTIONS - - class << self - def completed?(namespace, action) - where(namespace: namespace, action: action).exists? - end - - def create_action(namespace, action) - return unless namespace.root? - return if namespace.created_at < MONITORING_WINDOW.ago && !namespace.namespace_onboarding_actions.exists? - - NamespaceOnboardingAction.safe_find_or_create_by(namespace: namespace, action: action) - end - end -end diff --git a/app/models/onboarding_progress.rb b/app/models/onboarding_progress.rb new file mode 100644 index 00000000000..419bbd595e9 --- /dev/null +++ b/app/models/onboarding_progress.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +class OnboardingProgress < ApplicationRecord + belongs_to :namespace, optional: false + + validate :namespace_is_root_namespace + + ACTIONS = [ + :git_pull, + :git_write, + :merge_request_created, + :pipeline_created, + :user_added, + :trial_started, + :subscription_created, + :required_mr_approvals_enabled, + :code_owners_enabled, + :scoped_label_created, + :security_scan_enabled, + :issue_auto_closed, + :repository_imported, + :repository_mirrored + ].freeze + + class << self + def onboard(namespace) + return unless root_namespace?(namespace) + + safe_find_or_create_by(namespace: namespace) + end + + def register(namespace, action) + return unless root_namespace?(namespace) && ACTIONS.include?(action) + + action_column = column_name(action) + onboarding_progress = find_by(namespace: namespace, action_column => nil) + onboarding_progress&.update!(action_column => Time.current) + end + + def completed?(namespace, action) + return unless root_namespace?(namespace) && ACTIONS.include?(action) + + action_column = column_name(action) + where(namespace: namespace).where.not(action_column => nil).exists? + end + + private + + def column_name(action) + :"#{action}_at" + end + + def root_namespace?(namespace) + namespace && namespace.root? + end + end + + private + + def namespace_is_root_namespace + return unless namespace + + errors.add(:namespace, _('must be a root namespace')) if namespace.has_parent? + end +end diff --git a/app/services/groups/create_service.rb b/app/services/groups/create_service.rb index 52600f5b88f..06a3b31c665 100644 --- a/app/services/groups/create_service.rb +++ b/app/services/groups/create_service.rb @@ -35,6 +35,7 @@ module Groups @group.add_owner(current_user) @group.create_namespace_settings Service.create_from_active_default_integrations(@group, :group_id) + OnboardingProgress.onboard(@group) end end diff --git a/app/services/merge_requests/after_create_service.rb b/app/services/merge_requests/after_create_service.rb index 5313afd62b4..03fcb5a4c1b 100644 --- a/app/services/merge_requests/after_create_service.rb +++ b/app/services/merge_requests/after_create_service.rb @@ -13,7 +13,7 @@ module MergeRequests merge_request.diffs(include_stats: false).write_cache merge_request.create_cross_references!(current_user) - NamespaceOnboardingAction.create_action(merge_request.target_project.namespace, :merge_request_created) + OnboardingProgressService.new(merge_request.target_project.namespace).execute(action: :merge_request_created) end end end diff --git a/app/services/onboarding_progress_service.rb b/app/services/onboarding_progress_service.rb index fe00c96ed4c..241bd8a01ca 100644 --- a/app/services/onboarding_progress_service.rb +++ b/app/services/onboarding_progress_service.rb @@ -8,6 +8,6 @@ class OnboardingProgressService def execute(action:) return unless @namespace - NamespaceOnboardingAction.create_action(@namespace, action) + OnboardingProgress.register(@namespace, action) end end diff --git a/app/services/post_receive_service.rb b/app/services/post_receive_service.rb index bd9588844ad..84d9db5435b 100644 --- a/app/services/post_receive_service.rb +++ b/app/services/post_receive_service.rb @@ -94,7 +94,7 @@ class PostReceiveService end def record_onboarding_progress - NamespaceOnboardingAction.create_action(project.namespace, :git_write) + OnboardingProgressService.new(project.namespace).execute(action: :git_write) end end diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml index 43f1011a85b..dd2c5e2a19e 100644 --- a/app/views/layouts/nav/_breadcrumbs.html.haml +++ b/app/views/layouts/nav/_breadcrumbs.html.haml @@ -8,7 +8,7 @@ - if defined?(@left_sidebar) = button_tag class: 'toggle-mobile-nav', type: 'button' do %span.sr-only= _("Open sidebar") - = sprite_icon('hamburger') + = sprite_icon('hamburger', size: 18) .breadcrumbs-links.js-title-container{ data: { qa_selector: 'breadcrumb_links_content' } } %ul.list-unstyled.breadcrumbs-list.js-breadcrumbs-list - unless hide_top_links diff --git a/app/views/profiles/chat_names/index.html.haml b/app/views/profiles/chat_names/index.html.haml index e0b0f839455..782850afcda 100644 --- a/app/views/profiles/chat_names/index.html.haml +++ b/app/views/profiles/chat_names/index.html.haml @@ -9,7 +9,7 @@ = _('You can see your chat accounts.') .col-lg-8 - %h5 Active chat names (#{@chat_names.size}) + %h5.gl-mt-0 Active chat names (#{@chat_names.size}) - if @chat_names.present? .table-responsive diff --git a/changelogs/unreleased/294127-follow-up-investigate-whether-we-should-convert-namespace_onboardi.yml b/changelogs/unreleased/294127-follow-up-investigate-whether-we-should-convert-namespace_onboardi.yml new file mode 100644 index 00000000000..2688be6609f --- /dev/null +++ b/changelogs/unreleased/294127-follow-up-investigate-whether-we-should-convert-namespace_onboardi.yml @@ -0,0 +1,5 @@ +--- +title: Change onboarding actions table to use one record per namespace +merge_request: 50711 +author: +type: changed diff --git a/changelogs/unreleased/fix-color-of-hamburger-in-darkmode.yml b/changelogs/unreleased/fix-color-of-hamburger-in-darkmode.yml new file mode 100644 index 00000000000..f968a43485f --- /dev/null +++ b/changelogs/unreleased/fix-color-of-hamburger-in-darkmode.yml @@ -0,0 +1,5 @@ +--- +title: Fix color of hamburger in dark mode +merge_request: 51168 +author: Kev @KevSlashNull +type: fixed diff --git a/changelogs/unreleased/remove-feature-flag-cd_skipped_deployment_status.yml b/changelogs/unreleased/remove-feature-flag-cd_skipped_deployment_status.yml new file mode 100644 index 00000000000..6edfa7c9713 --- /dev/null +++ b/changelogs/unreleased/remove-feature-flag-cd_skipped_deployment_status.yml @@ -0,0 +1,5 @@ +--- +title: Add skipped status to deployments +merge_request: 51068 +author: +type: added diff --git a/changelogs/unreleased/yo-master-patch-07160.yml b/changelogs/unreleased/yo-master-patch-07160.yml new file mode 100644 index 00000000000..de1a072869d --- /dev/null +++ b/changelogs/unreleased/yo-master-patch-07160.yml @@ -0,0 +1,5 @@ +--- +title: Add margin to user chat settings +merge_request: 51282 +author: Yogi (@yo) +type: fixed diff --git a/config/feature_flags/development/cd_skipped_deployment_status.yml b/config/feature_flags/development/cd_skipped_deployment_status.yml deleted file mode 100644 index 45d9538ebfc..00000000000 --- a/config/feature_flags/development/cd_skipped_deployment_status.yml +++ /dev/null @@ -1,7 +0,0 @@ -name: cd_skipped_deployment_status -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46614 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/283884 -milestone: '13.6' -type: development -group: group::release -default_enabled: false diff --git a/config/feature_flags/experiment/invite_members_version_a_experiment_percentage.yml b/config/feature_flags/experiment/invite_members_version_a_experiment_percentage.yml index b284a0e2f78..d20cb10fcda 100644 --- a/config/feature_flags/experiment/invite_members_version_a_experiment_percentage.yml +++ b/config/feature_flags/experiment/invite_members_version_a_experiment_percentage.yml @@ -1,8 +1,8 @@ --- name: invite_members_version_a_experiment_percentage -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45689/ -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/219239 -milestone: '13.6' +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33210 +rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/299 +milestone: '13.1' type: experiment group: group::expansion default_enabled: false diff --git a/db/migrate/20201230180202_create_onboarding_progress.rb b/db/migrate/20201230180202_create_onboarding_progress.rb new file mode 100644 index 00000000000..b9fe64eb19d --- /dev/null +++ b/db/migrate/20201230180202_create_onboarding_progress.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +class CreateOnboardingProgress < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def up + with_lock_retries do + create_table :onboarding_progresses do |t| + t.references :namespace, null: false, index: { unique: true }, foreign_key: { on_delete: :cascade } + t.timestamps_with_timezone null: false + t.datetime_with_timezone :git_pull_at + t.datetime_with_timezone :git_write_at + t.datetime_with_timezone :merge_request_created_at + t.datetime_with_timezone :pipeline_created_at + t.datetime_with_timezone :user_added_at + t.datetime_with_timezone :trial_started_at + t.datetime_with_timezone :subscription_created_at + t.datetime_with_timezone :required_mr_approvals_enabled_at + t.datetime_with_timezone :code_owners_enabled_at + t.datetime_with_timezone :scoped_label_created_at + t.datetime_with_timezone :security_scan_enabled_at + t.datetime_with_timezone :issue_auto_closed_at + t.datetime_with_timezone :repository_imported_at + t.datetime_with_timezone :repository_mirrored_at + end + end + end + + def down + with_lock_retries do + drop_table :onboarding_progresses + end + end +end diff --git a/db/schema_migrations/20201230180202 b/db/schema_migrations/20201230180202 new file mode 100644 index 00000000000..62a0e277a55 --- /dev/null +++ b/db/schema_migrations/20201230180202 @@ -0,0 +1 @@ +c2766b50914c6b4d8c96fb958cdfb67f0d29e40df45654c35d62792c272e3d5a
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 0a66608ba32..bba1aee901d 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -14491,6 +14491,36 @@ CREATE SEQUENCE oauth_openid_requests_id_seq ALTER SEQUENCE oauth_openid_requests_id_seq OWNED BY oauth_openid_requests.id; +CREATE TABLE onboarding_progresses ( + id bigint NOT NULL, + namespace_id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + git_pull_at timestamp with time zone, + git_write_at timestamp with time zone, + merge_request_created_at timestamp with time zone, + pipeline_created_at timestamp with time zone, + user_added_at timestamp with time zone, + trial_started_at timestamp with time zone, + subscription_created_at timestamp with time zone, + required_mr_approvals_enabled_at timestamp with time zone, + code_owners_enabled_at timestamp with time zone, + scoped_label_created_at timestamp with time zone, + security_scan_enabled_at timestamp with time zone, + issue_auto_closed_at timestamp with time zone, + repository_imported_at timestamp with time zone, + repository_mirrored_at timestamp with time zone +); + +CREATE SEQUENCE onboarding_progresses_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +ALTER SEQUENCE onboarding_progresses_id_seq OWNED BY onboarding_progresses.id; + CREATE TABLE open_project_tracker_data ( id bigint NOT NULL, service_id integer NOT NULL, @@ -18715,6 +18745,8 @@ ALTER TABLE ONLY oauth_applications ALTER COLUMN id SET DEFAULT nextval('oauth_a ALTER TABLE ONLY oauth_openid_requests ALTER COLUMN id SET DEFAULT nextval('oauth_openid_requests_id_seq'::regclass); +ALTER TABLE ONLY onboarding_progresses ALTER COLUMN id SET DEFAULT nextval('onboarding_progresses_id_seq'::regclass); + ALTER TABLE ONLY open_project_tracker_data ALTER COLUMN id SET DEFAULT nextval('open_project_tracker_data_id_seq'::regclass); ALTER TABLE ONLY operations_feature_flag_scopes ALTER COLUMN id SET DEFAULT nextval('operations_feature_flag_scopes_id_seq'::regclass); @@ -20052,6 +20084,9 @@ ALTER TABLE ONLY oauth_applications ALTER TABLE ONLY oauth_openid_requests ADD CONSTRAINT oauth_openid_requests_pkey PRIMARY KEY (id); +ALTER TABLE ONLY onboarding_progresses + ADD CONSTRAINT onboarding_progresses_pkey PRIMARY KEY (id); + ALTER TABLE ONLY open_project_tracker_data ADD CONSTRAINT open_project_tracker_data_pkey PRIMARY KEY (id); @@ -22254,6 +22289,8 @@ CREATE INDEX index_on_users_lower_username ON users USING btree (lower((username CREATE INDEX index_on_users_name_lower ON users USING btree (lower((name)::text)); +CREATE UNIQUE INDEX index_onboarding_progresses_on_namespace_id ON onboarding_progresses USING btree (namespace_id); + CREATE INDEX index_open_project_tracker_data_on_service_id ON open_project_tracker_data USING btree (service_id); CREATE INDEX index_operations_feature_flags_issues_on_issue_id ON operations_feature_flags_issues USING btree (issue_id); @@ -24465,6 +24502,9 @@ ALTER TABLE ONLY geo_repository_updated_events ALTER TABLE ONLY boards_epic_board_labels ADD CONSTRAINT fk_rails_2bedeb8799 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE; +ALTER TABLE ONLY onboarding_progresses + ADD CONSTRAINT fk_rails_2ccfd420cc FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE; + ALTER TABLE ONLY protected_branch_unprotect_access_levels ADD CONSTRAINT fk_rails_2d2aba21ef FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md index 4aa857ba77f..148953dc418 100644 --- a/doc/development/geo/framework.md +++ b/doc/development/geo/framework.md @@ -287,7 +287,7 @@ For example, to add support for files referenced by a `Widget` model with a t.datetime_with_timezone :created_at, null: false t.text :last_sync_failure - t.index :widget_id, name: :index_widget_registry_on_widget_id + t.index :widget_id, name: :index_widget_registry_on_widget_id, unique: true t.index :retry_at t.index :state end diff --git a/package.json b/package.json index ac5cf111e6c..516d8f4c565 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "@gitlab/favicon-overlay": "2.0.0", "@gitlab/svgs": "1.178.0", "@gitlab/tributejs": "1.0.0", - "@gitlab/ui": "25.4.0", + "@gitlab/ui": "25.7.2", "@gitlab/visual-review-tools": "1.6.1", "@rails/actioncable": "^6.0.3-4", "@rails/ujs": "^6.0.3-4", diff --git a/spec/controllers/repositories/git_http_controller_spec.rb b/spec/controllers/repositories/git_http_controller_spec.rb index 551abf9241d..34052496871 100644 --- a/spec/controllers/repositories/git_http_controller_spec.rb +++ b/spec/controllers/repositories/git_http_controller_spec.rb @@ -52,7 +52,7 @@ RSpec.describe Repositories::GitHttpController do }.from(0).to(1) end - it 'records a namespace onboarding progress action' do + it 'records an onboarding progress action' do expect_next_instance_of(OnboardingProgressService) do |service| expect(service).to receive(:execute).with(action: :git_read) end diff --git a/spec/factories/namespace_onboarding_actions.rb b/spec/factories/namespace_onboarding_actions.rb deleted file mode 100644 index aca62013b57..00000000000 --- a/spec/factories/namespace_onboarding_actions.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true - -FactoryBot.define do - factory :namespace_onboarding_action do - namespace - action { :subscription_created } - end -end diff --git a/spec/factories/onboarding_progresses.rb b/spec/factories/onboarding_progresses.rb new file mode 100644 index 00000000000..e39bad91b19 --- /dev/null +++ b/spec/factories/onboarding_progresses.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :onboarding_progress do + namespace + end +end diff --git a/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap b/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap index 8948a9926bb..1eb9ccc9c6c 100644 --- a/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap +++ b/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap @@ -4,6 +4,7 @@ exports[`AddContextCommitsModal renders modal with 2 tabs 1`] = ` <gl-modal-stub body-class="add-review-item pt-0" cancel-variant="light" + dismisslabel="Close" modalclass="" modalid="add-review-item" ok-disabled="true" diff --git a/spec/frontend/blob/pipeline_tour_success_modal_spec.js b/spec/frontend/blob/pipeline_tour_success_modal_spec.js index 75a8994be4d..d4562019302 100644 --- a/spec/frontend/blob/pipeline_tour_success_modal_spec.js +++ b/spec/frontend/blob/pipeline_tour_success_modal_spec.js @@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils'; import Cookies from 'js-cookie'; import { GlSprintf, GlModal, GlLink } from '@gitlab/ui'; import { mockTracking, triggerEvent, unmockTracking } from 'helpers/tracking_helper'; +import { stubComponent } from 'helpers/stub_component'; import pipelineTourSuccess from '~/blob/pipeline_tour_success_modal.vue'; import modalProps from './pipeline_tour_success_mock_data'; @@ -15,7 +16,14 @@ describe('PipelineTourSuccessModal', () => { wrapper = shallowMount(pipelineTourSuccess, { propsData: modalProps, stubs: { - GlModal, + GlModal: stubComponent(GlModal, { + template: ` + <div> + <slot name="modal-title"></slot> + <slot></slot> + <slot name="modal-footer"></slot> + </div>`, + }), GlSprintf, GlEmoji, }, diff --git a/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap b/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap index f0eb54c1b3a..79ad5ad1bb9 100644 --- a/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap +++ b/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap @@ -52,6 +52,7 @@ exports[`Alert integration settings form should match the default snapshot 1`] = </gl-button-stub> <gl-modal-stub + dismisslabel="Close" modalclass="" modalid="resetWebhookModal" ok-title="Reset webhook URL" diff --git a/spec/frontend/invite_members/components/invite_members_modal_spec.js b/spec/frontend/invite_members/components/invite_members_modal_spec.js index 4eb1db70b11..fc039bdf6da 100644 --- a/spec/frontend/invite_members/components/invite_members_modal_spec.js +++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js @@ -68,7 +68,7 @@ describe('InviteMembersModal', () => { }); it('renders the modal with the correct title', () => { - expect(wrapper.attributes('title')).toBe('Invite team members'); + expect(wrapper.find(GlModal).props('title')).toBe('Invite team members'); }); it('renders the Cancel button text correctly', () => { diff --git a/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap b/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap index c51130dae00..b2df1ac5ab6 100644 --- a/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap +++ b/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap @@ -34,7 +34,7 @@ exports[`packages_list_app renders 1`] = ` class="svg-250 svg-content" > <img - alt="There are no packages yet" + alt="" class="gl-max-w-full" src="helpSvg" /> @@ -95,7 +95,7 @@ exports[`packages_list_app renders 1`] = ` class="svg-250 svg-content" > <img - alt="There are no Composer packages yet" + alt="" class="gl-max-w-full" src="helpSvg" /> @@ -156,7 +156,7 @@ exports[`packages_list_app renders 1`] = ` class="svg-250 svg-content" > <img - alt="There are no Conan packages yet" + alt="" class="gl-max-w-full" src="helpSvg" /> @@ -217,7 +217,7 @@ exports[`packages_list_app renders 1`] = ` class="svg-250 svg-content" > <img - alt="There are no Generic packages yet" + alt="" class="gl-max-w-full" src="helpSvg" /> @@ -278,7 +278,7 @@ exports[`packages_list_app renders 1`] = ` class="svg-250 svg-content" > <img - alt="There are no Maven packages yet" + alt="" class="gl-max-w-full" src="helpSvg" /> @@ -339,7 +339,7 @@ exports[`packages_list_app renders 1`] = ` class="svg-250 svg-content" > <img - alt="There are no NPM packages yet" + alt="" class="gl-max-w-full" src="helpSvg" /> @@ -400,7 +400,7 @@ exports[`packages_list_app renders 1`] = ` class="svg-250 svg-content" > <img - alt="There are no NuGet packages yet" + alt="" class="gl-max-w-full" src="helpSvg" /> @@ -461,7 +461,7 @@ exports[`packages_list_app renders 1`] = ` class="svg-250 svg-content" > <img - alt="There are no PyPI packages yet" + alt="" class="gl-max-w-full" src="helpSvg" /> diff --git a/spec/frontend/pipelines/test_reports/test_case_details_spec.js b/spec/frontend/pipelines/test_reports/test_case_details_spec.js index 9e66012818e..bfb8b43778d 100644 --- a/spec/frontend/pipelines/test_reports/test_case_details_spec.js +++ b/spec/frontend/pipelines/test_reports/test_case_details_spec.js @@ -44,7 +44,7 @@ describe('Test case details', () => { }); it('renders the test case classname as modal title', () => { - expect(findModal().attributes('title')).toBe(defaultTestCase.classname); + expect(findModal().props('title')).toBe(defaultTestCase.classname); }); it('renders the test case name', () => { diff --git a/spec/frontend/profile/account/components/update_username_spec.js b/spec/frontend/profile/account/components/update_username_spec.js index 45e5e0f885f..91c3c81ab30 100644 --- a/spec/frontend/profile/account/components/update_username_spec.js +++ b/spec/frontend/profile/account/components/update_username_spec.js @@ -84,7 +84,7 @@ describe('UpdateUsername component', () => { it('confirmation modal contains proper header and body', async () => { const { modal } = findElements(); - expect(modal.attributes('title')).toBe('Change username?'); + expect(modal.props('title')).toBe('Change username?'); expect(modal.text()).toContain( `You are going to change the username ${defaultProps.initialUsername} to ${newUsername}`, ); diff --git a/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap b/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap index 4eb5060cb0a..0b9f095a700 100644 --- a/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap +++ b/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap @@ -31,6 +31,7 @@ exports[`Project remove modal initialized matches the snapshot 1`] = ` <gl-modal-stub actioncancel="[object Object]" actionprimary="[object Object]" + dismisslabel="Close" footer-class="gl-bg-gray-10 gl-p-5" modalclass="" modalid="fakeUniqueId" diff --git a/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap b/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap index 4630415f61c..dd54db7dc0a 100644 --- a/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap +++ b/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap @@ -29,24 +29,12 @@ exports[`Project remove modal intialized matches the snapshot 1`] = ` Delete project </gl-button-stub> - <b-modal-stub - canceltitle="Cancel" - cancelvariant="secondary" - footerclass="gl-bg-gray-10 gl-p-5" - headerclosecontent="×" - headercloselabel="Close" - id="delete-project-modal-2" - ignoreenforcefocusselector="" - lazy="true" - modalclass="gl-modal," - oktitle="OK" - okvariant="danger" - size="sm" - title="" - titleclass="gl-text-red-500" - titletag="h4" + <div + footer-class="gl-bg-gray-10 gl-p-5" + ok-variant="danger" + title-class="gl-text-red-500" > - + Delete project. Are you ABSOLUTELY SURE? <div> <p @@ -70,49 +58,6 @@ exports[`Project remove modal intialized matches the snapshot 1`] = ` /> </div> - - <template /> - - <template> - Delete project. Are you ABSOLUTELY SURE? - </template> - - <template /> - - <template /> - - <template /> - - <template> - <gl-button-stub - buttontextclasses="" - category="primary" - class="js-modal-action-cancel" - icon="" - size="medium" - variant="default" - > - - Cancel, keep project - - </gl-button-stub> - - <!----> - - <gl-button-stub - buttontextclasses="" - category="primary" - class="js-modal-action-primary" - disabled="true" - icon="" - size="medium" - variant="danger" - > - - Yes, delete project - - </gl-button-stub> - </template> - </b-modal-stub> + </div> </form> `; diff --git a/spec/frontend/projects/components/shared/delete_button_spec.js b/spec/frontend/projects/components/shared/delete_button_spec.js index a6394a50011..cf7e41a2df2 100644 --- a/spec/frontend/projects/components/shared/delete_button_spec.js +++ b/spec/frontend/projects/components/shared/delete_button_spec.js @@ -1,5 +1,6 @@ import { shallowMount } from '@vue/test-utils'; import { GlModal } from '@gitlab/ui'; +import { stubComponent } from 'helpers/stub_component'; import SharedDeleteButton from '~/projects/components/shared/delete_button.vue'; jest.mock('~/lib/utils/csrf', () => ({ token: 'test-csrf-token' })); @@ -17,12 +18,19 @@ describe('Project remove modal', () => { formPath: 'some/path', }; - const createComponent = (data = {}) => { + const createComponent = (data = {}, stubs = {}) => { wrapper = shallowMount(SharedDeleteButton, { propsData: defaultProps, data: () => data, stubs: { - GlModal, + GlModal: stubComponent(GlModal, { + template: ` + <div> + <slot name="modal-title"></slot> + <slot></slot> + </div>`, + }), + ...stubs, }, }); }; @@ -52,7 +60,7 @@ describe('Project remove modal', () => { describe('when the user input does not match the confirmPhrase', () => { beforeEach(() => { - createComponent({ userInput: 'bar' }); + createComponent({ userInput: 'bar' }, { GlModal }); }); it('the confirm button is disabled', () => { @@ -62,7 +70,7 @@ describe('Project remove modal', () => { describe('when the user input matches the confirmPhrase', () => { beforeEach(() => { - createComponent({ userInput: defaultProps.confirmPhrase }); + createComponent({ userInput: defaultProps.confirmPhrase }, { GlModal }); }); it('the confirm button is not disabled', () => { diff --git a/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap b/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap index 02d5ca6bdb3..bd05eb69080 100644 --- a/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap +++ b/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap @@ -60,6 +60,7 @@ exports[`self monitor component When the self monitor project has not been creat <gl-modal-stub cancel-title="Cancel" category="primary" + dismisslabel="Close" modalclass="" modalid="delete-self-monitor-modal" ok-title="Delete project" diff --git a/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap b/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap index 6b3d65ff037..4b827301943 100644 --- a/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap +++ b/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap @@ -3,7 +3,7 @@ exports[`EmptyStateComponent should render content 1`] = ` "<section class=\\"row empty-state text-center\\"> <div class=\\"col-12\\"> - <div class=\\"svg-250 svg-content\\"><img src=\\"/image.svg\\" alt=\\"Getting started with serverless\\" class=\\"gl-max-w-full\\"></div> + <div class=\\"svg-250 svg-content\\"><img src=\\"/image.svg\\" alt=\\"\\" class=\\"gl-max-w-full\\"></div> </div> <div class=\\"col-12\\"> <div class=\\"text-content gl-mx-auto gl-my-0 gl-p-5\\"> diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index bb3228c2bf0..e18abcc2c7a 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -1183,26 +1183,12 @@ RSpec.describe Ci::Build do end context 'when transits to skipped' do - context 'when cd_skipped_deployment_status is disabled' do - before do - stub_feature_flags(cd_skipped_deployment_status: false) - build.skip! - end - - it 'transits deployment status to canceled' do - expect(deployment).to be_canceled - end + before do + build.skip! end - context 'when cd_skipped_deployment_status is enabled' do - before do - stub_feature_flags(cd_skipped_deployment_status: project) - build.skip! - end - - it 'transits deployment status to skipped' do - expect(deployment).to be_skipped - end + it 'transits deployment status to skipped' do + expect(deployment).to be_skipped end end diff --git a/spec/models/namespace_onboarding_action_spec.rb b/spec/models/namespace_onboarding_action_spec.rb deleted file mode 100644 index aba6b2061c3..00000000000 --- a/spec/models/namespace_onboarding_action_spec.rb +++ /dev/null @@ -1,79 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe NamespaceOnboardingAction do - let(:namespace) { create(:namespace) } - - describe 'associations' do - it { is_expected.to belong_to(:namespace).required } - end - - describe 'validations' do - it { is_expected.to validate_presence_of(:action) } - end - - describe '.completed?' do - let(:action) { :subscription_created } - - subject { described_class.completed?(namespace, action) } - - context 'action created for the namespace' do - before do - create(:namespace_onboarding_action, namespace: namespace, action: action) - end - - it { is_expected.to eq(true) } - end - - context 'action created for another namespace' do - before do - create(:namespace_onboarding_action, namespace: build(:namespace), action: action) - end - - it { is_expected.to eq(false) } - end - end - - describe '.create_action' do - let(:action) { :subscription_created } - - subject(:create_action) { described_class.create_action(namespace, action) } - - it 'creates the action for the namespace just once' do - expect { create_action }.to change { count_namespace_actions }.by(1) - - expect { create_action }.to change { count_namespace_actions }.by(0) - end - - context 'when the namespace is created outside the monitoring window' do - let(:namespace) { create(:namespace, created_at: (NamespaceOnboardingAction::MONITORING_WINDOW + 1.day).ago) } - - it 'does not create an action for the namespace' do - expect { create_action }.not_to change { count_namespace_actions } - end - - context 'when an action has already been recorded for the namespace' do - before do - described_class.create!(namespace: namespace, action: :git_write) - end - - it 'creates an action for the namespace' do - expect { create_action }.to change { count_namespace_actions }.by(1) - end - end - end - - context 'when the namespace is not a root' do - let(:namespace) { create(:namespace, parent: build(:namespace)) } - - it 'does not create an action for the namespace' do - expect { create_action }.not_to change { count_namespace_actions } - end - end - - def count_namespace_actions - described_class.where(namespace: namespace, action: action).count - end - end -end diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index 1c72c1fc6a6..a3c0a43115e 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -19,8 +19,8 @@ RSpec.describe Namespace do it { is_expected.to have_one :aggregation_schedule } it { is_expected.to have_one :namespace_settings } it { is_expected.to have_many :custom_emoji } - it { is_expected.to have_many :namespace_onboarding_actions } it { is_expected.to have_one :package_setting_relation } + it { is_expected.to have_one :onboarding_progress } end describe 'validations' do diff --git a/spec/models/onboarding_progress_spec.rb b/spec/models/onboarding_progress_spec.rb new file mode 100644 index 00000000000..bd951846bb8 --- /dev/null +++ b/spec/models/onboarding_progress_spec.rb @@ -0,0 +1,107 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe OnboardingProgress do + let(:namespace) { create(:namespace) } + let(:action) { :subscription_created } + + describe 'associations' do + it { is_expected.to belong_to(:namespace).required } + end + + describe 'validations' do + describe 'namespace_is_root_namespace' do + subject(:onboarding_progress) { build(:onboarding_progress, namespace: namespace)} + + context 'when associated namespace is root' do + it { is_expected.to be_valid } + end + + context 'when associated namespace is not root' do + let(:namespace) { build(:group, :nested) } + + it 'is invalid' do + expect(onboarding_progress).to be_invalid + expect(onboarding_progress.errors[:namespace]).to include('must be a root namespace') + end + end + end + end + + describe '.onboard' do + subject(:onboard) { described_class.onboard(namespace) } + + it 'adds a record for the namespace' do + expect { onboard }.to change(described_class, :count).from(0).to(1) + end + + context 'when not given a namespace' do + let(:namespace) { nil } + + it 'does not add a record for the namespace' do + expect { onboard }.not_to change(described_class, :count).from(0) + end + end + + context 'when not given a root namespace' do + let(:namespace) { create(:namespace, parent: build(:namespace)) } + + it 'does not add a record for the namespace' do + expect { onboard }.not_to change(described_class, :count).from(0) + end + end + end + + describe '.register' do + subject(:register_action) { described_class.register(namespace, action) } + + context 'when the namespace was onboarded' do + before do + described_class.onboard(namespace) + end + + it 'registers the action for the namespace' do + expect { register_action }.to change { described_class.completed?(namespace, action) }.from(false).to(true) + end + + context 'when the action does not exist' do + let(:action) { :foo } + + it 'does not register the action for the namespace' do + expect { register_action }.not_to change { described_class.completed?(namespace, action) }.from(nil) + end + end + end + + context 'when the namespace was not onboarded' do + it 'does not register the action for the namespace' do + expect { register_action }.not_to change { described_class.completed?(namespace, action) }.from(false) + end + end + end + + describe '.completed?' do + subject { described_class.completed?(namespace, action) } + + context 'when the namespace has not yet been onboarded' do + it { is_expected.to eq(false) } + end + + context 'when the namespace has been onboarded but not registered the action yet' do + before do + described_class.onboard(namespace) + end + + it { is_expected.to eq(false) } + + context 'when the action has been registered' do + before do + described_class.register(namespace, action) + end + + it { is_expected.to eq(true) } + end + end + end +end diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb index 4f5bc3a3d5a..f0cd42c1948 100644 --- a/spec/services/groups/create_service_spec.rb +++ b/spec/services/groups/create_service_spec.rb @@ -63,6 +63,10 @@ RSpec.describe Groups::CreateService, '#execute' do end it { is_expected.to be_persisted } + + it 'adds an onboarding progress record' do + expect { subject }.to change(OnboardingProgress, :count).from(0).to(1) + end end context 'when user can not create a group' do @@ -84,6 +88,10 @@ RSpec.describe Groups::CreateService, '#execute' do end it { is_expected.to be_persisted } + + it 'does not add an onboarding progress record' do + expect { subject }.not_to change(OnboardingProgress, :count).from(0) + end end context 'as guest' do diff --git a/spec/services/members/create_service_spec.rb b/spec/services/members/create_service_spec.rb index 7fd6b3e5b8d..50efee9f43c 100644 --- a/spec/services/members/create_service_spec.rb +++ b/spec/services/members/create_service_spec.rb @@ -13,14 +13,20 @@ RSpec.describe Members::CreateService, :clean_gitlab_redis_shared_state, :sideki subject(:execute_service) { described_class.new(user, params).execute(source) } before do - source.is_a?(Project) ? source.add_maintainer(user) : source.add_owner(user) + if source.is_a?(Project) + source.add_maintainer(user) + OnboardingProgress.onboard(source.namespace) + else + source.add_owner(user) + OnboardingProgress.onboard(source) + end end context 'when passing valid parameters' do it 'adds a user to members' do expect(execute_service[:status]).to eq(:success) expect(source.users).to include member - expect(NamespaceOnboardingAction.completed?(source.namespace, :user_added)).to be(true) + expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(true) end context 'when executing on a group' do @@ -29,7 +35,7 @@ RSpec.describe Members::CreateService, :clean_gitlab_redis_shared_state, :sideki it 'adds a user to members' do expect(execute_service[:status]).to eq(:success) expect(source.users).to include member - expect(NamespaceOnboardingAction.completed?(source, :user_added)).to be(true) + expect(OnboardingProgress.completed?(source, :user_added)).to be(true) end end end @@ -41,7 +47,7 @@ RSpec.describe Members::CreateService, :clean_gitlab_redis_shared_state, :sideki expect(execute_service[:status]).to eq(:error) expect(execute_service[:message]).to be_present expect(source.users).not_to include member - expect(NamespaceOnboardingAction.completed?(source.namespace, :user_added)).to be(false) + expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(false) end end @@ -52,7 +58,7 @@ RSpec.describe Members::CreateService, :clean_gitlab_redis_shared_state, :sideki expect(execute_service[:status]).to eq(:error) expect(execute_service[:message]).to be_present expect(source.users).not_to include member - expect(NamespaceOnboardingAction.completed?(source.namespace, :user_added)).to be(false) + expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(false) end end @@ -63,7 +69,7 @@ RSpec.describe Members::CreateService, :clean_gitlab_redis_shared_state, :sideki expect(execute_service[:status]).to eq(:error) expect(execute_service[:message]).to include("#{member.username}: Access level is not included in the list") expect(source.users).not_to include member - expect(NamespaceOnboardingAction.completed?(source.namespace, :user_added)).to be(false) + expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(false) end end @@ -73,7 +79,7 @@ RSpec.describe Members::CreateService, :clean_gitlab_redis_shared_state, :sideki it 'does not add a member' do expect(execute_service[:status]).to eq(:error) expect(execute_service[:message]).to eq('Invite email has already been taken') - expect(NamespaceOnboardingAction.completed?(source.namespace, :user_added)).to be(false) + expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(false) end end end diff --git a/spec/services/merge_requests/after_create_service_spec.rb b/spec/services/merge_requests/after_create_service_spec.rb index bdc064a6269..9ae310d8cee 100644 --- a/spec/services/merge_requests/after_create_service_spec.rb +++ b/spec/services/merge_requests/after_create_service_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe MergeRequests::AfterCreateService do + include AfterNextHelpers + let_it_be(:merge_request) { create(:merge_request) } subject(:after_create_service) do @@ -64,11 +66,15 @@ RSpec.describe MergeRequests::AfterCreateService do execute_service end - it 'records a namespace onboarding progress action' do - expect(NamespaceOnboardingAction).to receive(:create_action) - .with(merge_request.target_project.namespace, :merge_request_created).and_call_original + it 'registers an onboarding progress action' do + OnboardingProgress.onboard(merge_request.target_project.namespace) + + expect_next(OnboardingProgressService, merge_request.target_project.namespace) + .to receive(:execute).with(action: :merge_request_created).and_call_original + + execute_service - expect { execute_service }.to change(NamespaceOnboardingAction, :count).by(1) + expect(OnboardingProgress.completed?(merge_request.target_project.namespace, :merge_request_created)).to be(true) end end end diff --git a/spec/services/onboarding_progress_service_spec.rb b/spec/services/onboarding_progress_service_spec.rb index de4c0d2a3ba..340face4ae8 100644 --- a/spec/services/onboarding_progress_service_spec.rb +++ b/spec/services/onboarding_progress_service_spec.rb @@ -11,32 +11,38 @@ RSpec.describe OnboardingProgressService do subject(:execute_service) { described_class.new(namespace).execute(action: :subscription_created) } context 'when the namespace is a root' do - it 'records a namespace onboarding progress action fot the given namespace' do - expect(NamespaceOnboardingAction).to receive(:create_action) - .with(namespace, :subscription_created).and_call_original + before do + OnboardingProgress.onboard(namespace) + end + + it 'registers a namespace onboarding progress action for the given namespace' do + execute_service - expect { execute_service }.to change(NamespaceOnboardingAction, :count).by(1) + expect(OnboardingProgress.completed?(namespace, :subscription_created)).to eq(true) end end context 'when the namespace is not the root' do let(:root_namespace) { build(:namespace) } - it 'records a namespace onboarding progress action for the root namespace' do - expect(NamespaceOnboardingAction).to receive(:create_action) - .with(root_namespace, :subscription_created).and_call_original + before do + OnboardingProgress.onboard(root_namespace) + end + + it 'registers a namespace onboarding progress action for the root namespace' do + execute_service - expect { execute_service }.to change(NamespaceOnboardingAction, :count).by(1) + expect(OnboardingProgress.completed?(root_namespace, :subscription_created)).to eq(true) end end context 'when no namespace is passed' do let(:namespace) { nil } - it 'does not record a namespace onboarding progress action' do - expect(NamespaceOnboardingAction).not_to receive(:create_action) - + it 'does not register a namespace onboarding progress action' do execute_service + + expect(OnboardingProgress.completed?(root_namespace, :subscription_created)).to be(nil) end end end diff --git a/spec/services/post_receive_service_spec.rb b/spec/services/post_receive_service_spec.rb index 4e303bfc20a..6e2cd7edf04 100644 --- a/spec/services/post_receive_service_spec.rb +++ b/spec/services/post_receive_service_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe PostReceiveService do include Gitlab::Routing + include AfterNextHelpers let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, :repository, :wiki_repo, namespace: user.namespace) } @@ -46,8 +47,8 @@ RSpec.describe PostReceiveService do expect(subject).to be_empty end - it 'does not record a namespace onboarding progress action' do - expect(NamespaceOnboardingAction).not_to receive(:create_action) + it 'does not record an onboarding progress action' do + expect_next(OnboardingProgressService).not_to receive(:execute) subject end @@ -87,9 +88,9 @@ RSpec.describe PostReceiveService do expect(response.reference_counter_decreased).to be(true) end - it 'records a namespace onboarding progress action' do - expect(NamespaceOnboardingAction).to receive(:create_action) - .with(project.namespace, :git_write) + it 'records an onboarding progress action' do + expect_next(OnboardingProgressService, project.namespace) + .to receive(:execute).with(action: :git_write) subject end diff --git a/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb b/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb index 240a0b69834..f1789fa8fbd 100644 --- a/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb +++ b/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb @@ -7,20 +7,26 @@ RSpec.describe Namespaces::OnboardingPipelineCreatedWorker, '#perform' do let_it_be(:ci_pipeline) { create(:ci_pipeline) } - it 'records the event' do + before do + OnboardingProgress.onboard(ci_pipeline.project.namespace) + end + + it 'registers an onboarding progress action' do expect_next(OnboardingProgressService, ci_pipeline.project.namespace) .to receive(:execute).with(action: :pipeline_created).and_call_original - expect do - subject.perform(ci_pipeline.project.namespace_id) - end.to change(NamespaceOnboardingAction, :count).by(1) + subject.perform(ci_pipeline.project.namespace_id) + + expect(OnboardingProgress.completed?(ci_pipeline.project.namespace, :pipeline_created)).to eq(true) end context "when a namespace doesn't exist" do - it "does nothing" do + it 'does not register an onboarding progress action' do expect_next(OnboardingProgressService, ci_pipeline.project.namespace).not_to receive(:execute) - expect { subject.perform(nil) }.not_to change(NamespaceOnboardingAction, :count) + subject.perform(nil) + + expect(OnboardingProgress.completed?(ci_pipeline.project.namespace, :pipeline_created)).to eq(false) end end end diff --git a/spec/workers/namespaces/onboarding_user_added_worker_spec.rb b/spec/workers/namespaces/onboarding_user_added_worker_spec.rb index 03c668259f8..a773e160fab 100644 --- a/spec/workers/namespaces/onboarding_user_added_worker_spec.rb +++ b/spec/workers/namespaces/onboarding_user_added_worker_spec.rb @@ -7,10 +7,16 @@ RSpec.describe Namespaces::OnboardingUserAddedWorker, '#perform' do let_it_be(:group) { create(:group) } - it 'records the event' do + before do + OnboardingProgress.onboard(group) + end + + it 'registers an onboarding progress action' do expect_next(OnboardingProgressService, group) .to receive(:execute).with(action: :user_added).and_call_original - expect { subject.perform(group.id) }.to change(NamespaceOnboardingAction, :count).by(1) + subject.perform(group.id) + + expect(OnboardingProgress.completed?(group, :user_added)).to be(true) end end diff --git a/yarn.lock b/yarn.lock index 1520955baa6..df422680d02 100644 --- a/yarn.lock +++ b/yarn.lock @@ -876,10 +876,10 @@ resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8" integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw== -"@gitlab/ui@25.4.0": - version "25.4.0" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-25.4.0.tgz#67bfd2a905097fc4cec0272665c36c722b3475c9" - integrity sha512-/dffpdyDcX102wWTbzDQOmOGfAEyDitRWCBOk2U+WRKPJIsWYtZuw40putwNA/gUUE1U08TPHf3sGSLzwIKZPA== +"@gitlab/ui@25.7.2": + version "25.7.2" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-25.7.2.tgz#50271f99818645f9bc7ef675c08f9bf1bae54293" + integrity sha512-hgM9JHesIqnDujjJ16BHFQWYwzWd9php8xElhkGUdKWGV+PVw9TVdYcKfkIAb3TXtb9551uXN0Jv6wH5DRJyXw== dependencies: "@babel/standalone" "^7.0.0" "@gitlab/vue-toasted" "^1.3.0" |