Skip to content

Commit

Permalink
Various lint and test fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Zach Price committed Dec 18, 2024
1 parent c439ce4 commit 867bec0
Show file tree
Hide file tree
Showing 21 changed files with 1,636 additions and 2,482 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
// Jest
// -----------------------------
"jest.rootPath": "./frontend/src",
"jest.jestCommandLine": "yarn jest --runInBand",
"jest.jestCommandLine": "yarn jest",
"jest.monitorLongRun": "off",
"jest.enable": true,
"jest.runMode": {
Expand Down
1 change: 0 additions & 1 deletion frontend/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ module.exports = {
},
],
'@typescript-eslint/camelcase': 'off',
'@typescript-eslint/explicit-function-return-type': ['error'],
// Makes no sense to allow type inferrence for expression parameters, but require typing the response (https://github.com/iamturns/create-exposed-app/blob/master/.eslintrc.js)
'@typescript-eslint/explicit-function-return-type': [
'error',
Expand Down
13 changes: 6 additions & 7 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,7 @@
],
"testEnvironment": "jsdom",
"transform": {
"^.+.tsx?$": [
"ts-jest",
{}
]
"^.+.tsx?$": "@swc/jest"
}
},
"dependencies": {
Expand Down Expand Up @@ -97,6 +94,8 @@
"@babel/eslint-parser": "7.24.1",
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@babel/preset-env": "7.24.0",
"@swc/core": "^1.10.1",
"@swc/jest": "^0.2.37",
"@testing-library/dom": "9.3.4",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "14.2.1",
Expand All @@ -112,11 +111,12 @@
"@typescript-eslint/eslint-plugin": "7.3.1",
"@typescript-eslint/parser": "7.3.1",
"@vitejs/plugin-react": "^4.3.4",
"eslint": "8.57.0",
"eslint": "^8.57.0",
"eslint-config-airbnb": "19.0.4",
"eslint-config-airbnb-typescript": "18.0.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-import": "2.27.5",
"eslint-plugin-jest-dom": "^5.5.0",
"eslint-plugin-jsx-a11y": "6.7.1",
"eslint-plugin-prettier": "4.0.0",
"eslint-plugin-react": "7.33.0",
Expand All @@ -129,7 +129,6 @@
"prettier": "2.2.1",
"setimmediate": "1.0.5",
"ts-jest": "^29.2.5",
"vite": "^6.0.1",
"vite-jest": "^0.1.4"
"vite": "^6.0.1"
}
}
43 changes: 21 additions & 22 deletions frontend/src/common/DataPersister.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable no-underscore-dangle */
import { SetterOrUpdater } from 'recoil';
import { loadSessionValue, saveSessionValue } from '../api';

Expand All @@ -10,25 +9,25 @@ export type PersistData<T> = {
};

export class DataPersister {
private static _instance: DataPersister;
private static instance: DataPersister;

private _PERSISTENT_STORE: {
private PERSISTENT_STORE: {
[key: string]: PersistData<unknown>;
} = {};

private constructor() {
this._PERSISTENT_STORE = {};
this.PERSISTENT_STORE = {};
}

public static get Instance(): DataPersister {
if (!this._instance) {
this._instance = new this();
if (!this.instance) {
this.instance = new this();
}
return this._instance;
return this.instance;
}

initializeDataStore(dataStore: { [key: string]: PersistData<unknown> }): void {
this._PERSISTENT_STORE = dataStore;
this.PERSISTENT_STORE = dataStore;
}

addNewVar<T>(
Expand All @@ -37,7 +36,7 @@ export class DataPersister {
setterFunc: SetterOrUpdater<T> | ((val: T) => void),
loaderFunc?: () => Promise<T>
): void {
if (Object.hasOwn(this._PERSISTENT_STORE, varKey)) {
if (Object.hasOwn(this.PERSISTENT_STORE, varKey)) {
return;
}

Expand All @@ -49,52 +48,52 @@ export class DataPersister {
val = await loadSessionValue<T>(varKey);
}

this._PERSISTENT_STORE[varKey].value = val || defaultVal;
this.PERSISTENT_STORE[varKey].value = val || defaultVal;
setterFunc(val || defaultVal);

return val || defaultVal;
};

const saver = async (): Promise<void> => {
await saveSessionValue<T>(varKey, this._PERSISTENT_STORE[varKey].value as T);
await saveSessionValue<T>(varKey, this.PERSISTENT_STORE[varKey].value as T);
};

const setter = (val: T): void => {
this._PERSISTENT_STORE[varKey].value = val;
this.PERSISTENT_STORE[varKey].value = val;
setterFunc(val);
};

const newVar = { loader, saver, setter, value: defaultVal };
this._PERSISTENT_STORE[varKey] = newVar as PersistData<unknown>;
this.PERSISTENT_STORE[varKey] = newVar as PersistData<unknown>;
}

getValue<T>(varKey: string): T | null {
if (this._PERSISTENT_STORE[varKey]) {
return this._PERSISTENT_STORE[varKey].value as T;
if (this.PERSISTENT_STORE[varKey]) {
return this.PERSISTENT_STORE[varKey].value as T;
}
return null;
}

async loadValue<T>(varKey: string): Promise<T | null> {
if (this._PERSISTENT_STORE[varKey]) {
return this._PERSISTENT_STORE[varKey].loader() as Promise<T>;
if (this.PERSISTENT_STORE[varKey]) {
return this.PERSISTENT_STORE[varKey].loader() as Promise<T>;
}
return null;
}

async setValue<T>(varKey: string, value: T, save: boolean): Promise<void> {
if (this._PERSISTENT_STORE[varKey]) {
this._PERSISTENT_STORE[varKey].setter(value);
if (this.PERSISTENT_STORE[varKey]) {
this.PERSISTENT_STORE[varKey].setter(value);

if (save) {
await this._PERSISTENT_STORE[varKey].saver();
await this.PERSISTENT_STORE[varKey].saver();
}
}
}

async loadAllValues(): Promise<void> {
const loadFuncs: Promise<unknown>[] = [];
Object.values(this._PERSISTENT_STORE).forEach((persistVar) => {
Object.values(this.PERSISTENT_STORE).forEach((persistVar) => {
loadFuncs.push(persistVar.loader());
});

Expand All @@ -103,7 +102,7 @@ export class DataPersister {

async saveAllValues(): Promise<void> {
const saveFuncs: Promise<void>[] = [];
Object.values(this._PERSISTENT_STORE).forEach((persistVar) => {
Object.values(this.PERSISTENT_STORE).forEach((persistVar) => {
saveFuncs.push(persistVar.saver());
});

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/common/JoyrideTour.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class JoyrideTour {
addNextStep(
target: string,
content: string,
placement?: Placement | 'auto' | 'center' | undefined,
placement?: Placement | 'auto' | 'center',
action?: () => void | Promise<void>
): JoyrideTour {
this.actions.push({
Expand Down
9 changes: 3 additions & 6 deletions frontend/src/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,7 @@ export const getUrlFromSearch = (search: ActiveSearchQuery): string => {
// Convert array values to string if they are of size 1
Object.keys(search.activeFacets).forEach((key) => {
if ((newSearch.activeFacets[key] as string[]).length === 1) {
// eslint-disable-next-line
newSearch.activeFacets[key] = (search.activeFacets[key] as string[])[0];
[newSearch.activeFacets[key]] = search.activeFacets[key] as string[];
}
});
params.set('activeFacets', JSON.stringify(newSearch.activeFacets));
Expand All @@ -214,15 +213,14 @@ export const getAltSearchFromUrl = (url?: string): ActiveSearchQuery => {
};

const params = new URLSearchParams(url || window.location.search);
// eslint-disable-next-line

const paramEntries: { [k: string]: string } = Object.fromEntries(params.entries());
// eslint-disable-next-line

const activeFacets: { [k: string]: string[] } = {};
Object.keys(paramEntries).forEach((key: string) => {
activeFacets[key] = [paramEntries[key]];
});

// eslint-disable-next-line
const projName = (url || window.location.pathname).split('/').filter(Boolean).at(-1);

if (projName) {
Expand Down Expand Up @@ -277,7 +275,6 @@ export const getSearchFromUrl = (url?: string): ActiveSearchQuery => {
// Convert string values to array
Object.keys(searchQuery.activeFacets).forEach((key) => {
if (!Array.isArray(searchQuery.activeFacets[key])) {
// eslint-disable-next-line
searchQuery.activeFacets[key] = [searchQuery.activeFacets[key]] as string[];
}
});
Expand Down
18 changes: 8 additions & 10 deletions frontend/src/components/App/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* eslint-disable no-void */

import {
BookOutlined,
DeleteOutlined,
Expand Down Expand Up @@ -149,22 +147,22 @@ const App: React.FC<React.PropsWithChildren<Props>> = ({ searchQuery }) => {
React.useEffect(() => {
/* istanbul ignore else */
if (isAuthenticated) {
void fetchUserCart(pk, accessToken)
fetchUserCart(pk, accessToken)
.then((rawUserCart) => {
/* istanbul ignore next */
const localItems = JSON.parse(
localStorage.getItem('userCart') || '[]'
) as RawSearchResults;
const databaseItems = rawUserCart.items as RawSearchResults;
const combinedCarts = combineCarts(databaseItems, localItems);
void updateUserCart(pk, accessToken, combinedCarts);
updateUserCart(pk, accessToken, combinedCarts);
setUserCart(combinedCarts);
})
.catch((error: ResponseError) => {
showError(messageApi, error.message);
});

void fetchUserSearchQueries(accessToken)
fetchUserSearchQueries(accessToken)
.then((rawUserSearches) => {
/* istanbul ignore next */
const localItems = JSON.parse(
Expand All @@ -174,7 +172,7 @@ const App: React.FC<React.PropsWithChildren<Props>> = ({ searchQuery }) => {
const searchQueriesToAdd = unsavedLocalSearches(databaseItems, localItems);
/* istanbul ignore next */
searchQueriesToAdd.forEach((query) => {
void addUserSearchQuery(pk, accessToken, query);
addUserSearchQuery(pk, accessToken, query);
});
setUserSearchQueries(databaseItems.concat(searchQueriesToAdd));
})
Expand Down Expand Up @@ -347,7 +345,7 @@ const App: React.FC<React.PropsWithChildren<Props>> = ({ searchQuery }) => {

/* istanbul ignore else */
if (isAuthenticated) {
void updateUserCart(pk, accessToken, newCart);
updateUserCart(pk, accessToken, newCart);
}
};

Expand All @@ -356,7 +354,7 @@ const App: React.FC<React.PropsWithChildren<Props>> = ({ searchQuery }) => {

/* istanbul ignore else */
if (isAuthenticated) {
void updateUserCart(pk, accessToken, []);
updateUserCart(pk, accessToken, []);
}
};

Expand Down Expand Up @@ -392,7 +390,7 @@ const App: React.FC<React.PropsWithChildren<Props>> = ({ searchQuery }) => {
};

if (isAuthenticated) {
void addUserSearchQuery(pk, accessToken, savedSearch)
addUserSearchQuery(pk, accessToken, savedSearch)
.then(() => {
saveSuccess();
})
Expand Down Expand Up @@ -428,7 +426,7 @@ const App: React.FC<React.PropsWithChildren<Props>> = ({ searchQuery }) => {
};

if (isAuthenticated) {
void deleteUserSearchQuery(searchUUID, accessToken)
deleteUserSearchQuery(searchUUID, accessToken)
.then(() => {
deleteSuccess();
})
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/DataDisplay/Tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type Props = {
color?: string;
};

/* istanbul ignore next */
export const Tag: React.FC<React.PropsWithChildren<Props>> = ({
value,
onClose,
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/components/Facets/FacetsForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
parsedFacetsFixture,
parsedNodeStatusFixture,
} from '../../test/mock/fixtures';
import FacetsForm, { humanizeFacetNames, Props } from './FacetsForm';
import FacetsForm, { formatDate, humanizeFacetNames, Props } from './FacetsForm';
import customRender from '../../test/custom-render';

const user = userEvent.setup();
Expand All @@ -25,6 +25,12 @@ describe('Test humanizeFacetNames', () => {
});
});

describe('formatDate', () => {
it('standardizes date strings', () => {
expect(formatDate('2024-12-18', true)).toEqual('20241218');
});
});

const defaultProps: Props = {
activeSearchQuery: activeSearchQueryFixture(),
availableFacets: parsedFacetsFixture(),
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/components/Feedback/Modal.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { screen } from '@testing-library/react';
import React from 'react';
import Modal from './Modal';
import customRender from '../../test/custom-render';

it('renders the component', async () => {
customRender(
<Modal onClose={jest.fn} open closeText="Close Text">
<p>Test text</p>
</Modal>
);
// Check component renders
const text = await screen.findByText('Test text');
expect(text).toBeTruthy();
});
4 changes: 1 addition & 3 deletions frontend/src/components/Feedback/Popconfirm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import React from 'react';
import Popconfirm from './Popconfirm';
import customRender from '../../test/custom-render';

const user = userEvent.setup();

it('renders component with default exclamation circle', async () => {
customRender(
<Popconfirm onConfirm={jest.fn}>
Expand All @@ -18,7 +16,7 @@ it('renders component with default exclamation circle', async () => {
expect(text).toBeTruthy();

await act(async () => {
await user.click(text);
await userEvent.click(text);
});

// Check icon defaults to exclamation circle
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/Feedback/Popconfirm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Props = {
children: React.ReactElement;
};

/* istanbul ignore next */
const Popconfirm: React.FC<React.PropsWithChildren<Props>> = ({
title = 'Are you sure?',
icon = <ExclamationCircleOutlined />,
Expand Down
Loading

0 comments on commit 867bec0

Please sign in to comment.