Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ mergedConfig.transform['^.+\\.[tj]sx?$'] = [
];

module.exports = mergedConfig;

module.exports.transformIgnorePatterns = [
'/node_modules/(?!(@edx|@edunext|@openedx))',
];
540 changes: 525 additions & 15 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"url": "https://github.com/openedx/frontend-app-learning/issues"
},
"dependencies": {
"@edunext/frontend-essentials": "^5.0.1",
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.3",
"@edx/browserslist-config": "1.5.1",
"@edx/frontend-component-footer": "^14.6.0",
Expand Down Expand Up @@ -88,7 +89,7 @@
"files": [
{
"path": "dist/*.js",
"maxSize": "1450kB"
"maxSize": "1536kB"
}
],
"normalizeFilenames": "^.+?(\\..+?)\\.\\w+$"
Expand Down
4 changes: 4 additions & 0 deletions src/course-home/outline-tab/OutlineTab.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Button } from '@openedx/paragon';
import { FeedbackModal, useProgressStatus } from '@edunext/frontend-essentials';
import { CourseOutlineTabNotificationsSlot } from '../../plugin-slots/CourseOutlineTabNotificationsSlot';
import { AlertList } from '../../generic/user-messages';

Expand Down Expand Up @@ -116,6 +117,8 @@ const OutlineTab = () => {
}
}, [location.search]);

const { isComplete, isGraded, isPassing } = useProgressStatus(courseId);

return (
<>
<div data-learner-type={learnerType} className="row w-100 mx-0 my-3 justify-content-between">
Expand Down Expand Up @@ -186,6 +189,7 @@ const OutlineTab = () => {
<CourseHandouts />
</div>
)}
<FeedbackModal courseId={courseId} showModal={isGraded ? isPassing : isComplete} />
</div>
</>
);
Expand Down
4 changes: 4 additions & 0 deletions src/course-home/outline-tab/OutlineTab.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ describe('Outline Tab', () => {
const masqueradeUrl = `${getConfig().LMS_BASE_URL}/courses/${courseId}/masquerade`;
const outlineUrl = `${getConfig().LMS_BASE_URL}/api/course_home/outline/${courseId}`;
const proctoringInfoUrl = `${getConfig().EXAMS_BASE_URL}/api/v1/student/course_id/${encodeURIComponent(courseId)}/onboarding?username=MockUser`;
const progressUrl = `${getConfig().LMS_BASE_URL}/api/course_home/progress/${courseId}`;

const store = initializeStore();
const defaultMetadata = Factory.build('courseHomeMetadata');
Expand Down Expand Up @@ -94,6 +95,9 @@ describe('Outline Tab', () => {
onboarding_link: 'test',
expiration_date: null,
});
// This will return 404 in order to set the failure behavior and don't set extra
// extra conditions required by the success path.
axiosMock.onGet(progressUrl).reply(404, {});

// Mock courseware search params
mockSearchParams();
Expand Down
10 changes: 9 additions & 1 deletion src/courseware/course/sequence/Sequence.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { useIntl } from '@edx/frontend-platform/i18n';
import { useSelector } from 'react-redux';
import SequenceExamWrapper from '@edx/frontend-lib-special-exams';
import { LikeDislikeUnit } from '@edunext/frontend-essentials';

import PageLoading from '@src/generic/PageLoading';
import { useModel } from '@src/generic/model-store';
Expand Down Expand Up @@ -224,7 +225,14 @@ const Sequence = ({
isOriginalUserStaff={originalUserIsStaff}
renderUnitNavigation={renderUnitNavigation}
/>
{unitHasLoaded && renderUnitNavigation(false)}
{unitHasLoaded && (
<>
<div className="nelp-container">
<LikeDislikeUnit courseId={courseId} unitId={unitId} />
</div>
{renderUnitNavigation(false)}
</>
)}
</div>
</div>
<RightSidebarSlot courseId={courseId} />
Expand Down
4 changes: 2 additions & 2 deletions src/courseware/course/sequence/Sequence.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ describe('Sequence', () => {
waitFor(() => {
expect(screen.queryByText('Loading locked content messaging...')).toBeInTheDocument();
// `Previous`, `Prerequisite` and `Close Tray` buttons.
expect(screen.getAllByRole('button').length).toEqual(3);
expect(screen.getAllByRole('button').length).toEqual(5); // two more buttons like and dislike
// `Next` button.
expect(screen.getAllByRole('link').length).toEqual(1);

Expand Down Expand Up @@ -158,7 +158,7 @@ describe('Sequence', () => {
waitFor(() => {
expect(screen.findByText('Loading learning sequence...')).toBeInTheDocument();
// `Previous`, `Prerequisite` and `Close Tray` buttons.
expect(screen.getAllByRole('button')).toHaveLength(3);
expect(screen.getAllByRole('button')).toHaveLength(5); // two more buttons like and dislike
// Renders `Next` button.
expect(screen.getAllByRole('link')).toHaveLength(1);

Expand Down
4 changes: 4 additions & 0 deletions src/product-tours/ProductTours.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ describe('Course Home Tours', () => {
const outlineUrl = `${getConfig().LMS_BASE_URL}/api/course_home/outline/${courseId}`;
const tourDataUrl = `${getConfig().LMS_BASE_URL}/api/user_tours/v1/MockUser`;
const proctoringUrl = `${getConfig().LMS_BASE_URL}/api/edx_proctoring/v1/user_onboarding/status?is_learning_mfe=true&course_id=course-v1%3AedX%2BTest%2Brun&username=MockUser`;
const progressUrl = `${getConfig().LMS_BASE_URL}/api/course_home/progress/${courseId}`;

const store = initializeStore();
const defaultTabData = Factory.build('outlineTabData');
Expand Down Expand Up @@ -80,6 +81,9 @@ describe('Course Home Tours', () => {
course_home_tour_status: 'no-tour',
show_courseware_tour: false,
});
// This will return 404 in order to set the failure behavior and don't set extra
// extra conditions required by the success path.
axiosMock.onGet(progressUrl).reply(404, {});

logUnhandledRequests(axiosMock);
});
Expand Down
3 changes: 3 additions & 0 deletions src/setupTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ export async function initializeTestStore(options = {}, overrideStore = true) {
const proctoredExamApiUrl = `${getConfig().LMS_BASE_URL}/api/edx_proctoring/v1/proctored_exam/attempt/course_id/${courseMetadata.id}/content_id/${sequenceMetadata.item_id}?is_learning_mfe=true`;
axiosMock.onGet(proctoredExamApiUrl).reply(200, { exam: {}, active_attempt: {} });
});
// frontend essentials configuration, this will return an status 404 on every like-dislike request
const likeDislikeUrlPattern = new RegExp(`${getConfig().COURSE_EXPERIENCE_API_URL}/like/units/.*/`);
axiosMock.onGet(likeDislikeUrlPattern).reply(404, {});

logUnhandledRequests(axiosMock);

Expand Down
Loading