Skip to content

[frontend] Add tests for ExportButton component (#2285) #2218

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

Draft
wants to merge 4 commits into
base: release/current
Choose a base branch
from
Draft
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import ExportButton from '../../../components/common/ExportButton';
import { act, render } from '@testing-library/react'; // @testing-library/dom is needed as well as it is a peer dependency of @testing-library/react
import { describe, expect, it, vi } from 'vitest';
import {createDefaultTags, createTagMap} from "../../fixtures/api-types.fixtures";
import { faker } from '@faker-js/faker';
import TestRootComponent from "../../fixtures/TestRootComponent";
import React from "react";
import Intermediate from "../../fixtures/Intermediate";
import {storeHelper} from "../../../actions/Schema";

/* eslint-disable @typescript-eslint/no-explicit-any */
type testobj = { [key: string]: any };
function createObjWithDefaultKeys(objtype: string): testobj {
const obj: testobj = {};
['name', 'extra_prop_1', 'extra_prop_2'].forEach((prop) => {
obj[`${objtype}_${prop}`] = faker.lorem.sentence();
});
return obj;
}

describe('Generic export button', () => {
const exportType: string = "testobj"
const exportData: testobj[] = [
createObjWithDefaultKeys(exportType),
createObjWithDefaultKeys(exportType),
createObjWithDefaultKeys(exportType)
]
const numberOfElements : number = exportData.length;
const exportKeys = [
`${exportType}_name`,
`${exportType}_tags`,
];
const tags = createDefaultTags(5);
const tagMap = createTagMap(tags);
for(let obj of exportData) {
obj[`${exportType}_tags`] = tags.map(t => t.tag_id);
}

const { mockedMethod } = vi.hoisted(() => {
return { mockedMethod: vi.fn() }
})

vi.mock(import('../../../actions/Schema'),
async () => {
const orig = await vi.importActual('../../../actions/Schema');
let _cache: any = null;
const mock = (state: any) => {
if(!_cache) {
// @ts-ignore
const helper = orig.storeHelper(state);
helper.getTagsMap = mockedMethod;
_cache = helper;
}
return _cache;
};
return { ...orig, storeHelper: mock };
}
);

mockedMethod.mockReturnValue(tagMap);

it("does something", async () => {
const { getByRole } = render(
<TestRootComponent>
<Intermediate testData={tagMap}>
<ExportButton totalElements={numberOfElements} exportProps={{
exportType: exportType,
exportKeys: exportKeys,
exportData: exportData,
exportFileName: "export.csv"
}}/>
</Intermediate>
</TestRootComponent>
);
await act(async () => {
const firstname = getByRole("link");
if (firstname.onclick) {
const toto = await firstname.onclick(new MouseEvent("click"))
console.log("here it is");
console.log(firstname.href)
console.log(firstname);
}

expect(firstname).toBeDefined();
});
});
});
16 changes: 16 additions & 0 deletions openbas-front/src/__tests__/fixtures/Intermediate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {Provider} from "react-redux";
import {store} from "../../store";
import ConnectedIntlProvider from "../../components/AppIntlProvider";
import ConnectedThemeProvider from "../../components/AppThemeProvider";
import {CssBaseline} from "@mui/material";
import React from "react";
import {useAppDispatch} from "../../utils/hooks";
import {fetchTags} from "../../actions/Tag";
import {DATA_FETCH_SUCCESS} from "../../constants/ActionTypes";

// @ts-ignore
const TestRootComponent = ({children, testData}) => {
return (children);
};

export default TestRootComponent;
24 changes: 24 additions & 0 deletions openbas-front/src/__tests__/fixtures/TestRootComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {store} from "../../store";
import React from 'react';
import ConnectedIntlProvider from "../../components/AppIntlProvider";
import ConnectedThemeProvider from "../../components/AppThemeProvider";
import {CssBaseline} from "@mui/material";
import { Provider } from 'react-redux';
import {APP_BASE_PATH} from "../../utils/Action";
import {BrowserRouter} from "react-router";
import {useAppDispatch} from "../../utils/hooks";
import {fetchTags} from "../../actions/Tag";

// @ts-ignore
const TestRootComponent = ({children}) => {
return (<Provider store={store}>
<ConnectedIntlProvider>
<ConnectedThemeProvider>
<CssBaseline />
{children}
</ConnectedThemeProvider>
</ConnectedIntlProvider>
</Provider>);
};

export default TestRootComponent;
17 changes: 11 additions & 6 deletions openbas-front/src/__tests__/fixtures/api-types.fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ import { faker } from '@faker-js/faker';

import { Exercise, Organization, Scenario, Tag } from '../../utils/api-types';

export function createTagMap(numberTags: number): { [key: string]: Tag } {
export function createDefaultTags(numberTags: number) : Tag[] {
return Array(numberTags).fill(null)
.map<Tag>((x): Tag => {
return { tag_id: faker.string.uuid(), tag_name: faker.lorem.sentence(), }
});
}

export function createTagMap(tags: Tag[]): { [key: string]: Tag } {
const tagMap: { [key: string]: Tag } = {};
for (let i = 0; i < numberTags; i++) {
const id = faker.string.uuid();
tagMap[id] = {
tag_id: faker.string.uuid(), tag_name: faker.lorem.sentence(),
};
for (let tag of tags) {
const id = tag.tag_id;
tagMap[id] = tag;
}
return tagMap;
}
Expand Down
7 changes: 4 additions & 3 deletions openbas-front/src/__tests__/utils/Environment.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest';

import { exportData } from '../../utils/Environment';
import {
createDefaultTags,
createExercisesMap,
createOrganisationsMap,
createScenarioMap,
Expand Down Expand Up @@ -80,7 +81,7 @@ describe('exportData tests', () => {
objtype,
keys,
[obj],
createTagMap(3),
createTagMap(createDefaultTags(3)),
);
const line = result[0];
it('does not incorporate tags in line', () => {
Expand All @@ -90,7 +91,7 @@ describe('exportData tests', () => {

describe('when object has tags', () => {
const obj = createObjWithDefaultKeys(objtype);
const tagMap = createTagMap(3);
const tagMap = createTagMap(createDefaultTags(3));
obj[`${objtype}_tags`] = Object.keys(tagMap);

// the goal is to concatenate tag names in the export
Expand Down Expand Up @@ -122,7 +123,7 @@ describe('exportData tests', () => {

describe('when object has unknown tag', () => {
const obj = createObjWithDefaultKeys(objtype);
const tagMap = createTagMap(3);
const tagMap = createTagMap(createDefaultTags(3));
obj[`${objtype}_tags`] = [faker.string.uuid(), faker.string.uuid()]; // not found in tag map

// the goal is to concatenate tag names in the export
Expand Down
17 changes: 16 additions & 1 deletion openbas-front/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,24 @@ import react from '@vitejs/plugin-react';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import jsdom from 'jsdom';
import { defineConfig } from 'vitest/config';
import {transformWithEsbuild} from "vite";

export default defineConfig({
plugins: [react()],
plugins: [
{
name: 'treat-js-files-as-jsx',
async transform(code, id) {
if (!id.match(/src\/.*\.js$/)) return null;
// Use the exposed transform from vite, instead of directly
// transforming with esbuild
return transformWithEsbuild(code, id, {
loader: 'jsx',
jsx: 'automatic',
});
},
},
react()
],
test: {
environment: 'jsdom',
include: ['src/__tests__/**/**/*.test.{ts,tsx}'],
Expand Down