Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(tests) O3-4098 Add tests for downloading a schema #19

Merged
merged 1 commit into from
Nov 11, 2024
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
92 changes: 92 additions & 0 deletions src/components/dashboard/dashboard.component.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,65 @@ import userEvent from '@testing-library/user-event';

jest.mock('../../utils', () => ({
getAllPackagesFromLocalStorage: jest.fn(),
deletePackageFromLocalStorage: jest.fn(),
}));

const mockSetClinicalViews = jest.fn();

describe('DashboardComponent', () => {
const setupMocks = () => {
const mocks = {
setClinicalViews: jest.fn(),
consoleSpy: jest.spyOn(console, 'error').mockImplementation(() => {}),
localStorageGetItem: jest.fn(),
mockUrl: 'blob:mock-url',
mockAnchor: document.createElement('a'),
mockClick: jest.fn(),
originalCreateObjectURL: URL.createObjectURL,
originalRevokeObjectURL: URL.revokeObjectURL,
originalCreateElement: document.createElement.bind(document),
};

// Setup localStorage mock
Object.defineProperty(window, 'localStorage', {
value: {
getItem: mocks.localStorageGetItem,
setItem: jest.fn(),
removeItem: jest.fn(),
clear: jest.fn(),
},
writable: true,
});

// Setup URL mocks
URL.createObjectURL = jest.fn(() => mocks.mockUrl);
URL.revokeObjectURL = jest.fn();

// Setup anchor element mock
Object.defineProperties(mocks.mockAnchor, {
click: { value: mocks.mockClick, writable: true },
href: { value: '', writable: true },
download: { value: '', writable: true },
});

// Setup document.createElement mock
document.createElement = jest.fn((tag) => {
if (tag === 'a') {
return mocks.mockAnchor;
}
return mocks.originalCreateElement(tag);
});

return mocks;
};

const cleanupMocks = (mocks: ReturnType<typeof setupMocks>) => {
URL.createObjectURL = mocks.originalCreateObjectURL;
URL.revokeObjectURL = mocks.originalRevokeObjectURL;
document.createElement = mocks.originalCreateElement;
mocks.consoleSpy.mockRestore();
};

beforeEach(() => {
(getAllPackagesFromLocalStorage as jest.Mock).mockReturnValue(mockContentPackages);
});
Expand Down Expand Up @@ -73,4 +127,42 @@ describe('DashboardComponent', () => {
await userEvent.type(searchInput, 'Clinical View 1');
expect(searchInput).toHaveValue('Clinical View 1');
});

it('downloads the schema when the download button is clicked', async () => {
const mocks = setupMocks();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG. 'here i would say it ("downloads the schema when the download button is clicked') to be more more descriptive, though it doesnt make any diff

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

mocks.localStorageGetItem.mockImplementation(() => mockContentPackages[0]);

render(
<ContentPackagesList
t={(key) => key}
clinicalViews={mockContentPackages}
setClinicalViews={mocks.setClinicalViews}
/>,
);

const downloadButton = await screen.findByRole('button', {
name: /downloadSchema/i,
});

await userEvent.click(downloadButton);

expect(mocks.localStorageGetItem).toHaveBeenCalled();
expect(URL.createObjectURL).toHaveBeenCalledWith(expect.any(Blob));
expect(mocks.mockClick).toHaveBeenCalled();

mocks.localStorageGetItem.mockReset();
mocks.mockClick.mockReset();
mocks.consoleSpy.mockReset();

mocks.localStorageGetItem.mockReturnValue(null);

await userEvent.click(downloadButton);
const blobCall = (URL.createObjectURL as jest.Mock).mock.calls[0][0];
expect(blobCall).toBeInstanceOf(Blob);
expect(blobCall.type).toBe('application/json;charset=utf-8');

expect(mocks.mockAnchor.href).toBe('blob:mock-url');
cleanupMocks(mocks);
});
});
54 changes: 40 additions & 14 deletions src/components/dashboard/dashboard.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,14 @@ interface ActionButtonsProps {
onDownload: (key: string) => void;
}

function ActionButtons({ responsiveSize, clinicalViewKey, t, onDelete, onDownload, onEdit }: ActionButtonsProps) {
export function ActionButtons({
responsiveSize,
clinicalViewKey,
t,
onDelete,
onDownload,
onEdit,
}: ActionButtonsProps) {
const defaultEnterDelayInMs = 300;

const launchDeleteClinicalViewsPackageModal = () => {
Expand Down Expand Up @@ -145,16 +152,34 @@ export function ContentPackagesList({ t, clinicalViews, setClinicalViews }: Cont
const { paginated, goTo, results, currentPage } = usePagination(filteredViews, pageSize);

const handleDownload = (key) => {
const schema = localStorage.getItem(`packageJSON_${key}`);
if (schema) {
const blob = new Blob([schema], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${key}.json`;
a.click();
} else {
console.error('No schema found to download.');
let url;
let anchor;
try {
const schema = localStorage.getItem(key);
if (!schema) {
console.error('No schema found to download.');
return;
}

const blob = new Blob([schema], {
type: 'application/json;charset=utf-8',
});
url = URL.createObjectURL(blob);

anchor = document.createElement('a');
anchor.href = url;
anchor.download = `${key}.json`;
document.body.appendChild(anchor);
anchor.click();
} catch (error) {
console.error('Error downloading schema:', error);
} finally {
if (url) {
URL.revokeObjectURL(url);
}
if (anchor && anchor.parentNode) {
anchor.parentNode.removeChild(anchor);
}
}
};

Expand Down Expand Up @@ -196,7 +221,8 @@ export function ContentPackagesList({ t, clinicalViews, setClinicalViews }: Cont
const tableRows = results.map((contentPackage) => {
const clinicalViewName = getNavGroupTitle(contentPackage);
const dashboardTitles = getDashboardTitles(contentPackage);
const key = Object.keys(contentPackage)[0];

const key = Object.keys(contentPackage)[1];

return {
id: contentPackage.key,
Expand Down Expand Up @@ -272,8 +298,8 @@ export function ContentPackagesList({ t, clinicalViews, setClinicalViews }: Cont
</TableRow>
</TableHead>
<TableBody>
{rows.map((row) => (
<TableRow key="row.id" {...getRowProps({ row })} data-testid={`content-package-row-${row.id}`}>
{rows.map((row, key) => (
<TableRow key={key} {...getRowProps({ row })} data-testid={`content-package-row-${row.id}`}>
{row.cells.map((cell) => (
<TableCell key={cell.id}>{cell.value}</TableCell>
))}
Expand Down
Loading