diff --git a/.changeset/fair-laws-serve.md b/.changeset/fair-laws-serve.md new file mode 100644 index 00000000..dd5a1a8e --- /dev/null +++ b/.changeset/fair-laws-serve.md @@ -0,0 +1,6 @@ +--- +"ember-headless-table": patch +--- + +Fixes column resize and preference save sequencing +to ensure that the functions always run in the correct order. diff --git a/ember-headless-table/src/plugins/column-resizing/handle.ts b/ember-headless-table/src/plugins/column-resizing/handle.ts index db75eca2..b41d20ea 100644 --- a/ember-headless-table/src/plugins/column-resizing/handle.ts +++ b/ember-headless-table/src/plugins/column-resizing/handle.ts @@ -111,24 +111,41 @@ class ResizeHandle extends Modifier<{ Args: { Positional: [Column] } }> { } }; - queueUpdate = () => { - cancelAnimationFrame(this.dragFrame); + /** + * queueUpdate takes an optional function argument that is called + * in the requestAnimationFrame callback _after_ the resize function. + * + * We can use this to ensure that preferences are only ever saved after + * we have completed column resizing. + * + * Because the requestAnimationFrame 'hides' these function calls from the + * the ember test waiter, we also ensure that we track them by also cancelling + * the waiter in the requestAnimationFrame callback. + */ + queueUpdate = (callback?: () => void) => { + if (this.dragFrame) { + cancelAnimationFrame(this.dragFrame); + } + this.dragFrame = requestAnimationFrame(() => { this.meta.resize(this.pointerX - this.pointerStartX); this.pointerStartX = this.pointerX; + + if (callback) { + callback(); + } + + if (this.token) { + waiter.endAsync(this.token); + this.token = undefined; + } }); }; dragEndHandler = () => { this.meta.isResizing = false; - this.queueUpdate(); - - if (this.token) { - waiter.endAsync(this.token); - this.token = undefined; - } - this.meta.save(); + this.queueUpdate(this.meta.save); /** * No need to listen if we aren't dragging diff --git a/ember-headless-table/src/test-support/index.ts b/ember-headless-table/src/test-support/index.ts index 6f23b350..cdf21d6d 100644 --- a/ember-headless-table/src/test-support/index.ts +++ b/ember-headless-table/src/test-support/index.ts @@ -28,18 +28,9 @@ export function createHelpers(selectors: Selectors) { triggerEvent(element, 'mousedown', { clientX: startX, button: 0 }); triggerEvent(element, 'mousemove', { clientX: targetX, button: 0 }); - - await new Promise((resolve) => setTimeout(resolve, 50)); - triggerEvent(element, 'mouseup', { clientX: targetX, button: 0 }); await settled(); - - /** - * This has been super finnicky... :( - */ - await new Promise((resolve) => setTimeout(resolve, 100)); - await requestAnimationFrameSettled(); } function horizontalScrollElement() { diff --git a/test-app/tests/plugins/column-resizing/rendering-test.gts b/test-app/tests/plugins/column-resizing/rendering-test.gts index d4ed9e95..67459404 100644 --- a/test-app/tests/plugins/column-resizing/rendering-test.gts +++ b/test-app/tests/plugins/column-resizing/rendering-test.gts @@ -297,9 +297,7 @@ module('Plugins | resizing', function (hooks) { }, 'All column preferences reset'); }); - test('it resizes each column', async function (assert) { - // Columns are set to equal widths so each of the four columns - // will initially be 250px wide in the 1000px wide container + test('it resizes each column and persists the new widths in the preferences', async function (assert) { ctx.setContainerWidth(1000); await render(