Commit 3256a371 authored by Doug Stull's avatar Doug Stull

Add source tracking to invites

- to send to the backend and get logged.

Changelog: other
parent dd39fe1a
......@@ -68,6 +68,7 @@ export default {
newUsersToInvite: [],
selectedDate: undefined,
groupToBeSharedWith: {},
source: 'unknown',
};
},
computed: {
......@@ -195,6 +196,7 @@ export default {
...this.basePostData,
email: usersToInviteByEmail,
access_level: this.selectedAccessLevel,
invite_source: this.source,
};
},
addByUserIdPostData(usersToAddById) {
......@@ -202,6 +204,7 @@ export default {
...this.basePostData,
user_id: usersToAddById,
access_level: this.selectedAccessLevel,
invite_source: this.source,
};
},
shareWithGroupPostData(groupToBeSharedWith) {
......
......@@ -3,20 +3,19 @@
require 'spec_helper'
RSpec.describe 'Groups > Members > Manage members' do
include Select2Helper
include Spec::Support::Helpers::Features::MembersHelpers
include Spec::Support::Helpers::Features::InviteMembersModalHelper
let(:user1) { create(:user, name: 'John Doe') }
let(:user2) { create(:user, name: 'Mary Jane') }
let(:group) { create(:group) }
let_it_be(:user1) { create(:user, name: 'John Doe') }
let_it_be(:user2) { create(:user, name: 'Mary Jane') }
let_it_be(:group) { create(:group) }
before do
sign_in(user1)
end
shared_examples 'includes the correct Invite link' do |should_include, should_not_include|
it 'includes either the form or the modal trigger' do
it 'includes either the form or the modal trigger', :aggregate_failures do
group.add_owner(user1)
visit group_group_members_path(group)
......@@ -27,12 +26,12 @@ RSpec.describe 'Groups > Members > Manage members' do
end
shared_examples 'does not include either invite modal or either invite form' do
it 'does not include either of the invite members or invite group modal buttons' do
it 'does not include either of the invite members or invite group modal buttons', :aggregate_failures do
expect(page).not_to have_selector '.js-invite-members-modal'
expect(page).not_to have_selector '.js-invite-group-modal'
end
it 'does not include either of the invite users or invite group forms' do
it 'does not include either of the invite users or invite group forms', :aggregate_failures do
expect(page).not_to have_selector '.invite-users-form'
expect(page).not_to have_selector '.invite-group-form'
end
......@@ -66,7 +65,7 @@ RSpec.describe 'Groups > Members > Manage members' do
end
end
it 'add user to group', :js do
it 'add user to group', :js, :snowplow, :aggregate_failures do
group.add_owner(user1)
visit group_group_members_path(group)
......@@ -77,6 +76,13 @@ RSpec.describe 'Groups > Members > Manage members' do
expect(page).to have_content(user2.name)
expect(page).to have_button('Reporter')
end
expect_snowplow_event(
category: 'Members::CreateService',
action: 'create_member',
label: 'unknown',
property: 'existing_user'
)
end
it 'do not disclose email addresses', :js do
......@@ -143,11 +149,13 @@ RSpec.describe 'Groups > Members > Manage members' do
wait_for_requests
aggregate_failures do
expect(page).not_to have_content(user2.name)
expect(group.users).not_to include(user2)
end
end
it 'add yourself to group when already an owner', :js do
it 'add yourself to group when already an owner', :js, :aggregate_failures do
group.add_owner(user1)
visit group_group_members_path(group)
......@@ -160,7 +168,7 @@ RSpec.describe 'Groups > Members > Manage members' do
end
end
it 'invite user to group', :js do
it 'invite user to group', :js, :snowplow do
group.add_owner(user1)
visit group_group_members_path(group)
......@@ -170,14 +178,23 @@ RSpec.describe 'Groups > Members > Manage members' do
expect(page).to have_link 'Invited'
click_link 'Invited'
aggregate_failures do
page.within(members_table) do
expect(page).to have_content('test@example.com')
expect(page).to have_content('Invited')
expect(page).to have_button('Reporter')
end
expect_snowplow_event(
category: 'Members::InviteService',
action: 'create_member',
label: 'unknown',
property: 'net_new_user'
)
end
end
context 'as a guest', :js do
context 'when user is a guest' do
before do
group.add_guest(user1)
group.add_developer(user2)
......@@ -187,7 +204,7 @@ RSpec.describe 'Groups > Members > Manage members' do
it_behaves_like 'does not include either invite modal or either invite form'
it 'does not include a button on the members page list to manage or remove the existing member', :js do
it 'does not include a button on the members page list to manage or remove the existing member', :js, :aggregate_failures do
page.within(second_row) do
# Can not modify user2 role
expect(page).not_to have_button 'Developer'
......@@ -198,7 +215,7 @@ RSpec.describe 'Groups > Members > Manage members' do
end
end
context 'As a guest when the :invite_members_group_modal feature flag is disabled', :js do
context 'when user is a guest and the :invite_members_group_modal feature flag is disabled' do
before do
stub_feature_flags(invite_members_group_modal: false)
group.add_guest(user1)
......@@ -209,7 +226,7 @@ RSpec.describe 'Groups > Members > Manage members' do
it_behaves_like 'does not include either invite modal or either invite form'
it 'does not include a button on the members page list to manage or remove the existing member', :js do
it 'does not include a button on the members page list to manage or remove the existing member', :js, :aggregate_failures do
page.within(second_row) do
# Can not modify user2 role
expect(page).not_to have_button 'Developer'
......
......@@ -6,17 +6,17 @@ RSpec.describe 'Project members list', :js do
include Spec::Support::Helpers::Features::MembersHelpers
include Spec::Support::Helpers::Features::InviteMembersModalHelper
let(:user1) { create(:user, name: 'John Doe') }
let(:user2) { create(:user, name: 'Mary Jane') }
let(:group) { create(:group) }
let(:project) { create(:project, :internal, namespace: group) }
let_it_be(:user1) { create(:user, name: 'John Doe') }
let_it_be(:user2) { create(:user, name: 'Mary Jane') }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, :internal, namespace: group) }
before do
sign_in(user1)
group.add_owner(user1)
end
it 'show members from project and group' do
it 'show members from project and group', :aggregate_failures do
project.add_developer(user2)
visit_members_page
......@@ -25,7 +25,7 @@ RSpec.describe 'Project members list', :js do
expect(second_row).to have_content(user2.name)
end
it 'show user once if member of both group and project' do
it 'show user once if member of both group and project', :aggregate_failures do
project.add_developer(user1)
visit_members_page
......@@ -47,7 +47,7 @@ RSpec.describe 'Project members list', :js do
end
end
it 'add user to project' do
it 'add user to project', :snowplow, :aggregate_failures do
visit_members_page
invite_member(user2.name, role: 'Reporter')
......@@ -55,9 +55,16 @@ RSpec.describe 'Project members list', :js do
page.within find_member_row(user2) do
expect(page).to have_button('Reporter')
end
expect_snowplow_event(
category: 'Members::CreateService',
action: 'create_member',
label: 'unknown',
property: 'existing_user'
)
end
it 'uses ProjectMember access_level_roles for the invite members modal access option' do
it 'uses ProjectMember access_level_roles for the invite members modal access option', :aggregate_failures do
visit_members_page
click_on 'Invite members'
......@@ -95,7 +102,7 @@ RSpec.describe 'Project members list', :js do
expect(members_table).not_to have_content(other_user.name)
end
it 'invite user to project' do
it 'invite user to project', :snowplow, :aggregate_failures do
visit_members_page
invite_member('test@example.com', role: 'Reporter')
......@@ -105,6 +112,13 @@ RSpec.describe 'Project members list', :js do
page.within find_invited_member_row('test@example.com') do
expect(page).to have_button('Reporter')
end
expect_snowplow_event(
category: 'Members::InviteService',
action: 'create_member',
label: 'unknown',
property: 'net_new_user'
)
end
context 'as a signed out visitor viewing a public project' do
......@@ -128,7 +142,7 @@ RSpec.describe 'Project members list', :js do
project.add_maintainer(project_bot)
end
it 'does not show form used to change roles and "Expiration date" or the remove user button' do
it 'does not show form used to change roles and "Expiration date" or the remove user button', :aggregate_failures do
visit_members_page
page.within find_member_row(project_bot) do
......
......@@ -15,6 +15,7 @@ const isProject = false;
const inviteeType = 'members';
const accessLevels = { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 };
const defaultAccessLevel = 10;
const inviteSource = 'unknown';
const helpLink = 'https://example.com';
const user1 = { id: 1, name: 'Name One', username: 'one_1', avatar_url: '' };
......@@ -173,6 +174,7 @@ describe('InviteMembersModal', () => {
user_id: '1',
access_level: defaultAccessLevel,
expires_at: undefined,
invite_source: inviteSource,
format: 'json',
};
......@@ -245,6 +247,7 @@ describe('InviteMembersModal', () => {
access_level: defaultAccessLevel,
expires_at: undefined,
email: 'email@example.com',
invite_source: inviteSource,
format: 'json',
};
......@@ -293,6 +296,7 @@ describe('InviteMembersModal', () => {
const postData = {
access_level: defaultAccessLevel,
expires_at: undefined,
invite_source: inviteSource,
format: 'json',
};
......@@ -308,7 +312,10 @@ describe('InviteMembersModal', () => {
jest.spyOn(Api, 'addGroupMembersByUserId').mockResolvedValue({ data: postData });
jest.spyOn(wrapper.vm, 'showToastMessageSuccess');
jest.spyOn(wrapper.vm, 'trackInvite');
});
describe('when triggered from regular mounting', () => {
beforeEach(() => {
clickInviteButton();
});
......@@ -325,6 +332,22 @@ describe('InviteMembersModal', () => {
});
});
it('calls Apis with the invite source passed through to openModal', () => {
wrapper.vm.openModal({ inviteeType: 'members', source: '_invite_source_' });
clickInviteButton();
expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(id, {
...emailPostData,
invite_source: '_invite_source_',
});
expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(id, {
...idPostData,
invite_source: '_invite_source_',
});
});
});
describe('when any invite failed for any reason', () => {
beforeEach(() => {
wrapper = createComponent({ newUsersToInvite: [user1, user3] });
......@@ -403,18 +426,11 @@ describe('InviteMembersModal', () => {
});
describe('tracking', () => {
const postData = {
user_id: '1',
access_level: defaultAccessLevel,
expires_at: undefined,
format: 'json',
};
beforeEach(() => {
wrapper = createComponent({ newUsersToInvite: [user3] });
wrapper.vm.$toast = { show: jest.fn() };
jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({ data: postData });
jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({});
});
it('tracks the invite', () => {
......
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