eionet2-dashboard 3.2.0 → 3.2.2

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.
Files changed (61) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/Jenkinsfile +2 -2
  3. package/api/getGraphData/index.js +3 -4
  4. package/package.json +2 -2
  5. package/tabs/package-lock.json +2927 -1866
  6. package/tabs/package.json +3 -3
  7. package/tabs/public/auth-start.html +2 -2
  8. package/tabs/src/components/App.test.jsx +67 -0
  9. package/tabs/src/components/BottomMenu.test.jsx +94 -0
  10. package/tabs/src/components/CustomColumnResizeIcon.test.jsx +17 -0
  11. package/tabs/src/components/CustomDrawer.test.jsx +14 -0
  12. package/tabs/src/components/CustomGridToolbar.test.jsx +8 -0
  13. package/tabs/src/components/EventDialogTitle.test.jsx +25 -0
  14. package/tabs/src/components/HtmlBox.test.jsx +41 -0
  15. package/tabs/src/components/Privacy.test.jsx +11 -0
  16. package/tabs/src/components/ResizableGrid.test.jsx +64 -0
  17. package/tabs/src/components/Tab.scss +6 -0
  18. package/tabs/src/components/Tab.test.jsx +463 -0
  19. package/tabs/src/components/TabConfig.test.jsx +27 -0
  20. package/tabs/src/components/TabPanel.test.jsx +31 -0
  21. package/tabs/src/components/TermsOfUse.test.jsx +11 -0
  22. package/tabs/src/components/UnderConstruction.test.jsx +13 -0
  23. package/tabs/src/components/UserMenu.test.jsx +53 -0
  24. package/tabs/src/components/activity/Activity.test.jsx +218 -0
  25. package/tabs/src/components/activity/ConsultationList.test.jsx +114 -0
  26. package/tabs/src/components/activity/EventList.test.jsx +164 -0
  27. package/tabs/src/components/activity/GroupsTags.test.jsx +23 -0
  28. package/tabs/src/components/activity/ObligationList.test.jsx +46 -0
  29. package/tabs/src/components/activity/PublicationList.test.jsx +46 -0
  30. package/tabs/src/components/activity/Reporting.test.jsx +11 -0
  31. package/tabs/src/components/event_rating/EventRating.test.jsx +63 -0
  32. package/tabs/src/components/event_rating/EventRatingDialog.test.jsx +28 -0
  33. package/tabs/src/components/event_registration/Approval.test.jsx +25 -0
  34. package/tabs/src/components/event_registration/ApprovalDialog.test.jsx +25 -0
  35. package/tabs/src/components/event_registration/ApprovalList.test.jsx +36 -0
  36. package/tabs/src/components/event_registration/EventExternalRegistration.test.jsx +219 -0
  37. package/tabs/src/components/event_registration/EventRegistration.test.jsx +208 -0
  38. package/tabs/src/components/my_country/AtAGlance.test.jsx +157 -0
  39. package/tabs/src/components/my_country/CountryMembers.test.jsx +117 -0
  40. package/tabs/src/components/my_country/CountryProgress.test.jsx +21 -0
  41. package/tabs/src/components/my_country/DataReporters.test.jsx +156 -0
  42. package/tabs/src/components/my_country/FullCircularProgress.test.jsx +19 -0
  43. package/tabs/src/components/my_country/GroupView.test.jsx +165 -0
  44. package/tabs/src/components/my_country/GroupsBoard.test.jsx +30 -0
  45. package/tabs/src/components/my_country/IndicatorCard.test.jsx +27 -0
  46. package/tabs/src/components/my_country/ManagementBoard.test.jsx +119 -0
  47. package/tabs/src/components/my_country/MyCountry.test.jsx +220 -0
  48. package/tabs/src/components/my_country/ProgressGauge.test.jsx +34 -0
  49. package/tabs/src/components/my_country/ScientificCommittee.test.jsx +11 -0
  50. package/tabs/src/components/my_country/UserCard.test.jsx +24 -0
  51. package/tabs/src/components/my_country/YearlyProgress.test.jsx +33 -0
  52. package/tabs/src/components/self_service/UserEdit.test.jsx +213 -0
  53. package/tabs/src/data/apiProvider.test.js +228 -0
  54. package/tabs/src/data/icsHelper.test.js +76 -0
  55. package/tabs/src/data/provider.test.js +351 -0
  56. package/tabs/src/data/reportingProvider.test.js +103 -0
  57. package/tabs/src/data/selfServiceProvider.test.js +108 -0
  58. package/tabs/src/data/selfServiceSharepointProvider.test.js +100 -0
  59. package/tabs/src/data/sharepointProvider.test.js +669 -0
  60. package/tabs/src/data/validator.test.js +34 -2
  61. package/tabs/yarn.lock +415 -414
@@ -0,0 +1,218 @@
1
+ jest.mock('react', () => {
2
+ const actual = jest.requireActual('react');
3
+ return {
4
+ ...actual,
5
+ React: actual,
6
+ useState: jest.fn(actual.useState),
7
+ useEffect: jest.fn((fn) => fn()),
8
+ useCallback: jest.fn((fn) => fn),
9
+ };
10
+ });
11
+
12
+ import React from 'react';
13
+ import { renderToStaticMarkup } from 'react-dom/server';
14
+ import { Activity } from './Activity';
15
+ import {
16
+ getConsultations,
17
+ getMeetings,
18
+ getPublications,
19
+ getObligations,
20
+ } from '../../data/sharepointProvider';
21
+ import { useAppInsightsContext } from '@microsoft/applicationinsights-react-js';
22
+
23
+ jest.mock('./activity.scss', () => ({}));
24
+
25
+ jest.mock('@mui/material', () => {
26
+ const ReactLocal = require('react');
27
+ const passthrough =
28
+ (Tag = 'div') =>
29
+ ({ children }) =>
30
+ ReactLocal.createElement(Tag, {}, children);
31
+
32
+ const ListItemButton = ({ children, onClick }) => {
33
+ onClick && onClick();
34
+ return <div>{children}</div>;
35
+ };
36
+
37
+ return {
38
+ Backdrop: passthrough(),
39
+ CircularProgress: passthrough('span'),
40
+ Box: passthrough(),
41
+ ListItem: passthrough(),
42
+ ListItemIcon: passthrough(),
43
+ ListItemText: ({ primary }) => <div>{primary}</div>,
44
+ ListItemButton,
45
+ };
46
+ });
47
+
48
+ jest.mock('@mui/icons-material/Loop', () => () => <span>loop-icon</span>);
49
+ jest.mock('@mui/icons-material/FastForwardOutlined', () => () => <span>fast-forward-icon</span>);
50
+ jest.mock('@mui/icons-material/HistoryOutlined', () => () => <span>history-icon</span>);
51
+ jest.mock('@mui/icons-material/NextPlanOutlined', () => () => <span>next-plan-icon</span>);
52
+
53
+ jest.mock('./ConsultationList', () => ({
54
+ ConsultationList: () => <div>consultation-list</div>,
55
+ }));
56
+ jest.mock('./EventList', () => ({
57
+ EventList: () => <div>event-list</div>,
58
+ }));
59
+ jest.mock('./PublicationList', () => ({
60
+ PublicatonList: () => <div>publication-list</div>,
61
+ }));
62
+ jest.mock('./ObligationList', () => ({
63
+ ObligationList: () => <div>obligation-list</div>,
64
+ }));
65
+
66
+ jest.mock('../CustomDrawer', () => ({
67
+ __esModule: true,
68
+ default: ({ drawerOptions }) => <div>{drawerOptions}</div>,
69
+ }));
70
+
71
+ jest.mock('../../data/sharepointProvider', () => ({
72
+ getConsultations: jest.fn(),
73
+ getMeetings: jest.fn(),
74
+ getPublications: jest.fn(),
75
+ getObligations: jest.fn(),
76
+ }));
77
+
78
+ jest.mock('@microsoft/applicationinsights-react-js', () => ({
79
+ useAppInsightsContext: jest.fn(),
80
+ }));
81
+
82
+ function mockStateSequence(values) {
83
+ let index = 0;
84
+ React.useState.mockImplementation((initialValue) => {
85
+ if (index < values.length) {
86
+ const current = values[index];
87
+ index += 1;
88
+ return [current, jest.fn()];
89
+ }
90
+ return [initialValue, jest.fn()];
91
+ });
92
+ }
93
+
94
+ function buildStates(tabsValue) {
95
+ return [
96
+ tabsValue,
97
+ [{ id: 'past' }],
98
+ [{ id: 'current' }],
99
+ [{ id: 'upcoming' }],
100
+ [{ id: 'open-consultation' }],
101
+ [{ id: 'review-consultation' }],
102
+ [{ id: 'final-consultation' }],
103
+ [{ id: 'future-consultation' }],
104
+ [{ id: 'open-survey' }],
105
+ [{ id: 'review-survey' }],
106
+ [{ id: 'final-survey' }],
107
+ [{ id: 'future-survey' }],
108
+ [{ id: 'future-publication' }],
109
+ [{ id: 'past-publication' }],
110
+ [{ id: 'upcoming-obligation' }],
111
+ [{ id: 'continuous-obligation' }],
112
+ false,
113
+ ];
114
+ }
115
+
116
+ describe('Activity', () => {
117
+ const trackEvent = jest.fn();
118
+ const closeDrawer = jest.fn();
119
+
120
+ const baseProps = {
121
+ userInfo: { country: 'RO', isEionetUser: true, isNFP: true },
122
+ country: 'RO',
123
+ configuration: { DashboardNumberOfMonthsData: 24, PublicationsType: 'Report;Article' },
124
+ setData4Menu: jest.fn(),
125
+ openRating: jest.fn(),
126
+ openApproval: jest.fn(),
127
+ drawerOpen: true,
128
+ closeDrawer,
129
+ };
130
+
131
+ beforeEach(() => {
132
+ jest.clearAllMocks();
133
+ React.useCallback.mockImplementation((fn) => fn);
134
+ React.useEffect.mockImplementation((fn) => fn());
135
+ React.useState.mockImplementation((initialValue) => [initialValue, jest.fn()]);
136
+
137
+ useAppInsightsContext.mockReturnValue({ trackEvent });
138
+
139
+ getMeetings.mockResolvedValue([{ IsCurrent: true }, { IsUpcoming: true }, { IsPast: true }]);
140
+ getConsultations.mockResolvedValue([]);
141
+ getPublications.mockResolvedValue([{ ItemType: 'Report', IsPast: false }]);
142
+ getObligations.mockResolvedValue([{ IsUpcoming: true, IsContinuous: false }]);
143
+ });
144
+
145
+ test('renders drawer sections and event tab by default', () => {
146
+ mockStateSequence(buildStates(0));
147
+
148
+ const html = renderToStaticMarkup(<Activity {...baseProps} />);
149
+
150
+ expect(html).toContain('EVENTS');
151
+ expect(html).toContain('CONSULTATIONS');
152
+ expect(html).toContain('ENQUIRIES');
153
+ expect(html).toContain('PUBLICATIONS &amp; OUTREACH');
154
+ expect(html).toContain('REPORTING OBLIGATIONS');
155
+ expect(html).toContain('event-list');
156
+ expect(closeDrawer).toHaveBeenCalled();
157
+ expect(trackEvent).toHaveBeenCalled();
158
+ });
159
+
160
+ test('renders consultations view for consultation tabs', () => {
161
+ mockStateSequence(buildStates(4));
162
+
163
+ const html = renderToStaticMarkup(<Activity {...baseProps} />);
164
+
165
+ expect(html).toContain('consultation-list');
166
+ });
167
+
168
+ test('renders surveys view for enquiries tabs', () => {
169
+ mockStateSequence(buildStates(8));
170
+
171
+ const html = renderToStaticMarkup(<Activity {...baseProps} />);
172
+
173
+ expect(html).toContain('consultation-list');
174
+ });
175
+
176
+ test('renders publications view', () => {
177
+ mockStateSequence(buildStates(11));
178
+
179
+ const html = renderToStaticMarkup(<Activity {...baseProps} />);
180
+
181
+ expect(html).toContain('publication-list');
182
+ });
183
+
184
+ test('renders obligations view', () => {
185
+ mockStateSequence(buildStates(13));
186
+
187
+ const html = renderToStaticMarkup(<Activity {...baseProps} />);
188
+
189
+ expect(html).toContain('obligation-list');
190
+ });
191
+
192
+ test('loads activity data in effect', async () => {
193
+ mockStateSequence(buildStates(0));
194
+
195
+ renderToStaticMarkup(<Activity {...baseProps} />);
196
+ await Promise.resolve();
197
+ await Promise.resolve();
198
+
199
+ expect(getMeetings).toHaveBeenCalled();
200
+ expect(getConsultations).toHaveBeenCalled();
201
+ expect(getPublications).toHaveBeenCalled();
202
+ expect(getObligations).toHaveBeenCalled();
203
+ expect(baseProps.setData4Menu).toHaveBeenCalled();
204
+ });
205
+
206
+ test('handles meeting loading errors', async () => {
207
+ const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
208
+ getMeetings.mockRejectedValue(new Error('boom'));
209
+ mockStateSequence(buildStates(0));
210
+
211
+ renderToStaticMarkup(<Activity {...baseProps} />);
212
+ await Promise.resolve();
213
+ await Promise.resolve();
214
+
215
+ expect(logSpy).toHaveBeenCalledWith('boom');
216
+ logSpy.mockRestore();
217
+ });
218
+ });
@@ -0,0 +1,114 @@
1
+ import React from 'react';
2
+ import { renderToStaticMarkup } from 'react-dom/server';
3
+ import { ConsultationList } from './ConsultationList';
4
+
5
+ let mockGridProps;
6
+
7
+ jest.mock('../ResizableGrid', () => ({
8
+ __esModule: true,
9
+ default: (props) => {
10
+ mockGridProps = props;
11
+ return <div>grid-rows-{props.rows?.length || 0}</div>;
12
+ },
13
+ }));
14
+
15
+ jest.mock('./GroupsTags', () => ({
16
+ GroupsTags: ({ groups }) => <div>groups-{groups?.length || 0}</div>,
17
+ }));
18
+
19
+ describe('ConsultationList', () => {
20
+ beforeEach(() => {
21
+ mockGridProps = null;
22
+ });
23
+
24
+ test('renders future consultations grid for tab 0', () => {
25
+ const html = renderToStaticMarkup(
26
+ <ConsultationList
27
+ configuration={{ DateFormatDashboard: 'dd-MMM-yyyy' }}
28
+ openConsultations={[]}
29
+ reviewConsultations={[]}
30
+ finalisedConsultations={[]}
31
+ futureConsultations={[{ id: 1, Title: 'Future' }]}
32
+ type="Consultations"
33
+ country="RO"
34
+ tabsValue={0}
35
+ />,
36
+ );
37
+
38
+ expect(html).toContain('grid-rows-1');
39
+ });
40
+
41
+ test('renders open consultations grid for tab 1 and colors urgent values', () => {
42
+ const html = renderToStaticMarkup(
43
+ <ConsultationList
44
+ configuration={{ DateFormatDashboard: 'dd-MMM-yyyy' }}
45
+ openConsultations={[{ id: 1, Title: 'Open' }]}
46
+ reviewConsultations={[]}
47
+ finalisedConsultations={[]}
48
+ futureConsultations={[]}
49
+ type="Consultations"
50
+ country=""
51
+ tabsValue={1}
52
+ />,
53
+ );
54
+
55
+ expect(html).toContain('grid-rows-1');
56
+ const daysLeftColumn = mockGridProps.columns.find((column) => column.field === 'DaysLeft');
57
+ expect(daysLeftColumn.cellClassName({ value: 2 })).toBe('red-cell-text');
58
+ expect(daysLeftColumn.cellClassName({ value: 4 })).toBeUndefined();
59
+ });
60
+
61
+ test('renders review grid for tab 2', () => {
62
+ const html = renderToStaticMarkup(
63
+ <ConsultationList
64
+ configuration={{ DateFormatDashboard: 'dd-MMM-yyyy' }}
65
+ openConsultations={[]}
66
+ reviewConsultations={[{ id: 3, Title: 'Review', Startdate: new Date('2026-01-01') }]}
67
+ finalisedConsultations={[]}
68
+ futureConsultations={[]}
69
+ type="Consultations"
70
+ country="RO"
71
+ tabsValue={2}
72
+ />,
73
+ );
74
+
75
+ expect(html).toContain('grid-rows-1');
76
+ expect(mockGridProps.columns.some((column) => column.field === 'DaysFinalised')).toBe(true);
77
+ });
78
+
79
+ test('renders finalised grid for tab 3 and result/country cells', () => {
80
+ renderToStaticMarkup(
81
+ <ConsultationList
82
+ configuration={{
83
+ DateFormatDashboard: 'dd-MMM-yyyy',
84
+ ConsultationResultsTooltip: 'results',
85
+ CountryRespondedTooltip: 'responded',
86
+ }}
87
+ openConsultations={[]}
88
+ reviewConsultations={[]}
89
+ finalisedConsultations={[{ id: 4, Title: 'Final', Deadline: new Date('2026-02-01') }]}
90
+ futureConsultations={[]}
91
+ type="Consultations"
92
+ country=""
93
+ tabsValue={3}
94
+ />,
95
+ );
96
+
97
+ const resultsColumn = mockGridProps.columns.find((column) => column.field === 'Results');
98
+ const respondantsColumn = mockGridProps.columns.find(
99
+ (column) => column.field === 'HasUserCountryResponded',
100
+ );
101
+
102
+ const resultHtml = renderToStaticMarkup(
103
+ resultsColumn.renderCell({ row: { LinkToResults: 'https://example.org/results' } }),
104
+ );
105
+ const respondedHtml = renderToStaticMarkup(
106
+ respondantsColumn.renderCell({
107
+ row: { HasUserCountryResponded: false, Respondants: [{}, {}, {}] },
108
+ }),
109
+ );
110
+
111
+ expect(resultHtml).toContain('button');
112
+ expect(respondedHtml).toContain('3');
113
+ });
114
+ });
@@ -0,0 +1,164 @@
1
+ import React from 'react';
2
+ import { renderToStaticMarkup } from 'react-dom/server';
3
+ import { EventList } from './EventList';
4
+
5
+ let mockGridProps;
6
+
7
+ jest.mock('../ResizableGrid', () => ({
8
+ __esModule: true,
9
+ default: (props) => {
10
+ mockGridProps = props;
11
+ return <div>grid-rows-{props.rows?.length || 0}</div>;
12
+ },
13
+ }));
14
+
15
+ jest.mock('./GroupsTags', () => ({
16
+ GroupsTags: ({ groups }) => <div>groups-{groups?.length || 0}</div>,
17
+ }));
18
+
19
+ jest.mock('../event_registration/EventRegistration', () => ({
20
+ EventRegistration: () => <div>event-registration</div>,
21
+ }));
22
+
23
+ jest.mock('../event_registration/EventExternalRegistration', () => ({
24
+ EventExternalRegistration: () => <div>event-external-registration</div>,
25
+ }));
26
+
27
+ jest.mock('../EventDialogTitle', () => ({
28
+ EventDialogTitle: () => <div>event-dialog-title</div>,
29
+ }));
30
+
31
+ jest.mock('../../data/sharepointProvider', () => ({
32
+ getCurrentParticipant: jest.fn(),
33
+ }));
34
+
35
+ jest.mock('../../static/images/teams-icon.svg', () => ({
36
+ ReactComponent: () => <svg />,
37
+ }));
38
+
39
+ describe('EventList', () => {
40
+ beforeEach(() => {
41
+ mockGridProps = null;
42
+ });
43
+
44
+ test('renders upcoming meetings grid for tab 0', () => {
45
+ const html = renderToStaticMarkup(
46
+ <EventList
47
+ userInfo={{ country: 'RO', isEionetUser: true, isNFP: true }}
48
+ configuration={{
49
+ DateFormatDashboard: 'dd-MMM-yyyy',
50
+ RegisterEventButtonTooltip: 'register',
51
+ RegisterOthersButtonTooltip: 'register others',
52
+ }}
53
+ pastMeetings={[]}
54
+ currentMeetings={[]}
55
+ upcomingMeetings={[
56
+ {
57
+ id: 1,
58
+ Title: 'Upcoming meeting',
59
+ MeetingType: 'Physical',
60
+ NoOfRegistered: 2,
61
+ IsUpcoming: true,
62
+ },
63
+ ]}
64
+ tabsValue={0}
65
+ openRating={jest.fn()}
66
+ openApproval={jest.fn()}
67
+ />,
68
+ );
69
+
70
+ expect(html).toContain('grid-rows-1');
71
+ expect(mockGridProps.columns.some((column) => column.field === 'MeetingRegistrationLink')).toBe(
72
+ true,
73
+ );
74
+ expect(mockGridProps.columns.some((column) => column.field === 'Approval')).toBe(true);
75
+ expect(mockGridProps.columns.some((column) => column.field === 'id')).toBe(true);
76
+ expect(mockGridProps.columns.some((column) => column.field === 'NoOfRegistered')).toBe(true);
77
+
78
+ const registerColumn = mockGridProps.columns.find(
79
+ (column) => column.field === 'MeetingRegistrationLink',
80
+ );
81
+ const registerHtml = renderToStaticMarkup(
82
+ registerColumn.renderCell({ row: { MeetingType: 'physical', MeetingLink: '' } }),
83
+ );
84
+ expect(registerHtml).toContain('button');
85
+ });
86
+
87
+ test('renders current meetings grid for tab 1', () => {
88
+ const html = renderToStaticMarkup(
89
+ <EventList
90
+ userInfo={{ country: 'RO', isEionetUser: true, isNFP: true }}
91
+ configuration={{ DateFormatDashboard: 'dd-MMM-yyyy', JoinEventButtonTooltip: 'join' }}
92
+ pastMeetings={[]}
93
+ currentMeetings={[
94
+ {
95
+ id: 2,
96
+ Title: 'Current meeting',
97
+ MeetingType: 'Online',
98
+ MeetingLink: 'https://example.org/meeting',
99
+ NoOfRegistered: 3,
100
+ IsCurrent: true,
101
+ AllowVote: true,
102
+ HasVoted: true,
103
+ MeetingStart: new Date('2026-01-01'),
104
+ },
105
+ ]}
106
+ upcomingMeetings={[]}
107
+ tabsValue={1}
108
+ openRating={jest.fn()}
109
+ openApproval={jest.fn()}
110
+ />,
111
+ );
112
+
113
+ expect(html).toContain('grid-rows-1');
114
+ expect(mockGridProps.columns.some((column) => column.field === 'MeetingLink')).toBe(true);
115
+ expect(mockGridProps.columns.some((column) => column.field === 'AllowVote')).toBe(true);
116
+
117
+ const ratingColumn = mockGridProps.columns.find((column) => column.field === 'AllowVote');
118
+ const ratingHtml = renderToStaticMarkup(
119
+ ratingColumn.renderCell({ row: { AllowVote: true, HasVoted: true } }),
120
+ );
121
+ expect(ratingHtml).toContain('button');
122
+ });
123
+
124
+ test('renders past meetings grid for tab 2 with participants and no rating for missing country', () => {
125
+ const html = renderToStaticMarkup(
126
+ <EventList
127
+ userInfo={{ country: '', isEionetUser: false, isNFP: false }}
128
+ configuration={{
129
+ DateFormatDashboard: 'dd-MMM-yyyy',
130
+ NoOfParticipantsTooltip: 'participants',
131
+ }}
132
+ pastMeetings={[
133
+ {
134
+ id: 3,
135
+ Title: 'Past meeting',
136
+ IsPast: true,
137
+ NoOfParticipants: 0,
138
+ MeetingStart: new Date('2026-01-01'),
139
+ MeetingEnd: new Date('2026-01-02'),
140
+ },
141
+ ]}
142
+ currentMeetings={[]}
143
+ upcomingMeetings={[]}
144
+ tabsValue={2}
145
+ openRating={jest.fn()}
146
+ openApproval={jest.fn()}
147
+ />,
148
+ );
149
+
150
+ expect(html).toContain('grid-rows-1');
151
+ expect(mockGridProps.columns.some((column) => column.field === 'NoOfParticipants')).toBe(true);
152
+ expect(mockGridProps.columns.some((column) => column.field === 'AllowVote')).toBe(false);
153
+
154
+ const participantsColumn = mockGridProps.columns.find(
155
+ (column) => column.field === 'NoOfParticipants',
156
+ );
157
+ const participantsHtml = renderToStaticMarkup(
158
+ participantsColumn.renderCell({
159
+ row: { IsPast: true, NoOfParticipants: 0, ParticipantsUrl: '' },
160
+ }),
161
+ );
162
+ expect(participantsHtml).toContain('N/A');
163
+ });
164
+ });
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import { renderToStaticMarkup } from 'react-dom/server';
3
+ import { GroupsTags } from './GroupsTags';
4
+
5
+ describe('GroupsTags', () => {
6
+ test('renders chips and dialog class when isDialog is true', () => {
7
+ const html = renderToStaticMarkup(
8
+ <GroupsTags groups={['A', 'B']} handleClick={jest.fn()} isDialog={true} />,
9
+ );
10
+
11
+ expect(html).toContain('groups-tags-dialog');
12
+ expect(html).toContain('A');
13
+ expect(html).toContain('B');
14
+ });
15
+
16
+ test('renders without dialog class when isDialog is false', () => {
17
+ const html = renderToStaticMarkup(
18
+ <GroupsTags groups={['A']} handleClick={jest.fn()} isDialog={false} />,
19
+ );
20
+
21
+ expect(html).not.toContain('groups-tags-dialog');
22
+ });
23
+ });
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+ import { renderToStaticMarkup } from 'react-dom/server';
3
+ import { ObligationList } from './ObligationList';
4
+
5
+ jest.mock('../ResizableGrid', () => ({
6
+ __esModule: true,
7
+ default: ({ rows }) => <div>grid-rows-{rows?.length || 0}</div>,
8
+ }));
9
+
10
+ jest.mock('../HtmlBox', () => ({
11
+ HtmlBox: ({ html }) => <div>{html}</div>,
12
+ }));
13
+
14
+ describe('ObligationList', () => {
15
+ test('renders intro text and upcoming obligations grid for tab 0', () => {
16
+ const html = renderToStaticMarkup(
17
+ <ObligationList
18
+ userInfo={{}}
19
+ configuration={{
20
+ DateFormatDashboard: 'dd-MMM-yyyy',
21
+ ReportingObligationsIntroText: 'Reporting intro',
22
+ }}
23
+ upcomingObligations={[{ id: 1, Title: 'Upcoming' }]}
24
+ continuousObligations={[]}
25
+ tabsValue={0}
26
+ />,
27
+ );
28
+
29
+ expect(html).toContain('Reporting intro');
30
+ expect(html).toContain('grid-rows-1');
31
+ });
32
+
33
+ test('renders continuous obligations grid for tab 1', () => {
34
+ const html = renderToStaticMarkup(
35
+ <ObligationList
36
+ userInfo={{}}
37
+ configuration={{ DateFormatDashboard: 'dd-MMM-yyyy' }}
38
+ upcomingObligations={[]}
39
+ continuousObligations={[{ id: 1, Title: 'Continuous' }]}
40
+ tabsValue={1}
41
+ />,
42
+ );
43
+
44
+ expect(html).toContain('grid-rows-1');
45
+ });
46
+ });
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+ import { renderToStaticMarkup } from 'react-dom/server';
3
+ import { PublicatonList } from './PublicationList';
4
+
5
+ jest.mock('../ResizableGrid', () => ({
6
+ __esModule: true,
7
+ default: ({ rows }) => <div>grid-rows-{rows?.length || 0}</div>,
8
+ }));
9
+
10
+ jest.mock('../HtmlBox', () => ({
11
+ HtmlBox: ({ html }) => <div>{html}</div>,
12
+ }));
13
+
14
+ describe('PublicationList', () => {
15
+ test('renders intro text and future publications grid for tab 0', () => {
16
+ const html = renderToStaticMarkup(
17
+ <PublicatonList
18
+ userInfo={{}}
19
+ configuration={{
20
+ DateFormatDashboard: 'dd-MMM-yyyy',
21
+ PublicationsIntroText: 'Intro text',
22
+ }}
23
+ futurePublications={[{ id: 1, Title: 'Future Publication' }]}
24
+ pastPublications={[]}
25
+ tabsValue={0}
26
+ />,
27
+ );
28
+
29
+ expect(html).toContain('Intro text');
30
+ expect(html).toContain('grid-rows-1');
31
+ });
32
+
33
+ test('renders past publications grid for tab 1', () => {
34
+ const html = renderToStaticMarkup(
35
+ <PublicatonList
36
+ userInfo={{}}
37
+ configuration={{ DateFormatDashboard: 'dd-MMM-yyyy' }}
38
+ futurePublications={[]}
39
+ pastPublications={[{ id: 1, Title: 'Past Publication' }]}
40
+ tabsValue={1}
41
+ />,
42
+ );
43
+
44
+ expect(html).toContain('grid-rows-1');
45
+ });
46
+ });
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { renderToStaticMarkup } from 'react-dom/server';
3
+ import { Reporting } from './Reporting';
4
+
5
+ describe('Reporting', () => {
6
+ test('renders under construction message', () => {
7
+ const html = renderToStaticMarkup(<Reporting />);
8
+
9
+ expect(html).toContain('Page under construction');
10
+ });
11
+ });
@@ -0,0 +1,63 @@
1
+ import React from 'react';
2
+ import { renderToStaticMarkup } from 'react-dom/server';
3
+ import { EventRating } from './EventRating';
4
+
5
+ jest.mock('@mui/material', () => {
6
+ const ReactLocal = require('react');
7
+ const passthrough =
8
+ (Tag = 'div') =>
9
+ ({ children }) =>
10
+ ReactLocal.createElement(Tag, {}, children);
11
+
12
+ const Rating = ({ value, getLabelText }) => (
13
+ <div>
14
+ <span>rating-value-{value}</span>
15
+ <span>{getLabelText ? getLabelText(value) : ''}</span>
16
+ </div>
17
+ );
18
+
19
+ return {
20
+ Box: passthrough(),
21
+ Button: ({ children }) => <button>{children}</button>,
22
+ CircularProgress: passthrough('span'),
23
+ Backdrop: passthrough(),
24
+ Rating,
25
+ Typography: passthrough('span'),
26
+ };
27
+ });
28
+
29
+ jest.mock('@mui/icons-material/Check', () => () => <span>check-icon</span>);
30
+ jest.mock('@mui/icons-material/Save', () => () => <span>save-icon</span>);
31
+ jest.mock('@mui/icons-material/Star', () => () => <span>star-icon</span>);
32
+
33
+ jest.mock('../../data/sharepointProvider', () => ({
34
+ postRating: jest.fn(),
35
+ }));
36
+
37
+ describe('EventRating', () => {
38
+ test('renders modal text, rating caption and confirm button', () => {
39
+ const html = renderToStaticMarkup(
40
+ <EventRating
41
+ configuration={{ EventRatingModalText: 'Please rate this event' }}
42
+ participant={{ id: 1 }}
43
+ event={{ id: 2 }}
44
+ onRate={jest.fn()}
45
+ />,
46
+ );
47
+
48
+ expect(html).toContain('Please rate this event');
49
+ expect(html).toContain('rating-value-5');
50
+ expect(html).toContain('5 Stars, Excellent');
51
+ expect(html).toContain('Excellent');
52
+ expect(html).toContain('Confirm rating');
53
+ });
54
+
55
+ test('renders without optional modal text', () => {
56
+ const html = renderToStaticMarkup(
57
+ <EventRating configuration={{}} participant={{}} event={{}} onRate={jest.fn()} />,
58
+ );
59
+
60
+ expect(html).not.toContain('Please rate this event');
61
+ expect(html).toContain('Confirm rating');
62
+ });
63
+ });