Skip to content

Commit

Permalink
Use webpack to load JSON data
Browse files Browse the repository at this point in the history
  • Loading branch information
david-yz-liu committed Apr 10, 2024
1 parent 7b1066f commit 27edfd4
Show file tree
Hide file tree
Showing 13 changed files with 65 additions and 56 deletions.
58 changes: 11 additions & 47 deletions demo/src/MemoryModelsSample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@ import {
} from "@mui/material";
import { ExpandMore } from "@mui/icons-material";

import { SAMPLES } from "./sample";

type MemoryModelsSamplePropTypes = {
setTextData: React.Dispatch<React.SetStateAction<string>>;
setConfigData: React.Dispatch<React.SetStateAction<object>>;
onTextDataSubmit: () => void;
};

export default function MemoryModelsSample(props: MemoryModelsSamplePropTypes) {
const [fileContents, setFileContents] = useState<{
[key: string]: [string, Object];
}>({});
const [clickedBtnIndex, setClickedBtnIndex] = useState<Number>(null);

useEffect(() => {
Expand All @@ -28,45 +27,14 @@ export default function MemoryModelsSample(props: MemoryModelsSamplePropTypes) {
}
}, [clickedBtnIndex]);

// useEffect with empty dependency array mimics componentDidMount
// https://stackoverflow.com/a/58579462
useEffect(() => {
const samples = [
"automation",
"blankspace",
"manual",
"simple",
"style",
];
const tempFileContents = {};
for (const sample of samples) {
// client-side React doesn't have many options for reading local files
// fs doesn't work. Alternatively since the goal is storing string,
// we can just store the file as the product of JSON.stringify in .txt
// but that'd be a design choice
tempFileContents[sample] = [
JSON.stringify(
require(`./sample/${sample}/${sample}.json`),
null,
2
),
require(`./sample/${sample}/config.json`),
];
}
setFileContents({
...tempFileContents,
});
}, []);

const handleButtonClick = (
index: Number,
content: string,
config: Object
) => {
props.setTextData(content);
const handleButtonClick = (index: Number, sample: Object) => {
// Note: the following conversion to a string is inefficient, as the data is later parsed
// back into JSON for rendering.
// TODO: fix this.
props.setTextData(JSON.stringify(sample["data"], null, 4));
props.setConfigData((prevConfigData) => ({
...prevConfigData,
...config,
...sample["config"],
}));
setClickedBtnIndex(index);
};
Expand All @@ -83,16 +51,12 @@ export default function MemoryModelsSample(props: MemoryModelsSamplePropTypes) {
<Card color="neutral">
<CardContent>
<Grid container spacing={2}>
{Object.entries(fileContents).map((file, index) => (
{SAMPLES.map((sample, index) => (
<Grid item xs={12} sm={6} md={4} key={index}>
<Button
variant="contained"
onClick={() =>
handleButtonClick(
index,
file[1][0],
file[1][1]
)
handleButtonClick(index, sample)
}
color={
index === clickedBtnIndex
Expand All @@ -101,7 +65,7 @@ export default function MemoryModelsSample(props: MemoryModelsSamplePropTypes) {
}
sx={{ textTransform: "capitalize" }}
>
{file[0]}
{sample["name"]}
</Button>
</Grid>
))}
Expand Down
22 changes: 14 additions & 8 deletions demo/src/__tests__/MemoryModelsSample.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
jest.mock(
"../sample/automation/automation.json",
"../sample/automated-layout/data.json",
() => ({ sample: "automation" }),
{ virtual: true }
);
jest.mock("../sample/automation/config.json", () => ({ config: "config" }), {
virtual: true,
});
jest.mock(
"../sample/automated-layout/config.json",
() => ({ config: "config" }),
{
virtual: true,
}
);

import React from "react";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import MemoryModelsSample from "../MemoryModelsSample";
import { SAMPLES } from "../sample";

describe("MemoryModelsSample", () => {
// submit button by default resets the form https://stackoverflow.com/a/62404526
const onSubmitMock = jest.fn(() => {});
Expand Down Expand Up @@ -42,19 +48,19 @@ describe("MemoryModelsSample", () => {
// sx for MUI comps or non-inline CSS in general will not be loaded into Jest by default
// might be achievable with some libs but this test makes sure the base texts are present.
// Therefore, we can't test for capitalization (via sx) here
["automation", "blankspace", "manual", "simple", "style"].map(
(sample) => expect(screen.getByText(sample)).toBeDefined()
SAMPLES.map((sample) =>
expect(screen.getByText(sample["name"])).toBeDefined()
);
});

it("handles sample button click", async () => {
const button = screen.getByText("automation");
const button = screen.getByText("Automated Layout");
fireEvent.click(button);

// Wait for state updates and side effects to complete
await waitFor(() => {
expect(setTextDataMock).toHaveBeenCalledWith(
JSON.stringify({ sample: "automation" }, null, 2)
JSON.stringify({ sample: "automation" }, null, 4)
);
expect(nextState).toEqual({ config: "config" });
expect(onSubmitMock).toHaveBeenCalled();
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
38 changes: 38 additions & 0 deletions demo/src/sample/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import automated_layout_config from "./automated-layout/config";
import automated_layout_data from "./automated-layout/data";
import blanks_config from "./blanks/config";
import blanks_data from "./blanks/data";
import manual_layout_config from "./manual-layout/config";
import manual_layout_data from "./manual-layout/data";
import simple_config from "./simple/config";
import simple_data from "./simple/data";
import styling_config from "./styling/config";
import styling_data from "./styling/data";

export const SAMPLES = [
{
name: "Simple",
data: simple_data,
config: simple_config,
},
{
name: "Manual Layout",
data: manual_layout_data,
config: manual_layout_config,
},
{
name: "Automated Layout",
data: automated_layout_data,
config: automated_layout_config,
},
{
name: "Blank spaces",
data: blanks_data,
config: blanks_config,
},
{
name: "Custom styling",
data: styling_data,
config: styling_config,
},
];
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 2 additions & 1 deletion demo/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ module.exports = [
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{ test: /\.json$/, type: "json" },
],
},
mode: "development",
Expand All @@ -53,7 +54,7 @@ module.exports = [
}),
],
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx", ".css"],
extensions: [".ts", ".tsx", ".js", ".jsx", ".json", ".css"],
},
},
];

0 comments on commit 27edfd4

Please sign in to comment.