richie-education 2.29.3-dev50 → 2.29.3-dev55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,6 @@
1
1
  import { screen, waitFor } from '@testing-library/react';
2
2
  import fetchMock from 'fetch-mock';
3
+ import { faker } from '@faker-js/faker';
3
4
  import {
4
5
  CourseRunFactory,
5
6
  RichieContextFactory as mockRichieContextFactory,
@@ -11,12 +12,12 @@ import { render } from 'utils/test/render';
11
12
  import {
12
13
  CourseLightFactory,
13
14
  CredentialOrderFactory,
14
- EnrollmentFactory,
15
15
  ProductFactory,
16
16
  } from 'utils/test/factories/joanie';
17
17
  import { setupJoanieSession } from 'utils/test/wrappers/JoanieAppWrapper';
18
18
  import { mockPaginatedResponse } from 'utils/test/mockPaginatedResponse';
19
19
  import { expectNoSpinner } from 'utils/test/expectSpinner';
20
+ import { ACTIVE_ORDER_STATES, PURCHASABLE_ORDER_STATES } from 'types/Joanie';
20
21
  import CourseRunItemWithEnrollment from '.';
21
22
 
22
23
  jest.mock('utils/context', () => ({
@@ -61,10 +62,9 @@ describe("CourseRunItemWithEnrollment for joanie's product's course run", () =>
61
62
  expect(screen.queryByRole('link')).not.toBeInTheDocument();
62
63
  });
63
64
 
64
- it('should not render enrollment information when user is not enrolled to the course run', async () => {
65
+ it('should not render enrollment information when user has no order for the product', async () => {
65
66
  const course = CourseLightFactory().one();
66
67
  const product = ProductFactory().one();
67
- const order = CredentialOrderFactory().one();
68
68
  const user = UserFactory().one();
69
69
  const courseRun = CourseRunFactory({
70
70
  title: 'run',
@@ -73,6 +73,39 @@ describe("CourseRunItemWithEnrollment for joanie's product's course run", () =>
73
73
  resource_link: `https://joanie.endpoint/api/v1.0/courses/${course.code}/products/${product.id}`,
74
74
  }).one();
75
75
 
76
+ fetchMock.get(
77
+ `https://joanie.endpoint/api/v1.0/orders/?course_code=${course.code}&product_id=${product.id}`,
78
+ mockPaginatedResponse([], 0, false),
79
+ );
80
+
81
+ render(<CourseRunItemWithEnrollment item={courseRun} />, {
82
+ wrapper: BaseJoanieAppWrapper,
83
+ queryOptions: { client: createTestQueryClient({ user }) },
84
+ });
85
+ await expectNoSpinner();
86
+
87
+ // Only dates should be displayed.
88
+ screen.getByText('Run, from Jan 01, 2023 to Dec 31, 2023');
89
+ expect(fetchMock.called()).toBe(true);
90
+ const link = screen.queryByTitle('Go to course') as HTMLAnchorElement;
91
+ expect(link).not.toBeInTheDocument();
92
+ expect(screen.queryByLabelText('You are enrolled in this course run')).not.toBeInTheDocument();
93
+ });
94
+
95
+ it('should not render enrollment information when user has no active order for the product', async () => {
96
+ const course = CourseLightFactory().one();
97
+ const product = ProductFactory().one();
98
+ const user = UserFactory().one();
99
+ const order = CredentialOrderFactory({
100
+ state: faker.helpers.arrayElement(PURCHASABLE_ORDER_STATES),
101
+ }).one();
102
+ const courseRun = CourseRunFactory({
103
+ title: 'run',
104
+ start: new Date('2023-01-01').toISOString(),
105
+ end: new Date('2023-12-31').toISOString(),
106
+ resource_link: `https://joanie.endpoint/api/v1.0/courses/${course.code}/products/${product.id}`,
107
+ }).one();
108
+
76
109
  fetchMock.get(
77
110
  `https://joanie.endpoint/api/v1.0/orders/?course_code=${course.code}&product_id=${product.id}`,
78
111
  mockPaginatedResponse([order], 1, false),
@@ -84,20 +117,19 @@ describe("CourseRunItemWithEnrollment for joanie's product's course run", () =>
84
117
  });
85
118
  await expectNoSpinner();
86
119
 
87
- // Only dates should have been displayed.
120
+ // Only dates should be displayed.
88
121
  screen.getByText('Run, from Jan 01, 2023 to Dec 31, 2023');
89
122
  expect(fetchMock.called()).toBe(true);
90
123
  const link = screen.queryByTitle('Go to course') as HTMLAnchorElement;
91
- expect(link).toBeInTheDocument();
92
- expect(link.href).toBe(`https://localhost/en/dashboard/courses/orders/${order.id}`);
124
+ expect(link).not.toBeInTheDocument();
93
125
  expect(screen.queryByLabelText('You are enrolled in this course run')).not.toBeInTheDocument();
94
126
  });
95
127
 
96
- it('should render enrollment information when user is enrolled to the course run', async () => {
128
+ it('should render enrollment information when user has an active order for the product', async () => {
97
129
  const course = CourseLightFactory().one();
98
130
  const product = ProductFactory().one();
99
131
  const order = CredentialOrderFactory({
100
- target_enrollments: EnrollmentFactory({ is_active: true }).many(1),
132
+ state: faker.helpers.arrayElement(ACTIVE_ORDER_STATES),
101
133
  }).one();
102
134
  const user = UserFactory().one();
103
135
  const courseRun = CourseRunFactory({
@@ -121,7 +153,6 @@ describe("CourseRunItemWithEnrollment for joanie's product's course run", () =>
121
153
  expect(screen.queryByText('loading...')).not.toBeInTheDocument();
122
154
  });
123
155
 
124
- // Only dates should have been displayed.
125
156
  screen.getByText('Run, from Jan 01, 2023 to Dec 31, 2023');
126
157
  expect(fetchMock.called()).toBe(true);
127
158
 
@@ -8,6 +8,8 @@ import { getDashboardBasename } from 'widgets/Dashboard/hooks/useDashboardRouter
8
8
  import { LearnerDashboardPaths } from 'widgets/Dashboard/utils/learnerRoutesPaths';
9
9
  import useCourseRunOrder from 'hooks/useCourseRunOrder';
10
10
  import { Spinner } from 'components/Spinner';
11
+ import { OrderHelper } from 'utils/OrderHelper';
12
+ import { extractResourceMetadata } from 'api/lms/joanie';
11
13
 
12
14
  const messages = defineMessages({
13
15
  goToCourse: {
@@ -33,6 +35,8 @@ type Props = {
33
35
 
34
36
  const CourseRunItemWithEnrollment = ({ item }: Props) => {
35
37
  const intl = useIntl();
38
+ const resourceLinkResources = extractResourceMetadata(item.resource_link);
39
+ const isProduct = !!(resourceLinkResources?.course && resourceLinkResources?.product);
36
40
  const {
37
41
  item: order,
38
42
  states: { isFetched },
@@ -43,14 +47,12 @@ const CourseRunItemWithEnrollment = ({ item }: Props) => {
43
47
 
44
48
  const { enrollmentIsActive: courseRunEnrollmentIsActive } = useCourseEnrollment(
45
49
  item.resource_link,
46
- isFetched && !order,
50
+ !isProduct,
47
51
  );
48
52
 
49
- // user is enroll to a product if any of the product's target course have a active enrollment
50
- const productEnrollmentIsActive = order?.target_enrollments.some((enrollment) => {
51
- return enrollment.is_active;
52
- });
53
- const enrollmentIsActive = !!(courseRunEnrollmentIsActive || productEnrollmentIsActive);
53
+ // user is enrolled to a product if there is an active order for the product
54
+ const orderIsActive = OrderHelper.isActive(order);
55
+ const enrollmentIsActive = !!(courseRunEnrollmentIsActive || orderIsActive);
54
56
 
55
57
  if (!isFetched) {
56
58
  return <Spinner />;
@@ -58,7 +60,7 @@ const CourseRunItemWithEnrollment = ({ item }: Props) => {
58
60
 
59
61
  return (
60
62
  <>
61
- {enrollmentIsActive || !!order ? (
63
+ {enrollmentIsActive ? (
62
64
  // eslint-disable-next-line jsx-a11y/control-has-associated-label
63
65
  <a href={courseUrl} title={intl.formatMessage(messages.goToCourse)}>
64
66
  <CourseRunItem item={item} />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "richie-education",
3
- "version": "2.29.3-dev50",
3
+ "version": "2.29.3-dev55",
4
4
  "description": "A CMS to build learning portals for Open Education",
5
5
  "main": "sandbox/manage.py",
6
6
  "scripts": {