Skip to content

Commit 4d981ca

Browse files
committed
Export all the shadcn autoform subcomponents from the factory
Before, the factory for shadcn auto components only returned the top level `<AutoForm/>` component, but now, we export all the other little inner input components as well. This allows users to use the inner components by name when they want to take control, like we do in a bunch of the tests. This also matches the kind of barrel-file export we do with Polaris as well. [no-changelog-required]
1 parent 6ff6af3 commit 4d981ca

22 files changed

+575
-959
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ packages/react/src/internal/gql
2222
packages/react/auto
2323

2424
*storybook.log
25+
26+
packages/react/cypress/screenshots/

packages/react/cypress/component/auto/form/PolarisAutoEnumInput.cy.tsx renamed to packages/react/cypress/component/auto/form/AutoEnumInput.cy.tsx

Lines changed: 76 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
import React from "react";
22
import { apiTriggerOnly } from "../../../../spec/auto/support/Triggers.js";
33
import { getStadiumRecord } from "../../../../spec/auto/support/stadiumModel.js";
4-
import { PolarisAutoForm } from "../../../../src/auto/polaris/PolarisAutoForm.js";
54
import { api } from "../../../support/api.js";
6-
import { PolarisWrapper } from "../../../support/auto.js";
5+
import { describeForEachAutoAdapter } from "../../../support/auto.js";
6+
import { SUITE_NAMES } from "../../../support/constants.js";
77

8-
describe("PolarisEnumInput", () => {
8+
describeForEachAutoAdapter("AutoEnumInput", ({ name, adapter: { AutoForm }, wrapper }) => {
99
const blurComboboxes = () => {
10-
cy.get("#type-combobox-textfield").blur({ force: true });
11-
cy.get("#tags-combobox-textfield").blur({ force: true });
10+
cy.get("body").click({ force: true });
11+
};
12+
13+
const checkBadgeWithButton = (value: string) => {
14+
cy.get(`div`)
15+
.contains(value)
16+
.should("exist")
17+
.within(() => {
18+
cy.get(`button`).should("exist").and("be.visible");
19+
});
1220
};
1321

1422
beforeEach(() => {
@@ -55,18 +63,24 @@ describe("PolarisEnumInput", () => {
5563
).as("updateStadium");
5664
});
5765

66+
const getInputSelector = (id: string) => {
67+
return name == SUITE_NAMES.SHADCN ? `[data-testid='${id}-combobox-textfield']` : `#${id}-combobox-textfield`;
68+
};
69+
70+
const selectedItemsSelector = name == SUITE_NAMES.SHADCN ? `[role="presentation"]` : ".Polaris-InlineStack";
71+
5872
it("should include the enum options in the dropdown", () => {
5973
cy.mockModelActionMetadata(api, baseModelActionMetadata);
6074

61-
cy.mountWithWrapper(<PolarisAutoForm action={api.game.stadium.create} />, PolarisWrapper);
62-
cy.get("#type-combobox-textfield").click();
75+
cy.mountWithWrapper(<AutoForm action={api.game.stadium.create} />, wrapper);
76+
cy.get(getInputSelector("type")).click();
6377
cy.contains("football").should("exist");
6478
cy.contains("basketball").should("exist");
6579
cy.contains("baseball").should("exist");
6680
// Close the "type" dropdown
6781
blurComboboxes();
6882

69-
cy.get("#tags-combobox-textfield").click();
83+
cy.get(getInputSelector("tags")).click();
7084
cy.contains("hello").should("exist");
7185
cy.contains("world").should("exist");
7286
});
@@ -75,15 +89,23 @@ describe("PolarisEnumInput", () => {
7589
it("should show the selected value in the dropdown for single select enum", () => {
7690
cy.mockModelActionMetadata(api, baseModelActionMetadata);
7791

78-
cy.mountWithWrapper(<PolarisAutoForm action={api.game.stadium.create} />, PolarisWrapper);
79-
cy.get("#type-combobox-textfield").click();
92+
cy.mountWithWrapper(<AutoForm action={api.game.stadium.create} />, wrapper);
93+
cy.get(getInputSelector("type")).click();
8094
cy.contains("football").click();
81-
cy.get(".Polaris-InlineStack").should("contain", "football");
82-
83-
cy.get("#tags-combobox-textfield").click();
84-
cy.contains("hello").parent().parent().click();
85-
cy.get(".Polaris-InlineStack").should("contain", "hello");
86-
cy.get(".Polaris-InlineStack").should("not.contain", "world");
95+
cy.get(selectedItemsSelector).should("contain", "football");
96+
97+
if (name == SUITE_NAMES.SHADCN) {
98+
cy.get("[cmdk-input]").eq(1).click();
99+
cy.get('[cmdk-item][data-value="hello"]').click();
100+
cy.get("[cmdk-input]").eq(1).click();
101+
cy.get('[cmdk-item][data-value="hello"][data-selected="true"]').should("exist");
102+
cy.get('[cmdk-item][data-value="world"][data-selected="true"]').should("not.exist");
103+
} else {
104+
cy.get(getInputSelector("tags")).click();
105+
cy.contains("hello").parent().parent().click();
106+
cy.get(selectedItemsSelector).should("contain", "hello");
107+
cy.get(selectedItemsSelector).should("not.contain", "world");
108+
}
87109

88110
blurComboboxes();
89111

@@ -99,27 +121,37 @@ describe("PolarisEnumInput", () => {
99121
it("should allow searching for options in the dropdown", () => {
100122
cy.mockModelActionMetadata(api, baseModelActionMetadata);
101123

102-
cy.mountWithWrapper(<PolarisAutoForm action={api.game.stadium.create} />, PolarisWrapper);
124+
cy.mountWithWrapper(<AutoForm action={api.game.stadium.create} />, wrapper);
103125
// For single select enums
104-
cy.get("#type-combobox-textfield").type("foot");
126+
cy.get(getInputSelector("type")).type("foot");
105127

106128
// The dropdown items should be filtered
107129
cy.contains("football").should("exist");
108130
cy.contains("basketball").should("not.exist");
109131
cy.contains("baseball").should("not.exist");
110132

111133
cy.contains("football").click();
112-
cy.get(".Polaris-InlineStack").should("contain", "football");
134+
cy.get(selectedItemsSelector).should("contain", "football");
113135

114136
// For multi-select enums
115-
cy.get("#tags-combobox-textfield").type("hel");
137+
cy.get(getInputSelector("tags")).type("hel");
116138

117139
// The dropdown items should be filtered
118140
cy.contains("hello").should("exist");
119141
cy.contains("world").should("not.exist");
120142

121-
cy.contains("hello").parent().parent().click();
122-
cy.get(".Polaris-InlineStack").should("contain", "hello");
143+
if (name == SUITE_NAMES.SHADCN) {
144+
cy.get('[cmdk-item][data-value="hello"]').click();
145+
// Verify that the chip/tag appears after selection
146+
checkBadgeWithButton("hello");
147+
148+
cy.get("[cmdk-input]").eq(1).click();
149+
150+
cy.contains('Add "hel"').should("exist");
151+
} else {
152+
cy.contains("hello").parent().parent().click();
153+
cy.get(selectedItemsSelector).should("contain", "hello");
154+
}
123155

124156
blurComboboxes();
125157

@@ -171,14 +203,14 @@ describe("PolarisEnumInput", () => {
171203

172204
cy.mockModelActionMetadata(api, mockedMetadata);
173205

174-
cy.mountWithWrapper(<PolarisAutoForm action={api.game.stadium.create} />, PolarisWrapper);
175-
cy.get("#type-combobox-textfield").type("extra");
206+
cy.mountWithWrapper(<AutoForm action={api.game.stadium.create} />, wrapper);
207+
cy.get(getInputSelector("type")).type("extra");
176208
cy.contains(`Add "extra"`).click();
177-
cy.get(".Polaris-InlineStack").should("contain", "extra");
209+
cy.get(selectedItemsSelector).should("contain", "extra");
178210

179-
cy.get("#tags-combobox-textfield").type("more");
211+
cy.get(getInputSelector("tags")).type("more");
180212
cy.contains(`Add "more"`).click();
181-
cy.get(".Polaris-InlineStack").should("contain", "more");
213+
cy.get(selectedItemsSelector).should("contain", "more");
182214

183215
blurComboboxes();
184216

@@ -226,14 +258,14 @@ describe("PolarisEnumInput", () => {
226258
],
227259
});
228260

229-
cy.mountWithWrapper(<PolarisAutoForm action={api.game.stadium.create} />, PolarisWrapper);
230-
cy.get("#type-combobox-textfield").type("hello");
261+
cy.mountWithWrapper(<AutoForm action={api.game.stadium.create} />, wrapper);
262+
cy.get(getInputSelector("type")).type("hello");
231263
cy.contains(`Add "hello"`).should("not.exist");
232264
cy.contains(`No options found matching "hello"`).should("exist");
233265

234266
blurComboboxes();
235267

236-
cy.get("#tags-combobox-textfield").type("nope");
268+
cy.get(getInputSelector("tags")).type("nope");
237269
cy.contains(`Add "nope"`).should("not.exist");
238270
cy.contains(`No options found matching "nope"`).should("exist");
239271
});
@@ -264,10 +296,17 @@ describe("PolarisEnumInput", () => {
264296
},
265297
});
266298

267-
cy.mountWithWrapper(<PolarisAutoForm action={api.game.stadium.update} findBy="42" />, PolarisWrapper);
268-
cy.get(".Polaris-InlineStack").should("contain", "football");
269-
cy.get(".Polaris-InlineStack").should("contain", "hello");
270-
cy.get(".Polaris-InlineStack").should("contain", "world");
299+
cy.mountWithWrapper(<AutoForm action={api.game.stadium.update} findBy="42" />, wrapper);
300+
301+
if (name == SUITE_NAMES.SHADCN) {
302+
checkBadgeWithButton("football");
303+
checkBadgeWithButton("hello");
304+
checkBadgeWithButton("world");
305+
} else {
306+
cy.get(".Polaris-InlineStack").should("contain", "football");
307+
cy.get(".Polaris-InlineStack").should("contain", "hello");
308+
cy.get(".Polaris-InlineStack").should("contain", "world");
309+
}
271310
});
272311

273312
it("should be able to clear the value", () => {
@@ -279,13 +318,13 @@ describe("PolarisEnumInput", () => {
279318
},
280319
});
281320

282-
cy.mountWithWrapper(<PolarisAutoForm action={api.game.stadium.update} findBy="42" />, PolarisWrapper);
283-
cy.get("#type-combobox-textfield").click();
321+
cy.mountWithWrapper(<AutoForm action={api.game.stadium.update} findBy="42" />, wrapper);
322+
cy.get(getInputSelector("type")).click();
284323
cy.get('[aria-label="Remove football"]').click();
285324

286325
blurComboboxes();
287326

288-
cy.get("#tags-combobox-textfield").click();
327+
cy.get(getInputSelector("tags")).click();
289328
cy.get('[aria-label="Remove hello"]').click();
290329
cy.get('[aria-label="Remove world"]').click();
291330

packages/react/cypress/component/auto/form/AutoFormDateTimePicker.cy.tsx

Lines changed: 8 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
import { format } from "date-fns";
22
import { utcToZonedTime } from "date-fns-tz";
33
import React, { useState } from "react";
4-
import { elements } from "../../../../spec/auto/shadcn-defaults/index.js";
54
import { apiTriggerOnly } from "../../../../spec/auto/support/Triggers.js";
6-
import { PolarisAutoForm } from "../../../../src/auto/polaris/PolarisAutoForm.js";
7-
import { PolarisAutoDateTimePicker } from "../../../../src/auto/polaris/inputs/PolarisAutoDateTimePicker.js";
8-
import { makeAutoForm } from "../../../../src/auto/shadcn/ShadcnAutoForm.js";
9-
import { makeShadcnAutoDateTimePicker } from "../../../../src/auto/shadcn/inputs/ShadcnAutoDateTimePicker.js";
105
import { api } from "../../../support/api.js";
116
import { describeForEachAutoAdapter } from "../../../support/auto.js";
127
import { SUITE_NAMES } from "../../../support/constants.js";
@@ -15,52 +10,17 @@ const baseDate = new Date("2021-03-05T11:23:00.000Z");
1510
const localTz = Intl.DateTimeFormat().resolvedOptions().timeZone;
1611
const dateInLocalTZ = utcToZonedTime(baseDate, localTz);
1712

18-
const ShadcnAutoDateTimePicker = makeShadcnAutoDateTimePicker(elements);
19-
const ShadcnAutoForm = makeAutoForm(elements);
13+
describeForEachAutoAdapter("AutoFormDateTimePicker", ({ name, adapter: { AutoForm, AutoDateTimePicker }, wrapper }) => {
14+
const TestComponentWithCustomOnChange = () => {
15+
const [date, setDate] = useState(baseDate);
2016

21-
const TestComponentWithCustomOnChange = ({ suiteName }: { suiteName: string }) => {
22-
const [date, setDate] = useState(baseDate);
23-
24-
if (suiteName === SUITE_NAMES.POLARIS) {
2517
return (
26-
<PolarisAutoForm action={api.widget.create}>
27-
<PolarisAutoDateTimePicker id="test" value={date} onChange={setDate} field="startsAt" />
28-
</PolarisAutoForm>
18+
<AutoForm action={api.widget.create}>
19+
<AutoDateTimePicker id="test" value={date} onChange={setDate} field="startsAt" />
20+
</AutoForm>
2921
);
30-
}
22+
};
3123

32-
if (suiteName === SUITE_NAMES.SHADCN) {
33-
return (
34-
<ShadcnAutoForm action={api.widget.create}>
35-
<ShadcnAutoDateTimePicker id="test" value={date} onChange={setDate} field="startsAt" />
36-
</ShadcnAutoForm>
37-
);
38-
}
39-
40-
throw new Error("Invalid suite name");
41-
};
42-
43-
const AutoDateTimePicker = (props: {
44-
suiteName?: string;
45-
field: string;
46-
label?: string;
47-
id?: string;
48-
onChange?: (date: Date) => void;
49-
value?: Date;
50-
includeTime?: boolean;
51-
}) => {
52-
if (props.suiteName === SUITE_NAMES.POLARIS) {
53-
return <PolarisAutoDateTimePicker {...props} />;
54-
}
55-
56-
if (props.suiteName === SUITE_NAMES.SHADCN) {
57-
return <ShadcnAutoDateTimePicker {...props} />;
58-
}
59-
60-
throw new Error("Invalid suite name");
61-
};
62-
63-
describeForEachAutoAdapter("AutoFormDateTimePicker", ({ name, adapter: { AutoForm }, wrapper }) => {
6424
beforeEach(() => {
6525
cy.viewport("macbook-13");
6626
});
@@ -347,7 +307,7 @@ describeForEachAutoAdapter("AutoFormDateTimePicker", ({ name, adapter: { AutoFor
347307

348308
it("can show the selected date", () => {
349309
mockMetadataResponse();
350-
cy.mountWithWrapper(<TestComponentWithCustomOnChange suiteName={name} />, wrapper);
310+
cy.mountWithWrapper(<TestComponentWithCustomOnChange />, wrapper);
351311
cy.wait("@ModelCreateActionMetadata");
352312
cy.get("#test-date").click();
353313

packages/react/cypress/component/auto/form/AutoFormInputLabels.cy.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { api } from "../../../support/api.js";
88
import { describeForEachAutoAdapter } from "../../../support/auto.js";
99
import { SUITE_NAMES } from "../../../support/constants.js";
1010

11-
const ShadcnAutoInput = makeShadcnAutoInput(elements);
11+
const { AutoInput: ShadcnAutoInput } = makeShadcnAutoInput(elements);
1212

1313
const AutoInput = (props: { suiteName: string; field: string; label?: string }) => {
1414
if (props.suiteName === SUITE_NAMES.POLARIS) {

0 commit comments

Comments
 (0)