/* * Copyright 2017 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 { render } from "@testing-library/react"; import { Component } from "react"; import { describe, it } from "@blueprintjs/test-commons/vitest"; import { CellType, expectCellLoading } from "./cell/cellTestUtils"; import * as Classes from "./common/classes"; import { ElementHarness } from "./harness"; import { Cell, Column, ColumnHeaderCell, ColumnLoadingOption, RowHeaderCell, Table, TableLoadingOption } from "."; interface TableLoadingOptionsTesterProps { columnLoadingOptions: ColumnLoadingOption[]; tableLoadingOptions: TableLoadingOption[]; } class TableLoadingOptionsTester extends Component { public static isCellLoading = (index: number) => { if (index === 0) { return true; } else if (index === 1) { return false; } else { return undefined; } }; private static cellRenderer = (rowIndex: number) => { return some cell text; }; private static columnHeaderCellRenderer = (columnIndex: number) => { return ; }; private static rowHeaderCellRenderer = (rowIndex: number) => { return ; }; public render() { const { columnLoadingOptions, tableLoadingOptions } = this.props; return (
); } } describe("Loading Options", () => { const allTableLoadingOptions = generatePowerSet([ TableLoadingOption.CELLS, TableLoadingOption.COLUMN_HEADERS, TableLoadingOption.ROW_HEADERS, ]); const allColumnLoadingOptions = generatePowerSet([ColumnLoadingOption.CELLS, ColumnLoadingOption.HEADER]); // Below is an exhaustive set of tests of all possible combinations of loading options allTableLoadingOptions.forEach(tableLoadingOptions => { allColumnLoadingOptions.forEach(columnLoadingOptions => { it(`table: [${tableLoadingOptions}], column: [${columnLoadingOptions}]`, () => { const { container } = render( , ); const tableHarness = new ElementHarness(container); // only testing the first column of body cells because the second and third // columns are meant to test column related loading combinations const quadrantSelector = `.${Classes.TABLE_QUADRANT_MAIN}`; const cells = Array.from( tableHarness.element!.querySelectorAll( `${quadrantSelector} .${Classes.TABLE_CELL}.${Classes.columnCellIndexClass(0)}`, ), ); const columnHeaders = Array.from( tableHarness.element!.querySelectorAll( `${quadrantSelector} .${Classes.TABLE_COLUMN_HEADERS} .${Classes.TABLE_HEADER}`, ), ); const rowHeaders = Array.from( tableHarness.element!.querySelectorAll( `${quadrantSelector} .${Classes.TABLE_ROW_HEADERS} .${Classes.TABLE_HEADER}`, ), ); testLoadingOptionOverrides( columnHeaders, CellType.COLUMN_HEADER, TableLoadingOptionsTester.isCellLoading, columnLoadingOptions, tableLoadingOptions, ); testLoadingOptionOverrides( rowHeaders, CellType.ROW_HEADER, TableLoadingOptionsTester.isCellLoading, columnLoadingOptions, tableLoadingOptions, ); testLoadingOptionOverrides( cells, CellType.BODY_CELL, TableLoadingOptionsTester.isCellLoading, columnLoadingOptions, tableLoadingOptions, ); }); }); }); }); function generatePowerSet(list: T[]) { const base2 = (num: number) => num.toString(2); const numberOfSubsets = Math.pow(2, list.length); const listOfSubsets: T[][] = [[]]; for (let i = 1; i < numberOfSubsets; i++) { const subset: T[] = []; // front-pad the string and then slice from the back to ensure fixed length binary string const binaryString = (Array(list.length).join("0") + base2(i)).slice(list.length * -1); for (let j = 0; j < binaryString.length; j++) { if (binaryString.charAt(j) === "1") { subset.push(list[j]); } } listOfSubsets.push(subset); } return listOfSubsets; } /* * This function tests the expected loading option override behavior for all cell types. * * For convenience, it accepts a list of cells of a single type and tests that each cell conforms to * the expected loading option override behavior. * * For any given cell, beginning at the cell-level, if loading options are present, use them for * cell rendering and ignore parent options. If loading options are absent look to the closest * parent. For body cells and column headers, this means look to the column-level loading options. * For row headers, this means look to the table-level. Repeat this process until loading options * are found. If loading options ultimately remain undefined, do not render the loading state for * the cell. */ function testLoadingOptionOverrides( cells: Element[], cellType: CellType, cellLoading: (index: number) => boolean | undefined, columnLoadingOptions: ColumnLoadingOption[], tableLoadingOptions: TableLoadingOption[], ) { cells.forEach((cell, i) => { if (cellLoading(i)) { expectCellLoading(cell, cellType, true); } else if (cellLoading(i) === false) { expectCellLoading(cell, cellType, false); } else if ( (cellType === CellType.BODY_CELL || cellType === CellType.COLUMN_HEADER) && columnLoadingOptions != null ) { // cast is safe because cellType is guaranteed to not be TableLoadingOption.ROW_HEADERS const loading = columnLoadingOptions.indexOf(cellType as any as ColumnLoadingOption) >= 0; // HACKHACK: see https://github.com/palantir/blueprint/issues/5114 console.debug(`Skipped test assertion for '${cellType}' @ index ${i}, expecting loading=${loading}`); // expectCellLoading(cell, cellType, loading); } else if (tableLoadingOptions != null) { expectCellLoading(cell, cellType, tableLoadingOptions.indexOf(cellType) >= 0); } else { expectCellLoading(cell, cellType, false); } }); }