Skip to content

Commit

Permalink
Merge branch 'main' of github.com:great-expectations/jsonforms-antd-r…
Browse files Browse the repository at this point in the history
…enderers into f/FE-59/add-numeric-slider-control
  • Loading branch information
NathanFarmer committed Mar 7, 2024
2 parents ba8c728 + 37cf52b commit b32d5b6
Show file tree
Hide file tree
Showing 7 changed files with 403 additions and 7 deletions.
3 changes: 1 addition & 2 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ const config: StorybookConfig = {
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-onboarding",
"@storybook/addon-interactions",
"@storybook/addon-onboarding",
],
framework: {
name: "@storybook/react-vite",
Expand Down
8 changes: 7 additions & 1 deletion src/common/StorybookAntDJsonForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type Props = {
uiSchema?: UISchema;
uiSchemaRegistryEntries?: JsonFormsUISchemaRegistryEntry[];
config?: Record<string, unknown>;
onChange: (data: Record<string, unknown>) => void;
};

// this component exists to facilitate storybook rendering
Expand All @@ -24,14 +25,19 @@ export function StorybookAntDJsonForm({
uiSchemaRegistryEntries,
rendererRegistryEntries,
config,
onChange
}: Props) {
const [data, setData] = useState(initialData);
const updateData = (newData: Record<string, unknown>) => {
setData(newData);
onChange(newData);
}
return (
<AntDJsonForm
uiSchema={uiSchema}
jsonSchema={jsonSchema}
data={data}
updateData={(newData) => setData(newData)}
updateData={(newData) => updateData(newData)}
uiSchemaRegistryEntries={uiSchemaRegistryEntries}
rendererRegistryEntries={rendererRegistryEntries}
config={config}
Expand Down
163 changes: 163 additions & 0 deletions src/controls/NumberControl.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import { describe, expect, test, it } from "vitest"
import { screen, waitFor } from "@testing-library/react"
import { userEvent } from "@testing-library/user-event"
import { render } from "../common/test-render"
import { JSONSchema } from "json-schema-to-ts"
import {
numberBasisPointsSchema,
numberBasisPointsUISchema,
numberMagnitudeSchema,
numberMagnitudeUISchema,
numberTheNumberSchema,
numberTheNumberUISchema,
numberHumiditySchema,
numberPercentageUISchema,
numberTemperatureSchema,
numberTemperatureUISchema,
numberUISchemaWithRule,
} from "../testSchemas/numberSchema"

describe("NumberControl", () => {
test("renders a number input with no UISchema provided", () => {
render({
schema: numberMagnitudeSchema,
})

expect(screen.getByText("Magnitude")).not.toBeNull()
})

it("Follows the hide rule", () => {
const data = { magnitude: 1000 }
render({
data: data,
schema: numberMagnitudeSchema,
uischema: numberUISchemaWithRule,
})
expect(screen.queryByText("Magnitude")).toBeNull()
})

it.each([[0], [100]])("renders when data of %s is included", (dataVal: number) => {
const data = { theNumber: dataVal}
render({
data: data,
schema: numberTheNumberSchema, // this has a default of 42.42
uischema: numberTheNumberUISchema,
})
expect(screen.getByText("The Number")).not.toBeNull()
expect(screen.getByRole("spinbutton")).toHaveValue(`${dataVal}`)
})

it.each([[0], [100]])("renders default value of %s when no data is provided", (defaultValue: number) => {
// create a new schema with a default value set
const { properties, ...rest } = numberMagnitudeSchema
properties.magnitude = { ...properties.magnitude, ...{ default: defaultValue }}
render({
schema: { ...rest, properties },
uischema: numberMagnitudeUISchema,
})

expect(screen.getByText("Magnitude")).not.toBeNull()
expect(screen.getByRole("spinbutton")).toHaveValue(`${defaultValue}`)
})
it("renders default value when no data is provided", () => {
render({
schema: numberTheNumberSchema,
uischema: numberTheNumberUISchema,
})
expect(screen.getByRole("spinbutton")).toHaveValue("42.42")
})

it("changes its value when users type", async () => {
let data: JSONSchema
render({
schema: numberMagnitudeSchema,
uischema: numberMagnitudeUISchema,
onChange: (state: { data: JSONSchema }) => {
data = state.data
},
})

await userEvent.clear(screen.getByRole("spinbutton"))
await userEvent.type(screen.getByRole("spinbutton"), "123")

await waitFor(() => {
expect(data).toEqual({ magnitude: 123 })
})
})

it("renders slider when min max values are present", () => {
const data = { basisPoints: 1 }
render({
data: data,
schema: numberBasisPointsSchema,
uischema: numberBasisPointsUISchema,
})
expect(screen.getByText("Basis Points")).not.toBeNull()
expect(screen.getByRole("spinbutton")).toHaveValue("1")
expect(screen.getByRole("slider")).not.toBeNull()
expect(screen.getByRole("slider")).toHaveAttribute("aria-valuenow", "1")
})

it("doesn't show slider when min max values are not present", () => {
render({
schema: numberMagnitudeSchema,
uischema: numberMagnitudeUISchema,
})
expect(screen.queryByRole("slider")).toBeNull()
})
})

it ("renders slider and input box when number of steps is greater than threshold", () => {
const data = { basisPoints: 1 }
render({
data: data,
schema: numberBasisPointsSchema, // 10,000 steps created by multipleOf
uischema: numberBasisPointsUISchema,
})
expect(screen.getByRole("slider"))
expect(screen.getByRole("spinbutton"))
})

it ("renders slider without input box when number of steps is less than threshold", () => {
const data = { basisPoints: 1 }
render({
data: data,
schema: numberHumiditySchema, // 100 steps
uischema: numberPercentageUISchema,
})
expect(screen.getByRole("slider"))
expect(screen.queryByRole("spinbutton")).toBeNull()
})

it ("shows error message onBlur when field is required and empty", async () => {
render({
schema: numberTheNumberSchema,
uischema: numberTheNumberUISchema,
})
const input = screen.getByRole("spinbutton")
await userEvent.clear(input)
await userEvent.tab()
expect(await screen.findByText("The Number is required")).not.toBeNull()
})

it ("shows units in text control if set in UI schema", async () => {
render({
schema: numberTemperatureSchema,
uischema: numberTemperatureUISchema,
})
expect(await screen.findByText("°F")).not.toBeNull()
})

it ("shows units in tooltip if set in UI schema", async () => {
render({
schema: numberHumiditySchema,
uischema: numberPercentageUISchema,
})
// we are using a schema that doesn't have the text input,
// so we can be sure the units are showing up in the tooltip
expect(screen.queryByRole("spinbutton")).toBeNull()
const slider = screen.getByRole("slider")
expect(screen.queryByText("0%")).toBeNull()
await userEvent.hover(slider)
expect(await screen.findByText("0%")).not.toBeNull()
})
8 changes: 6 additions & 2 deletions src/stories/controls/AlertControl.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@ const meta: Meta<typeof StorybookAntDJsonForm> = {
]
},
argTypes: {
rendererRegistryEntries: {},
rendererRegistryEntries: { table: { disable: true } },
uiSchemaRegistryEntries: { table: { disable: true } },
jsonSchema: {
control: "object",
}
},
data: {table: {disable: true}},
config: {control: "object"},
onChange: {table: {disable: true, action: "on-change"}},
}
};

Expand Down
6 changes: 4 additions & 2 deletions src/stories/controls/BooleanControl.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { StorybookAntDJsonForm } from "../../common/StorybookAntDJsonForm";
const schema = {
type: "object",
properties: { checkbox: { type: "boolean" } },
// required: ["name"],
};

const meta: Meta<typeof StorybookAntDJsonForm> = {
Expand Down Expand Up @@ -37,10 +36,13 @@ const meta: Meta<typeof StorybookAntDJsonForm> = {
// More on argTypes: https://storybook.js.org/docs/api/argtypes
argTypes: {
rendererRegistryEntries: { table: { disable: true } },
uiSchemaRegistryEntries: { table: { disable: true } },
jsonSchema: {
control: "object",
description: "this is a simple schema with one property (name)",
},
data: {table: {disable: true}},
config: {control: "object"},
onChange: {table: {disable: true, action: "on-change"}},
},
};

Expand Down
4 changes: 4 additions & 0 deletions src/stories/controls/TextControl.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ const meta: Meta<typeof StorybookAntDJsonForm> = {
control: "object",
description: "this is a simple schema with one property (name)",
},
uiSchemaRegistryEntries: { table: { disable: true } },
data: {table: {disable: true}},
config: {control: "object"},
onChange: {table: {disable: true, action: "on-change"}},
},
};

Expand Down
Loading

0 comments on commit b32d5b6

Please sign in to comment.