Skip to content

Commit

Permalink
refactor and mock group to improve tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielburnworth committed Feb 5, 2025
1 parent 3120745 commit e20cbff
Show file tree
Hide file tree
Showing 17 changed files with 309 additions and 274 deletions.
11 changes: 0 additions & 11 deletions frontend/__test_support__/fake_html_events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,6 @@ export const changeEvent = (value: string): ChangeEvent => {
return event as ChangeEvent;
};

type IMGEvent = React.SyntheticEvent<HTMLImageElement, Event>;
export const imgEvent = (): IMGEvent => {
const event: DeepPartial<IMGEvent> = {
currentTarget: {
getAttribute: jest.fn(),
setAttribute: jest.fn(),
}
};
return event as IMGEvent;
};

type FormEvent = React.FormEvent<HTMLFormElement>;
export const formEvent = (): FormEvent => {
const event: Partial<FormEvent> = { preventDefault: jest.fn() };
Expand Down
2 changes: 1 addition & 1 deletion frontend/__test_support__/fake_props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const fakeAddPlantProps =
(plants: TaggedPlant[]): AddPlantProps => ({
gridSize: { x: 1000, y: 2000 },
dispatch: jest.fn(),
getConfigValue: jest.fn(),
getConfigValue: jest.fn(() => true),
plants,
curves: [],
designer: fakeDesignerState(),
Expand Down
13 changes: 13 additions & 0 deletions frontend/__test_support__/three_d_mocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ import {
import * as THREE from "three";
import React, { ReactNode } from "react";
import { TransitionFn, UseSpringProps } from "@react-spring/three";
import { ThreeElements } from "@react-three/fiber";

const GroupForTests = (props: ThreeElements["group"]) =>
// @ts-expect-error Property does not exist on type JSX.IntrinsicElements
<group {...props} />;

jest.mock("../three_d_garden/components", () => ({
...jest.requireActual("../three_d_garden/components"),
Group: (props: ThreeElements["group"]) =>
props.visible === false
? <></>
: <GroupForTests {...props} />,
}));

jest.mock("three/examples/jsm/Addons.js", () => ({
SVGLoader: class {
Expand Down
6 changes: 4 additions & 2 deletions frontend/external_urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ export namespace ExternalUrl {
export const cameraCalibrationCard = `${PRODUCTS}/camera-calibration-card`;
export const cameraReplacement =
`${PRODUCTS}/genesis-v1-5-express-v1-0-camera-free-replacement`;
export const genesisKitBase = `${KITS}/farmbot-genesis`;
export const genesisXlKitBase = `${KITS}/farmbot-genesis-xl`;
export const genesisKit = (version: string) =>
`${KITS}/farmbot-genesis-${version.replace(".", "-")}`;
export const genesisXlKit = (version: string) =>
`${KITS}/farmbot-genesis-xl-${version.replace(".", "-")}`;
}
}
18 changes: 12 additions & 6 deletions frontend/three_d_garden/__tests__/bot_test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@ import { clone } from "lodash";
import { SVGLoader } from "three/examples/jsm/Addons";

describe("<Bot />", () => {
const fakeProps = (): FarmbotModelProps => ({
config: clone(INITIAL),
activeFocus: "",
});
const fakeProps = (): FarmbotModelProps => {
const config = clone(INITIAL);
config.bot = true;
config.tracks = true;
config.cableCarriers = true;
return {
config,
activeFocus: "",
};
};

it("renders", () => {
const p = fakeProps();
Expand Down Expand Up @@ -38,14 +44,14 @@ describe("<Bot />", () => {
const p = fakeProps();
p.config.kitVersion = "v1.7";
const wrapper = mount(<Bot {...p} />);
expect(wrapper.find({ name: "button-group" }).length).toEqual(10);
expect(wrapper.find({ name: "button-group" }).length).toEqual(15); // 5 * 3
});

it("renders: v1.8", () => {
const p = fakeProps();
p.config.kitVersion = "v1.8";
const wrapper = mount(<Bot {...p} />);
expect(wrapper.find({ name: "button-group" }).length).toEqual(6);
expect(wrapper.find({ name: "button-group" }).length).toEqual(9); // 3 * 3
});

it("loads shapes", () => {
Expand Down
12 changes: 12 additions & 0 deletions frontend/three_d_garden/__tests__/components_test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,24 @@ import { mount } from "enzyme";
import {
AmbientLight,
DirectionalLight,
Group,
Mesh,
MeshBasicMaterial,
PointLight,
} from "../components";
import { ThreeElements } from "@react-three/fiber";

describe("<Group />", () => {
const fakeProps = (): ThreeElements["group"] => ({
visible: true,
});

it("adds props", () => {
const wrapper = mount(<Group {...fakeProps()} />);
expect(wrapper.props().visible).toEqual(true);
});
});

describe("<AmbientLight />", () => {
const fakeProps = (): ThreeElements["ambientLight"] => ({
intensity: 0.5,
Expand Down
20 changes: 10 additions & 10 deletions frontend/three_d_garden/__tests__/garden_test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import { GardenModelProps, GardenModel } from "../garden";
import { clone } from "lodash";
import { INITIAL } from "../config";
import { render, screen } from "@testing-library/react";
import { fakePlant, fakePoint, fakeWeed } from "../../__test_support__/fake_state/resources";
import {
fakePlant, fakePoint, fakeWeed,
} from "../../__test_support__/fake_state/resources";
import { fakeAddPlantProps } from "../../__test_support__/fake_props";
import { ASSETS } from "../constants";

Expand Down Expand Up @@ -144,17 +146,15 @@ describe("<GardenModel />", () => {
expect(console.log).toHaveBeenCalledWith(["1", "2"]);
});

it("renders different ground based on scene", () => {
const scenes = [
{ name: "Greenhouse", expectedClass: "ground Greenhouse" },
{ name: "Lab", expectedClass: "ground Lab" },
{ name: "Outdoor", expectedClass: "ground Outdoor" },
];
scenes.forEach(({ name, expectedClass }) => {
it.each<[string, string]>([
["Greenhouse", "ground Greenhouse"],
["Lab", "ground Lab"],
["Outdoor", "ground Outdoor"],
])("renders different ground based on scene: %s %s",
(sceneName, expectedClass) => {
const p = fakeProps();
p.config.scene = name;
p.config.scene = sceneName;
const { container } = render(<GardenModel {...p} />);
expect(container.innerHTML).toContain(expectedClass);
});
});
});
36 changes: 20 additions & 16 deletions frontend/three_d_garden/__tests__/greenhouse_test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { mount } from "enzyme";
import { render } from "@testing-library/react";
import { Greenhouse, GreenhouseProps } from "../greenhouse";
import { INITIAL } from "../config";
import { clone } from "lodash";
Expand All @@ -12,39 +12,43 @@ describe("<Greenhouse />", () => {

it("renders", () => {
const p = fakeProps();
p.config.scene = "Greenhouse";
p.config.people = false;
p.activeFocus = "";
const wrapper = mount(<Greenhouse {...p} />);
expect(wrapper.html()).toContain("greenhouse-environment");
expect(wrapper.find({ name: "people" }).first().props().visible).toBeFalsy();
expect(wrapper.html()).toContain("starter-tray-1");
expect(wrapper.html()).toContain("starter-tray-2");
expect(wrapper.html()).toContain("left-greenhouse-wall");
expect(wrapper.html()).toContain("right-greenhouse-wall");
expect(wrapper.html()).toContain("potted-plant");
const { container } = render(<Greenhouse {...p} />);
expect(container).toContainHTML("greenhouse-environment");
expect(container).not.toContainHTML("people");
expect(container).toContainHTML("starter-tray-1");
expect(container).toContainHTML("starter-tray-2");
expect(container).toContainHTML("left-greenhouse-wall");
expect(container).toContainHTML("right-greenhouse-wall");
expect(container).toContainHTML("potted-plant");
});

it("not visible when scene is not greenhouse", () => {
const p = fakeProps();
p.config.scene = "Lab";
const wrapper = mount(<Greenhouse {...p} />);
expect(wrapper.find({ name: "greenhouse-environment" }).first().props().visible).toBeFalsy();
const { container } = render(<Greenhouse {...p} />);
expect(container).not.toContainHTML("greenhouse-environment");
});

it("renders with people", () => {
const p = fakeProps();
p.config.scene = "Greenhouse";
p.config.people = true;
p.activeFocus = "";
const wrapper = mount(<Greenhouse {...p} />);
expect(wrapper.find({ name: "people" }).first().props().visible).toBeTruthy();
const { container } = render(<Greenhouse {...p} />);
expect(container).toContainHTML("greenhouse-environment");
expect(container).toContainHTML("people");
});

it("doesn't render people or potted plant when active focus is set", () => {
const p = fakeProps();
p.config.scene = "Greenhouse";
p.config.people = true;
p.activeFocus = "foo";
const wrapper = mount(<Greenhouse {...p} />);
expect(wrapper.find({ name: "people" }).first().props().visible).toBeFalsy();
expect(wrapper.find({ name: "potted-plant" }).first().props().visible).toBeFalsy();
const { container } = render(<Greenhouse {...p} />);
expect(container).toContainHTML("greenhouse-environment");
expect(container).not.toContainHTML("people");
});
});
23 changes: 15 additions & 8 deletions frontend/three_d_garden/__tests__/lab_test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { mount } from "enzyme";
import { render } from "@testing-library/react";
import { Lab, LabProps } from "../lab";
import { INITIAL } from "../config";
import { clone } from "lodash";
Expand All @@ -12,25 +12,32 @@ describe("<Lab />", () => {

it("renders", () => {
const p = fakeProps();
p.config.scene = "Lab";
p.config.people = false;
p.activeFocus = "";
const wrapper = mount(<Lab {...p} />);
expect(wrapper.html()).toContain("lab");
expect(wrapper.find({ name: "people" }).first().props().visible).toBeFalsy();
render(<Lab {...p} />);
const { container } = render(<Lab {...p} />);
expect(container).toContainHTML("shelf");
expect(container).not.toContainHTML("people");
});

it("not visible when scene is not lab", () => {
const p = fakeProps();
p.config.scene = "Greenhouse";
const wrapper = mount(<Lab {...p} />);
expect(wrapper.find({ name: "lab-environment" }).first().props().visible).toBeFalsy();
render(<Lab {...p} />);
const { container } = render(<Lab {...p} />);
expect(container).not.toContainHTML("shelf");
expect(container).not.toContainHTML("people");
});

it("renders with people", () => {
const p = fakeProps();
p.config.scene = "Lab";
p.config.people = true;
p.activeFocus = "";
const wrapper = mount(<Lab {...p} />);
expect(wrapper.find({ name: "people" }).first().props().visible).toBeTruthy();
render(<Lab {...p} />);
const { container } = render(<Lab {...p} />);
expect(container).toContainHTML("shelf");
expect(container).toContainHTML("people");
});
});
16 changes: 14 additions & 2 deletions frontend/three_d_garden/__tests__/packaging_test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,31 @@ describe("<Packaging />", () => {

it("renders", () => {
const p = fakeProps();
p.config.packaging = true;
p.config.kitVersion = "v1.7";
const wrapper = mount(<Packaging {...p} />);
expect(wrapper.html()).toContain("packaging");
expect(wrapper.html()).toContain("100");
expect(wrapper.html()).not.toContain("170");
});

it("renders: XL", () => {
it("renders: v1.7 XL", () => {
const p = fakeProps();
p.config.packaging = true;
p.config.sizePreset = "Genesis XL";
p.config.kitVersion = "v1.8";
p.config.kitVersion = "v1.7";
const wrapper = mount(<Packaging {...p} />);
expect(wrapper.html()).toContain("170");
expect(wrapper.html()).not.toContain("100");
});

it("renders: v1.8 XL", () => {
const p = fakeProps();
p.config.packaging = true;
p.config.sizePreset = "Genesis XL";
p.config.kitVersion = "v1.8";
const wrapper = mount(<Packaging {...p} />);
expect(wrapper.html()).not.toContain("170");
expect(wrapper.html()).not.toContain("100");
});
});
8 changes: 5 additions & 3 deletions frontend/three_d_garden/__tests__/solar_test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { mount } from "enzyme";
import { render } from "@testing-library/react";
import { Solar, SolarProps } from "../solar";
import { INITIAL } from "../config";
import { clone } from "lodash";
Expand All @@ -11,7 +11,9 @@ describe("<Solar />", () => {
});

it("renders", () => {
const wrapper = mount(<Solar {...fakeProps()} />);
expect(wrapper.html()).toContain("solar");
const p = fakeProps();
p.config.solar = true;
const { container } = render(<Solar {...p} />);
expect(container).toContainHTML("solar");
});
});
5 changes: 2 additions & 3 deletions frontend/three_d_garden/config_overlays.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ interface PromoInfoProps {

const PromoInfo = (props: PromoInfoProps) => {
const { isGenesis, kitVersion } = props;
const kitVersionSlug = kitVersion.replace(".", "-");
return <div className="promo-info">
<h2 className="title">Explore our models</h2>
{isGenesis
Expand Down Expand Up @@ -144,8 +143,8 @@ const PromoInfo = (props: PromoInfoProps) => {
<a className="buy-button"
target="_top"
href={isGenesis
? ExternalUrl.Store.genesisKitBase + "-" + kitVersionSlug
: ExternalUrl.Store.genesisXlKitBase + "-" + kitVersionSlug}>
? ExternalUrl.Store.genesisKit(kitVersion)
: ExternalUrl.Store.genesisXlKit(kitVersion)}>
<p>Order Genesis</p>
<p className="genesis-xl"
style={{ display: isGenesis ? "none" : "inline-block" }}>
Expand Down
34 changes: 15 additions & 19 deletions frontend/three_d_garden/garden.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,22 +111,18 @@ export const GardenModel = (props: GardenModelProps) => {
const gridZ = zero.z - config.soilHeight + 5;
const extents = extentsFunc(config);

let groundTexture;
let groundColor;
let lowDetailGroundColor;
if (config.scene === "Greenhouse") {
groundTexture = brickTexture;
groundColor = "#999";
lowDetailGroundColor = "#8c6f64";
} else if (config.scene === "Lab") {
groundTexture = labFloorTexture;
groundColor = "#aaa";
lowDetailGroundColor = "gray";
} else {
groundTexture = grassTexture;
groundColor = "#ddd";
lowDetailGroundColor = "darkgreen";
}
const getGroundProperties = (sceneName: string) => {
switch (sceneName) {
case "Greenhouse":
return { texture: brickTexture, color: "#999", lowDetailColor: "#8c6f64" };
case "Lab":
return { texture: labFloorTexture, color: "#aaa", lowDetailColor: "gray" };
default:
return { texture: grassTexture, color: "#ddd", lowDetailColor: "darkgreen" };
}
};

const groundProperties = getGroundProperties(config.scene);

// eslint-disable-next-line no-null/no-null
return <Group dispose={null}
Expand Down Expand Up @@ -167,13 +163,13 @@ export const GardenModel = (props: GardenModelProps) => {
<Detailed distances={detailLevels(config)}>
<Ground>
<MeshPhongMaterial
map={groundTexture}
color={groundColor}
map={groundProperties.texture}
color={groundProperties.color}
shininess={0} />
</Ground>
<Ground>
<MeshPhongMaterial
color={lowDetailGroundColor}
color={groundProperties.lowDetailColor}
shininess={0} />
</Ground>
</Detailed>
Expand Down
Loading

0 comments on commit e20cbff

Please sign in to comment.