Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
bc0c5df2f1
commit
97eb4a0095
39 changed files with 542 additions and 349 deletions
|
@ -333,10 +333,6 @@ Rails/TimeZone:
|
|||
- 'spec/tooling/rspec_flaky/listener_spec.rb'
|
||||
- 'spec/tooling/rspec_flaky/report_spec.rb'
|
||||
|
||||
# WIP: https://gitlab.com/gitlab-org/gitlab/-/issues/325836
|
||||
RSpec/EmptyLineAfterFinalLetItBe:
|
||||
Exclude:
|
||||
|
||||
RSpec/TimecopFreeze:
|
||||
Exclude:
|
||||
- 'ee/spec/controllers/admin/application_settings_controller_spec.rb'
|
||||
|
|
|
@ -4,12 +4,10 @@ import blankProjectIllustration from '@gitlab/svgs/dist/illustrations/project-cr
|
|||
import importProjectIllustration from '@gitlab/svgs/dist/illustrations/project-import-sm.svg';
|
||||
import ciCdProjectIllustration from '@gitlab/svgs/dist/illustrations/project-run-CICD-pipelines-sm.svg';
|
||||
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
|
||||
import { experiment } from '~/experimentation/utils';
|
||||
import { s__ } from '~/locale';
|
||||
import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue';
|
||||
import NewProjectPushTipPopover from './new_project_push_tip_popover.vue';
|
||||
|
||||
const NEW_REPO_EXPERIMENT = 'new_repo';
|
||||
const CI_CD_PANEL = 'cicd_for_external_repo';
|
||||
const PANELS = [
|
||||
{
|
||||
|
@ -79,28 +77,8 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
decoratedPanels() {
|
||||
const PANEL_TITLES = experiment(NEW_REPO_EXPERIMENT, {
|
||||
use: () => ({
|
||||
blank: s__('ProjectsNew|Create blank project'),
|
||||
import: s__('ProjectsNew|Import project'),
|
||||
}),
|
||||
try: () => ({
|
||||
blank: s__('ProjectsNew|Create blank project/repository'),
|
||||
import: s__('ProjectsNew|Import project/repository'),
|
||||
}),
|
||||
});
|
||||
|
||||
return PANELS.map(({ key, title, ...el }) => ({
|
||||
...el,
|
||||
title: PANEL_TITLES[key] ?? title,
|
||||
}));
|
||||
},
|
||||
|
||||
availablePanels() {
|
||||
return this.isCiCdAvailable
|
||||
? this.decoratedPanels
|
||||
: this.decoratedPanels.filter((p) => p.name !== CI_CD_PANEL);
|
||||
return this.isCiCdAvailable ? PANELS : PANELS.filter((p) => p.name !== CI_CD_PANEL);
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -112,7 +90,6 @@ export default {
|
|||
}
|
||||
},
|
||||
},
|
||||
EXPERIMENT: NEW_REPO_EXPERIMENT,
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -122,7 +99,6 @@ export default {
|
|||
:panels="availablePanels"
|
||||
:jump-to-last-persisted-panel="hasErrors"
|
||||
:title="s__('ProjectsNew|Create new project')"
|
||||
:experiment="$options.EXPERIMENT"
|
||||
persistence-key="new_project_last_active_tab"
|
||||
@panel-change="resetProjectErrors"
|
||||
>
|
||||
|
|
|
@ -16,14 +16,9 @@ export default {
|
|||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
experiment: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
created() {
|
||||
const trackingMixin = Tracking.mixin({ ...gon.tracking_data, experiment: this.experiment });
|
||||
const trackingMixin = Tracking.mixin();
|
||||
const trackingInstance = new Vue({
|
||||
...trackingMixin,
|
||||
render() {
|
||||
|
|
|
@ -36,11 +36,6 @@ export default {
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
experiment: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
|
@ -103,12 +98,7 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<welcome-page
|
||||
v-if="activePanelName === null"
|
||||
:panels="panels"
|
||||
:title="title"
|
||||
:experiment="experiment"
|
||||
>
|
||||
<welcome-page v-if="!activePanelName" :panels="panels" :title="title">
|
||||
<template #footer>
|
||||
<slot name="welcome-footer"> </slot>
|
||||
</template>
|
||||
|
|
|
@ -39,11 +39,6 @@ class ProjectsController < Projects::ApplicationController
|
|||
push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml)
|
||||
end
|
||||
|
||||
before_action only: [:new] do
|
||||
# Run experiment before render so it will be written to the `gon` for FE
|
||||
helpers.new_repo_experiment_text
|
||||
end
|
||||
|
||||
layout :determine_layout
|
||||
|
||||
feature_category :projects, [
|
||||
|
@ -78,7 +73,6 @@ class ProjectsController < Projects::ApplicationController
|
|||
@project = ::Projects::CreateService.new(current_user, project_params(attributes: project_params_create_attributes)).execute
|
||||
|
||||
if @project.saved?
|
||||
experiment(:new_repo, user: current_user).track(:project_created)
|
||||
experiment(:new_project_readme, actor: current_user).track(
|
||||
:created,
|
||||
property: active_new_project_tab,
|
||||
|
|
|
@ -240,8 +240,7 @@ module EventsHelper
|
|||
DESIGN_ICONS = {
|
||||
'created' => 'upload',
|
||||
'updated' => 'pencil',
|
||||
'destroyed' => ICON_NAMES_BY_EVENT_TYPE['destroyed'],
|
||||
'archived' => 'archive'
|
||||
'destroyed' => ICON_NAMES_BY_EVENT_TYPE['destroyed']
|
||||
}.freeze
|
||||
|
||||
def design_event_icon(action, size: 24)
|
||||
|
|
|
@ -21,13 +21,6 @@ module Nav
|
|||
}
|
||||
end
|
||||
|
||||
def new_repo_experiment_text
|
||||
experiment(:new_repo, user: current_user) do |e|
|
||||
e.use { _('New project') }
|
||||
e.try { _('New project/repository') }
|
||||
end.run
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def group_menu_section(group)
|
||||
|
@ -37,9 +30,9 @@ module Nav
|
|||
menu_items.push(
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
id: 'new_project',
|
||||
title: new_repo_experiment_text,
|
||||
title: _('New project/repository'),
|
||||
href: new_project_path(namespace_id: group.id),
|
||||
data: { track_experiment: 'new_repo', track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' }
|
||||
data: { track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' }
|
||||
)
|
||||
)
|
||||
end
|
||||
|
@ -129,9 +122,9 @@ module Nav
|
|||
menu_items.push(
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
id: 'general_new_project',
|
||||
title: new_repo_experiment_text,
|
||||
title: _('New project/repository'),
|
||||
href: new_project_path,
|
||||
data: { track_experiment: 'new_repo', track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' }
|
||||
data: { track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' }
|
||||
)
|
||||
)
|
||||
end
|
||||
|
|
|
@ -98,7 +98,7 @@ module Nav
|
|||
builder.add_primary_menu_item_with_shortcut(
|
||||
active: nav == 'project' || active_nav_link?(path: %w[root#index projects#trending projects#starred dashboard/projects#index]),
|
||||
css_class: 'qa-projects-dropdown',
|
||||
data: { track_label: "projects_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" },
|
||||
data: { track_label: "projects_dropdown", track_event: "click_dropdown" },
|
||||
view: PROJECTS_VIEW,
|
||||
shortcut_href: dashboard_projects_path,
|
||||
**projects_menu_item_attrs
|
||||
|
|
7
app/models/error_tracking.rb
Normal file
7
app/models/error_tracking.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module ErrorTracking
|
||||
def self.table_name_prefix
|
||||
'error_tracking_'
|
||||
end
|
||||
end
|
12
app/models/error_tracking/error.rb
Normal file
12
app/models/error_tracking/error.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ErrorTracking::Error < ApplicationRecord
|
||||
belongs_to :project
|
||||
|
||||
has_many :events, class_name: 'ErrorTracking::ErrorEvent'
|
||||
|
||||
validates :project, presence: true
|
||||
validates :name, presence: true
|
||||
validates :description, presence: true
|
||||
validates :actor, presence: true
|
||||
end
|
11
app/models/error_tracking/error_event.rb
Normal file
11
app/models/error_tracking/error_event.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ErrorTracking::ErrorEvent < ApplicationRecord
|
||||
belongs_to :error
|
||||
|
||||
validates :payload, json_schema: { filename: 'error_tracking_event_payload' }
|
||||
|
||||
validates :error, presence: true
|
||||
validates :description, presence: true
|
||||
validates :occurred_at, presence: true
|
||||
end
|
|
@ -24,6 +24,8 @@ module ErrorTracking
|
|||
self.reactive_cache_key = ->(setting) { [setting.class.model_name.singular, setting.project_id] }
|
||||
self.reactive_cache_work_type = :external_dependency
|
||||
|
||||
self.table_name = 'project_error_tracking_settings'
|
||||
|
||||
belongs_to :project
|
||||
|
||||
validates :api_url, length: { maximum: 255 }, public_url: { enforce_sanitization: true, ascii_only: true }, allow_nil: true
|
||||
|
|
|
@ -24,15 +24,14 @@ class Event < ApplicationRecord
|
|||
left: 9, # User left project
|
||||
destroyed: 10,
|
||||
expired: 11, # User left project due to expiry
|
||||
approved: 12,
|
||||
archived: 13 # Recoverable deletion
|
||||
approved: 12
|
||||
).freeze
|
||||
|
||||
private_constant :ACTIONS
|
||||
|
||||
WIKI_ACTIONS = [:created, :updated, :destroyed].freeze
|
||||
|
||||
DESIGN_ACTIONS = [:created, :updated, :destroyed, :archived].freeze
|
||||
DESIGN_ACTIONS = [:created, :updated, :destroyed].freeze
|
||||
|
||||
TARGET_TYPES = HashWithIndifferentAccess.new(
|
||||
issue: Issue,
|
||||
|
@ -437,8 +436,7 @@ class Event < ApplicationRecord
|
|||
{
|
||||
created: _('uploaded'),
|
||||
updated: _('revised'),
|
||||
destroyed: _('deleted'),
|
||||
archived: _('archived')
|
||||
destroyed: _('deleted')
|
||||
}
|
||||
end
|
||||
|
||||
|
|
324
app/validators/json_schemas/error_tracking_event_payload.json
Normal file
324
app/validators/json_schemas/error_tracking_event_payload.json
Normal file
|
@ -0,0 +1,324 @@
|
|||
{
|
||||
"description": "Error tracking event payload",
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"event_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"level": {
|
||||
"type": "string"
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "string"
|
||||
},
|
||||
"release": {
|
||||
"type": "string"
|
||||
},
|
||||
"environment": {
|
||||
"type": "string"
|
||||
},
|
||||
"server_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"user": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {}
|
||||
},
|
||||
"tags": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"request_id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"contexts": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"os": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"build": {
|
||||
"type": "string"
|
||||
},
|
||||
"kernel_version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"runtime": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"trace": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"trace_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"span_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"parent_span_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"op": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fingerprint": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"breadcrumbs": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"values": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"category": {
|
||||
"type": "string"
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"controller": {
|
||||
"type": "string"
|
||||
},
|
||||
"action": {
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"controller": {
|
||||
"type": "string"
|
||||
},
|
||||
"action": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"format": {
|
||||
"type": "string"
|
||||
},
|
||||
"method": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"start_timestamp": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
},
|
||||
"level": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "number"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"transaction": {
|
||||
"type": "string"
|
||||
},
|
||||
"platform": {
|
||||
"type": "string"
|
||||
},
|
||||
"sdk": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"method": {
|
||||
"type": "string"
|
||||
},
|
||||
"headers": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"Host": {
|
||||
"type": "string"
|
||||
},
|
||||
"User-Agent": {
|
||||
"type": "string"
|
||||
},
|
||||
"Accept": {
|
||||
"type": "string"
|
||||
},
|
||||
"Accept-Language": {
|
||||
"type": "string"
|
||||
},
|
||||
"Accept-Encoding": {
|
||||
"type": "string"
|
||||
},
|
||||
"Referer": {
|
||||
"type": "string"
|
||||
},
|
||||
"Turbolinks-Referrer": {
|
||||
"type": "string"
|
||||
},
|
||||
"Connection": {
|
||||
"type": "string"
|
||||
},
|
||||
"X-Request-Id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"SERVER_NAME": {
|
||||
"type": "string"
|
||||
},
|
||||
"SERVER_PORT": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"exception": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"values": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
},
|
||||
"module": {
|
||||
"type": "string"
|
||||
},
|
||||
"thread_id": {
|
||||
"type": "number"
|
||||
},
|
||||
"stacktrace": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"frames": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"project_root": {
|
||||
"type": "string"
|
||||
},
|
||||
"abs_path": {
|
||||
"type": "string"
|
||||
},
|
||||
"function": {
|
||||
"type": "string"
|
||||
},
|
||||
"lineno": {
|
||||
"type": "number"
|
||||
},
|
||||
"in_app": {
|
||||
"type": "string"
|
||||
},
|
||||
"filename": {
|
||||
"type": "string"
|
||||
},
|
||||
"pre_context": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"context_line": {
|
||||
"type": "string"
|
||||
},
|
||||
"post_context": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
- return if menu_sections.empty?
|
||||
|
||||
%li.header-new.dropdown{ class: top_class, data: { track_label: "new_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } }
|
||||
%li.header-new.dropdown{ class: top_class, data: { track_label: "new_dropdown", track_event: "click_dropdown" } }
|
||||
= link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip", id: "js-onboarding-new-project-link", title: title, ref: 'tooltip', aria: { label: title }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static', qa_selector: 'new_menu_toggle' } do
|
||||
= sprite_icon('plus-square')
|
||||
= sprite_icon('chevron-down', css_class: 'caret-down')
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
-# [1]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587
|
||||
%ul.list-unstyled.navbar-sub-nav
|
||||
- if dashboard_nav_link?(:projects)
|
||||
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects", data: { track_label: "projects_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } }) do
|
||||
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects", data: { track_label: "projects_dropdown", track_event: "click_dropdown" } }) do
|
||||
%button{ type: 'button', data: { toggle: "dropdown" } }
|
||||
= _('Projects')
|
||||
= sprite_icon('chevron-down', css_class: 'caret-down')
|
||||
|
|
|
@ -15,21 +15,12 @@
|
|||
= nav_link(path: 'projects#trending') do
|
||||
= link_to explore_root_path, data: { track_label: "projects_dropdown_explore_projects", track_event: "click_link" } do
|
||||
= _('Explore projects')
|
||||
- experiment(:new_repo, user: current_user) do |e|
|
||||
- e.use do
|
||||
= nav_link(path: 'projects/new#blank_project', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
|
||||
= link_to new_project_path(anchor: 'blank_project'), data: { track_label: "projects_dropdown_blank_project", track_event: "click_link", track_experiment: "new_repo", qa_selector: "create_project_link" } do
|
||||
= _('Create blank project')
|
||||
= nav_link(path: 'projects/new#import_project') do
|
||||
= link_to new_project_path(anchor: 'import_project'), data: { track_label: "projects_dropdown_import_project", track_event: "click_link", track_experiment: "new_repo", qa_selector: "import_project_link" } do
|
||||
= _('Import project')
|
||||
- e.try do
|
||||
= nav_link(path: 'projects/new#blank_project', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
|
||||
= link_to new_project_path(anchor: 'blank_project'), data: { track_label: "projects_dropdown_blank_project", track_event: "click_link", track_experiment: "new_repo" } do
|
||||
= _('Create blank project/repository')
|
||||
= nav_link(path: 'projects/new#import_project') do
|
||||
= link_to new_project_path(anchor: 'import_project'), data: { track_label: "projects_dropdown_import_project", track_event: "click_link", track_experiment: "new_repo" } do
|
||||
= _('Import project/repository')
|
||||
= nav_link(path: 'projects/new#blank_project', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
|
||||
= link_to new_project_path(anchor: 'blank_project'), data: { track_label: "projects_dropdown_blank_project", track_event: "click_link", qa_selector: "create_project_link" } do
|
||||
= _('Create blank project')
|
||||
= nav_link(path: 'projects/new#import_project') do
|
||||
= link_to new_project_path(anchor: 'import_project'), data: { track_label: "projects_dropdown_import_project", track_event: "click_link", qa_selector: "import_project_link" } do
|
||||
= _('Import project')
|
||||
= nav_link(path: 'projects/new#create_from_template') do
|
||||
= link_to new_project_path(anchor: 'create_from_template'), data: { track_label: "projects_dropdown_create_from_template", track_event: "click_link" } do
|
||||
= _('Create from template')
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: new_repo
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55818
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285153
|
||||
milestone: '13.11'
|
||||
type: experiment
|
||||
group: group::adoption
|
||||
default_enabled: false
|
28
db/migrate/20210623133635_create_error_tracking_errors.rb
Normal file
28
db/migrate/20210623133635_create_error_tracking_errors.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateErrorTrackingErrors < ActiveRecord::Migration[6.1]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
def up
|
||||
create_table_with_constraints :error_tracking_errors do |t|
|
||||
t.references :project, index: true, null: false, foreign_key: { on_delete: :cascade }
|
||||
t.text :name, null: false
|
||||
t.text :description, null: false
|
||||
t.text :actor, null: false
|
||||
t.datetime_with_timezone :first_seen_at, null: false, default: -> { 'NOW()' }
|
||||
t.datetime_with_timezone :last_seen_at, null: false, default: -> { 'NOW()' }
|
||||
t.text :platform
|
||||
|
||||
t.text_limit :name, 255
|
||||
t.text_limit :description, 1024
|
||||
t.text_limit :actor, 255
|
||||
t.text_limit :platform, 255
|
||||
|
||||
t.timestamps_with_timezone
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table :error_tracking_errors
|
||||
end
|
||||
end
|
|
@ -0,0 +1,30 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateErrorTrackingErrorEvents < ActiveRecord::Migration[6.1]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
def up
|
||||
create_table_with_constraints :error_tracking_error_events do |t|
|
||||
t.references :error,
|
||||
index: true,
|
||||
null: false,
|
||||
foreign_key: { on_delete: :cascade, to_table: :error_tracking_errors }
|
||||
|
||||
t.text :description, null: false
|
||||
t.text :environment
|
||||
t.text :level
|
||||
t.datetime_with_timezone :occurred_at, null: false
|
||||
t.jsonb :payload, null: false, default: {}
|
||||
|
||||
t.text_limit :description, 255
|
||||
t.text_limit :environment, 255
|
||||
t.text_limit :level, 255
|
||||
|
||||
t.timestamps_with_timezone
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table :error_tracking_error_events
|
||||
end
|
||||
end
|
1
db/schema_migrations/20210623133635
Normal file
1
db/schema_migrations/20210623133635
Normal file
|
@ -0,0 +1 @@
|
|||
1a930fec524c91c5d382c40514d0d1943e59514f5dbd8588595363c24819b8d0
|
1
db/schema_migrations/20210625094554
Normal file
1
db/schema_migrations/20210625094554
Normal file
|
@ -0,0 +1 @@
|
|||
df9e976b0f294284ad9e9b617da42310c83cb1acc6db6ea00ea93c49c2310a1c
|
|
@ -12732,6 +12732,56 @@ CREATE SEQUENCE epics_id_seq
|
|||
|
||||
ALTER SEQUENCE epics_id_seq OWNED BY epics.id;
|
||||
|
||||
CREATE TABLE error_tracking_error_events (
|
||||
id bigint NOT NULL,
|
||||
error_id bigint NOT NULL,
|
||||
description text NOT NULL,
|
||||
environment text,
|
||||
level text,
|
||||
occurred_at timestamp with time zone NOT NULL,
|
||||
payload jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
CONSTRAINT check_92ecc3077b CHECK ((char_length(description) <= 255)),
|
||||
CONSTRAINT check_c67d5b8007 CHECK ((char_length(level) <= 255)),
|
||||
CONSTRAINT check_f4b52474ad CHECK ((char_length(environment) <= 255))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE error_tracking_error_events_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
ALTER SEQUENCE error_tracking_error_events_id_seq OWNED BY error_tracking_error_events.id;
|
||||
|
||||
CREATE TABLE error_tracking_errors (
|
||||
id bigint NOT NULL,
|
||||
project_id bigint NOT NULL,
|
||||
name text NOT NULL,
|
||||
description text NOT NULL,
|
||||
actor text NOT NULL,
|
||||
first_seen_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
last_seen_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
platform text,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
CONSTRAINT check_18a758e537 CHECK ((char_length(name) <= 255)),
|
||||
CONSTRAINT check_b5cb4d3888 CHECK ((char_length(actor) <= 255)),
|
||||
CONSTRAINT check_c739788b12 CHECK ((char_length(description) <= 1024)),
|
||||
CONSTRAINT check_fe99886883 CHECK ((char_length(platform) <= 255))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE error_tracking_errors_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
ALTER SEQUENCE error_tracking_errors_id_seq OWNED BY error_tracking_errors.id;
|
||||
|
||||
CREATE TABLE events (
|
||||
id integer NOT NULL,
|
||||
project_id integer,
|
||||
|
@ -19887,6 +19937,10 @@ ALTER TABLE ONLY epic_user_mentions ALTER COLUMN id SET DEFAULT nextval('epic_us
|
|||
|
||||
ALTER TABLE ONLY epics ALTER COLUMN id SET DEFAULT nextval('epics_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY error_tracking_error_events ALTER COLUMN id SET DEFAULT nextval('error_tracking_error_events_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY error_tracking_errors ALTER COLUMN id SET DEFAULT nextval('error_tracking_errors_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY events ALTER COLUMN id SET DEFAULT nextval('events_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY evidences ALTER COLUMN id SET DEFAULT nextval('evidences_id_seq'::regclass);
|
||||
|
@ -21197,6 +21251,12 @@ ALTER TABLE ONLY epic_user_mentions
|
|||
ALTER TABLE ONLY epics
|
||||
ADD CONSTRAINT epics_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY error_tracking_error_events
|
||||
ADD CONSTRAINT error_tracking_error_events_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY error_tracking_errors
|
||||
ADD CONSTRAINT error_tracking_errors_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY events
|
||||
ADD CONSTRAINT events_pkey PRIMARY KEY (id);
|
||||
|
||||
|
@ -23343,6 +23403,10 @@ CREATE INDEX index_epics_on_start_date_sourcing_epic_id ON epics USING btree (st
|
|||
|
||||
CREATE INDEX index_epics_on_start_date_sourcing_milestone_id ON epics USING btree (start_date_sourcing_milestone_id);
|
||||
|
||||
CREATE INDEX index_error_tracking_error_events_on_error_id ON error_tracking_error_events USING btree (error_id);
|
||||
|
||||
CREATE INDEX index_error_tracking_errors_on_project_id ON error_tracking_errors USING btree (project_id);
|
||||
|
||||
CREATE INDEX index_esc_protected_branches_on_external_status_check_id ON external_status_checks_protected_branches USING btree (external_status_check_id);
|
||||
|
||||
CREATE INDEX index_esc_protected_branches_on_protected_branch_id ON external_status_checks_protected_branches USING btree (protected_branch_id);
|
||||
|
@ -26560,6 +26624,9 @@ ALTER TABLE ONLY packages_debian_group_component_files
|
|||
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 error_tracking_error_events
|
||||
ADD CONSTRAINT fk_rails_2c096c0076 FOREIGN KEY (error_id) REFERENCES error_tracking_errors(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY onboarding_progresses
|
||||
ADD CONSTRAINT fk_rails_2ccfd420cc FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
|
||||
|
||||
|
@ -26968,6 +27035,9 @@ ALTER TABLE ONLY plan_limits
|
|||
ALTER TABLE ONLY operations_feature_flags_issues
|
||||
ADD CONSTRAINT fk_rails_6a8856ca4f FOREIGN KEY (feature_flag_id) REFERENCES operations_feature_flags(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY error_tracking_errors
|
||||
ADD CONSTRAINT fk_rails_6b41f837ba FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY prometheus_alerts
|
||||
ADD CONSTRAINT fk_rails_6d9b283465 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
|
@ -14378,7 +14378,6 @@ Event action.
|
|||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| <a id="eventactionapproved"></a>`APPROVED` | Approved action. |
|
||||
| <a id="eventactionarchived"></a>`ARCHIVED` | Archived action. |
|
||||
| <a id="eventactionclosed"></a>`CLOSED` | Closed action. |
|
||||
| <a id="eventactioncommented"></a>`COMMENTED` | Commented action. |
|
||||
| <a id="eventactioncreated"></a>`CREATED` | Created action. |
|
||||
|
|
|
@ -9093,9 +9093,6 @@ msgstr ""
|
|||
msgid "Create blank project"
|
||||
msgstr ""
|
||||
|
||||
msgid "Create blank project/repository"
|
||||
msgstr ""
|
||||
|
||||
msgid "Create branch"
|
||||
msgstr ""
|
||||
|
||||
|
@ -16503,9 +16500,6 @@ msgstr ""
|
|||
msgid "Import project members"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import project/repository"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import projects from Bitbucket"
|
||||
msgstr ""
|
||||
|
||||
|
@ -25964,9 +25958,6 @@ msgstr ""
|
|||
msgid "ProjectsNew|Create blank project"
|
||||
msgstr ""
|
||||
|
||||
msgid "ProjectsNew|Create blank project/repository"
|
||||
msgstr ""
|
||||
|
||||
msgid "ProjectsNew|Create from template"
|
||||
msgstr ""
|
||||
|
||||
|
@ -25982,9 +25973,6 @@ msgstr ""
|
|||
msgid "ProjectsNew|Import project"
|
||||
msgstr ""
|
||||
|
||||
msgid "ProjectsNew|Import project/repository"
|
||||
msgstr ""
|
||||
|
||||
msgid "ProjectsNew|Initialize repository with a README"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -459,12 +459,6 @@ RSpec.describe ProjectsController do
|
|||
|
||||
post :create, params: { project: project_params }
|
||||
end
|
||||
|
||||
it 'tracks a created event for the new_repo experiment', :experiment do
|
||||
expect(experiment(:new_repo, :candidate)).to track(:project_created).on_next_instance
|
||||
|
||||
post :create, params: { project: project_params }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #archive' do
|
||||
|
|
|
@ -17,7 +17,6 @@ FactoryBot.define do
|
|||
trait(:left) { action { :left } }
|
||||
trait(:destroyed) { action { :destroyed } }
|
||||
trait(:expired) { action { :expired } }
|
||||
trait(:archived) { action { :archived } }
|
||||
trait(:approved) { action { :approved } }
|
||||
|
||||
factory :closed_issue_event do
|
||||
|
|
|
@ -447,35 +447,6 @@ RSpec.describe 'Group' do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'new_repo experiment' do
|
||||
let_it_be(:group) { create_default(:group) }
|
||||
|
||||
it 'when in candidate renders "project/repository"' do
|
||||
stub_experiments(new_repo: :candidate)
|
||||
|
||||
visit group_path(group)
|
||||
|
||||
find('li.header-new.dropdown').click
|
||||
|
||||
page.within('li.header-new.dropdown') do
|
||||
expect(page).to have_selector('a', text: 'New project/repository')
|
||||
end
|
||||
end
|
||||
|
||||
it 'when in control renders "project/repository"' do
|
||||
stub_experiments(new_repo: :control)
|
||||
|
||||
visit group_path(group)
|
||||
|
||||
find('li.header-new.dropdown').click
|
||||
|
||||
page.within('li.header-new.dropdown') do
|
||||
expect(page).to have_selector('a', text: 'New project')
|
||||
expect(page).to have_no_selector('a', text: 'New project/repository')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def remove_with_confirm(button_text, confirm_with)
|
||||
click_button button_text
|
||||
fill_in 'confirm_name_input', with: confirm_with
|
||||
|
|
|
@ -8,7 +8,6 @@ RSpec.describe 'Projects > Activity > User sees design Activity', :js do
|
|||
let_it_be(:uploader) { create(:user) }
|
||||
let_it_be(:editor) { create(:user) }
|
||||
let_it_be(:deleter) { create(:user) }
|
||||
let_it_be(:archiver) { create(:user) }
|
||||
|
||||
def design_activity(user, action)
|
||||
[user.name, user.to_reference, action, 'design'].join(' ')
|
||||
|
@ -24,7 +23,6 @@ RSpec.describe 'Projects > Activity > User sees design Activity', :js do
|
|||
create(:design_event, :created, author: uploader, **common_attrs)
|
||||
create(:design_event, :updated, author: editor, **common_attrs)
|
||||
create(:design_event, :destroyed, author: deleter, **common_attrs)
|
||||
create(:design_event, :archived, author: archiver, **common_attrs)
|
||||
end
|
||||
|
||||
before do
|
||||
|
@ -39,7 +37,6 @@ RSpec.describe 'Projects > Activity > User sees design Activity', :js do
|
|||
expect(page).to have_content(design_activity(uploader, 'uploaded'))
|
||||
expect(page).to have_content(design_activity(editor, 'revised'))
|
||||
expect(page).to have_content(design_activity(deleter, 'deleted'))
|
||||
expect(page).to have_content(design_activity(archiver, 'archived'))
|
||||
end
|
||||
|
||||
it 'allows filtering out the design events', :aggregate_failures do
|
||||
|
@ -48,7 +45,6 @@ RSpec.describe 'Projects > Activity > User sees design Activity', :js do
|
|||
expect(page).not_to have_content(design_activity(uploader, 'uploaded'))
|
||||
expect(page).not_to have_content(design_activity(editor, 'revised'))
|
||||
expect(page).not_to have_content(design_activity(deleter, 'deleted'))
|
||||
expect(page).not_to have_content(design_activity(archiver, 'archived'))
|
||||
end
|
||||
|
||||
it 'allows filtering in the design events', :aggregate_failures do
|
||||
|
@ -58,7 +54,6 @@ RSpec.describe 'Projects > Activity > User sees design Activity', :js do
|
|||
expect(page).to have_content(design_activity(uploader, 'uploaded'))
|
||||
expect(page).to have_content(design_activity(editor, 'revised'))
|
||||
expect(page).to have_content(design_activity(deleter, 'deleted'))
|
||||
expect(page).to have_content(design_activity(archiver, 'archived'))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -14,75 +14,6 @@ RSpec.describe 'New project', :js do
|
|||
sign_in(user)
|
||||
end
|
||||
|
||||
context 'new repo experiment', :experiment do
|
||||
it 'when in control renders "project"' do
|
||||
stub_experiments(new_repo: :control)
|
||||
|
||||
visit new_project_path
|
||||
|
||||
find('li.header-new.dropdown').click
|
||||
|
||||
page.within('li.header-new.dropdown') do
|
||||
expect(page).to have_selector('a', text: 'New project')
|
||||
expect(page).to have_no_selector('a', text: 'New project/repository')
|
||||
end
|
||||
|
||||
expect(page).to have_selector('h3', text: 'Create blank project')
|
||||
expect(page).to have_no_selector('h3', text: 'Create blank project/repository')
|
||||
end
|
||||
|
||||
it 'when in candidate renders "project/repository"' do
|
||||
stub_experiments(new_repo: :candidate)
|
||||
|
||||
visit new_project_path
|
||||
|
||||
find('li.header-new.dropdown').click
|
||||
|
||||
page.within('li.header-new.dropdown') do
|
||||
expect(page).to have_selector('a', text: 'New project/repository')
|
||||
end
|
||||
|
||||
expect(page).to have_selector('h3', text: 'Create blank project/repository')
|
||||
end
|
||||
|
||||
it 'when in control it renders "project" in the new projects dropdown' do
|
||||
stub_experiments(new_repo: :control)
|
||||
|
||||
visit new_project_path
|
||||
|
||||
open_top_nav_projects
|
||||
|
||||
within_top_nav do
|
||||
if Feature.enabled?(:combined_menu, default_enabled: :yaml)
|
||||
expect(page).to have_selector('a', text: 'Create new project')
|
||||
expect(page).to have_no_selector('a', text: 'Create blank project/repository')
|
||||
else
|
||||
expect(page).to have_selector('a', text: 'Create blank project')
|
||||
expect(page).to have_selector('a', text: 'Import project')
|
||||
expect(page).to have_no_selector('a', text: 'Create blank project/repository')
|
||||
expect(page).to have_no_selector('a', text: 'Import project/repository')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'when in candidate it renders "project/repository" in the new projects dropdown' do
|
||||
stub_experiments(new_repo: :candidate)
|
||||
|
||||
visit new_project_path
|
||||
|
||||
open_top_nav_projects
|
||||
|
||||
within_top_nav do
|
||||
if Feature.enabled?(:combined_menu, default_enabled: :yaml)
|
||||
expect(page).to have_selector('a', text: 'Create new project')
|
||||
else
|
||||
expect(page).to have_selector('a', text: 'Create blank project/repository')
|
||||
expect(page).to have_selector('a', text: 'Import project/repository')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'shows a message if multiple levels are restricted' do
|
||||
Gitlab::CurrentSettings.update!(
|
||||
restricted_visibility_levels: [Gitlab::VisibilityLevel::PRIVATE, Gitlab::VisibilityLevel::INTERNAL]
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { assignGitlabExperiment } from 'helpers/experimentation_helper';
|
||||
import App from '~/pages/projects/new/components/app.vue';
|
||||
import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue';
|
||||
|
||||
describe('Experimental new project creation app', () => {
|
||||
let wrapper;
|
||||
|
||||
const findNewNamespacePage = () => wrapper.findComponent(NewNamespacePage);
|
||||
|
||||
const createComponent = (propsData) => {
|
||||
wrapper = shallowMount(App, { propsData });
|
||||
};
|
||||
|
@ -16,36 +13,6 @@ describe('Experimental new project creation app', () => {
|
|||
wrapper.destroy();
|
||||
});
|
||||
|
||||
describe('new_repo experiment', () => {
|
||||
it('passes new_repo experiment', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findNewNamespacePage().props().experiment).toBe('new_repo');
|
||||
});
|
||||
|
||||
describe('when in the candidate variant', () => {
|
||||
assignGitlabExperiment('new_repo', 'candidate');
|
||||
|
||||
it('has "repository" in the panel title', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findNewNamespacePage().props().panels[0].title).toBe(
|
||||
'Create blank project/repository',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when in the control variant', () => {
|
||||
assignGitlabExperiment('new_repo', 'control');
|
||||
|
||||
it('has "project" in the panel title', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findNewNamespacePage().props().panels[0].title).toBe('Create blank project');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('passes custom new project guideline text to underlying component', () => {
|
||||
const DEMO_GUIDELINES = 'Demo guidelines';
|
||||
const guidelineSelector = '#new-project-guideline';
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import { GlAlert, GlToggle, GlTooltip } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import MockAxiosAdapter from 'axios-mock-adapter';
|
||||
import CcValidationRequiredAlert from 'ee_component/billings/components/cc_validation_required_alert.vue';
|
||||
import { TEST_HOST } from 'helpers/test_constants';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import SharedRunnersToggleComponent from '~/projects/settings/components/shared_runners_toggle.vue';
|
||||
|
@ -31,7 +29,6 @@ describe('projects/settings/components/shared_runners', () => {
|
|||
const findErrorAlert = () => wrapper.find(GlAlert);
|
||||
const findSharedRunnersToggle = () => wrapper.find(GlToggle);
|
||||
const findToggleTooltip = () => wrapper.find(GlTooltip);
|
||||
const findCcValidationRequiredAlert = () => wrapper.findComponent(CcValidationRequiredAlert);
|
||||
const getToggleValue = () => findSharedRunnersToggle().props('value');
|
||||
const isToggleLoading = () => findSharedRunnersToggle().props('isLoading');
|
||||
const isToggleDisabled = () => findSharedRunnersToggle().props('disabled');
|
||||
|
@ -158,40 +155,4 @@ describe('projects/settings/components/shared_runners', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with credit card validation required and shared runners DISABLED', () => {
|
||||
beforeEach(() => {
|
||||
window.gon = {
|
||||
subscriptions_url: TEST_HOST,
|
||||
payment_form_url: TEST_HOST,
|
||||
};
|
||||
|
||||
createComponent({
|
||||
isCreditCardValidationRequired: true,
|
||||
isEnabled: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('toggle should not be visible', () => {
|
||||
expect(findSharedRunnersToggle().exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('credit card validation component should exist', () => {
|
||||
expect(findCcValidationRequiredAlert().exists()).toBe(true);
|
||||
expect(findCcValidationRequiredAlert().text()).toBe(
|
||||
SharedRunnersToggleComponent.i18n.REQUIRES_VALIDATION_TEXT,
|
||||
);
|
||||
});
|
||||
|
||||
describe('when credit card is validated', () => {
|
||||
it('should show the toggle button', async () => {
|
||||
findCcValidationRequiredAlert().vm.$emit('verifiedCreditCard');
|
||||
await waitForPromises();
|
||||
|
||||
expect(findSharedRunnersToggle().exists()).toBe(true);
|
||||
expect(getToggleValue()).toBe(false);
|
||||
expect(isToggleDisabled()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { nextTick } from 'vue';
|
||||
import { mockTracking } from 'helpers/tracking_helper';
|
||||
import { TRACKING_CONTEXT_SCHEMA } from '~/experimentation/constants';
|
||||
import { getExperimentData } from '~/experimentation/utils';
|
||||
import WelcomePage from '~/vue_shared/new_namespace/components/welcome.vue';
|
||||
|
||||
jest.mock('~/experimentation/utils', () => ({ getExperimentData: jest.fn() }));
|
||||
|
||||
describe('Welcome page', () => {
|
||||
let wrapper;
|
||||
let trackingSpy;
|
||||
|
@ -28,7 +24,6 @@ describe('Welcome page', () => {
|
|||
beforeEach(() => {
|
||||
trackingSpy = mockTracking('_category_', document, jest.spyOn);
|
||||
trackingSpy.mockImplementation(() => {});
|
||||
getExperimentData.mockReturnValue(undefined);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -38,7 +33,7 @@ describe('Welcome page', () => {
|
|||
});
|
||||
|
||||
it('tracks link clicks', async () => {
|
||||
createComponent({ propsData: { experiment: 'foo', panels: [{ name: 'test', href: '#' }] } });
|
||||
createComponent({ propsData: { panels: [{ name: 'test', href: '#' }] } });
|
||||
const link = wrapper.find('a');
|
||||
link.trigger('click');
|
||||
await nextTick();
|
||||
|
@ -47,25 +42,6 @@ describe('Welcome page', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('adds experiment data if in experiment', async () => {
|
||||
const mockExperimentData = 'data';
|
||||
getExperimentData.mockReturnValue(mockExperimentData);
|
||||
|
||||
createComponent({ propsData: { experiment: 'foo', panels: [{ name: 'test', href: '#' }] } });
|
||||
const link = wrapper.find('a');
|
||||
link.trigger('click');
|
||||
await nextTick();
|
||||
return wrapper.vm.$nextTick().then(() => {
|
||||
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_tab', {
|
||||
label: 'test',
|
||||
context: {
|
||||
data: mockExperimentData,
|
||||
schema: TRACKING_CONTEXT_SCHEMA,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('renders footer slot if provided', () => {
|
||||
const DUMMY = 'Test message';
|
||||
createComponent({
|
||||
|
|
|
@ -37,13 +37,6 @@ describe('Experimental new project creation app', () => {
|
|||
window.location.hash = '';
|
||||
});
|
||||
|
||||
it('passes experiment to welcome component if provided', () => {
|
||||
const EXPERIMENT = 'foo';
|
||||
createComponent({ propsData: { experiment: EXPERIMENT } });
|
||||
|
||||
expect(findWelcomePage().props().experiment).toBe(EXPERIMENT);
|
||||
});
|
||||
|
||||
describe('with empty hash', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
|
|
|
@ -13,7 +13,6 @@ RSpec.describe Nav::NewDropdownHelper do
|
|||
let(:with_can_create_project) { false }
|
||||
let(:with_can_create_group) { false }
|
||||
let(:with_can_create_snippet) { false }
|
||||
let(:with_new_repo_experiment) { :control }
|
||||
let(:with_invite_members_experiment) { false }
|
||||
let(:with_invite_members_experiment_enabled) { false }
|
||||
|
||||
|
@ -29,7 +28,6 @@ RSpec.describe Nav::NewDropdownHelper do
|
|||
end
|
||||
|
||||
before do
|
||||
stub_experiments(new_repo: with_new_repo_experiment)
|
||||
allow(::Gitlab::Experimentation).to receive(:active?).with(:invite_members_new_dropdown) { with_invite_members_experiment }
|
||||
allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { with_invite_members_experiment_enabled }
|
||||
allow(helper).to receive(:tracking_label) { 'test_tracking_label' }
|
||||
|
@ -43,19 +41,6 @@ RSpec.describe Nav::NewDropdownHelper do
|
|||
allow(user).to receive(:can?).with(:create_snippet) { with_can_create_snippet }
|
||||
end
|
||||
|
||||
shared_examples 'new repo experiment shared example' do |title|
|
||||
let(:with_new_repo_experiment) { :candidate }
|
||||
|
||||
it 'has experiment project title' do
|
||||
expect(subject[:menu_sections]).to match(
|
||||
expected_menu_section(
|
||||
title: title,
|
||||
menu_item: a_hash_including(title: 'New project/repository')
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'invite member link shared example' do
|
||||
it 'shows invite member link' do
|
||||
expect(subject[:menu_sections]).to eq(
|
||||
|
@ -117,15 +102,13 @@ RSpec.describe Nav::NewDropdownHelper do
|
|||
title: 'GitLab',
|
||||
menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
|
||||
id: 'general_new_project',
|
||||
title: 'New project',
|
||||
title: 'New project/repository',
|
||||
href: '/projects/new',
|
||||
data: { track_experiment: 'new_repo', track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' }
|
||||
data: { track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' }
|
||||
)
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
it_behaves_like 'new repo experiment shared example', 'GitLab'
|
||||
end
|
||||
|
||||
context 'when can create group' do
|
||||
|
@ -193,15 +176,13 @@ RSpec.describe Nav::NewDropdownHelper do
|
|||
title: 'This group',
|
||||
menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
|
||||
id: 'new_project',
|
||||
title: 'New project',
|
||||
title: 'New project/repository',
|
||||
href: "/projects/new?namespace_id=#{group.id}",
|
||||
data: { track_experiment: 'new_repo', track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' }
|
||||
data: { track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' }
|
||||
)
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
it_behaves_like 'new repo experiment shared example', 'This group'
|
||||
end
|
||||
|
||||
context 'when can create subgroup' do
|
||||
|
|
|
@ -143,7 +143,6 @@ RSpec.describe Nav::TopNavHelper do
|
|||
css_class: 'qa-projects-dropdown',
|
||||
data: {
|
||||
track_event: 'click_dropdown',
|
||||
track_experiment: 'new_repo',
|
||||
track_label: 'projects_dropdown'
|
||||
},
|
||||
icon: 'project',
|
||||
|
|
14
spec/models/error_tracking/error_event_spec.rb
Normal file
14
spec/models/error_tracking/error_event_spec.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ErrorTracking::ErrorEvent, type: :model do
|
||||
describe 'relationships' do
|
||||
it { is_expected.to belong_to(:error) }
|
||||
end
|
||||
|
||||
describe 'validations' do
|
||||
it { is_expected.to validate_presence_of(:description) }
|
||||
it { is_expected.to validate_presence_of(:occurred_at) }
|
||||
end
|
||||
end
|
16
spec/models/error_tracking/error_spec.rb
Normal file
16
spec/models/error_tracking/error_spec.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ErrorTracking::Error, type: :model do
|
||||
describe 'relationships' do
|
||||
it { is_expected.to belong_to(:project) }
|
||||
it { is_expected.to have_many(:events) }
|
||||
end
|
||||
|
||||
describe 'validations' do
|
||||
it { is_expected.to validate_presence_of(:name) }
|
||||
it { is_expected.to validate_presence_of(:description) }
|
||||
it { is_expected.to validate_presence_of(:actor) }
|
||||
end
|
||||
end
|
|
@ -978,14 +978,13 @@ RSpec.describe Event do
|
|||
|
||||
describe '#action_name' do
|
||||
it 'handles all valid design events' do
|
||||
created, updated, destroyed, archived = %i[created updated destroyed archived].map do |trait|
|
||||
created, updated, destroyed = %i[created updated destroyed].map do |trait|
|
||||
build(:design_event, trait).action_name
|
||||
end
|
||||
|
||||
expect(created).to eq('uploaded')
|
||||
expect(updated).to eq('revised')
|
||||
expect(destroyed).to eq('deleted')
|
||||
expect(archived).to eq('archived')
|
||||
end
|
||||
|
||||
it 'handles correct push_action' do
|
||||
|
|
Loading…
Reference in a new issue