/* * Copyright 2021 Palantir Technologies, Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { mount } from "enzyme"; import { act } from "react"; import * as sinon from "sinon"; import { Classes } from "@blueprintjs/core"; import { describe, expect, it } from "@blueprintjs/test-commons/vitest"; import { Cell, EditableCell } from ".."; import * as TableClasses from "../common/classes"; import { CellType, expectCellLoading } from "./cellTestUtils"; describe("", () => { it("renders", () => { const elem = mount(); expect(elem.find(`.${TableClasses.TABLE_TRUNCATED_TEXT}`).text()).to.equal("test-value-5000"); }); it("renders loading state", () => { const editableCellHarness = mount(); expectCellLoading(editableCellHarness.first().getDOMNode(), CellType.BODY_CELL); }); it("renders cell with default tabIndex as zero", () => { const tabIndex = 0; const elem = mount(); const cellInstance = elem.find(Cell).instance() as Cell; expect(cellInstance.props.tabIndex).to.equal(tabIndex); }); it("renders cell with tabIndex", () => { const tabIndex = 1; const elem = mount(); const cellInstance = elem.find(Cell).instance() as Cell; expect(cellInstance.props.tabIndex).to.equal(tabIndex); }); it("renders new value if props.value changes", () => { const VALUE_1 = "foo"; const VALUE_2 = "bar"; const elem = mount(); expect(elem.find(`.${TableClasses.TABLE_TRUNCATED_TEXT}`).text()).to.equal(VALUE_1); elem.setProps({ value: VALUE_2 }); expect(elem.find(`.${TableClasses.TABLE_TRUNCATED_TEXT}`).text()).to.equal(VALUE_2); }); it("edits", () => { const onCancel = sinon.spy(); const onChange = sinon.spy(); const onConfirm = sinon.spy(); const elem = mount( , ); // start editing act(() => { elem.setState({ dirtyValue: "test-value-5000", isEditing: true }); }); const input = elem.find("input"); expect(input).to.have.lengthOf(1); // make changes input.simulate("change", { target: { value: "new-text" } }); expect(onChange.called).to.be.true; expect(onCancel.called).to.be.false; expect(onConfirm.called).to.be.false; expect(elem.text()).to.equal("new-text"); // confirm input.simulate("blur"); expect(onCancel.called).to.be.false; expect(onConfirm.called).to.be.true; }); it("changes value state on non-value prop changes", () => { const onCancel = sinon.spy(); const onChange = sinon.spy(); const onConfirm = sinon.spy(); const elem = mount( , ); // start editing act(() => { elem.setState({ dirtyValue: "test-value-5000", isEditing: true }); }); const input = elem.find(`.${TableClasses.TABLE_EDITABLE_TEXT} input`); expect(input).to.have.lengthOf(1); // make changes input.simulate("change", { target: { value: "new-text" } }); expect(onChange.called).to.be.true; expect(onCancel.called).to.be.false; expect(onConfirm.called).to.be.false; expect(elem.text()).to.equal("new-text"); // confirm input.simulate("blur"); expect(onCancel.called).to.be.false; expect(onConfirm.called).to.be.true; // cell shows user-entered text until re-render expect(elem.text()).to.equal("new-text"); // set non-value prop, forces EditableCell update elem.setProps({ onChange: null }); // value resets to prop expect(elem.text()).to.equal("test-value-5000"); }); it("passes index prop to callbacks if index was provided", () => { const onCancelSpy = sinon.spy(); const onChangeSpy = sinon.spy(); const onConfirmSpy = sinon.spy(); const CHANGED_VALUE = "my-changed-value"; const ROW_INDEX = 17; const COLUMN_INDEX = 44; const elem = mount( , ); // start editing act(() => { elem.setState({ dirtyValue: "", isEditing: true }); }); // change value elem.find("input").simulate("change", { target: { value: CHANGED_VALUE } }); expect(onChangeSpy.firstCall.args).to.deep.equal([CHANGED_VALUE, ROW_INDEX, COLUMN_INDEX]); // confirm elem.find("input").simulate("blur"); expect(onChangeSpy.firstCall.args).to.deep.equal([CHANGED_VALUE, ROW_INDEX, COLUMN_INDEX]); }); it("defaults to no wrapText", () => { const elem = mount(); expect(elem.find(`.${TableClasses.TABLE_NO_WRAP_TEXT}`).exists()).to.be.true; }); it("wraps text when wrapText is true", () => { const elem = mount(); expect(elem.find(`.${TableClasses.TABLE_NO_WRAP_TEXT}`).exists()).to.be.false; }); it("Passes editableTextProps to inner EditableText", () => { const onCancel = sinon.spy(); const onChange = sinon.spy(); const onConfirm = sinon.spy(); const elem = mount( , ); // start editing act(() => { elem.setState({ dirtyValue: "test-value-5000", isEditing: true }); }); const input = elem.find("input"); // input props that EditableCell does not care about should pass through unchanged expect(input.prop("maxLength")).to.equal(345); expect(elem.find(`.${Classes.EDITABLE_TEXT}`).prop("className")).to.contain("input-only-class"); // But special values should be overridden by EditableCell expect(input.prop("value")).to.equal("test-value-5000"); }); });