blob: 9cfe90f9b70fd02d305e9f2536f7ff0f4ab91fc0 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/** @type {!FileTableColumnModel} */
let model;
/** @type {!Array<cr.ui.table.TableColumn>} */
let columns;
function setUp() {
window.loadTimeData.getString = id => id;
window.loadTimeData.getBoolean = id => false;
columns = [
new cr.ui.table.TableColumn('col0', 'col0', 100),
new cr.ui.table.TableColumn('col1', 'col1', 100),
new cr.ui.table.TableColumn('col2', 'col2', 100),
new cr.ui.table.TableColumn('col3', 'col3', 100),
new cr.ui.table.TableColumn('col4', 'col4', 100)
];
model = new FileTableColumnModel(columns);
}
/**
* Extracts column widths from the model.
* @param {!FileTableColumnModel} model
*/
function getColumnWidths(model) {
const widths = [];
for (let i = 0; i < model.size; i++) {
widths[i] = model.getWidth(i);
}
return widths;
}
// Verify that column visibility and width are correctly set when the visibility
// setting is toggled.
function testToggleVisibility() {
// The column under test.
const INDEX = 2;
const width = model.getWidth(INDEX);
// All columns should be visible to start.
for (let i = 0; i < model.size; i++) {
assertTrue(model.isVisible(i));
}
// Test toggling visibility.
model.setVisible(INDEX, false);
assertFalse(model.isVisible(INDEX));
assertEquals(0, model.getWidth(INDEX));
model.setVisible(INDEX, true);
assertTrue(model.isVisible(INDEX));
assertEquals(width, model.getWidth(INDEX));
}
// Verify that the table layout does not drift when a column is repeatedly shown
// and hidden.
function testToggleVisibilityColumnLayout() {
// The index of the column under test.
const INDEX = 2;
// Capture column widths.
const visibleWidths = getColumnWidths(model);
// Total width should be invariant throughout.
const totalWidth = model.totalWidth;
// Hide a column, check total width.
model.setVisible(INDEX, false);
assertEquals(totalWidth, model.totalWidth);
const hiddenWidths = getColumnWidths(model);
// Show the column again, match the column widths to the original state.
model.setVisible(INDEX, true);
assertArrayEquals(visibleWidths, getColumnWidths(model));
assertEquals(totalWidth, model.totalWidth);
// Hide the column again, match the column widths to the hidden state.
model.setVisible(INDEX, false);
assertArrayEquals(hiddenWidths, getColumnWidths(model));
assertEquals(totalWidth, model.totalWidth);
}
// Verify that table layout stays constant when the column config is exported
// and then restored, with no hidden columns.
function testExportAndRestoreColumnConfigWithNoHiddenColumns() {
// Change some column widths, then capture then.
for (let i = 0; i < model.size; i++) {
model.setWidth(i, i * 50);
}
const expectedWidths = getColumnWidths(model);
const expectedTotalWidth = model.totalWidth;
// Export column config, restore it to the new model.
const config = model.exportColumnConfig();
const newModel = new FileTableColumnModel(columns);
newModel.restoreColumnConfig(config);
assertArrayEquals(expectedWidths, getColumnWidths(newModel));
assertEquals(expectedTotalWidth, newModel.totalWidth);
}
// Verify that table layout stays constant when the column config is exported
// and then restored, with a hidden column.
function testExportAndRestoreColumnConfigWithHiddenColumns() {
// The index of the column under test.
const INDEX = 2;
// Change some column widths, then capture then.
for (let i = 0; i < model.size; i++) {
model.setWidth(i, (i + 1) * 50);
}
// Hide a column.
model.setVisible(INDEX, false);
const expectedWidths = getColumnWidths(model);
const expectedTotalWidth = model.totalWidth;
// Export column config, restore it to the new model.
const config = model.exportColumnConfig();
const newModel = new FileTableColumnModel(columns);
// Hide the same column.
newModel.setVisible(INDEX, false);
newModel.restoreColumnConfig(config);
assertArrayEquals(expectedWidths, getColumnWidths(newModel));
assertEquals(expectedTotalWidth, newModel.totalWidth);
}
// Verify that table layout stays constant when the column config is exported
// with a hidden column but then restored with the column visible.
function testExportAndRestoreColumnConfigWithShowingColumn() {
// The index of the column under test.
const INDEX = 2;
// Change some column widths, then capture then.
for (let i = 0; i < model.size; i++) {
model.setWidth(i, (i + 1) * 50);
}
// Hide a column.
model.setVisible(INDEX, false);
const expectedWidths = getColumnWidths(model);
const expectedTotalWidth = model.totalWidth;
// Export column config, restore it to the new model.
const config = model.exportColumnConfig();
const newModel = new FileTableColumnModel(columns);
// Restore column config while the test column is shown.
newModel.setVisible(INDEX, true);
newModel.restoreColumnConfig(config);
// Then hide it.
newModel.setVisible(INDEX, false);
assertArrayEquals(expectedWidths, getColumnWidths(newModel));
assertEquals(expectedTotalWidth, newModel.totalWidth);
}
// Verify that table layout stays constant when the column config is exported
// with all columns visible but then restored with a hidden column.
function testExportAndRestoreColumnConfigWithHidingColumn() {
// The index of the column under test.
const INDEX = 2;
// Change some column widths, then capture then.
for (let i = 0; i < model.size; i++) {
model.setWidth(i, (i + 1) * 50);
}
// Verify the precondition.
assertTrue(model.isVisible(INDEX));
const expectedWidths = getColumnWidths(model);
const expectedTotalWidth = model.totalWidth;
// Export column config, restore it to the new model.
const config = model.exportColumnConfig();
const newModel = new FileTableColumnModel(columns);
// Restore column config while the test column is hidden.
newModel.setVisible(INDEX, false);
newModel.restoreColumnConfig(config);
// Then show it.
newModel.setVisible(INDEX, true);
assertArrayEquals(expectedWidths, getColumnWidths(newModel));
assertEquals(expectedTotalWidth, newModel.totalWidth);
}
function testNormalizeWidth() {
let newContentWidth = 0;
const initialWidths = [
10 * 17,
20 * 17,
30 * 17,
40 * 17,
50 * 17,
];
// The rounding technique used in the implementation doesn't match floor() or
// ceil(), it diverges by +/- 1. So hard coding here.
const expectedWidths = [
56, // ~(17 * 10 / 3)
114, // ~(17 * 20 / 3)
170, // ~(17 * 30 / 3)
226, // ~(17 * 40 / 3)
284, // ~(17 * 50 / 3)
];
for (let i = 0; i < model.size; i++) {
const colWidth = initialWidths[i];
model.setWidth(i, colWidth);
newContentWidth += colWidth;
}
// Reduce total with to 1/3 to Resizes columns proportionally.
newContentWidth = newContentWidth / 3;
model.normalizeWidths(newContentWidth);
assertArrayEquals(expectedWidths, getColumnWidths(model));
assertEquals(newContentWidth, model.totalWidth);
}
function testNormalizeWidthWithSmallWidth() {
model.normalizeWidths(10); // not enough width to contain all columns
// Should keep the minimum width.
getColumnWidths(model).map(width => {
assertEquals(FileTableColumnModel.MIN_WIDTH_, width);
});
}
function testSetWidthAndKeepTotal() {
// Make sure to take column snapshot. Required for setWidthAndKeepTotal.
model.initializeColumnPos();
// Attempt to expand the 3rd column exceeding the window.
model.setWidthAndKeepTotal(2, 400);
// Should keep the minimum width.
getColumnWidths(model).map(width => {
assertTrue(width >= FileTableColumnModel.MIN_WIDTH_);
});
const minWidth = FileTableColumnModel.MIN_WIDTH_;
// Total width = 500.
const expectedWidths =
[100, 100, 500 - 100 * 2 - minWidth * 2, minWidth, minWidth];
assertArrayEquals(expectedWidths, getColumnWidths(model));
}