devextreme
Version:
JavaScript/TypeScript Component Suite for Responsive Web Development
414 lines (413 loc) • 15.4 kB
JavaScript
/**
* DevExtreme (esm/__internal/grids/new/grid_core/editing/options.test.js)
* Version: 25.2.7
* Build date: Tue May 05 2026
*
* Copyright (c) 2012 - 2026 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
import {
afterEach,
describe,
expect,
it,
jest
} from "@jest/globals";
import $ from "../../../../../core/renderer";
import dxCalendar from "../../../../../ui/calendar";
import CardView from "../../../../grids/new/card_view/widget";
import {
rerender
} from "inferno";
import {
getContext
} from "../di.test_utils";
import {
OptionsControllerMock
} from "../options_controller/options_controller.mock";
import {
ToolbarController
} from "../toolbar/controller";
import {
ConfirmController
} from "./confirm_controller";
import {
EditingController
} from "./controller";
import {
EditPopupView
} from "./popup/view";
const SELECTORS = {
cardView: ".dx-cardview",
card: ".dx-cardview-card"
};
class MockConfirmController {
constructor() {
this.confirm = jest.fn().mockImplementation(() => Promise.resolve(true))
}
}
MockConfirmController.dependencies = [];
const rootQuerySelector = selector => document.body.querySelector(selector);
const setupCardView = function() {
let options = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
const container = document.createElement("div");
const {
body: body
} = document;
body.append(container);
const cardView = new CardView(container, options);
rerender();
return cardView
};
const setup = config => {
const rootElement = document.createElement("div");
const context = getContext(config);
const mockConfirmController = new MockConfirmController;
context.registerInstance(ConfirmController, mockConfirmController);
const optionsController = context.get(OptionsControllerMock);
const editingController = context.get(EditingController);
const toolbarController = context.get(ToolbarController);
const editPopupView = context.get(EditPopupView);
editPopupView.render(rootElement);
rerender();
return {
optionsController: optionsController,
editingController: editingController,
editPopupView: editPopupView,
rootElement: rootElement,
toolbarController: toolbarController,
context: context,
getForm: () => {
const form = editPopupView.formRef.current;
if (!form) {
throw new Error("form is not visible")
}
return form
},
mockConfirmController: mockConfirmController
}
};
describe("ColumnProperties", () => {
describe("allowEditing", () => {
describe("when it is false", () => {
it("should make editor disabled", () => {
const {
getForm: getForm
} = setup({
dataSource: [{
field1: 1
}],
keyExpr: "field1",
editing: {
editCardKey: 1
},
columns: [{
dataField: "field1",
allowEditing: false
}]
});
expect(getForm().getEditor("field1").option("disabled")).toBe(true)
})
})
});
describe("editorOptions", () => {
it("should be passed to form item editorOptions", () => {
const {
getForm: getForm
} = setup({
dataSource: [{
field1: 1
}],
keyExpr: "field1",
editing: {
editCardKey: 1
},
columns: [{
dataField: "field1",
editorOptions: {
someEditOption: "someEditOptionValue"
}
}]
});
expect(getForm().getEditor("field1").option("someEditOption")).toBe("someEditOptionValue")
})
});
describe("setFieldValue", () => {
it("should be used as callback for setting editor value", async () => {
const setFieldValue = jest.fn((newData, value) => {
newData.mycustomfield = value
});
const {
editPopupView: editPopupView,
editingController: editingController,
getForm: getForm
} = setup({
columns: [{
dataField: "field1",
setFieldValue: setFieldValue
}, "id"],
dataSource: [{
id: 1,
field1: "value1"
}],
keyExpr: "id",
editing: {
editCardKey: 1
}
});
getForm().getEditor("field1").option("value", "qwe");
await editPopupView.promises.waitForAll();
expect(setFieldValue.mock.calls[0]).toMatchSnapshot();
expect(editingController.changes.peek()).toMatchSnapshot()
})
});
describe("formItem", () => {
it("should be passed to form item", () => {
const {
getForm: getForm
} = setup({
dataSource: [{
field1: 1
}],
keyExpr: "field1",
editing: {
editCardKey: 1
},
columns: [{
dataField: "field1",
formItem: {
editorType: "dxCalendar"
}
}]
});
expect(getForm().getEditor("field1")).toBeInstanceOf(dxCalendar)
})
});
describe("validationRules", () => {
it("should be passed to form item", async () => {
const {
getForm: getForm,
editingController: editingController
} = setup({
dataSource: [],
keyExpr: "field1",
columns: [{
dataField: "field1",
validationRules: [{
type: "required"
}]
}]
});
await editingController.addCard();
const validationResult = getForm().validate();
expect(validationResult.isValid).toBe(false)
})
})
});
describe("Options", () => {
describe("editing", () => {
afterEach(() => {
var _$;
const cardView = rootQuerySelector(SELECTORS.cardView);
null === (_$ = $(cardView ?? void 0)) || void 0 === _$ || _$.dxCardView("dispose")
});
describe("editCardKey", () => {
it("should open popup with given item", () => {
const {
getForm: getForm
} = setup({
columns: [{
dataField: "field1"
}, "id"],
dataSource: [{
id: 1,
field1: "value1"
}],
keyExpr: "id",
editing: {
editCardKey: 1
}
});
expect(getForm().getEditor("field1").option("value")).toBe("value1");
expect(getForm().getEditor("id").option("value")).toBe(1)
})
});
describe("allowAdding", () => {
it('should add "add" button to toolbar', () => {
const {
toolbarController: toolbarController,
optionsController: optionsController
} = setup({});
expect(toolbarController.items.peek()).toEqual([]);
optionsController.option("editing.allowAdding", "true");
expect(toolbarController.items.peek()).toMatchSnapshot()
})
});
describe("allowUpdating", () => {
it('should add "edit" button to card', () => {
setupCardView({
columns: [{
dataField: "field1"
}, "id"],
dataSource: [{
id: 1,
field1: "value1"
}],
keyExpr: "id",
editing: {
allowUpdating: true
}
});
rerender();
const card = rootQuerySelector(SELECTORS.card);
expect(null === card || void 0 === card ? void 0 : card.innerHTML).toContain('aria-label="edit"')
})
});
describe("allowRemoving", () => {
it('should add "remove" button to card', () => {
setupCardView({
columns: [{
dataField: "field1"
}, "id"],
dataSource: [{
id: 1,
field1: "value1"
}],
keyExpr: "id",
editing: {
allowDeleting: true
}
});
rerender();
const card = rootQuerySelector(SELECTORS.card);
expect(null === card || void 0 === card ? void 0 : card.innerHTML).toContain('aria-label="trash"')
})
});
describe("changes", () => {
const config = {
dataSource: [{
key: 1,
some_field: "asd"
}],
columns: ["some_field"],
keyExpr: "key",
editing: {
editCardKey: 1
}
};
it("should be empty initially", () => {
const {
editingController: editingController
} = setup(config);
expect(editingController.changes.peek()).toEqual([])
});
it("should contain unsaved changes", async () => {
var _getForm$getEditor;
const {
editingController: editingController,
editPopupView: editPopupView,
getForm: getForm
} = setup(config);
null === (_getForm$getEditor = getForm().getEditor("some_field")) || void 0 === _getForm$getEditor || _getForm$getEditor.option("value", "qwe");
await editPopupView.promises.waitForAll();
expect(editingController.changes.peek()).toMatchSnapshot()
})
});
describe("form", () => {
it("should pass options to edit form", () => {
const {
getForm: getForm
} = setup({
dataSource: [{
key: 1,
some_field: "asd"
}],
columns: ["some_field"],
keyExpr: "key",
editing: {
editCardKey: 1,
form: {
disabled: true
}
}
});
expect(getForm().option("disabled")).toBe(true)
})
});
describe("texts", () => {
describe("confirmDeleteMessage", () => {
it("should be used to show confirm delete dialog", async () => {
const {
editingController: editingController,
mockConfirmController: mockConfirmController
} = setup({
columns: [{
dataField: "field1"
}, "id"],
dataSource: [{
id: 1,
field1: "value1"
}],
keyExpr: "id",
editing: {
texts: {
confirmDeleteMessage: "my custom title"
}
}
});
await editingController.deleteCard(1);
expect(mockConfirmController.confirm.mock.calls[0][0]).toBe("my custom title")
})
});
describe("confirmDeleteTitle", () => {
it("should be used to show confirm delete dialog", async () => {
const {
editingController: editingController,
mockConfirmController: mockConfirmController
} = setup({
columns: [{
dataField: "field1"
}, "id"],
dataSource: [{
id: 1,
field1: "value1"
}],
keyExpr: "id",
editing: {
texts: {
confirmDeleteTitle: "my custom title"
}
}
});
await editingController.deleteCard(1);
expect(mockConfirmController.confirm.mock.calls[0][1]).toBe("my custom title")
});
describe("when it is undefined", () => {
it("should hide title", async () => {
const {
editingController: editingController,
mockConfirmController: mockConfirmController
} = setup({
columns: [{
dataField: "field1"
}, "id"],
dataSource: [{
id: 1,
field1: "value1"
}],
keyExpr: "id",
editing: {
texts: {
confirmDeleteTitle: void 0
}
}
});
await editingController.deleteCard(1);
expect(mockConfirmController.confirm.mock.calls[0][1]).toBe("");
expect(mockConfirmController.confirm.mock.calls[0][2]).toBe(false)
})
})
})
})
})
});