Skip to content

Commit

Permalink
feat: add events (#126)
Browse files Browse the repository at this point in the history
* chore: events

add tab for events

* chore: units

prefer em to px
  • Loading branch information
jlangy authored Nov 17, 2023
1 parent faa3e93 commit b120ccd
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 9 deletions.
88 changes: 87 additions & 1 deletion app/__tests__/custom-realm-dashboard.test.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React from 'react';
import { render, screen, within, waitFor } from '@testing-library/react';
import { render, screen, within, waitFor, fireEvent } from '@testing-library/react';
import App from 'pages/_app';
import CustomRealmDashboard from 'pages/custom-realm-dashboard';
import { updateRealmProfile } from 'services/realm';
import { getRealmEvents } from 'services/events';
import { CustomRealmFormData } from 'types/realm-profile';
import Router from 'next/router';
import { Event } from 'types/event';

jest.mock('services/realm', () => {
return {
Expand All @@ -13,6 +15,38 @@ jest.mock('services/realm', () => {
};
});

jest.mock('services/events', () => {
return {
getRealmEvents: jest.fn((realmId: string) => {
if (realmId === '1') {
return Promise.resolve([
[
{
id: 1,
idirUserId: 'idir',
createdAt: '2023-11-10T20:25:06.856Z',
eventCode: 'request-create-success',
realmId: 1,
},
],
]);
} else {
return Promise.resolve([
[
{
id: 1,
idirUserId: 'idir',
createdAt: '2023-11-11T20:25:06.856Z',
eventCode: 'request-update-success',
realmId: 2,
},
],
]);
}
}),
};
});

jest.mock('next/router', () => ({
useRouter() {
return {
Expand Down Expand Up @@ -235,3 +269,55 @@ describe('Status update', () => {
await waitFor(() => within(firstRow).getByText('Declined'));
});
});

describe('Events table', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('fetches correct events when selected row changes', async () => {
render(<CustomRealmDashboard defaultRealmRequests={defaultData} />);
expect(getRealmEvents).toHaveBeenCalledTimes(1);
// Called with correct realm id
expect(getRealmEvents).toHaveBeenCalledWith('1');

const table = screen.getByTestId('custom-realm-table');
const row = within(table).getByText('realm 2');
row.click();

await waitFor(() => expect(getRealmEvents).toHaveBeenCalledTimes(2));
// Called with correct realm id
expect(getRealmEvents).toHaveBeenCalledWith('2');
});

it('displays events for the selected realm and updates when changing rows', async () => {
render(<CustomRealmDashboard defaultRealmRequests={defaultData} />);

const table = screen.getByTestId('custom-realm-table');
const secondRealmRow = within(table).getByText('realm 2');
const eventTab = screen.getByText('Events');
eventTab.click();

// Expect only realm 1 event to show
await waitFor(() => screen.getByText('request-create-success'));
expect(screen.queryByText('request-update-success')).toBeNull();

secondRealmRow.click();
await waitFor(() => screen.getByText('request-update-success'));
expect(screen.queryByText('request-create-success')).toBeNull();
});

it('flashes an error message if network request fails', async () => {
(getRealmEvents as jest.MockedFunction<any>).mockImplementationOnce(() =>
Promise.resolve([null, { message: 'failure' }]),
);
render(
<App
Component={CustomRealmDashboard}
pageProps={{ session: {}, defaultRealmRequests: defaultData }}
router={Router as any}
/>,
);
await waitFor(() => screen.getByText('Network error when fetching realm events.'));
});
});
65 changes: 62 additions & 3 deletions app/page-partials/custom-realm-dashboard/CustomRealmTabs.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import styled from 'styled-components';
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { CustomRealmFormData } from 'types/realm-profile';
import { faCircleCheck, faSpinner } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Button from '@button-inc/bcgov-theme/Button';
import { getRealmEvents } from 'services/events';
import { withBottomAlert, BottomAlert } from 'layout/BottomAlert';
import { Event } from 'types/event';

const Tabs = styled.ul`
display: flex;
Expand Down Expand Up @@ -63,6 +66,12 @@ const SApprovalList = styled.ul`
}
`;

const EventContents = styled.div`
margin-top: 1em;
max-height: 25em;
overflow-y: auto;
`;

const realmCreationFailedStatuses = ['PrFailed', 'planFailed', 'applyFailed'];

const realmCreatingStatuses = ['pending', 'prSuccess', 'planned'];
Expand Down Expand Up @@ -124,15 +133,38 @@ function ApprovalList({ selectedRow, lastUpdateTime }: Props) {
);
}

const tabs = ['Details', 'Access Request'];
const tabs = ['Details', 'Access Request', 'Events'];

interface CRTProps extends Props {
handleRequestStatusChange: (status: 'approved' | 'declined', row: CustomRealmFormData) => void;
alert: BottomAlert;
}

export default function CutsomRealmTabs({ selectedRow, handleRequestStatusChange, lastUpdateTime }: CRTProps) {
function CutsomRealmTabs({ selectedRow, handleRequestStatusChange, lastUpdateTime, alert }: CRTProps) {
const [selectedTab, setSelectedTab] = useState('Details');
const [events, setEvents] = useState<Event[]>([]);
const formattedRealmData = formatRealmData(selectedRow);

const fetchEvents = async () => {
if (selectedRow.id) {
const [events, err] = await getRealmEvents(String(selectedRow.id));
if (events) {
setEvents(events);
} else if (err) {
return alert.show({
variant: 'danger',
fadeOut: 3500,
closable: true,
content: `Network error when fetching realm events.`,
});
}
}
};

useEffect(() => {
fetchEvents();
}, [selectedRow]);

return (
<>
<h2>Custom Realm Details</h2>
Expand Down Expand Up @@ -171,6 +203,33 @@ export default function CutsomRealmTabs({ selectedRow, handleRequestStatusChange
)}
</TabPanel>
)}
{selectedTab === 'Events' && (
<EventContents>
<h2>Events</h2>
<hr />
{events.length === 0 ? (
<div>No events found</div>
) : (
events.map((event) => (
<div key={event.id}>
<div>
<strong>Event Code: </strong>
{event.eventCode}
</div>
{event.createdAt && (
<div>
<strong>Created Time: </strong>
{new Date(event.createdAt).toLocaleString()}
</div>
)}
<hr />
</div>
))
)}
</EventContents>
)}
</>
);
}

export default withBottomAlert(CutsomRealmTabs);
13 changes: 8 additions & 5 deletions app/pages/custom-realm-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,17 +174,18 @@ function RealmForm({ alert }: Props) {

const handleSubmit = async () => {
const submission = cloneDeep(formData);
// Add other primary users if present
if (otherPrimaryEndUsersSelected) {
submission.primaryEndUsers.push(otherPrimaryEndUserDetails);
}

const { valid, errors } = validateForm(submission);
if (!valid) {
setFormErrors(errors as any);
return;
}
setSubmittingForm(true);

// Add other primary users if present
if (otherPrimaryEndUsersSelected) {
submission.primaryEndUsers.push(otherPrimaryEndUserDetails);
}
const [response, err] = await submitRealmRequest(submission);
if (err) {
const content = err?.response?.data?.error || 'Network request failure. Please try again.';
Expand Down Expand Up @@ -240,7 +241,9 @@ function RealmForm({ alert }: Props) {
<FontAwesomeIcon icon={faInfoCircle} title="Select a unique realm name." color="#777777" />
</label>
<input required id="realm-name-input" name="realm" onChange={handleFormInputChange} value={formData.realm} />
{formErrors.realm && <p className="error-message">{twoCharactersRequiredMessage}</p>}
{formErrors.realm && (
<p className="error-message">Please include a realm name with only letters, underscores and hypens</p>
)}
</div>

<div className="input-wrapper second-col">
Expand Down
11 changes: 11 additions & 0 deletions app/services/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { instance } from './axios';

export const getRealmEvents = async (realmId: string): Promise<[any[], null] | [null, any]> => {
try {
const result = await instance.get(`events?realmId=${realmId}`).then((res) => res.data);
return [result as any[], null];
} catch (err: any) {
console.error(err);
return [null, err];
}
};
8 changes: 8 additions & 0 deletions app/types/event.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface Event {
createdAt: string;
eventCode: string;
id: number;
realmId: number;
idirUserId: string;
details?: any;
}

0 comments on commit b120ccd

Please sign in to comment.