Skip to content

Commit

Permalink
chat control (#1092)
Browse files Browse the repository at this point in the history
* chat control
resolves #1044

* WiP use data type and pagination for messages

* pagination WiP

* fix tests

* manage new message indicator

* cleaning

* use rowCount

* make it work

* fix js tests

* fix doc

* fix tests

* managing load more

* pagesize in data key

---------

Co-authored-by: Fred Lefévère-Laoide <Fred.Lefevere-Laoide@Taipy.io>
  • Loading branch information
FredLL-Avaiga and Fred Lefévère-Laoide committed May 17, 2024
1 parent 6d21c4e commit 3bf293a
Show file tree
Hide file tree
Showing 19 changed files with 3,132 additions and 2,172 deletions.
4 changes: 2 additions & 2 deletions frontend/taipy-gui/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
* specific language governing permissions and limitations under the License.
*/

/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */
module.exports = {
// testEnvironment: 'jest-environment-jsdom',
preset: 'ts-jest',
testEnvironment: 'jsdom',
setupFiles: ['./test-config/jest.env.js', './test-config/createObjectUrl.js', './test-config/Canvas.js', './test-config/mockFileUpload.js'],
setupFiles: ['./test-config/jest.env.js', './test-config/createObjectUrl.js', './test-config/Canvas.js', './test-config/mockFileUpload.js', './test-config/intersectionObserver.js'],
coverageReporters: ["json", "html", "text"],
};
731 changes: 290 additions & 441 deletions frontend/taipy-gui/package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions frontend/taipy-gui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
},
"devDependencies": {
"@testing-library/jest-dom": "^6.1.3",
"@testing-library/react": "^14.0.0",
"@testing-library/react": "^15.0.7",
"@testing-library/user-event": "^14.2.1",
"@types/css-mediaquery": "^0.1.1",
"@types/jest": "^29.0.1",
Expand All @@ -94,11 +94,11 @@
"autoprefixer": "^10.4.0",
"copy-webpack-plugin": "^12.0.1",
"cross-env": "^7.0.3",
"css-loader": "^6.5.0",
"css-loader": "^7.1.0",
"css-mediaquery": "^0.1.2",
"dotenv-webpack": "^8.0.0",
"dts-bundle-generator": "^9.2.1",
"eslint": "^8.3.0",
"eslint": "^8.57.0",
"eslint-plugin-react": "^7.26.1",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-tsdoc": "^0.2.16",
Expand Down
121 changes: 121 additions & 0 deletions frontend/taipy-gui/src/components/Taipy/Chat.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Copyright 2021-2024 Avaiga Private Limited
*
* 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 React from "react";
import { render } from "@testing-library/react";
import "@testing-library/jest-dom";
import userEvent from "@testing-library/user-event";

import Chat from "./Chat";
import { INITIAL_STATE, TaipyState } from "../../context/taipyReducers";
import { TaipyContext } from "../../context/taipyContext";
import { stringIcon } from "../../utils/icon";
import { TableValueType } from "./tableUtils";

const valueKey = "Infinite-Entity--asc";
const messages: TableValueType = {
[valueKey]: {
data: [
["1", "msg 1", "Fred"],
["2", "msg From Another unknown User", "Fredo"],
["3", "This from the sender User", "taipy"],
["4", "And from another known one", "Fredi"],
], rowcount: 4, start: 0}};
const user1: [string, stringIcon] = ["Fred", { path: "/images/favicon.png", text: "Fred.png" }];
const user2: [string, stringIcon] = ["Fredi", { path: "/images/fred.png", text: "Fredi.png" }];
const users = [user1, user2];

const searchMsg = messages[valueKey].data[0][1];

describe("Chat Component", () => {
it("renders", async () => {
const { getByText, getByLabelText } = render(<Chat messages={messages} defaultKey={valueKey} />);
const elt = getByText(searchMsg);
expect(elt.tagName).toBe("DIV");
const input = getByLabelText("message (taipy)");
expect(input.tagName).toBe("INPUT");
});
it("uses the class", async () => {
const { getByText } = render(<Chat messages={messages} className="taipy-chat" defaultKey={valueKey} />);
const elt = getByText(searchMsg);
expect(elt.parentElement?.parentElement?.parentElement?.parentElement).toHaveClass("taipy-chat");
});
it("can display an avatar", async () => {
const { getByAltText } = render(<Chat messages={messages} users={users} defaultKey={valueKey} />);
const elt = getByAltText("Fred.png");
expect(elt.tagName).toBe("IMG");
});
it("is disabled", async () => {
const { getAllByRole } = render(<Chat messages={messages} active={false} defaultKey={valueKey} />);
const elts = getAllByRole("button");
elts.forEach((elt) => expect(elt).toHaveClass("Mui-disabled"));
});
it("is enabled by default", async () => {
const { getAllByRole } = render(<Chat messages={messages} defaultKey={valueKey} />);
const elts = getAllByRole("button");
elts.forEach((elt) => expect(elt).not.toHaveClass("Mui-disabled"));
});
it("is enabled by active", async () => {
const { getAllByRole } = render(<Chat messages={messages} active={true} defaultKey={valueKey} />);
const elts = getAllByRole("button");
elts.forEach((elt) => expect(elt).not.toHaveClass("Mui-disabled"));
});
it("can hide input", async () => {
render(<Chat messages={messages} withInput={false} className="taipy-chat" defaultKey={valueKey} />);
const elt = document.querySelector(".taipy-chat input");
expect(elt).toBeNull();
});
it("dispatch a well formed message by Keyboard", async () => {
const dispatch = jest.fn();
const state: TaipyState = INITIAL_STATE;
const { getByLabelText } = render(
<TaipyContext.Provider value={{ state, dispatch }}>
<Chat messages={messages} updateVarName="varname" defaultKey={valueKey} />
</TaipyContext.Provider>
);
const elt = getByLabelText("message (taipy)");
await userEvent.click(elt);
await userEvent.keyboard("new message{Enter}");
expect(dispatch).toHaveBeenCalledWith({
type: "SEND_ACTION_ACTION",
name: "",
context: undefined,
payload: {
action: undefined,
args: ["Enter", "varname", "new message", "taipy"],
},
});
});
it("dispatch a well formed message by button", async () => {
const dispatch = jest.fn();
const state: TaipyState = INITIAL_STATE;
const { getByLabelText, getByRole } = render(
<TaipyContext.Provider value={{ state, dispatch }}>
<Chat messages={messages} updateVarName="varname" defaultKey={valueKey} />
</TaipyContext.Provider>
);
const elt = getByLabelText("message (taipy)");
await userEvent.click(elt);
await userEvent.keyboard("new message");
await userEvent.click(getByRole("button"))
expect(dispatch).toHaveBeenCalledWith({
type: "SEND_ACTION_ACTION",
name: "",
context: undefined,
payload: {
action: undefined,
args: ["click", "varname", "new message", "taipy"],
},
});
});
});

0 comments on commit 3bf293a

Please sign in to comment.