refactor: [UEPR-71] changed user eligibility logic

This commit is contained in:
MiroslavDionisiev 2024-10-25 11:19:37 +03:00
parent ff9a54bfdd
commit f6b5253264
6 changed files with 50 additions and 91 deletions

View file

@ -70,7 +70,7 @@ jobs:
SCRATCH_ENV: ${{ vars.SCRATCH_ENV }} SCRATCH_ENV: ${{ vars.SCRATCH_ENV }}
SORTING_HAT_HOST: ${{ vars.SORTING_HAT_HOST }} SORTING_HAT_HOST: ${{ vars.SORTING_HAT_HOST }}
USER_GUIDING_ID: ${{ secrets.USER_GUIDING_ID }} USER_GUIDING_ID: ${{ secrets.USER_GUIDING_ID }}
ONBOARDING_TESTING_TOGGLED: ${{ secrets.ONBOARDING_TESTING_TOGGLED }} ONBOARDING_TEST_ACTIVE: ${{ secrets.ONBOARDING_TEST_ACTIVE }}
ONBOARDING_TESTING_STARTING_DATE: ${{ secrets.ONBOARDING_TESTING_STARTING_DATE }} ONBOARDING_TESTING_STARTING_DATE: ${{ secrets.ONBOARDING_TESTING_STARTING_DATE }}
ONBOARDING_TESTING_ENDING_DATE: ${{ secrets.ONBOARDING_TESTING_ENDING_DATE }} ONBOARDING_TESTING_ENDING_DATE: ${{ secrets.ONBOARDING_TESTING_ENDING_DATE }}

View file

@ -7,43 +7,36 @@ const isAdmin = permissions => permissions.admin;
const isMuted = permissions => !!Object.keys(permissions.mute_status).length; const isMuted = permissions => !!Object.keys(permissions.mute_status).length;
const isDateInRange = (date, startingDate, endingDate) => { const isDateInOnboardingRange = date => {
const dateToCompare = Date.parse(date); const dateToCompare = Date.parse(date);
const startDate = Date.parse(startingDate); const startDate = Date.parse(process.env.ONBOARDING_TESTING_STARTING_DATE);
const endDate = Date.parse(endingDate); const endDate = Date.parse(process.env.ONBOARDING_TESTING_ENDING_DATE);
if (dateToCompare >= startDate && dateToCompare <= endDate) { return dateToCompare >= startDate && dateToCompare <= endDate;
return true;
}
return false;
}; };
const isRegisteredInRange = user => { const isRegisteredInRange = user => {
const dateOfJoin = user.dateJoined.split('T')[0]; const dateOfJoin = user.dateJoined.split('T')[0];
return isDateInRange( return isDateInOnboardingRange(dateOfJoin);
dateOfJoin,
process.env.ONBOARDING_TESTING_STARTING_DATE,
process.env.ONBOARDING_TESTING_ENDING_DATE
);
}; };
const isCurrentDayInRange = () => { const isCurrentDayInRange = () => {
const currentDate = new Date().toJSON() const currentDate = new Date().toJSON()
.split('T')[0]; .split('T')[0];
return isDateInRange( return isDateInOnboardingRange(currentDate);
currentDate,
process.env.ONBOARDING_TESTING_STARTING_DATE,
process.env.ONBOARDING_TESTING_ENDING_DATE
);
}; };
const isOnboardingTestingToggledOn = () => const isUserEligible = (user, permissions) =>
JSON.parse(process.env.ONBOARDING_TESTING_TOGGLED); Object.keys(user).length !== 0 &&
Object.keys(permissions).length !== 0 &&
const isUserEligible = user => JSON.parse(process.env.ONBOARDING_TEST_ACTIVE) &&
user.id % 2 === 0 && isRegisteredInRange(user) && isCurrentDayInRange(); isRegisteredInRange(user) &&
isCurrentDayInRange() &&
!isAdmin(permissions) &&
!isMuted(permissions) &&
!isBanned(user);
const calculateAgeGroup = (birthYear, birthMonth) => { const calculateAgeGroup = (birthYear, birthMonth) => {
const today = new Date(); const today = new Date();
@ -66,14 +59,8 @@ const onboardingTestGroup = user =>
ONBOARDING_TESTING_GROUP_A_NAME : ONBOARDING_TESTING_GROUP_A_NAME :
ONBOARDING_TESTING_GROUP_B_NAME); ONBOARDING_TESTING_GROUP_B_NAME);
export const onboardingEligibilityCheck = (user, permissions) => export const shouldDisplayOnboarding = (user, permissions) =>
Object.keys(user).length !== 0 && user.id % 2 === 0 && isUserEligible(user, permissions);
Object.keys(permissions).length !== 0 &&
isOnboardingTestingToggledOn() &&
isUserEligible(user) &&
!isAdmin(permissions) &&
!isMuted(permissions) &&
!isBanned(user);
export const triggerAnalyticsEvent = eventVaribles => { export const triggerAnalyticsEvent = eventVaribles => {
window.dataLayer = window.dataLayer || []; window.dataLayer = window.dataLayer || [];
@ -83,12 +70,8 @@ export const triggerAnalyticsEvent = eventVaribles => {
}); });
}; };
export const sendUserProperties = user => { export const sendUserProperties = (user, permissions) => {
if ( if (!isUserEligible(user, permissions)) {
!isOnboardingTestingToggledOn() ||
!isRegisteredInRange(user) ||
!isCurrentDayInRange()
) {
window.dataLayer.push({ window.dataLayer.push({
testGroup: null, testGroup: null,
ageGroup: null, ageGroup: null,

View file

@ -43,7 +43,7 @@ require('./preview.scss');
const frameless = require('../../lib/frameless'); const frameless = require('../../lib/frameless');
const {useState, useCallback, useEffect} = require('react'); const {useState, useCallback, useEffect} = require('react');
const ProjectJourney = require('../../components/journeys/project-journey/project-journey.jsx'); const ProjectJourney = require('../../components/journeys/project-journey/project-journey.jsx');
const {triggerAnalyticsEvent, onboardingEligibilityCheck} = require('../../lib/onboarding.js'); const {triggerAnalyticsEvent, shouldDisplayOnboarding} = require('../../lib/onboarding.js');
// disable enter key submission on formsy input fields; otherwise formsy thinks // disable enter key submission on formsy input fields; otherwise formsy thinks
// we meant to trigger the "See inside" button. Instead, treat these keypresses // we meant to trigger the "See inside" button. Instead, treat these keypresses
@ -157,7 +157,7 @@ const PreviewPresentation = ({
setCanViewProjectJourney( setCanViewProjectJourney(
queryString.parse(location.search, {parseBooleans: true}).showJourney && queryString.parse(location.search, {parseBooleans: true}).showJourney &&
!userOwnsProject && !userOwnsProject &&
onboardingEligibilityCheck(user, permissions) shouldDisplayOnboarding(user, permissions)
); );
}, [userOwnsProject, user, permissions]); }, [userOwnsProject, user, permissions]);
const shareDate = ((projectInfo.history && projectInfo.history.shared)) ? projectInfo.history.shared : ''; const shareDate = ((projectInfo.history && projectInfo.history.shared)) ? projectInfo.history.shared : '';

View file

@ -47,7 +47,7 @@ const {useEffect, useState} = require('react');
const EditorJourney = require('../../components/journeys/editor-journey/editor-journey.jsx'); const EditorJourney = require('../../components/journeys/editor-journey/editor-journey.jsx');
const {usePrevious} = require('react-use'); const {usePrevious} = require('react-use');
const TutorialsHighlight = require('../../components/journeys/tutorials-highlight/tutorials-highlight.jsx'); const TutorialsHighlight = require('../../components/journeys/tutorials-highlight/tutorials-highlight.jsx');
const {triggerAnalyticsEvent, sendUserProperties, onboardingEligibilityCheck} = require('../../lib/onboarding.js'); const {triggerAnalyticsEvent, sendUserProperties, shouldDisplayOnboarding} = require('../../lib/onboarding.js');
const IntlGUIWithProjectHandler = ({...props}) => { const IntlGUIWithProjectHandler = ({...props}) => {
const [showJourney, setShowJourney] = useState(false); const [showJourney, setShowJourney] = useState(false);
@ -62,7 +62,7 @@ const IntlGUIWithProjectHandler = ({...props}) => {
props.projectId && props.projectId &&
props.projectId !== '0' && props.projectId !== '0' &&
!isTutorialOpen && !isTutorialOpen &&
onboardingEligibilityCheck(props.user, props.permissions) shouldDisplayOnboarding(props.user, props.permissions)
) { ) {
setShowJourney(true); setShowJourney(true);
} }
@ -258,8 +258,8 @@ class Preview extends React.Component {
); );
} }
if (!prevProps.user.id && this.props.user.id) { if (!prevProps.user.id && this.props.user.id && this.props.permissions) {
sendUserProperties(this.props.user); sendUserProperties(this.props.user, this.props.permissions);
} }
} }
componentWillUnmount () { componentWillUnmount () {
@ -548,7 +548,7 @@ class Preview extends React.Component {
} }
const showJourney = queryString.parse(location.search, {parseBooleans: true}).showJourney; const showJourney = queryString.parse(location.search, {parseBooleans: true}).showJourney;
if (showJourney && onboardingEligibilityCheck(this.props.user, this.props.permissions)) { if (showJourney && shouldDisplayOnboarding(this.props.user, this.props.permissions)) {
triggerAnalyticsEvent({ triggerAnalyticsEvent({
event: 'tutorial-played', event: 'tutorial-played',
playedProject: this.props.projectInfo.title playedProject: this.props.projectInfo.title
@ -667,7 +667,7 @@ class Preview extends React.Component {
} }
handleRemix () { handleRemix () {
const showJourney = queryString.parse(location.search, {parseBooleans: true}).showJourney; const showJourney = queryString.parse(location.search, {parseBooleans: true}).showJourney;
if (showJourney && onboardingEligibilityCheck(this.props.user, this.props.permissions)) { if (showJourney && shouldDisplayOnboarding(this.props.user, this.props.permissions)) {
triggerAnalyticsEvent({ triggerAnalyticsEvent({
event: 'tutorial-remixed', event: 'tutorial-remixed',
remixedProject: this.props.projectInfo.title remixedProject: this.props.projectInfo.title

View file

@ -1,4 +1,4 @@
import {onboardingEligibilityCheck} from '../../../src/lib/onboarding'; import {shouldDisplayOnboarding} from '../../../src/lib/onboarding';
describe('unit test lib/onboarding.js', () => { describe('unit test lib/onboarding.js', () => {
const startDate = new Date(); const startDate = new Date();
@ -9,7 +9,7 @@ describe('unit test lib/onboarding.js', () => {
let permissions; let permissions;
beforeEach(() => { beforeEach(() => {
process.env.ONBOARDING_TESTING_TOGGLED = true; process.env.ONBOARDING_TEST_ACTIVE = 'true';
process.env.ONBOARDING_TESTING_STARTING_DATE = startDate.toJSON().split('T')[0]; process.env.ONBOARDING_TESTING_STARTING_DATE = startDate.toJSON().split('T')[0];
process.env.ONBOARDING_TESTING_ENDING_DATE = endDate.toJSON().split('T')[0]; process.env.ONBOARDING_TESTING_ENDING_DATE = endDate.toJSON().split('T')[0];
@ -17,95 +17,71 @@ describe('unit test lib/onboarding.js', () => {
permissions = {admin: false, mute_status: {}, new_scratcher: true}; permissions = {admin: false, mute_status: {}, new_scratcher: true};
}); });
describe('#onboardingEligibilityCheck', () => { describe('#shouldDisplayOnboarding', () => {
describe('when user is eligible to view onboarding journeys', () => { describe('when user is eligible to view onboarding journeys', () => {
describe('when there is time frame for A/B testing', () => { describe('when there is time frame for A/B testing', () => {
test('returns true', () => { test('returns true', () => {
expect(onboardingEligibilityCheck(user, permissions)).toBeTruthy(); expect(shouldDisplayOnboarding(user, permissions)).toBeTruthy();
}); });
}); });
}); });
describe('when user is not eligible to view onboarding journeys', () => { describe('when user is not eligible to view onboarding journeys', () => {
describe('when feature flag is toggled off', () => { describe('when feature flag is toggled off', () => {
beforeEach(() => {
process.env.ONBOARDING_TESTING_TOGGLED = false;
});
test('returns false', () => { test('returns false', () => {
expect(onboardingEligibilityCheck(user, permissions)).toBeFalsy(); process.env.ONBOARDING_TEST_ACTIVE = 'false';
expect(shouldDisplayOnboarding(user, permissions)).toBeFalsy();
}); });
}); });
describe('when user is in other testing group', () => { describe('when user is in other testing group', () => {
beforeEach(() => {
user.id = 1;
});
test('returns false', () => { test('returns false', () => {
expect(onboardingEligibilityCheck(user, permissions)).toBeFalsy(); user.id = 1;
expect(shouldDisplayOnboarding(user, permissions)).toBeFalsy();
}); });
}); });
describe('when user is registered outside of time frame', () => { describe('when user is registered outside of time frame', () => {
beforeEach(() => { test('returns false', () => {
const currentDate = new Date(); const currentDate = new Date();
currentDate.setDate(currentDate.getDate() - 1); currentDate.setDate(currentDate.getDate() - 1);
user.dateJoined = currentDate.toJSON(); user.dateJoined = currentDate.toJSON();
}); expect(shouldDisplayOnboarding(user, permissions)).toBeFalsy();
test('returns false', () => {
expect(onboardingEligibilityCheck(user, permissions)).toBeFalsy();
}); });
}); });
describe('when user is admin', () => { describe('when user is admin', () => {
beforeEach(() => {
permissions.admin = true;
});
test('returns false', () => { test('returns false', () => {
expect(onboardingEligibilityCheck(user, permissions)).toBeFalsy(); permissions.admin = true;
expect(shouldDisplayOnboarding(user, permissions)).toBeFalsy();
}); });
}); });
describe('when user is muted', () => { describe('when user is muted', () => {
beforeEach(() => {
permissions.mute_status = {showWarning: true};
});
test('returns false', () => { test('returns false', () => {
expect(onboardingEligibilityCheck(user, permissions)).toBeFalsy(); permissions.mute_status = {showWarning: true};
expect(shouldDisplayOnboarding(user, permissions)).toBeFalsy();
}); });
}); });
describe('when user is banned', () => { describe('when user is banned', () => {
beforeEach(() => {
user.banned = true;
});
test('returns false', () => { test('returns false', () => {
expect(onboardingEligibilityCheck(user, permissions)).toBeFalsy(); user.banned = true;
expect(shouldDisplayOnboarding(user, permissions)).toBeFalsy();
}); });
}); });
describe('when user is empty', () => { describe('when user is empty', () => {
beforeEach(() => {
user = {};
});
test('returns false', () => { test('returns false', () => {
expect(onboardingEligibilityCheck(user, permissions)).toBeFalsy(); user = {};
expect(shouldDisplayOnboarding(user, permissions)).toBeFalsy();
}); });
}); });
describe('when permissions is empty', () => { describe('when permissions is empty', () => {
beforeEach(() => {
permissions = {};
});
test('returns false', () => { test('returns false', () => {
expect(onboardingEligibilityCheck(user, permissions)).toBeFalsy(); permissions = {};
expect(shouldDisplayOnboarding(user, permissions)).toBeFalsy();
}); });
}); });
}); });

View file

@ -287,8 +287,8 @@ module.exports = {
'process.env.GTM_ID': process.env.GTM_ID ? `"${process.env.GTM_ID}"` : null, 'process.env.GTM_ID': process.env.GTM_ID ? `"${process.env.GTM_ID}"` : null,
'process.env.USER_GUIDING_ID': `"${process.env.USER_GUIDING_ID || ''}"`, 'process.env.USER_GUIDING_ID': `"${process.env.USER_GUIDING_ID || ''}"`,
'process.env.SORTING_HAT_HOST': `"${process.env.SORTING_HAT_HOST || ''}"`, 'process.env.SORTING_HAT_HOST': `"${process.env.SORTING_HAT_HOST || ''}"`,
'process.env.ONBOARDING_TESTING_TOGGLED': `"${ 'process.env.ONBOARDING_TEST_ACTIVE': `"${
process.env.ONBOARDING_TESTING_TOGGLED || true process.env.ONBOARDING_TEST_ACTIVE || true
}"`, }"`,
'process.env.ONBOARDING_TESTING_STARTING_DATE': `"${ 'process.env.ONBOARDING_TESTING_STARTING_DATE': `"${
process.env.ONBOARDING_TESTING_STARTING_DATE || '2024-01-20' process.env.ONBOARDING_TESTING_STARTING_DATE || '2024-01-20'