Skip to content

Commit

Permalink
feat: Integrated Optimizely Prompt Experiment (#52)
Browse files Browse the repository at this point in the history
* feat: Integrated Optimizely Prompt Experiment

* fix: Fixed useOptimizelyExperiment() infinite updates

* feat: trigger survey monkey on chat close (#55)

* feat: trigger survey monkey on chat close

* fix: Fixed useOptimizelyExperiment() infinite updates

* fix: read experiment state correctly

* feat: add tests

* fix: fix lint errors

* fix: remove flaky test

---------

Co-authored-by: Marcos <rigoli82@gmail.com>

* chore: Added unit tests to useOptimizelyExperiment()

* chore: Updated tests to silence warnings on CI

* chore: Added coverage for experiment on Sidebar

* fix: Updated Sidebar test and fixed warning

* chore: Added test coverage for ToggleXpertButton component

* chore: Updated logic for privacy policy in Dixclosure

* fix: Added ensureConfig() rather than conditioning the render

* fix: Casting number to string for useDecision() payload.

Co-authored-by: Zachary Hancock <zhancock278@gmail.com>

* chore: Updated test based on Optimizely fix

---------

Co-authored-by: Alison Langston <46360176+alangsto@users.noreply.github.com>
Co-authored-by: Zachary Hancock <zhancock278@gmail.com>
  • Loading branch information
3 people authored Jul 11, 2024
1 parent 3cf84b8 commit e9791c8
Show file tree
Hide file tree
Showing 21 changed files with 707 additions and 77 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Default CI
on:
on:
push:
branches:
- 'main'
Expand Down Expand Up @@ -28,7 +28,7 @@ jobs:
- name: Lint
run: npm run lint
- name: Test
run: npm run test
run: npm run test:ci
- name: Build
run: npm run build
- name: i18n_extract
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Install dependencies
run: npm ci
- name: Test
run: npm run test
run: npm run test:ci
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
68 changes: 52 additions & 16 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"lint:fix": "fedx-scripts eslint --fix --ext .js --ext .jsx .",
"snapshot": "fedx-scripts jest --updateSnapshot",
"start": "fedx-scripts webpack-dev-server --progress",
"test": "fedx-scripts jest --coverage --passWithNoTests"
"test": "fedx-scripts jest --coverage --passWithNoTests",
"test:ci": "fedx-scripts jest --silent --coverage --passWithNoTests"
},
"files": [
"/dist"
Expand Down Expand Up @@ -72,6 +73,7 @@
"@reduxjs/toolkit": "1.8.1",
"@testing-library/jest-dom": "6.4.5",
"@testing-library/react": "^12.1.5",
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^14.4.3",
"glob": "7.2.3",
"husky": "7.0.4",
Expand Down
4 changes: 3 additions & 1 deletion src/components/Disclosure/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import React from 'react';

import { Hyperlink, Icon } from '@openedx/paragon';
import { Chat } from '@openedx/paragon/icons';
import { getConfig } from '@edx/frontend-platform/config';
import { ensureConfig, getConfig } from '@edx/frontend-platform/config';

import './Disclosure.scss';

ensureConfig(['PRIVACY_POLICY_URL']);

const Disclosure = ({ children }) => (
<div className="disclosure d-flex flex-column align-items-stretch px-4 py-3">
<h2 className="text-light-100">
Expand Down
27 changes: 18 additions & 9 deletions src/components/Sidebar/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import {
} from '@openedx/paragon';
import { Close } from '@openedx/paragon/icons';

import { clearMessages } from '../../data/thunks';
import { PROMPT_EXPERIMENT_FLAG, PROMPT_EXPERIMENT_KEY } from '../../constants/experiments';
import { showControlSurvey, showVariationSurvey } from '../../utils/surveyMonkey';

import APIError from '../APIError';
import ChatBox from '../ChatBox';
import Disclosure from '../Disclosure';
import MessageForm from '../MessageForm';
import './Sidebar.scss';
import {
clearMessages,
} from '../../data/thunks';

const Sidebar = ({
courseId,
Expand All @@ -28,7 +29,9 @@ const Sidebar = ({
apiError,
disclosureAcknowledged,
messageList,
experiments,
} = useSelector(state => state.learningAssistant);
const { variationKey } = experiments?.[PROMPT_EXPERIMENT_FLAG] || {};
const chatboxContainerRef = useRef(null);
const dispatch = useDispatch();

Expand Down Expand Up @@ -69,17 +72,20 @@ const Sidebar = ({
const handleClick = () => {
setIsOpen(false);

// check to see if hotjar is available, then trigger hotjar event if user has sent and received a message
const hasWindow = typeof window !== 'undefined';
if (hasWindow && window.hj && messageList.length >= 2) {
window.hj('event', 'ocm_learning_assistant_chat_closed');
if (messageList.length >= 2) {
if (variationKey === PROMPT_EXPERIMENT_KEY) {
showVariationSurvey();
} else {
showControlSurvey();
}
}
};

const handleClearMessages = () => {
dispatch(clearMessages());
sendTrackEvent('edx.ui.lms.learning_assistant.clear', {
course_id: courseId,
...(variationKey ? { experiment_name: PROMPT_EXPERIMENT_FLAG, variation_key: variationKey } : {}),
});
};

Expand All @@ -88,7 +94,7 @@ const Sidebar = ({
);

const getSidebar = () => (
<div className="h-100 d-flex flex-column justify-content-stretch">
<div className="h-100 d-flex flex-column justify-content-stretch" data-testid="sidebar-xpert">
<div className="d-flex flex-column align-items-center p-3">
<h1 className="font-weight-bold mb-3">
Hi, I&apos;m Xpert!
Expand Down Expand Up @@ -119,6 +125,7 @@ const Sidebar = ({
aria-label="clear"
variant="primary"
type="button"
data-testid="sidebar-clear-btn"
>
Clear
</Button>
Expand All @@ -130,16 +137,18 @@ const Sidebar = ({
isOpen && (
<div
className="sidebar position-fixed"
data-testid="sidebar"
>
<IconButton
className="chat-close position-absolute m-2 border-0"
src={Close}
iconAs={Icon}
data-testid="close-button"
onClick={handleClick}
alt="close"
aria-label="close"
variant="primary"
invertColors={!disclosureAcknowledged}
data-testid="close-button"
/>
{disclosureAcknowledged ? (getSidebar()) : (<Disclosure>{getMessageForm()}</Disclosure>)}
</div>
Expand Down
Loading

0 comments on commit e9791c8

Please sign in to comment.