Skip to content

Commit

Permalink
Clean up tests ahead of offset fixes (#950)
Browse files Browse the repository at this point in the history
  • Loading branch information
mixonic authored Jul 22, 2022
1 parent cdfaa3a commit cafec13
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 31 deletions.
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

0 comments on commit cafec13

Please sign in to comment.