Commit 4ed028e8 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Merge branch 'dennis-update-new-project-ui-experiment' into 'master'

Finalize new create project UI experiment

See merge request gitlab-org/gitlab!47804
parents 958fdc20 842d5281
......@@ -2,46 +2,28 @@ import initProjectVisibilitySelector from '../../../project_visibility';
import initProjectNew from '../../../projects/project_new';
import { __ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import Tracking from '~/tracking';
import { isExperimentEnabled } from '~/lib/utils/experimentation';
document.addEventListener('DOMContentLoaded', () => {
initProjectVisibilitySelector();
initProjectNew.bindEvents();
const { category, property } = gon.tracking_data ?? { category: 'projects:new' };
const hasNewCreateProjectUi = isExperimentEnabled('newCreateProjectUi');
import(
/* webpackChunkName: 'experiment_new_project_creation' */ '../../../projects/experiment_new_project_creation'
)
.then(m => {
const el = document.querySelector('.js-experiment-new-project-creation');
if (!hasNewCreateProjectUi) {
// Setting additional tracking for HAML template
if (!el) {
return;
}
Array.from(
document.querySelectorAll('.project-edit-container [data-experiment-track-label]'),
).forEach(node =>
node.addEventListener('click', event => {
const { experimentTrackLabel: label } = event.currentTarget.dataset;
Tracking.event(category, 'click_tab', { property, label });
}),
);
} else {
import(
/* webpackChunkName: 'experiment_new_project_creation' */ '../../../projects/experiment_new_project_creation'
)
.then(m => {
const el = document.querySelector('.js-experiment-new-project-creation');
if (!el) {
return;
}
const config = {
hasErrors: 'hasErrors' in el.dataset,
isCiCdAvailable: 'isCiCdAvailable' in el.dataset,
};
m.default(el, config);
})
.catch(() => {
createFlash(__('An error occurred while loading project creation UI'));
});
}
const config = {
hasErrors: 'hasErrors' in el.dataset,
isCiCdAvailable: 'isCiCdAvailable' in el.dataset,
};
m.default(el, config);
})
.catch(() => {
createFlash(__('An error occurred while loading project creation UI'));
});
});
......@@ -12,6 +12,7 @@ import ciCdProjectIllustration from '../illustrations/ci-cd-project.svg';
const BLANK_PANEL = 'blank_project';
const CI_CD_PANEL = 'cicd_for_external_repo';
const LAST_ACTIVE_TAB_KEY = 'new_project_last_active_tab';
const PANELS = [
{
name: BLANK_PANEL,
......@@ -105,7 +106,7 @@ export default {
this.handleLocationHashChange();
if (this.hasErrors) {
this.activeTab = BLANK_PANEL;
this.activeTab = localStorage.getItem(LAST_ACTIVE_TAB_KEY) || BLANK_PANEL;
}
window.addEventListener('hashchange', () => {
......@@ -127,6 +128,9 @@ export default {
handleLocationHashChange() {
this.activeTab = window.location.hash.substring(1) || null;
if (this.activeTab) {
localStorage.setItem(LAST_ACTIVE_TAB_KEY, this.activeTab);
}
},
},
......
......@@ -34,12 +34,6 @@ class ProjectsController < Projects::ApplicationController
# Project Export Rate Limit
before_action :export_rate_limit, only: [:export, :download_export, :generate_new_export]
# Experiments
before_action only: [:new, :create] do
frontend_experimentation_tracking_data(:new_create_project_ui, 'click_tab')
push_frontend_experiment(:new_create_project_ui)
end
before_action only: [:edit] do
push_frontend_feature_flag(:service_desk_custom_address, @project)
push_frontend_feature_flag(:approval_suggestions, @project, default_enabled: true)
......
......@@ -8,10 +8,9 @@
.project-edit-errors
= render 'projects/errors'
- if experiment_enabled?(:new_create_project_ui)
.js-experiment-new-project-creation{ data: { is_ci_cd_available: ci_cd_projects_available?, has_errors: @project.errors.any? } }
.js-experiment-new-project-creation{ data: { is_ci_cd_available: (ci_cd_projects_available? if Gitlab.ee?), has_errors: @project.errors.any? } }
.row{ 'v-cloak': experiment_enabled?(:new_create_project_ui) }
.row{ 'v-cloak': true }
.col-lg-3.profile-settings-sidebar
%h4.gl-mt-0
= _('New project')
......
---
title: Finalize new create project UI experiment
merge_request: 47804
author:
type: changed
......@@ -190,6 +190,7 @@ RSpec.describe 'Admin::AuditLogs', :js do
click_link 'Impersonate'
visit(new_project_path)
find('[data-qa-selector="blank_project_link"]').click
fill_in(:project_name, with: 'Gotham City')
......
......@@ -43,7 +43,7 @@ RSpec.describe 'Project' do
new_path = 'example-custom-project-template'
new_name = 'Example Custom Project Template'
find('#create-from-template-tab').click
find('[data-qa-selector="create_from_template_link"]').click
find('.project-template .custom-instance-project-templates-tab').click
find("label[for='#{projects.first.name}']").click
......@@ -68,7 +68,7 @@ RSpec.describe 'Project' do
new_path = 'example-custom-project-template'
new_name = 'Example Custom Project Template'
find('#create-from-template-tab').click
find('[data-qa-selector="create_from_template_link"]').click
find('.project-template .custom-instance-project-templates-tab').click
find("label[for='#{projects.first.name}']").click
......@@ -90,7 +90,7 @@ RSpec.describe 'Project' do
new_path = 'example-custom-project-template'
new_name = 'Example Custom Project Template'
find('#create-from-template-tab').click
find('[data-qa-selector="create_from_template_link"]').click
find('.project-template .custom-instance-project-templates-tab').click
find("label[for='#{projects.first.name}']").click
......@@ -111,7 +111,7 @@ RSpec.describe 'Project' do
it 'has a working pagination', :js do
last_project = "label[for='#{projects.last.name}']"
find('#create-from-template-tab').click
find('[data-qa-selector="create_from_template_link"]').click
find('.project-template .custom-instance-project-templates-tab').click
expect(page).to have_css('.custom-project-templates .gl-pagination')
......
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe 'New project' do
RSpec.describe 'New project', :js do
let(:user) { create(:admin) }
before do
......@@ -17,7 +17,7 @@ RSpec.describe 'New project' do
it 'shows mirror repository checkbox enabled', :js do
visit new_project_path
find('#import-project-tab').click
find('[data-qa-selector="import_project_link"]').click
first('.js-import-git-toggle-button').click
expect(page).to have_unchecked_field('Mirror repository', disabled: false)
......@@ -31,6 +31,7 @@ RSpec.describe 'New project' do
it 'does not show mirror repository option' do
visit new_project_path
find('[data-qa-selector="import_project_link"]').click
first('.js-import-git-toggle-button').click
expect(page).not_to have_content('Mirror repository')
......@@ -59,16 +60,16 @@ RSpec.describe 'New project' do
it 'shows CI/CD tab and pane' do
visit new_project_path
expect(page).to have_css('#ci-cd-project-tab')
expect(page).to have_css('[data-qa-selector="cicd_for_external_repo_link"]')
find('#ci-cd-project-tab').click
find('[data-qa-selector="cicd_for_external_repo_link"]').click
expect(page).to have_css('#ci-cd-project-pane')
end
it '"Import project" tab creates projects with features enabled' do
visit new_project_path
find('#import-project-tab').click
find('[data-qa-selector="import_project_link"]').click
page.within '#import-project-pane' do
first('.js-import-git-toggle-button').click
......@@ -88,7 +89,7 @@ RSpec.describe 'New project' do
it 'creates CI/CD project from repo URL', :sidekiq_might_not_need_inline do
visit new_project_path
find('#ci-cd-project-tab').click
find('[data-qa-selector="cicd_for_external_repo_link"]').click
page.within '#ci-cd-project-pane' do
find('.js-import-git-toggle-button').click
......@@ -108,7 +109,7 @@ RSpec.describe 'New project' do
it 'creates CI/CD project from GitHub' do
visit new_project_path
find('#ci-cd-project-tab').click
find('[data-qa-selector="cicd_for_external_repo_link"]').click
page.within '#ci-cd-project-pane' do
find('.js-import-github').click
......@@ -145,7 +146,7 @@ RSpec.describe 'New project' do
it 'stays on GitHub import page after access token failure' do
visit new_project_path
find('#ci-cd-project-tab').click
find('[data-qa-selector="cicd_for_external_repo_link"]').click
page.within '#ci-cd-project-pane' do
find('.js-import-github').click
......@@ -169,7 +170,7 @@ RSpec.describe 'New project' do
it 'does not show CI/CD only tab' do
visit new_project_path
expect(page).not_to have_css('#ci-cd-project-tab')
expect(page).not_to have_css('[data-qa-selector="cicd_for_external_repo_link"]')
end
end
end
......@@ -422,7 +423,7 @@ RSpec.describe 'New project' do
context 'Built-in project templates' do
let(:enterprise_templates) { Gitlab::ProjectTemplate.localized_ee_templates_table }
context 'when `enterprise_templates` is licensed' do
context 'when `enterprise_templates` is licensed', :js do
before do
stub_licensed_features(enterprise_templates: true)
end
......@@ -437,7 +438,7 @@ RSpec.describe 'New project' do
end
end
context 'when `enterprise_templates` is unlicensed' do
context 'when `enterprise_templates` is unlicensed', :js do
before do
stub_licensed_features(enterprise_templates: false)
end
......@@ -457,9 +458,7 @@ RSpec.describe 'New project' do
def visit_create_from_built_in_templates_tab
visit new_project_path
expect(page).to have_css('#create-from-template-tab')
find('#create-from-template-tab').click
find('[data-qa-selector="create_from_template_link"]').click
end
end
end
......@@ -19,7 +19,7 @@ RSpec.describe 'Project', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab
it "defaults to correct namespace" do
visit new_project_path
find('#create-from-template-tab').click
find('[data-qa-selector="create_from_template_link"]').click
find('.custom-group-project-templates-tab').click
find("label[for=#{template.name}]").click
......@@ -28,7 +28,7 @@ RSpec.describe 'Project', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab
it "uses supplied namespace" do
visit new_project_path(namespace_id: other_subgroup.id)
find('#create-from-template-tab').click
find('[data-qa-selector="create_from_template_link"]').click
find('.custom-group-project-templates-tab').click
find("label[for=#{template.name}]").click
......
......@@ -54,10 +54,6 @@ module Gitlab
tracking_category: 'Growth::Expansion::Experiment::InviteMembersEmptyGroupVersionA',
use_backwards_compatible_subject_index: true
},
new_create_project_ui: {
tracking_category: 'Manage::Import::Experiment::NewCreateProjectUi',
use_backwards_compatible_subject_index: true
},
contact_sales_btn_in_app: {
tracking_category: 'Growth::Conversion::Experiment::ContactSalesInApp',
use_backwards_compatible_subject_index: true
......
......@@ -41,27 +41,6 @@ RSpec.describe ProjectsController do
end
end
end
context 'with the new_create_project_ui experiment enabled and the user is part of the control group' do
before do
stub_experiment(new_create_project_ui: true)
stub_experiment_for_user(new_create_project_ui: false)
allow_any_instance_of(described_class).to receive(:experimentation_subject_id).and_return('uuid')
end
it 'passes the right tracking parameters to the frontend' do
get(:new)
expect(Gon.tracking_data).to eq(
{
category: 'Manage::Import::Experiment::NewCreateProjectUi',
action: 'click_tab',
label: 'uuid',
property: 'control_group'
}
)
end
end
end
end
......
......@@ -28,73 +28,40 @@ RSpec.describe 'Import/Export - project import integration test', :js do
let(:project_name) { 'Test Project Name' + randomHex }
let(:project_path) { 'test-project-name' + randomHex }
context 'prefilled the path' do
it 'user imports an exported project successfully', :sidekiq_might_not_need_inline do
visit new_project_path
it 'user imports an exported project successfully', :sidekiq_might_not_need_inline do
visit new_project_path
click_import_project_tab
click_link 'GitLab export'
fill_in :project_name, with: project_name, visible: true
click_import_project_tab
click_link 'GitLab export'
fill_in :name, with: 'Test Project Name', visible: true
fill_in :path, with: 'test-project-path', visible: true
attach_file('file', file)
expect(page).to have_content('Import an exported GitLab project')
expect(URI.parse(current_url).query).to eq("namespace_id=#{namespace.id}&name=#{ERB::Util.url_encode(project_name)}&path=#{project_path}")
expect { click_on 'Import project' }.to change { Project.count }.by(1)
attach_file('file', file)
click_on 'Import project'
expect(Project.count).to eq(1)
project = Project.last
expect(project).not_to be_nil
expect(project.description).to eq("Foo Bar")
expect(project.issues).not_to be_empty
expect(project.merge_requests).not_to be_empty
expect(wiki_exists?(project)).to be true
expect(project.import_state.status).to eq('finished')
end
project = Project.last
expect(project).not_to be_nil
expect(page).to have_content("Project 'test-project-path' is being imported")
end
context 'path is not prefilled' do
it 'user imports an exported project successfully', :sidekiq_might_not_need_inline do
visit new_project_path
click_import_project_tab
click_link 'GitLab export'
it 'invalid project' do
project = create(:project, namespace: user.namespace)
fill_in :name, with: 'Test Project Name', visible: true
fill_in :path, with: 'test-project-path', visible: true
attach_file('file', file)
visit new_project_path
expect { click_on 'Import project' }.to change { Project.count }.by(1)
click_import_project_tab
click_link 'GitLab export'
fill_in :name, with: project.name, visible: true
attach_file('file', file)
click_on 'Import project'
project = Project.last
expect(project).not_to be_nil
expect(page).to have_content("Project 'test-project-path' is being imported")
page.within('.flash-container') do
expect(page).to have_content('Project could not be imported')
end
end
end
it 'invalid project' do
project = create(:project, namespace: user.namespace)
visit new_project_path
fill_in :project_name, with: project.name, visible: true
click_import_project_tab
click_link 'GitLab export'
attach_file('file', file)
click_on 'Import project'
page.within('.flash-container') do
expect(page).to have_content('Project could not be imported')
end
end
def wiki_exists?(project)
wiki = ProjectWiki.new(project)
wiki.repository.exists? && !wiki.repository.empty?
end
def click_import_project_tab
find('#import-project-tab').click
find('[data-qa-selector="import_project_link"]').click
end
end
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe 'New project' do
RSpec.describe 'New project', :js do
include Select2Helper
context 'as a user' do
......@@ -18,6 +18,7 @@ RSpec.describe 'New project' do
)
visit new_project_path
find('[data-qa-selector="blank_project_link"]').click
expect(page).to have_content 'Other visibility settings have been disabled by the administrator.'
end
......@@ -28,6 +29,7 @@ RSpec.describe 'New project' do
)
visit new_project_path
find('[data-qa-selector="blank_project_link"]').click
expect(page).to have_content 'Visibility settings have been disabled by the administrator.'
end
......@@ -42,12 +44,14 @@ RSpec.describe 'New project' do
it 'shows "New project" page', :js do
visit new_project_path
find('[data-qa-selector="blank_project_link"]').click
expect(page).to have_content('Project name')
expect(page).to have_content('Project URL')
expect(page).to have_content('Project slug')
find('#import-project-tab').click
click_link('New project')
find('[data-qa-selector="import_project_link"]').click
expect(page).to have_link('GitHub')
expect(page).to have_link('Bitbucket')
......@@ -61,7 +65,7 @@ RSpec.describe 'New project' do
before do
visit new_project_path
find('#import-project-tab').click
find('[data-qa-selector="import_project_link"]').click
end
it { expect(page).to have_link('Manifest file') }
......@@ -73,6 +77,7 @@ RSpec.describe 'New project' do
stub_application_setting(default_project_visibility: level)
visit new_project_path
find('[data-qa-selector="blank_project_link"]').click
page.within('#blank-project-pane') do
expect(find_field("project_visibility_level_#{level}")).to be_checked
end
......@@ -80,6 +85,7 @@ RSpec.describe 'New project' do
it "saves visibility level #{level} on validation error" do
visit new_project_path
find('[data-qa-selector="blank_project_link"]').click
choose(s_(key))
click_button('Create project')
......@@ -97,6 +103,7 @@ RSpec.describe 'New project' do
it 'has private selected' do
group = create(:group, visibility_level: Gitlab::VisibilityLevel::PRIVATE)
visit new_project_path(namespace_id: group.id)
find('[data-qa-selector="blank_project_link"]').click
page.within('#blank-project-pane') do
expect(find_field("project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).to be_checked
......@@ -112,6 +119,7 @@ RSpec.describe 'New project' do
it 'has private selected' do
group = create(:group, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
visit new_project_path(namespace_id: group.id, project: { visibility_level: Gitlab::VisibilityLevel::PRIVATE })
find('[data-qa-selector="blank_project_link"]').click
page.within('#blank-project-pane') do
expect(find_field("project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).to be_checked
......@@ -123,6 +131,7 @@ RSpec.describe 'New project' do
context 'Readme selector' do
it 'shows the initialize with Readme checkbox on "Blank project" tab' do
visit new_project_path
find('[data-qa-selector="blank_project_link"]').click
expect(page).to have_css('input#project_initialize_with_readme')
expect(page).to have_content('Initialize repository with a README')
......@@ -130,7 +139,7 @@ RSpec.describe 'New project' do
it 'does not show the initialize with Readme checkbox on "Create from template" tab' do
visit new_project_path
find('#create-from-template-pane').click
find('[data-qa-selector="create_from_template_link"]').click
first('.choose-template').click
page.within '.project-fields-form' do
......@@ -141,7 +150,7 @@ RSpec.describe 'New project' do
it 'does not show the initialize with Readme checkbox on "Import project" tab' do
visit new_project_path
find('#import-project-tab').click
find('[data-qa-selector="import_project_link"]').click
first('.js-import-git-toggle-button').click
page.within '.toggle-import-form' do
......@@ -155,13 +164,12 @@ RSpec.describe 'New project' do
context 'with user namespace' do
before do
visit new_project_path
find('[data-qa-selector="blank_project_link"]').click
end
it 'selects the user namespace' do
page.within('#blank-project-pane') do
namespace = find('#project_namespace_id')
expect(namespace.text).to eq user.username
expect(page).to have_select('project[namespace_id]', visible: false, selected: user.username)
end
end
end
......@@ -172,13 +180,12 @@ RSpec.describe 'New project' do
before do
group.add_owner(user)
visit new_project_path(namespace_id: group.id)
find('[data-qa-selector="blank_project_link"]').click
end
it 'selects the group namespace' do
page.within('#blank-project-pane') do
namespace = find('#project_namespace_id option[selected]')
expect(namespace.text).to eq group.name
expect(page).to have_select('project[namespace_id]', visible: false, selected: group.name)
end
end
end
......@@ -190,13 +197,12 @@ RSpec.describe 'New project' do
before do
group.add_maintainer(user)
visit new_project_path(namespace_id: subgroup.id)
find('[data-qa-selector="blank_project_link"]').click
end
it 'selects the group namespace' do
page.within('#blank-project-pane') do
namespace = find('#project_namespace_id option[selected]')
expect(namespace.text).to eq subgroup.full_path
expect(page).to have_select('project[namespace_id]', visible: false, selected: subgroup.full_path)
end
end
end
......@@ -211,6 +217,7 @@ RSpec.describe 'New project' do
internal_group.add_owner(user)
private_group.add_owner(user)
visit new_project_path(namespace_id: public_group.id)
find('[data-qa-selector="blank_project_link"]').click
end
it 'enables the correct visibility options' do
......@@ -240,7 +247,7 @@ RSpec.describe 'New project' do
context 'Import project options', :js do
before do
visit new_project_path
find('#import-project-tab').click
find('[data-qa-selector="import_project_link"]').click
end
context 'from git repository url, "Repo by URL"' do
......@@ -315,13 +322,12 @@ RSpec.describe 'New project' do
before do
group.add_developer(user)
visit new_project_path(namespace_id: group.id)
find('[data-qa-selector="blank_project_link"]').click
end
it 'selects the group namespace' do
page.within('#blank-project-pane') do
namespace = find('#project_namespace_id option[selected]')
expect(namespace.text).to eq group.full_path
expect(page).to have_select('project[namespace_id]', visible: false, selected: group.full_path)
end
end
end
......
......@@ -13,6 +13,7 @@ RSpec.describe 'User creates a project', :js do
it 'creates a new project' do
visit(new_project_path)
find('[data-qa-selector="blank_project_link"]').click
fill_in(:project_name, with: 'Empty')
page.within('#content-body') do
......@@ -39,6 +40,7 @@ RSpec.describe 'User creates a project', :js do
it 'creates a new project' do
visit(new_project_path)
find('[data-qa-selector="blank_project_link"]').click
fill_in :project_name, with: 'A Subgroup Project'
fill_in :project_path, with: 'a-subgroup-project'
......@@ -67,6 +69,7 @@ RSpec.describe 'User creates a project', :js do
it 'creates a new project' do
visit(new_project_path)
find('[data-qa-selector="blank_project_link"]').click
fill_in :project_name, with: 'a-new-project'
fill_in :project_path, with: 'a-new-project'
......
......@@ -16,7 +16,7 @@ RSpec.describe 'Project' do
shared_examples 'creates from template' do |template, sub_template_tab = nil|
it "is created from template", :js do
find('#create-from-template-tab').click
find('[data-qa-selector="create_from_template_link"]').click
find(".project-template #{sub_template_tab}").click if sub_template_tab
find("label[for=#{template.name}]").click
fill_in("project_name", with: template.name)
......@@ -47,9 +47,7 @@ RSpec.describe 'Project' do
end
it 'shows the command in a popover', :js do
page.within '.profile-settings-sidebar' do
click_link 'Show command'
end
click_link 'Show command'
expect(page).to have_css('.popover .push-to-create-popover #push_to_create_tip')
expect(page).to have_content 'Private projects can be created in your personal namespace with:'
......
......@@ -13,7 +13,6 @@ RSpec.describe Gitlab::Experimentation::EXPERIMENTS do
:invite_members_version_a,
:invite_members_version_b,
:invite_members_empty_group_version_a,
:new_create_project_ui,
:contact_sales_btn_in_app,
:customize_homepage,
:invite_email,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment