diff --git a/src/components/EditableText/__tests__/editableText-tests.jest.tsx b/src/components/EditableText/__tests__/editableText-tests.jest.tsx
index 31336470e3..14754cfdc5 100644
--- a/src/components/EditableText/__tests__/editableText-tests.jest.tsx
+++ b/src/components/EditableText/__tests__/editableText-tests.jest.tsx
@@ -29,6 +29,29 @@ describe("EditableText", () => {
expect(input).not.toBeInTheDocument();
});
+ describe("rendered value", () => {
+ it("should render original value when value of an editable component is cleared", async () => {
+ const value = "Editable test";
+ render();
+
+ const component = screen.getByRole("button");
+ fireEvent.click(component);
+
+ const input = screen.getByRole("input");
+ fireEvent.change(input, {
+ target: { value: "" }
+ });
+
+ expect(input).toHaveValue("");
+
+ await waitFor(() => {
+ fireEvent.keyDown(input, { key: "Enter" });
+ });
+
+ expect(within(screen.getByRole("button")).getByText(value)).toBeInTheDocument();
+ });
+ });
+
describe("event handling", () => {
describe("onClick", () => {
const onClick = jest.fn();
@@ -50,13 +73,114 @@ describe("EditableText", () => {
expect(onClick).toHaveBeenCalledTimes(1);
});
});
+
+ describe("onChange", () => {
+ const onChange = jest.fn();
+ it("should call onChange with new value when changed in an editable component", async () => {
+ const value = "Editable test";
+ const newValue = "New Editable test";
+ render();
+
+ const component = screen.getByRole("button");
+ fireEvent.click(component);
+
+ const input = screen.getByRole("input");
+ fireEvent.change(input, {
+ target: { value: newValue }
+ });
+
+ expect(input).toHaveValue(newValue);
+
+ await waitFor(() => {
+ fireEvent.keyDown(input, { key: "Enter" });
+ });
+
+ expect(within(screen.getByRole("button")).getByText(newValue)).toBeInTheDocument();
+
+ expect(onChange).toHaveBeenCalledTimes(1);
+ expect(onChange).toHaveBeenCalledWith(newValue);
+ });
+
+ it("should not call onChange when value isn't changed in an editable component", async () => {
+ const value = "Editable test";
+ render();
+
+ const component = screen.getByRole("button");
+ fireEvent.click(component);
+
+ const input = screen.getByRole("input");
+
+ expect(input).toHaveValue(value);
+
+ await waitFor(() => {
+ fireEvent.keyDown(input, { key: "Enter" });
+ });
+
+ expect(within(screen.getByRole("button")).getByText(value)).toBeInTheDocument();
+
+ expect(onChange).not.toBeCalled();
+ });
+
+ it("should not call onChange when value of an editable component is cleared", async () => {
+ const value = "Editable test";
+ render();
+
+ const component = screen.getByRole("button");
+ fireEvent.click(component);
+
+ const input = screen.getByRole("input");
+ fireEvent.change(input, {
+ target: { value: "" }
+ });
+
+ expect(input).toHaveValue("");
+
+ await waitFor(() => {
+ fireEvent.keyDown(input, { key: "Enter" });
+ });
+
+ expect(within(screen.getByRole("button")).getByText(value)).toBeInTheDocument();
+ expect(onChange).not.toBeCalled();
+ });
+ });
+
+ describe("onEditModeChange", () => {
+ const onEditModeChange = jest.fn();
+ it("should call onEditModeChange with true when enter edit mode", async () => {
+ const value = "Editable test";
+ render();
+
+ const component = screen.getByRole("button");
+ fireEvent.click(component);
+
+ expect(onEditModeChange).toHaveBeenCalledTimes(1);
+ expect(onEditModeChange).toHaveBeenCalledWith(true);
+ });
+
+ it("should call onEditModeChange with false when exit edit mode", async () => {
+ const value = "Editable test";
+ render();
+
+ const component = screen.getByRole("button");
+ fireEvent.click(component);
+
+ const input = screen.getByRole("input");
+ await waitFor(() => {
+ fireEvent.keyDown(input, { key: "Enter" });
+ });
+
+ expect(onEditModeChange).toHaveBeenCalledTimes(2);
+ expect(onEditModeChange).toHaveBeenLastCalledWith(false);
+ });
+ });
});
describe("with placeholder", () => {
it("should show a placeholder if provided and input is empty", async () => {
+ const onChange = jest.fn();
const placeholderText = "Placeholder text";
const value = "Editable test";
- render();
+ render();
const component = screen.getByRole("button");
fireEvent.click(component);
@@ -74,6 +198,32 @@ describe("EditableText", () => {
});
expect(within(screen.getByRole("button")).getByText(placeholderText)).toBeInTheDocument();
+ expect(onChange).toHaveBeenCalledTimes(1);
+ expect(onChange).toHaveBeenCalledWith("");
+ });
+
+ it("should not show a placeholder if provided and input is not empty", async () => {
+ const placeholderText = "Placeholder text";
+ const value = "Editable test";
+ const newValue = "New Editable test";
+ render();
+
+ const component = screen.getByRole("button");
+ fireEvent.click(component);
+
+ const input = screen.getByRole("input");
+ fireEvent.change(input, {
+ target: { value: newValue }
+ });
+
+ expect(input).toHaveValue(newValue);
+ expect(screen.getByPlaceholderText(placeholderText)).toBeInTheDocument();
+
+ await waitFor(() => {
+ fireEvent.keyDown(input, { key: "Enter" });
+ });
+
+ expect(within(screen.getByRole("button")).getByText(newValue)).toBeInTheDocument();
});
});
});
diff --git a/src/components/EditableTypography/EditableTypography.tsx b/src/components/EditableTypography/EditableTypography.tsx
index 9d284be92b..7303a29cb3 100644
--- a/src/components/EditableTypography/EditableTypography.tsx
+++ b/src/components/EditableTypography/EditableTypography.tsx
@@ -94,11 +94,16 @@ const EditableTypography: VibeComponent =
function handleInputValueChange() {
handleEditModeChange(false);
+ if (value === inputValue) {
+ return;
+ }
+
const shouldShowPlaceholderWhenEmpty = clearable && placeholder;
- if ((!inputValue && !shouldShowPlaceholderWhenEmpty) || value === inputValue) {
+ if (!inputValue && !shouldShowPlaceholderWhenEmpty) {
setInputValue(value);
return;
}
+ setInputValue(inputValue);
onChange?.(inputValue);
}