Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up tests ahead of offset fixes #950

Merged
merged 1 commit into from
Jul 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 77 additions & 7 deletions addon-test-support/pages/-private/ember-table-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ import { click } from '@ember/test-helpers';
import { mouseDown, mouseMove, mouseUp } from '../../helpers/mouse';
import { getScale } from '../../helpers/element';

function computedStyleInPixels(target, property) {
let stringValue = window.getComputedStyle(target)[property];
let numberValue = Number(stringValue.substring(0, stringValue.length - 2));
if (isNaN(numberValue)) {
throw new Error(
`computedStyleInPixels failed to convert the computed style property of '${property}' into a Number. Value was '${stringValue}'`
);
}
return numberValue;
}

export const SortPage = PageObject.extend({
indicator: {
scope: '[data-test-sort-indicator]',
Expand All @@ -29,18 +40,46 @@ const Header = PageObject.extend({

/**
* Retrieves selected header cell width.
*
* offsetWidth returns a rounded integer, and so can
* result in unreliable tests.
*
* @returns {number}
*/
get width() {
return findElement(this).offsetWidth;
},

/**
* Retrieves selected header cell height.
*
* offsetHeight returns a rounded integer, and so can
* result in unreliable tests.
*
* @returns {number}
*/
get height() {
return findElement(this).offsetHeight;
},

/**
* Retrieves selected header cell logical width.
*
* @returns {number}
*/
get logicalWidth() {
return computedStyleInPixels(findElement(this), 'width');
},

/**
* Retrieves the rendered width of the selected header cell.
*
* @returns {number}
*/
get renderedWidth() {
return findElement(this).getBoundingClientRect().width;
},

get isLeaf() {
return findElement(this).dataset.testLeafHeader;
},
Expand All @@ -59,27 +98,58 @@ const Header = PageObject.extend({
contextMenu: triggerable('contextmenu'),

/**
* Resizes this column by dragging right border several pixels.
* Resize the table header. This API isn't clear about if a logical
* or rendered size is being passed. It defers to the more explicit
* logicalResize which should probably be preferred in future use.
*/
async resize(targetSize) {
let resizeHandle = findElement(this, '.et-header-resize-area');
await this.logicalResize(targetSize);
},

async logicalResize(targetSize) {
let renderedTargetSize =
targetSize / getScale(document.getElementById('ember-testing-container').firstElementChild);
await this.renderedResize(renderedTargetSize);
},

/**
* Resizes this column by dragging right border several pixels,
* unless the column is fixed right in quick case it drags left.
*/
async renderedResize(targetSize) {
let resizeHandle = findElement(this, '[data-test-resize-handle]');

if (!resizeHandle) {
return;
}

let box = resizeHandle.getBoundingClientRect();
let startX = (box.right + box.left) / 2;
let deltaX = (targetSize - this.width) / getScale(resizeHandle);
let y = box.top + (box.bottom - box.top) / 2;
let deltaX = targetSize - this.renderedWidth;

if (this.isFixedRight) {
deltaX = -deltaX;
}

await mouseDown(resizeHandle, startX, resizeHandle.clientHeight / 2);
await mouseMove(resizeHandle, startX + 20, resizeHandle.clientHeight / 2);
await mouseMove(resizeHandle, startX + deltaX, resizeHandle.clientHeight / 2);
await mouseUp(resizeHandle, startX + deltaX, resizeHandle.clientHeight / 2);
let finalX = startX + deltaX;

await mouseDown(resizeHandle, startX, y);

/**
* Below a certain number of steps, Hammer (the gesture library
* which recognizes panning) will not pick up the pointermove
* events emitted by `mouseMove` before the gestrure completes.
*
* 5 seems a reasonable number.
*/
let current = startX;
for (let steps = 5; steps > 0; steps--) {
await mouseMove(resizeHandle, current, y);
current = current + (finalX - current) / steps;
}
await mouseMove(resizeHandle, finalX, y);
await mouseUp(resizeHandle, finalX, y);
},

/**
Expand Down
10 changes: 10 additions & 0 deletions addon-test-support/pages/ember-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,23 @@ export default PageObject.extend({

/**
* Returns the table width.
*
* offsetWidth returns a rounded integer, and so can
* result in unreliable tests.
*
* @returns {number}
*/
get width() {
return findElement(this, 'table').offsetWidth;
},

/**
* Returns the table container width.
*
* offsetWidth returns a rounded integer, and so can
* result in unreliable tests.
*
* @returns {number}
*/
get containerWidth() {
return findElement(this).offsetWidth;
Expand Down
12 changes: 10 additions & 2 deletions tests/integration/components/cell-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,16 @@ module('Integration | cell', function() {
assert.ok(cell.isLastColumn, 'is-last-column applied to normal cell');
assert.notOk(slackCell.isLastColumn, 'is-last-column not applied to slack cell');

// shrink cell "A"; now slack column gets the `is-last-column` class
await header.resize(header.width - 1);
/**
* shrink cell "A"; now slack column gets the `is-last-column`
* class.
*
* The number 27 here for the resize is fairly arbitrary, it may be
* tied to the size of the resize handle or another drag/drop
* threshold.
*/
await header.logicalResize(header.logicalWidth - 27);

assert.notOk(cell.isLastColumn, 'is-last-column not applied to normal cell');
assert.ok(slackCell.isLastColumn, 'is-last-column applied to slack cell');
});
Expand Down
12 changes: 10 additions & 2 deletions tests/integration/components/headers/ember-th-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,16 @@ module('[Unit] ember-th', function(hooks) {
assert.ok(header.isLastColumn, 'is-last-column applied to normal header');
assert.notOk(slackHeader.isLastColumn, 'is-last-column not applied to slack header');

// shrink header "A"; now slack column gets the `is-last-column` class
await header.resize(header.width - 1);
/**
* shrink header "A"; now slack column gets the `is-last-column`
* class.
*
* The number 27 here for the resize is fairly arbitrary, it may be
* tied to the size of the resize handle or another drag/drop
* threshold.
*/
await header.logicalResize(header.logicalWidth - 27);

assert.notOk(header.isLastColumn, 'is-last-column not applied to normal header');
assert.ok(slackHeader.isLastColumn, 'is-last-column applied to slack header');
});
Expand Down
58 changes: 42 additions & 16 deletions tests/integration/components/headers/reorder-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,56 @@ import { parameterizedComponentModule } from '../../../helpers/module';
import { find, findAll } from '@ember/test-helpers';
import scrollTo from '../../../helpers/scroll-to';
import { mouseDown, mouseMove, mouseUp } from 'ember-table/test-support/helpers/mouse';
import { getScale } from 'ember-table/test-support/helpers/element';

import TablePage from 'ember-table/test-support/pages/ember-table';
import { toBase26 } from 'dummy/utils/base-26';

const table = new TablePage();

/**
*
* Scroll to a given edge, accepting an offset for how many rendered
* pixels to stay from the edge.
*
*/
export async function scrollToEdge(targetElement, edgeOffset, direction) {
let targetElementRight = targetElement.getBoundingClientRect().right;
let container = find('.ember-table');
let scale = getScale(container);
let edge;

let initialTargetX, finalTargetX;
if (direction === 'right') {
await mouseDown(targetElement, targetElementRight - 30, 0);
await mouseMove(targetElement, targetElementRight - 20, 0);
await mouseMove(targetElement, targetElementRight - 10, 0);

edge = container.getBoundingClientRect().right - edgeOffset / scale;
initialTargetX = targetElementRight - 5;
finalTargetX = container.getBoundingClientRect().right - edgeOffset;
if (initialTargetX >= finalTargetX) {
throw new Error(
'When dragging right, the starting position X must be smaller than the ending position'
);
}
} else {
await mouseDown(targetElement, targetElementRight - 10, 0);
await mouseMove(targetElement, targetElementRight - 20, 0);
await mouseMove(targetElement, targetElementRight - 30, 0);

edge = container.getBoundingClientRect().left + edgeOffset / scale;
initialTargetX = targetElementRight - 5;
finalTargetX = container.getBoundingClientRect().left + edgeOffset;
if (initialTargetX <= finalTargetX) {
throw new Error(
'When dragging left, the starting position X must be greater than the ending position'
);
}
}

await mouseMove(targetElement, edge, 0);
await mouseDown(targetElement, initialTargetX, 0);

/*
* Below a certain number of steps, Hammer (the gesture library
* which recognizes panning) will not pick up the pointermove
* events emitted by `mouseMove` before the gestrure completes.
*
* 5 seems a reasonable number.
*/
let current = initialTargetX;
for (let steps = 5; steps > 0; steps--) {
await mouseMove(targetElement, current, 0);
current = current + (finalTargetX - current) / steps;
}
await mouseMove(targetElement, finalTargetX, 0);
await mouseUp(targetElement);
}

Expand Down Expand Up @@ -309,7 +331,9 @@ module('Integration | headers | reorder', function() {
let tableOverflowContainer = find('[data-test-ember-table-overflow]');
let header = findAll('th')[0];

await reorderToRightEdge(header, columnWidth);
let headerBoundingRect = header.getBoundingClientRect();
let headerWidth = headerBoundingRect.right - headerBoundingRect.left;
await reorderToRightEdge(header, headerWidth);

assert.ok(tableOverflowContainer.scrollLeft > 0, 'table scrolled');
assert.equal(table.headers.objectAt(columnCount - 2).text, toBase26(0), 'table scrolled');
Expand All @@ -331,7 +355,9 @@ module('Integration | headers | reorder', function() {
let header = findAll('th')[columnCount - 1];

await scrollTo(tableOverflowContainer, 10000, 0);
await reorderToLeftEdge(header, columnWidth);
let headerBoundingRect = header.getBoundingClientRect();
let headerWidth = headerBoundingRect.right - headerBoundingRect.left;
await reorderToLeftEdge(header, headerWidth);

assert.equal(tableOverflowContainer.scrollLeft, 0, 'table scrolled back to the left');
assert.equal(table.headers.objectAt(1).text, toBase26(columnCount - 1), 'table scrolled');
Expand Down
9 changes: 6 additions & 3 deletions tests/integration/components/headers/resize-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,17 @@ module('Integration | header | resize', function() {
});

test('column resize action is sent up to controller', async function(assert) {
this.set('onResize', function(column) {
assert.equal(column.name, 'B', 'action is sent to controller after resizing');
let calls = [];
this.set('onResize', (...args) => {
calls.push(args);
});

await generateTable(this, { widthConstraint: 'eq-container' });

let originalWidth = table.headers.objectAt(1).width;
await table.headers.objectAt(1).resize(originalWidth + 20);
await table.headers.objectAt(1).resize(originalWidth + 30);
assert.equal(calls.length, 1, 'resize called once');
assert.equal(calls[0][0].name, 'B', 'The correct resized column ("B") is passed');
});

test('can disable resize per column', async function(assert) {
Expand Down
6 changes: 5 additions & 1 deletion tests/unit/-private/table-sticky-polyfill-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,11 @@ function verifyMultiLineHeader(assert) {
firstTableCellOfEachHeaderRow.forEach(cell => {
let firstCellRect = cell.getBoundingClientRect();
expectedOffset += firstCellRect.height;
assert.equal(expectedOffset, firstCellRect.bottom);
assert.equal(
expectedOffset,
firstCellRect.bottom,
'bottom of the cell matches based on expected offset'
);
});
}

Expand Down