Merge pull request #411 from edx/bseverino/optimizely

[MST-655] Add Optimizely to be used with IDV experiments
This commit is contained in:
Bianca Severino
2021-03-11 11:56:20 -05:00
committed by GitHub
7 changed files with 58 additions and 5 deletions

View File

@@ -5,6 +5,11 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="<%=webpackConfig.output.publicPath%>favicon.ico" type="image/x-icon" />
<% if (process.env.OPTIMIZELY_PROJECT_ID) { %>
<script
src="<%= process.env.MARKETING_SITE_BASE_URL %>/optimizelyjs/<%= process.env.OPTIMIZELY_PROJECT_ID %>.js"
></script>
<% } %>
</head>
<body>
<div id="root"></div>

View File

@@ -20,6 +20,7 @@ export default function IdVerificationContextProvider({ children }) {
const [canVerify, setCanVerify] = useState(true);
const [error, setError] = useState('');
const { authenticatedUser } = useContext(AppContext);
const [optimizelyExperimentName, setOptimizelyExperimentName] = useState('');
const contextValue = {
existingIdVerification,
@@ -30,10 +31,12 @@ export default function IdVerificationContextProvider({ children }) {
mediaAccess,
userId: authenticatedUser.userId,
nameOnAccount: authenticatedUser.name,
optimizelyExperimentName,
setExistingIdVerification,
setFacePhotoFile,
setIdPhotoFile,
setIdPhotoName,
setOptimizelyExperimentName,
tryGetUserMedia: async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });

View File

@@ -64,6 +64,7 @@ export async function submitIdVerification(verificationData) {
facePhotoFile: 'face_image',
idPhotoFile: 'photo_id_image',
idPhotoName: 'full_name',
optimizelyExperimentName: 'experiment_name',
};
const postData = {};
// Don't include blank/null/undefined values.

View File

@@ -11,15 +11,29 @@ import messages from '../IdVerification.messages';
import exampleCard from '../assets/example-card.png';
function ReviewRequirementsPanel(props) {
const { userId } = useContext(IdVerificationContext);
const { userId, setOptimizelyExperimentName } = useContext(IdVerificationContext);
const panelSlug = 'review-requirements';
const nextPanelSlug = useNextPanelSlug(panelSlug);
const getExperiments = () => {
const {
experimentVariables: {
experimentName = '',
} = {},
} = window;
if (experimentName) {
setOptimizelyExperimentName(experimentName);
}
};
useEffect(() => {
sendTrackEvent('edx.id_verification.started', {
category: 'id_verification',
user_id: userId,
});
getExperiments();
}, [userId]);
return (

View File

@@ -24,6 +24,7 @@ function SummaryPanel(props) {
nameOnAccount,
idPhotoName,
stopUserMedia,
optimizelyExperimentName,
} = useContext(IdVerificationContext);
const nameToBeUsed = idPhotoName || nameOnAccount || '';
const [isSubmitting, setIsSubmitting] = useState(false);
@@ -32,12 +33,15 @@ function SummaryPanel(props) {
function SubmitButton() {
async function handleClick() {
setIsSubmitting(true);
const verificationData = {
let verificationData = {
facePhotoFile,
idPhotoFile,
idPhotoName: nameToBeUsed,
courseRunKey: sessionStorage.getItem('courseRunKey'),
};
if (optimizelyExperimentName) {
verificationData = { ...verificationData, optimizelyExperimentName };
}
const result = await submitIdVerification(verificationData);
if (result.success) {
stopUserMedia();

View File

@@ -6,6 +6,7 @@ import {
} from '@testing-library/react';
import '@edx/frontend-platform/analytics';
import { injectIntl, IntlProvider } from '@edx/frontend-platform/i18n';
import IdVerificationContext from '../../IdVerificationContext';
import ReviewRequirementsPanel from '../../panels/ReviewRequirementsPanel';
jest.mock('@edx/frontend-platform/analytics', () => ({
@@ -21,6 +22,8 @@ describe('ReviewRequirementsPanel', () => {
intl: {},
};
const context = { setOptimizelyExperimentName: jest.fn() };
afterEach(() => {
cleanup();
});
@@ -37,4 +40,19 @@ describe('ReviewRequirementsPanel', () => {
fireEvent.click(button);
expect(history.location.pathname).toEqual('/request-camera-access');
});
it('updates optimizely experiment name in context', async () => {
window.experimentVariables = {};
window.experimentVariables.experimentName = 'test-experiment';
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={context}>
<IntlReviewRequirementsPanel {...defaultProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
expect(context.setOptimizelyExperimentName).toHaveBeenCalledWith('test-experiment');
});
});

View File

@@ -30,8 +30,9 @@ describe('SummaryPanel', () => {
const contextValue = {
facePhotoFile: 'test.jpg',
idPhotoFile: 'test.jpg',
nameOnAccount: '',
idPhotoName: '',
nameOnAccount: 'test name',
idPhotoName: 'test name',
optimizelyExperimentName: 'test-experiment',
stopUserMedia: jest.fn(),
};
@@ -76,10 +77,17 @@ describe('SummaryPanel', () => {
});
it('submits', async () => {
const verificationData = {
facePhotoFile: contextValue.facePhotoFile,
idPhotoFile: contextValue.idPhotoFile,
idPhotoName: contextValue.idPhotoName,
optimizelyExperimentName: contextValue.optimizelyExperimentName,
courseRunKey: null,
};
await getPanel();
const button = await screen.findByTestId('submit-button');
fireEvent.click(button);
expect(dataService.submitIdVerification).toHaveBeenCalled();
expect(dataService.submitIdVerification).toHaveBeenCalledWith(verificationData);
await waitFor(() => expect(contextValue.stopUserMedia).toHaveBeenCalled());
});