Commit a0c2bd17 authored by Tyler Williams's avatar Tyler Williams Committed by Paul Slaughter

Add Free Trial dataLayer events for GitLab.org

Related to
https://gitlab.com/gitlab-com/marketing/digital-experience/buyer-experience/-/issues/212,
specifically adds the dataLayer events for /-/trial_registrations/new.

Adds an ops feature flag so we can activate only on GitLab.com,
updates the auth_helper to allow GTM for signed in users, updates
the controller to pass the frontend feature flag, and adds an RSpec test
to verify behavior.

https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76305
parent 6fa714ee
import { logError } from '~/lib/logger';
const isSupported = () => Boolean(window.dataLayer) && gon.features?.gitlabGtmDatalayer;
const pushEvent = (event, args = {}) => {
if (!window.dataLayer) {
return;
}
try {
window.dataLayer.push({
event,
...args,
});
} catch (e) {
logError('Unexpected error while pushing to dataLayer', e);
}
};
const pushAccountSubmit = (accountType, accountMethod) =>
pushEvent('accountSubmit', { accountType, accountMethod });
const trackFormSubmission = (accountType) => {
const form = document.getElementById('new_new_user');
form.addEventListener('submit', () => {
pushAccountSubmit(accountType, 'form');
});
};
const trackOmniAuthSubmission = (accountType) => {
const links = document.querySelectorAll('.js-oauth-login');
links.forEach((link) => {
const { provider } = link.dataset;
link.addEventListener('click', () => {
pushAccountSubmit(accountType, provider);
});
});
};
export const trackFreeTrialAccountSubmissions = () => {
if (!isSupported()) {
return;
}
trackFormSubmission('freeThirtyDayTrial');
trackOmniAuthSubmission('freeThirtyDayTrial');
};
export const trackNewRegistrations = () => {
if (!isSupported()) {
return;
}
trackFormSubmission('standardSignUp');
trackOmniAuthSubmission('standardSignUp');
};
export const trackSaasTrialSubmit = () => {
if (!isSupported()) {
return;
}
const form = document.getElementById('new_trial');
form.addEventListener('submit', () => {
pushEvent('saasTrialSubmit');
});
};
export const trackSaasTrialSkip = () => {
if (!isSupported()) {
return;
}
const skipLink = document.querySelector('.js-skip-trial');
skipLink.addEventListener('click', () => {
pushEvent('saasTrialSkip');
});
};
export const trackSaasTrialGroup = () => {
if (!isSupported()) {
return;
}
const form = document.getElementById('new_group');
form.addEventListener('submit', () => {
pushEvent('saasTrialGroup');
});
};
export const trackSaasTrialProject = () => {
if (!isSupported()) {
return;
}
const form = document.getElementById('new_project');
form.addEventListener('submit', () => {
pushEvent('saasTrialProject');
});
};
export const trackSaasTrialProjectImport = () => {
if (!isSupported()) {
return;
}
const importButtons = document.querySelectorAll('.js-import-project-btn');
importButtons.forEach((button) => {
button.addEventListener('click', () => {
const { platform } = button.dataset;
pushEvent('saasTrialProjectImport', { saasProjectImport: platform });
});
});
};
export const trackSaasTrialGetStarted = () => {
if (!isSupported()) {
return;
}
const getStartedButton = document.querySelector('.js-get-started-btn');
getStartedButton.addEventListener('click', () => {
pushEvent('saasTrialGetStarted');
});
};
import { trackNewRegistrations } from '~/google_tag_manager';
import NoEmojiValidator from '~/emoji/no_emoji_validator';
import LengthValidator from '~/pages/sessions/new/length_validator';
import UsernameValidator from '~/pages/sessions/new/username_validator';
......@@ -5,3 +7,5 @@ import UsernameValidator from '~/pages/sessions/new/username_validator';
new UsernameValidator(); // eslint-disable-line no-new
new LengthValidator(); // eslint-disable-line no-new
new NoEmojiValidator(); // eslint-disable-line no-new
trackNewRegistrations();
......@@ -18,6 +18,7 @@ class RegistrationsController < Devise::RegistrationsController
def new
@resource = build_resource
push_frontend_feature_flag(:gitlab_gtm_datalayer, type: :ops)
end
def create
......
......@@ -177,15 +177,13 @@ module AuthHelper
def google_tag_manager_enabled?
return false unless Gitlab.dev_env_or_com?
has_config_key = if Feature.enabled?(:gtm_nonce, type: :ops)
extra_config.has_key?('google_tag_manager_nonce_id') &&
extra_config.google_tag_manager_nonce_id.present?
else
extra_config.has_key?('google_tag_manager_id') &&
extra_config.google_tag_manager_id.present?
end
has_config_key && !current_user
if Feature.enabled?(:gtm_nonce, type: :ops)
extra_config.has_key?('google_tag_manager_nonce_id') &&
extra_config.google_tag_manager_nonce_id.present?
else
extra_config.has_key?('google_tag_manager_id') &&
extra_config.google_tag_manager_id.present?
end
end
def google_tag_manager_id
......
......@@ -13,6 +13,10 @@ module TrackingHelper
}
end
def tracking_attrs_data(label, action, property)
tracking_attrs(label, action, property).fetch(:data, {})
end
private
def tracking_enabled?
......
......@@ -2,7 +2,7 @@
= _("Create an account using:")
.gl-display-flex.gl-justify-content-between.gl-flex-wrap
- providers.each do |provider|
= link_to omniauth_authorize_path(:user, provider), method: :post, class: "btn gl-button btn-default gl-w-full gl-mb-3 js-oauth-login #{qa_class_for_provider(provider)}", id: "oauth-login-#{provider}" do
= link_to omniauth_authorize_path(:user, provider), method: :post, class: "btn gl-button btn-default gl-w-full gl-mb-3 js-oauth-login #{qa_class_for_provider(provider)}", data: { provider: provider }, id: "oauth-login-#{provider}" do
- if provider_has_icon?(provider)
= provider_image_tag(provider)
%span.gl-button-text
......
......@@ -8,22 +8,22 @@
.import-buttons
- if gitlab_project_import_enabled?
.import_gitlab_project.has-tooltip{ data: { container: 'body', qa_selector: 'gitlab_import_button' } }
= link_to new_import_gitlab_project_path, class: 'gl-button btn-default btn btn_import_gitlab_project', **tracking_attrs(track_label, 'click_button', 'gitlab_export') do
= link_to new_import_gitlab_project_path, class: 'gl-button btn-default btn btn_import_gitlab_project js-import-project-btn', **tracking_attrs(track_label, 'click_button', 'gitlab_export') do
.gl-button-icon
= sprite_icon('tanuki')
= _("GitLab export")
- if github_import_enabled?
%div
= link_to new_import_github_path, class: 'gl-button btn-default btn js-import-github', **tracking_attrs(track_label, 'click_button', 'github') do
= link_to new_import_github_path, class: 'gl-button btn-default btn js-import-github js-import-project-btn', data: { platform: 'github', **tracking_attrs_data(track_label, 'click_button', 'github') } do
.gl-button-icon
= sprite_icon('github')
GitHub
- if bitbucket_import_enabled?
%div
= link_to status_import_bitbucket_path, class: "gl-button btn-default btn import_bitbucket #{'how_to_import_link' unless bitbucket_import_configured?}",
**tracking_attrs(track_label, 'click_button', 'bitbucket_cloud') do
= link_to status_import_bitbucket_path, class: "gl-button btn-default btn import_bitbucket js-import-project-btn #{'how_to_import_link' unless bitbucket_import_configured?}",
data: { platform: 'bitbucket_cloud', **tracking_attrs_data(track_label, 'click_button', 'bitbucket_cloud') } do
.gl-button-icon
= sprite_icon('bitbucket')
Bitbucket Cloud
......@@ -31,15 +31,14 @@
= render 'projects/bitbucket_import_modal'
- if bitbucket_server_import_enabled?
%div
= link_to status_import_bitbucket_server_path, class: "gl-button btn-default btn import_bitbucket", **tracking_attrs(track_label, 'click_button', 'bitbucket_server') do
= link_to status_import_bitbucket_server_path, class: "gl-button btn-default btn import_bitbucket js-import-project-btn", data: { platform: 'bitbucket_server', **tracking_attrs_data(track_label, 'click_button', 'bitbucket_server') } do
.gl-button-icon
= sprite_icon('bitbucket')
Bitbucket Server
%div
- if gitlab_import_enabled?
%div
= link_to status_import_gitlab_path, class: "gl-button btn-default btn import_gitlab #{'how_to_import_link' unless gitlab_import_configured?}",
**tracking_attrs(track_label, 'click_button', 'gitlab_com') do
= link_to status_import_gitlab_path, class: "gl-button btn-default btn import_gitlab js-import-project-btn #{'how_to_import_link' unless gitlab_import_configured?}", data: { platform: 'gitlab_com', **tracking_attrs_data(track_label, 'click_button', 'gitlab_com') } do
.gl-button-icon
= sprite_icon('tanuki')
= _("GitLab.com")
......@@ -48,35 +47,35 @@
- if fogbugz_import_enabled?
%div
= link_to new_import_fogbugz_path, class: 'gl-button btn-default btn import_fogbugz', **tracking_attrs(track_label, 'click_button', 'fogbugz') do
= link_to new_import_fogbugz_path, class: 'gl-button btn-default btn import_fogbugz js-import-project-btn', data: { platform: 'fogbugz', **tracking_attrs_data(track_label, 'click_button', 'fogbugz') } do
.gl-button-icon
= sprite_icon('bug')
FogBugz
- if gitea_import_enabled?
%div
= link_to new_import_gitea_path, class: 'gl-button btn-default btn import_gitea', **tracking_attrs(track_label, 'click_button', 'gitea') do
= link_to new_import_gitea_path, class: 'gl-button btn-default btn import_gitea js-import-project-btn', data: { platform: 'gitea', **tracking_attrs_data(track_label, 'click_button', 'gitea') } do
.gl-button-icon
= custom_icon('gitea_logo')
Gitea
- if git_import_enabled?
%div
%button.gl-button.btn-default.btn.btn-svg.js-toggle-button.js-import-git-toggle-button{ type: "button", data: { toggle_open_class: 'active' }, **tracking_attrs(track_label, 'click_button', 'repo_url') }
%button.gl-button.btn-default.btn.btn-svg.js-toggle-button.js-import-git-toggle-button.js-import-project-btn{ type: "button", data: { platform: 'repo_url', toggle_open_class: 'active', **tracking_attrs_data(track_label, 'click_button', 'repo_url') } }
.gl-button-icon
= sprite_icon('link', css_class: 'gl-icon')
= _('Repo by URL')
- if manifest_import_enabled?
%div
= link_to new_import_manifest_path, class: 'gl-button btn-default btn import_manifest', **tracking_attrs(track_label, 'click_button', 'manifest_file') do
= link_to new_import_manifest_path, class: 'gl-button btn-default btn import_manifest js-import-project-btn', data: { platform: 'manifest_file', **tracking_attrs_data(track_label, 'click_button', 'manifest_file') } do
.gl-button-icon
= sprite_icon('doc-text')
Manifest file
- if phabricator_import_enabled?
%div
= link_to new_import_phabricator_path, class: 'gl-button btn-default btn import_phabricator', data: { track_label: "#{track_label}", track_action: "click_button", track_property: "phabricator" } do
= link_to new_import_phabricator_path, class: 'gl-button btn-default btn import_phabricator js-import-project-btn', data: { platform: 'phabricator', track_label: "#{track_label}", track_action: "click_button", track_property: "phabricator" } do
.gl-button-icon
= custom_icon('issues')
= _("Phabricator Tasks")
......
......@@ -2,6 +2,10 @@
- page_title _('Your profile')
- add_page_specific_style 'page_bundles/signup'
- gitlab_experience_text = _('To personalize your GitLab experience, we\'d like to know a bit more about you')
- content_for :page_specific_javascripts do
= render "layouts/google_tag_manager_head"
= render "layouts/one_trust"
= render "layouts/google_tag_manager_body"
.row.gl-flex-grow-1
.d-flex.gl-flex-direction-column.gl-align-items-center.gl-w-full.gl-px-5.gl-pb-5
......
---
name: gitlab_gtm_datalayer
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76305
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348932
milestone: '14.6'
type: ops
group: group::buyer experience
default_enabled: false
......@@ -3,9 +3,11 @@
import mountComponents from 'ee/registrations/groups/new';
import BindInOut from '~/behaviors/bind_in_out';
import Group from '~/group';
import { trackSaasTrialGroup } from '~/google_tag_manager';
import GroupPathValidator from '~/pages/groups/new/group_path_validator';
mountComponents();
new GroupPathValidator();
BindInOut.initAll();
new Group();
trackSaasTrialGroup();
import initProjectVisibilitySelector from '~/project_visibility';
import initProjectNew from '~/projects/project_new';
import { trackSaasTrialProject, trackSaasTrialProjectImport } from '~/google_tag_manager';
initProjectVisibilitySelector();
initProjectNew.bindEvents();
trackSaasTrialProject();
trackSaasTrialProjectImport();
import { trackSaasTrialGetStarted } from '~/google_tag_manager';
trackSaasTrialGetStarted();
import '~/pages/sessions/index';
import { trackFreeTrialAccountSubmissions } from '~/google_tag_manager';
import NoEmojiValidator from '~/emoji/no_emoji_validator';
import LengthValidator from '~/pages/sessions/new/length_validator';
......@@ -11,3 +12,5 @@ new LengthValidator(); // eslint-disable-line no-new
new SigninTabsMemoizer(); // eslint-disable-line no-new
new NoEmojiValidator(); // eslint-disable-line no-new
new UsernameSuggester('new_user_username', ['new_user_first_name', 'new_user_last_name']); // eslint-disable-line no-new
trackFreeTrialAccountSubmissions();
import 'ee/trials/country_select';
import { trackSaasTrialSubmit, trackSaasTrialSkip } from '~/google_tag_manager';
trackSaasTrialSubmit();
trackSaasTrialSkip();
......@@ -26,6 +26,7 @@ module EE
end
def trial_getting_started
push_frontend_feature_flag(:gitlab_gtm_datalayer, type: :ops)
render locals: { learn_gitlab_project: learn_gitlab_project }
end
......
......@@ -15,6 +15,7 @@ module Registrations
.track(:render, label: 'registrations:groups:new', user: current_user)
@group = Group.new(visibility_level: helpers.default_group_visibility)
experiment(:combined_registration, user: current_user).track(:view_new_group_action)
push_frontend_feature_flag(:gitlab_gtm_datalayer, type: :ops)
end
def create
......
......@@ -18,6 +18,7 @@ module Registrations
def new
@project = Project.new(namespace: @namespace)
push_frontend_feature_flag(:gitlab_gtm_datalayer, type: :ops)
end
def create
......
......@@ -13,6 +13,7 @@ class TrialRegistrationsController < RegistrationsController
before_action :set_redirect_url, only: [:new]
def new
push_frontend_feature_flag(:gitlab_gtm_datalayer, type: :ops)
end
private
......
......@@ -20,6 +20,7 @@ class TrialsController < ApplicationController
def new
experiment(:trial_registration_with_reassurance, actor: current_user)
.track(:render, label: 'trials:new', user: current_user)
push_frontend_feature_flag(:gitlab_gtm_datalayer, type: :ops)
end
def select
......
......@@ -2,7 +2,9 @@
- page_title _('Your GitLab group')
- form_params = { trial_onboarding_flow: params[:trial_onboarding_flow], glm_source: params[:glm_source], glm_content: params[:glm_content] }
- content_for :page_specific_javascripts do
= render "layouts/google_tag_manager_head"
= render "layouts/one_trust"
= render "layouts/google_tag_manager_body"
.row.gl-flex-grow-1
.gl-display-flex.gl-flex-direction-column.gl-align-items-center.gl-w-full.gl-px-5.gl-pb-5
......
......@@ -2,7 +2,9 @@
- page_title _('Your first project')
- visibility_level = selected_visibility_level(@project, params.dig(:project, :visibility_level))
- content_for :page_specific_javascripts do
= render "layouts/google_tag_manager_head"
= render "layouts/one_trust"
= render "layouts/google_tag_manager_body"
- if in_trial_during_signup_flow? || in_trial_onboarding_flow?
= render 'registrations/trial_is_activated_banner'
......
- return unless learn_gitlab_project
- page_title _('Get started with GitLab')
- content_for :page_specific_javascripts do
= render "layouts/google_tag_manager_head"
= render "layouts/one_trust"
= render "layouts/google_tag_manager_body"
.row.gl-flex-grow-1
.gl-display-flex.gl-flex-direction-column.gl-align-items-center.gl-w-full
......@@ -10,4 +13,4 @@
%h2.gl-text-center.gl-mt-5= _('Get started with GitLab')
%p.gl-text-center.gl-mb-5= _('We created a sandbox project that will help you learn the basics of GitLab. You’ll be guided by issues in an issue board. You can go through the issues at your own pace.')
= image_tag 'board-intro.svg', class: 'gl-w-full'
= link_to s_("Ok, let's go"), trial_onboarding_board_users_sign_up_welcome_path(learn_gitlab_project_id: learn_gitlab_project.id), class: 'btn btn-success gl-button gl-mt-5'
= link_to s_("Ok, let's go"), trial_onboarding_board_users_sign_up_welcome_path(learn_gitlab_project_id: learn_gitlab_project.id), class: 'btn btn-success gl-button gl-mt-5 js-get-started-btn'
.gl-mt-4
- if params[:glm_source] == 'gitlab.com'
= link_to s_('Trials|Go back to GitLab'), skip_trials_path, class: 'block py-2'
= link_to s_('Trials|Go back to GitLab'), skip_trials_path, class: 'block py-2 js-skip-trial'
.gl-font-sm.gl-text-gray-700
= s_("Trials|You can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'")
- else
= link_to s_('Trials|Skip Trial'), skip_trials_path, class: 'block py-2'
= link_to s_('Trials|Skip Trial'), skip_trials_path, class: 'block py-2 js-skip-trial'
.gl-font-sm.gl-text-gray-700
= s_("Trials|You won't get a free trial right now but you can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'")
- page_title _('Start your Free Ultimate Trial')
- glm_params = { glm_source: params[:glm_source], glm_content: params[:glm_content] }
- content_for :page_specific_javascripts do
= render "layouts/google_tag_manager_head"
= render "layouts/one_trust"
= render "layouts/google_tag_manager_body"
.row
.col-md-6.m-sm-6
......@@ -13,7 +15,7 @@
= render 'errors'
= form_tag create_lead_trials_path(glm_params), method: :post do |f|
= form_tag create_lead_trials_path(glm_params), method: :post, id: "new_trial" do |f|
.form-row
.col-12.col-sm-6.form-group
= label_tag :first_name, s_('Trial|First name'), for: :first_name, class: 'col-form-label'
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'GitLab.com Google Analytics DataLayer', :js do
let!(:google_tag_manager_id) { 'GTM-WWKMTWS'}
let!(:user_attrs) { attributes_for(:user, first_name: 'GitLab', last_name: 'GitLab', company_name: 'GitLab', phone_number: '555-555-5555', number_of_users: 10) }
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
before do
allow(Gitlab).to receive(:dev_env_or_com?).and_return(true)
stub_application_setting(require_admin_approval_after_user_signup: false)
stub_feature_flags(gitlab_gtm_datalayer: true)
stub_config(extra: { google_tag_manager_id: google_tag_manager_id, google_tag_manager_nonce_id: google_tag_manager_id })
end
context 'on account sign up pages' do
context 'when creating a new trial registration' do
it 'tracks form submissions in the dataLayer' do
visit new_trial_registration_path
evaluate_script('document.getElementById("new_new_user").addEventListener("submit", e => e.preventDefault())')
fill_in 'new_user_first_name', with: user_attrs[:first_name]
fill_in 'new_user_last_name', with: user_attrs[:last_name]
fill_in 'new_user_username', with: user_attrs[:username]
fill_in 'new_user_email', with: user_attrs[:email]
fill_in 'new_user_password', with: user_attrs[:password]
click_button 'Continue'
data_layer = execute_script('return window.dataLayer')
last_event_in_data_layer = data_layer[-1]
expect(last_event_in_data_layer["event"]).to eq("accountSubmit")
expect(last_event_in_data_layer["accountType"]).to eq("freeThirtyDayTrial")
expect(last_event_in_data_layer["accountMethod"]).to eq("form")
end
end
context 'when creating a new user' do
it 'track form submissions in the dataLayer' do
visit new_user_registration_path
evaluate_script('document.getElementById("new_new_user").addEventListener("submit", e => e.preventDefault())')
fill_in 'new_user_first_name', with: user_attrs[:first_name]
fill_in 'new_user_last_name', with: user_attrs[:last_name]
fill_in 'new_user_username', with: user_attrs[:username]
fill_in 'new_user_email', with: user_attrs[:email]
fill_in 'new_user_password', with: user_attrs[:password]
click_button 'Register'
data_layer = execute_script('return window.dataLayer')
last_event_in_data_layer = data_layer[-1]
expect(last_event_in_data_layer["event"]).to eq("accountSubmit")
expect(last_event_in_data_layer["accountType"]).to eq("standardSignUp")
expect(last_event_in_data_layer["accountMethod"]).to eq("form")
end
end
end
context 'on new trial page' do
it 'tracks form submissions in the dataLayer' do
sign_in user
visit new_trial_path
evaluate_script('document.getElementById("new_trial").addEventListener("submit", e => e.preventDefault())')
fill_in 'first_name', with: user_attrs[:first_name]
fill_in 'last_name', with: user_attrs[:last_name]
fill_in 'company_name', with: user_attrs[:company_name]
evaluate_script("document.getElementById('company_size').value = '1-99'")
fill_in 'phone_number', with: user_attrs[:phone_number]
fill_in 'number_of_users', with: user_attrs[:number_of_users]
evaluate_script("document.getElementById('country_select').value = 'US'")
click_button 'Continue'
data_layer = execute_script('return window.dataLayer')
last_event_in_data_layer = data_layer[-1]
expect(last_event_in_data_layer["event"]).to eq("saasTrialSubmit")
end
end
context 'on new registration groups page' do
it 'tracks saasTrialGroup events in the dataLayer' do
sign_in user
visit new_users_sign_up_group_path
evaluate_script('document.getElementById("new_group").addEventListener("submit", e => e.preventDefault())')
fill_in 'group_name', with: 'Test Group'
click_button 'Create group'
data_layer = execute_script('return window.dataLayer')
last_event_in_data_layer = data_layer[-1]
expect(last_event_in_data_layer["event"]).to eq("saasTrialGroup")
end
end
context 'on new registration projects page' do
context 'when creating a new project through the form' do
it 'tracks saasTrialProject events in the dataLayer' do
sign_in user
group.add_owner(user)
visit new_users_sign_up_project_path(namespace_id: group.id)
evaluate_script('document.getElementById("new_project").addEventListener("submit", e => e.preventDefault())')
fill_in 'project_name', with: 'Test Project'
click_button 'Create project'
data_layer = execute_script('return window.dataLayer')
last_event_in_data_layer = data_layer[-1]
expect(last_event_in_data_layer["event"]).to eq("saasTrialProject")
end
end
end
end
import { merge } from 'lodash';
import {
trackFreeTrialAccountSubmissions,
trackNewRegistrations,
trackSaasTrialSubmit,
trackSaasTrialSkip,
trackSaasTrialGroup,
trackSaasTrialProject,
trackSaasTrialProjectImport,
trackSaasTrialGetStarted,
} from '~/google_tag_manager';
import { setHTMLFixture } from 'helpers/fixtures';
import { logError } from '~/lib/logger';
jest.mock('~/lib/logger');
describe('~/google_tag_manager/index', () => {
let spy;
beforeEach(() => {
spy = jest.fn();
window.dataLayer = {
push: spy,
};
window.gon.features = {
gitlabGtmDatalayer: true,
};
});
const createHTML = ({ links = [], forms = [] } = {}) => {
// .foo elements are used to test elements which shouldn't do anything
const allLinks = links.concat({ cls: 'foo' });
const allForms = forms.concat({ cls: 'foo' });
const el = document.createElement('div');
allLinks.forEach(({ cls = '', id = '', href = '#', text = 'Hello', attributes = {} }) => {
const a = document.createElement('a');
a.id = id;
a.href = href || '#';
a.className = cls;
a.textContent = text;
Object.entries(attributes).forEach(([key, value]) => {
a.setAttribute(key, value);
});
el.append(a);
});
allForms.forEach(({ cls = '', id = '' }) => {
const form = document.createElement('form');
form.id = id;
form.className = cls;
el.append(form);
});
return el.innerHTML;
};
const triggerEvent = (selector, eventType) => {
const el = document.querySelector(selector);
el.dispatchEvent(new Event(eventType));
};
const getSelector = ({ id, cls }) => (id ? `#${id}` : `.${cls}`);
const createTestCase = (subject, { forms = [], links = [] }) => {
const expectedFormEvents = forms.map(({ expectation, ...form }) => ({
selector: getSelector(form),
trigger: 'submit',
expectation,
}));
const expectedLinkEvents = links.map(({ expectation, ...link }) => ({
selector: getSelector(link),
trigger: 'click',
expectation,
}));
return [
subject,
{
forms,
links,
expectedEvents: [...expectedFormEvents, ...expectedLinkEvents],
},
];
};
const createOmniAuthTestCase = (subject, accountType) =>
createTestCase(subject, {
forms: [
{
id: 'new_new_user',
expectation: {
event: 'accountSubmit',
accountMethod: 'form',
accountType,
},
},
],
links: [
{
// id is needed so that the test selects the right element to trigger
id: 'test-0',
cls: 'js-oauth-login',
attributes: {
'data-provider': 'myspace',
},
expectation: {
event: 'accountSubmit',
accountMethod: 'myspace',
accountType,
},
},
{
id: 'test-1',
cls: 'js-oauth-login',
attributes: {
'data-provider': 'gitlab',
},
expectation: {
event: 'accountSubmit',
accountMethod: 'gitlab',
accountType,
},
},
],
});
describe.each([
createOmniAuthTestCase(trackFreeTrialAccountSubmissions, 'freeThirtyDayTrial'),
createOmniAuthTestCase(trackNewRegistrations, 'standardSignUp'),
createTestCase(trackSaasTrialSubmit, {
forms: [{ id: 'new_trial', expectation: { event: 'saasTrialSubmit' } }],
}),
createTestCase(trackSaasTrialSkip, {
links: [{ cls: 'js-skip-trial', expectation: { event: 'saasTrialSkip' } }],
}),
createTestCase(trackSaasTrialGroup, {
forms: [{ id: 'new_group', expectation: { event: 'saasTrialGroup' } }],
}),
createTestCase(trackSaasTrialProject, {
forms: [{ id: 'new_project', expectation: { event: 'saasTrialProject' } }],
}),
createTestCase(trackSaasTrialProjectImport, {
links: [
{
id: 'js-test-btn-0',
cls: 'js-import-project-btn',
attributes: { 'data-platform': 'bitbucket' },
expectation: { event: 'saasTrialProjectImport', saasProjectImport: 'bitbucket' },
},
{
// id is neeeded so we trigger the right element in the test
id: 'js-test-btn-1',
cls: 'js-import-project-btn',
attributes: { 'data-platform': 'github' },
expectation: { event: 'saasTrialProjectImport', saasProjectImport: 'github' },
},
],
}),
createTestCase(trackSaasTrialGetStarted, {
links: [
{
cls: 'js-get-started-btn',
expectation: { event: 'saasTrialGetStarted' },
},
],
}),
])('%p', (subject, { links = [], forms = [], expectedEvents }) => {
beforeEach(() => {
setHTMLFixture(createHTML({ links, forms }));
subject();
});
it.each(expectedEvents)('when %p', ({ selector, trigger, expectation }) => {
expect(spy).not.toHaveBeenCalled();
triggerEvent(selector, trigger);
expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledWith(expectation);
expect(logError).not.toHaveBeenCalled();
});
it('when random link is clicked, does nothing', () => {
triggerEvent('a.foo', 'click');
expect(spy).not.toHaveBeenCalled();
});
it('when random form is submitted, does nothing', () => {
triggerEvent('form.foo', 'submit');
expect(spy).not.toHaveBeenCalled();
});
});
describe.each([
{ dataLayer: null },
{ gon: { features: null } },
{ gon: { features: { gitlabGtmDatalayer: false } } },
])('when window %o', (windowAttrs) => {
beforeEach(() => {
merge(window, windowAttrs);
});
it('no ops', () => {
setHTMLFixture(createHTML({ forms: [{ id: 'new_project' }] }));
trackSaasTrialProject();
triggerEvent('#new_project', 'submit');
expect(spy).not.toHaveBeenCalled();
expect(logError).not.toHaveBeenCalled();
});
});
describe('when window.dataLayer throws error', () => {
const pushError = new Error('test');
beforeEach(() => {
window.dataLayer = {
push() {
throw pushError;
},
};
});
it('logs error', () => {
setHTMLFixture(createHTML({ forms: [{ id: 'new_project' }] }));
trackSaasTrialProject();
triggerEvent('#new_project', 'submit');
expect(logError).toHaveBeenCalledWith(
'Unexpected error while pushing to dataLayer',
pushError,
);
});
});
});
......@@ -312,12 +312,6 @@ RSpec.describe AuthHelper do
it { is_expected.to be_truthy }
end
context 'when current user is set' do
let(:user) { instance_double('User') }
it { is_expected.to eq(false) }
end
context 'when no key is set' do
before do
stub_config(extra: {})
......
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