Skip to content

Commit

Permalink
Fix routing form field input loosing focus on typing (#18381)
Browse files Browse the repository at this point in the history
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
  • Loading branch information
hariombalhara and Udit-takkar authored Dec 27, 2024
1 parent b5bec79 commit ab942ed
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 7 deletions.
163 changes: 163 additions & 0 deletions packages/app-store/routing-forms/__tests__/uiConfig.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import type { Settings } from "react-awesome-query-builder";
import { describe, it, vi, expect } from "vitest";

import {
ConfigFor,
withRaqbSettingsAndWidgets,
} from "../components/react-awesome-query-builder/config/uiConfig";

// Mock dependencies
vi.mock("../components/react-awesome-query-builder/widgets", () => ({
default: {
TextWidget: vi.fn(),
TextAreaWidget: vi.fn(),
MultiSelectWidget: vi.fn(),
SelectWidget: vi.fn(),
NumberWidget: vi.fn(),
FieldSelect: vi.fn(),
Conjs: vi.fn(),
Button: vi.fn(),
ButtonGroup: vi.fn(),
Provider: vi.fn(),
},
}));

vi.mock("@calcom/ui", () => ({
EmailField: vi.fn(),
}));

describe("uiConfig", () => {
const mockConfig = {
widgets: {
text: {
type: "text",
},
textarea: {
type: "textarea",
},
number: {
type: "number",
},
multiselect: {
type: "multiselect",
},
select: {
type: "select",
},
phone: {
type: "phone",
},
email: {
type: "email",
},
},
settings: {} as Settings,
};

describe("withRaqbSettingsAndWidgets", () => {
it("should add factory functions to all widgets", () => {
const result = withRaqbSettingsAndWidgets({
config: mockConfig,
configFor: ConfigFor.FormFields,
});

// Verify each widget has a factory function
expect(result.widgets.text).toHaveProperty("factory");
expect(result.widgets.textarea).toHaveProperty("factory");
expect(result.widgets.number).toHaveProperty("factory");
expect(result.widgets.multiselect).toHaveProperty("factory");
expect(result.widgets.select).toHaveProperty("factory");
expect(result.widgets.phone).toHaveProperty("factory");
expect(result.widgets.email).toHaveProperty("factory");
});

it("should add render functions to settings", () => {
const result = withRaqbSettingsAndWidgets({
config: mockConfig,
configFor: ConfigFor.FormFields,
});

// Verify settings have all required render functions
expect(result.settings).toHaveProperty("renderField");
expect(result.settings).toHaveProperty("renderOperator");
expect(result.settings).toHaveProperty("renderFunc");
expect(result.settings).toHaveProperty("renderConjs");
expect(result.settings).toHaveProperty("renderButton");
expect(result.settings).toHaveProperty("renderButtonGroup");
expect(result.settings).toHaveProperty("renderProvider");
});

it("should preserve existing widget properties while adding factory", () => {
const configWithExistingProps = {
...mockConfig,
widgets: {
...mockConfig.widgets,
text: {
type: "text",
existingProp: "value",
},
},
};

const result = withRaqbSettingsAndWidgets({
config: configWithExistingProps,
configFor: ConfigFor.FormFields,
});

expect(result.widgets.text).toHaveProperty("existingProp", "value");
expect(result.widgets.text).toHaveProperty("factory");
});

it("should set correct placeholder for phone widget", () => {
const result = withRaqbSettingsAndWidgets({
config: mockConfig,
configFor: ConfigFor.FormFields,
});

expect(result.widgets.phone).toHaveProperty("valuePlaceholder", "Enter Phone Number");
});

it("should reuse same component fns for widgets - ensures remounting is not happening", () => {
const configWithExistingProps = {
...mockConfig,
};

const result = withRaqbSettingsAndWidgets({
config: configWithExistingProps,
configFor: ConfigFor.FormFields,
});

// @ts-expect-error - TODO: fix this
const textFactory = result.widgets.text.factory;

const result2 = withRaqbSettingsAndWidgets({
config: configWithExistingProps,
configFor: ConfigFor.FormFields,
});

// @ts-expect-error - TODO: fix this
// Using same reference
expect(result2.widgets.text.factory).toBe(textFactory);
});

it("should reuse same component fns for settings - ensures remounting is not happening", () => {
const configWithExistingProps = {
...mockConfig,
};

const result1 = withRaqbSettingsAndWidgets({
config: configWithExistingProps,
configFor: ConfigFor.FormFields,
});

const renderFieldOnFirstCallOfWithRaqbSettingsAndWidgets = result1.settings.renderField;

const result2 = withRaqbSettingsAndWidgets({
config: configWithExistingProps,
configFor: ConfigFor.FormFields,
});

expect(result2.settings.renderField).toBe(renderFieldOnFirstCallOfWithRaqbSettingsAndWidgets);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,21 @@ function withFactoryWidgets(widgets: WidgetsWithoutFactory) {
return widgetsWithFactory;
}

// These are components and components reference when changed causes remounting of components. So, ensure that renderField and others are defined only once
const sharedSettingsProps: Partial<Settings> = {
renderField: (props) => renderComponent(props, FieldSelect),
renderOperator: (props) => renderComponent(props, FieldSelect),
renderFunc: (props) => renderComponent(props, FieldSelect),
renderConjs: (props) => renderComponent(props, Conjs),
renderButton: (props) => renderComponent(props, Button),
renderButtonGroup: (props) => renderComponent(props, ButtonGroup),
renderProvider: (props) => renderComponent(props, Provider),
};

function withRenderFnsSettings(settings: Settings) {
const settingsWithRenderFns: Settings = {
...settings,
renderField: (props) => renderComponent(props, FieldSelect),
renderOperator: (props) => renderComponent(props, FieldSelect),
renderFunc: (props) => renderComponent(props, FieldSelect),
renderConjs: (props) => renderComponent(props, Conjs),
renderButton: (props) => renderComponent(props, Button),
renderButtonGroup: (props) => renderComponent(props, ButtonGroup),
renderProvider: (props) => renderComponent(props, Provider),
...sharedSettingsProps,
};
return settingsWithRenderFns;
}
Expand Down

0 comments on commit ab942ed

Please sign in to comment.