Add tests for AircraftLayer.

This commit is contained in:
Dan Albert 2023-06-05 23:58:35 -07:00 committed by Raffson
parent 389d230ea3
commit 3b40aef70c
No known key found for this signature in database
GPG Key ID: B0402B2C9B764D99
5 changed files with 121 additions and 26 deletions

View File

@ -1,11 +1,11 @@
import App from "./App"; import App from "./App";
import { store } from "./app/store"; import { setupStore } from "./app/store";
import { render } from "@testing-library/react"; import { render } from "@testing-library/react";
import { Provider } from "react-redux"; import { Provider } from "react-redux";
test("app renders", () => { test("app renders", () => {
render( render(
<Provider store={store}> <Provider store={setupStore()}>
<App /> <App />
</Provider> </Provider>
); );

View File

@ -3,36 +3,48 @@ import combatReducer from "../api/combatSlice";
import controlPointsReducer from "../api/controlPointsSlice"; import controlPointsReducer from "../api/controlPointsSlice";
import flightsReducer from "../api/flightsSlice"; import flightsReducer from "../api/flightsSlice";
import frontLinesReducer from "../api/frontLinesSlice"; import frontLinesReducer from "../api/frontLinesSlice";
import iadsNetworkReducer from "../api/iadsNetworkSlice";
import mapReducer from "../api/mapSlice"; import mapReducer from "../api/mapSlice";
import navMeshReducer from "../api/navMeshSlice"; import navMeshReducer from "../api/navMeshSlice";
import supplyRoutesReducer from "../api/supplyRoutesSlice"; import supplyRoutesReducer from "../api/supplyRoutesSlice";
import tgosReducer from "../api/tgosSlice"; import tgosReducer from "../api/tgosSlice";
import iadsNetworkReducer from "../api/iadsNetworkSlice";
import threatZonesReducer from "../api/threatZonesSlice"; import threatZonesReducer from "../api/threatZonesSlice";
import unculledZonesReducer from "../api/unculledZonesSlice"; import unculledZonesReducer from "../api/unculledZonesSlice";
import { Action, ThunkAction, configureStore } from "@reduxjs/toolkit"; import {
Action,
PreloadedState,
ThunkAction,
combineReducers,
configureStore,
} from "@reduxjs/toolkit";
export const store = configureStore({ const rootReducer = combineReducers({
reducer: { combat: combatReducer,
combat: combatReducer, controlPoints: controlPointsReducer,
controlPoints: controlPointsReducer, flights: flightsReducer,
flights: flightsReducer, frontLines: frontLinesReducer,
frontLines: frontLinesReducer, map: mapReducer,
map: mapReducer, navmeshes: navMeshReducer,
navmeshes: navMeshReducer, supplyRoutes: supplyRoutesReducer,
supplyRoutes: supplyRoutesReducer, iadsNetwork: iadsNetworkReducer,
iadsNetwork: iadsNetworkReducer, tgos: tgosReducer,
tgos: tgosReducer, threatZones: threatZonesReducer,
threatZones: threatZonesReducer, [baseApi.reducerPath]: baseApi.reducer,
[baseApi.reducerPath]: baseApi.reducer, unculledZones: unculledZonesReducer,
unculledZones: unculledZonesReducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(baseApi.middleware),
}); });
export type AppDispatch = typeof store.dispatch; export function setupStore(preloadedState?: PreloadedState<RootState>) {
export type RootState = ReturnType<typeof store.getState>; return configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(baseApi.middleware),
preloadedState: preloadedState,
});
}
export type AppStore = ReturnType<typeof setupStore>;
export type AppDispatch = AppStore["dispatch"];
export type RootState = ReturnType<typeof rootReducer>;
export type AppThunk<ReturnType = void> = ThunkAction< export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType, ReturnType,
RootState, RootState,

View File

@ -0,0 +1,53 @@
import { renderWithProviders } from "../../testutils";
import AircraftLayer from "./AircraftLayer";
import { PropsWithChildren } from "react";
const mockLayerGroup = jest.fn();
const mockMarker = jest.fn();
jest.mock("react-leaflet", () => ({
LayerGroup: (props: PropsWithChildren<any>) => {
mockLayerGroup(props);
return <>{props.children}</>;
},
Marker: (props: any) => {
mockMarker(props);
},
}));
test("layer is empty by default", async () => {
renderWithProviders(<AircraftLayer />);
expect(mockLayerGroup).toHaveBeenCalledTimes(1);
expect(mockMarker).not.toHaveBeenCalled();
});
test("layer has aircraft if non-empty", async () => {
renderWithProviders(<AircraftLayer />, {
preloadedState: {
flights: {
flights: {
foo: {
id: "foo",
blue: true,
sidc: "",
position: {
lat: 0,
lng: 0,
},
},
bar: {
id: "bar",
blue: false,
sidc: "",
position: {
lat: 0,
lng: 0,
},
},
},
selected: null,
},
},
});
expect(mockLayerGroup).toHaveBeenCalledTimes(1);
expect(mockMarker).toHaveBeenCalledTimes(2);
});

View File

@ -1,5 +1,5 @@
import App from "./App"; import App from "./App";
import { store } from "./app/store"; import { setupStore } from "./app/store";
import { SocketProvider } from "./components/socketprovider/socketprovider"; import { SocketProvider } from "./components/socketprovider/socketprovider";
import "./index.css"; import "./index.css";
import * as serviceWorker from "./serviceWorker"; import * as serviceWorker from "./serviceWorker";
@ -12,7 +12,7 @@ const root = ReactDOM.createRoot(
); );
root.render( root.render(
<React.StrictMode> <React.StrictMode>
<Provider store={store}> <Provider store={setupStore()}>
<SocketProvider> <SocketProvider>
<App /> <App />
</SocketProvider> </SocketProvider>

View File

@ -0,0 +1,30 @@
// https://redux.js.org/usage/writing-tests
import { setupStore } from "../app/store";
import type { AppStore, RootState } from "../app/store";
import type { PreloadedState } from "@reduxjs/toolkit";
import { render } from "@testing-library/react";
import type { RenderOptions } from "@testing-library/react";
import React, { PropsWithChildren } from "react";
import { Provider } from "react-redux";
// This type interface extends the default options for render from RTL, as well
// as allows the user to specify other things such as initialState, store.
interface ExtendedRenderOptions extends Omit<RenderOptions, "queries"> {
preloadedState?: PreloadedState<RootState>;
store?: AppStore;
}
export function renderWithProviders(
ui: React.ReactElement,
{
preloadedState = {},
// Automatically create a store instance if no store was passed in
store = setupStore(preloadedState),
...renderOptions
}: ExtendedRenderOptions = {}
) {
function Wrapper({ children }: PropsWithChildren<{}>): JSX.Element {
return <Provider store={store}>{children}</Provider>;
}
return { store, ...render(ui, { wrapper: Wrapper, ...renderOptions }) };
}