/
vshmidt
/
streamlit
Обзор
Документация
Войти
/
vshmidt
/
streamlit
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
develop
frontend/lib/src/components/widgets/DataFrame/hooks/useDataLoader.test.ts
247 строк
8 KB
Lukas Masuch
Split `Arrow.proto` into `Table.proto` and `Dataframe.proto` (#13768)
04 фев 2026, 22:22
Не верифицирован
04 фев 2026, 22:22
dc9d8fe
Код
Авторство
О чём код?
/** * Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2026) * * 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 { useRef } from "react" import { GridCellKind } from "@glideapps/glide-data-grid" import { renderHook } from "@testing-library/react" import { Field, Utf8 } from "apache-arrow" import { IArrowData } from "@streamlit/protobuf" import { BaseColumn, isErrorCell, TextColumn, } from "~lib/components/widgets/DataFrame/columns" import { DataFrameCellType } from "~lib/dataframes/arrowTypeUtils" import { Quiver } from "~lib/dataframes/Quiver" import { MULTI, UNICODE } from "~lib/mocks/arrow" import EditingState from "./EditingState" import useDataLoader from "./useDataLoader" // These columns are based on the UNICODE mock arrow table: const MOCK_COLUMNS: BaseColumn[] = [ TextColumn({ arrowType: { type: DataFrameCellType.DATA, arrowField: new Field("index-0", new Utf8(), true), pandasType: { field_name: "index-0", name: "index-0", pandas_type: "unicode", numpy_type: "unicode", metadata: null, }, }, id: "index-0", name: "", indexNumber: 0, isEditable: true, isHidden: false, isIndex: true, isPinned: true, isStretched: false, title: "", }), TextColumn({ arrowType: { type: DataFrameCellType.DATA, arrowField: new Field("column-c1-0", new Utf8(), true), pandasType: { field_name: "column-c1-0", name: "column-c1-0", pandas_type: "unicode", numpy_type: "object", metadata: null, }, }, id: "column-c1-0", name: "c1", indexNumber: 1, isEditable: true, isHidden: false, isIndex: false, isPinned: false, isStretched: false, title: "c1", }), TextColumn({ arrowType: { type: DataFrameCellType.DATA, arrowField: new Field("column-c2-1", new Utf8(), true), pandasType: { field_name: "column-c2-1", name: "column-c2-1", pandas_type: "unicode", numpy_type: "object", metadata: null, }, }, columnTypeOptions: undefined, id: "column-c2-1", name: "c2", indexNumber: 2, isEditable: true, isHidden: false, isIndex: false, isPinned: false, isStretched: false, title: "c2", }), ] describe("useDataLoader hook", () => { it("creates a glide-data-grid compatible callback to access cells", () => { const arrowData: IArrowData = { data: UNICODE } const data = new Quiver(arrowData) const numRows = data.dimensions.numRows const { result } = renderHook(() => { const editingStateRef = useRef<EditingState>(new EditingState(numRows)) return useDataLoader(data, MOCK_COLUMNS, numRows, editingStateRef) }) // Row 1 expect( MOCK_COLUMNS[0].getCellValue(result.current.getCellContent([0, 0])) ).toBe("i1") expect( MOCK_COLUMNS[1].getCellValue(result.current.getCellContent([1, 0])) ).toBe("foo") expect( MOCK_COLUMNS[2].getCellValue(result.current.getCellContent([2, 0])) ).toBe("1") // Row 2 expect( MOCK_COLUMNS[0].getCellValue(result.current.getCellContent([0, 1])) ).toBe("i2") expect( MOCK_COLUMNS[1].getCellValue(result.current.getCellContent([1, 1])) ).toBe("bar") expect( MOCK_COLUMNS[2].getCellValue(result.current.getCellContent([2, 1])) ).toBe("2") // if row out of bounds. return error cell expect(isErrorCell(result.current.getCellContent([0, 2]))).toBe(true) // if column out of bounds. return error cell expect(isErrorCell(result.current.getCellContent([3, 0]))).toBe(true) }) it("correctly handles multi-index headers", () => { const arrowData: IArrowData = { data: MULTI } const data = new Quiver(arrowData) const numRows = data.dimensions.numRows const { result } = renderHook(() => { const editingStateRef = useRef<EditingState>(new EditingState(numRows)) return useDataLoader(data, MOCK_COLUMNS, numRows, editingStateRef) }) // Check that row 0 is returning the correct cell value: expect( MOCK_COLUMNS[0].getCellValue(result.current.getCellContent([2, 0])) ).toBe("foo") }) it("uses editing state if a cell got edited", () => { const arrowData: IArrowData = { data: UNICODE } const data = new Quiver(arrowData) const numRows = data.dimensions.numRows const { result } = renderHook(() => { const editingStateRef = useRef<EditingState>(new EditingState(numRows)) editingStateRef.current.setCell(1, 0, { kind: GridCellKind.Text, displayData: "edited", data: "edited", allowOverlay: true, }) return useDataLoader(data, MOCK_COLUMNS, numRows, editingStateRef) }) // Check if value got edited expect( MOCK_COLUMNS[1].getCellValue(result.current.getCellContent([1, 0])) ).toEqual("edited") }) it("uses editing state if a row got deleted", () => { const arrowData: IArrowData = { data: UNICODE } const data = new Quiver(arrowData) const numRows = data.dimensions.numRows const { result } = renderHook(() => { const editingStateRef = useRef<EditingState>(new EditingState(numRows)) editingStateRef.current.deleteRow(0) return useDataLoader(data, MOCK_COLUMNS, numRows, editingStateRef) }) // Should return value of second row expect( MOCK_COLUMNS[1].getCellValue(result.current.getCellContent([1, 0])) ).toEqual("bar") }) it("returns an error cell if getCell from Quiver throws an error", () => { const arrowData: IArrowData = { data: UNICODE } const realData = new Quiver(arrowData) const numRows = realData.dimensions.numRows // Create a data object that throws an error when getCell is called const errorData = { getCell: () => { throw new Error("Error getting cell from Quiver") }, dimensions: realData.dimensions, styler: realData.styler, } as unknown as Quiver const { result } = renderHook(() => { const editingStateRef = useRef<EditingState>(new EditingState(numRows)) return useDataLoader(errorData, MOCK_COLUMNS, numRows, editingStateRef) }) // We should get an error cell since an error is thrown in the try/catch block expect(isErrorCell(result.current.getCellContent([1, 0]))).toBe(true) }) it("returns an error cell if getCell from editing state throws an error", () => { const arrowData: IArrowData = { data: UNICODE } const realData = new Quiver(arrowData) const numRows = realData.dimensions.numRows const { result } = renderHook(() => { const editingStateRef = useRef<EditingState>(new EditingState(numRows)) editingStateRef.current.getCell = () => { throw new Error("Error getting cell from editing state") } editingStateRef.current.isAddedRow = () => { return true } return useDataLoader(realData, MOCK_COLUMNS, numRows, editingStateRef) }) // We should get an error cell since an error is thrown in the try/catch block expect(isErrorCell(result.current.getCellContent([1, 0]))).toBe(true) }) })