Skip to content

Commit 36a04b0

Browse files
authored
Merge pull request #45 from lolmaus/issue-44-jumps-and-freezes
Fix jumps of unstyled content and test freezes, credit to @simonihmig, fixes #44
2 parents b7190ed + acaf7bf commit 36a04b0

File tree

5 files changed

+1632
-61
lines changed

5 files changed

+1632
-61
lines changed

addon/-private/modifier.ts

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
SIZES_HEIGHT_DEFAULT,
1212
} from 'ember-element-query';
1313
import { inject as service } from '@ember/service';
14-
import { waitFor } from '@ember/test-waiters';
1514
export interface SizeObject {
1615
name: string;
1716
value: number;
@@ -43,7 +42,7 @@ export default class ElementQueryModifier extends Modifier<ModifierArgs> {
4342
sizesRatioDefault: Sizes = SIZES_RATIO_DEFAULT;
4443

4544
_element?: HTMLElement; // For some reason, this.element is not always available
46-
_promiseResolveHasBeenInstalled?: (value?: unknown) => void;
45+
_firstCall = true;
4746

4847
// -------------------
4948
// Computed properties
@@ -544,20 +543,16 @@ export default class ElementQueryModifier extends Modifier<ModifierArgs> {
544543
: sizeObjectsSortedAsc[sizeObjectsSortedAsc.length - 1];
545544
}
546545

547-
_maybeRunPromiseResolveHasBeenInstalled(): void {
548-
if (this._promiseResolveHasBeenInstalled) {
549-
this._promiseResolveHasBeenInstalled();
550-
this._promiseResolveHasBeenInstalled = undefined;
546+
_didResizeHandlerSync(): void {
547+
if (!this.args.named.isDisabled && !this.isDestroying && !this.isDestroyed) {
548+
this.applyAttributesToElement();
549+
this.callOnResize();
551550
}
552551
}
553552

554-
_didResizeHandler(): void {
553+
_didResizeHandlerRequestAnimationFrame(): void {
555554
window.requestAnimationFrame(() => {
556-
if (!this.args.named.isDisabled && !this.isDestroying && !this.isDestroyed) {
557-
this.applyAttributesToElement();
558-
this.callOnResize();
559-
}
560-
this._maybeRunPromiseResolveHasBeenInstalled?.();
555+
this._didResizeHandlerSync();
561556
});
562557
}
563558

@@ -566,27 +561,20 @@ export default class ElementQueryModifier extends Modifier<ModifierArgs> {
566561
// -------------------
567562

568563
@action didResizeHandler(): void {
569-
debounceTask(this, '_didResizeHandler', this.debounce);
564+
debounceTask(this, '_didResizeHandlerRequestAnimationFrame', this.debounce);
570565
}
571566

572567
// -------------------
573568
// Lifecycle hooks
574569
// -------------------
575-
@waitFor
576-
didInstall(): void | Promise<void> {
570+
didInstall(): void {
577571
if (!this.element) throw new Error('Expected this.element to be available');
578572

579573
this._element = this.element;
580574

581575
this.resizeObserver.observe(this.element, this.didResizeHandler); // eslint-disable-line @typescript-eslint/unbound-method
582576

583-
if (!this.args.named.isDisabled && this.resizeObserver.isEnabled) {
584-
return new Promise((resolve) => {
585-
this._promiseResolveHasBeenInstalled = resolve;
586-
});
587-
} else {
588-
return Promise.resolve();
589-
}
577+
this._didResizeHandlerSync(); // We want to run it as soon as possible to avoid a jump of unstyled content
590578
}
591579

592580
didUpdateArguments(): void {

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@
6767
}
6868
},
6969
"dependencies": {
70-
"@ember/test-waiters": "^3.0.0",
7170
"ember-cli-babel": "^7.26.3",
7271
"ember-cli-htmlbars": "5.7.1",
7372
"ember-cli-typescript": "^4.2.1",
@@ -100,7 +99,7 @@
10099
"d3-scale": "^4.0.0",
101100
"d3-selection": "^3.0.0",
102101
"d3-shape": "^3.0.1",
103-
"ember-auto-import": "^1.11.2",
102+
"ember-auto-import": "^2.4.1",
104103
"ember-cli": "~3.26.1",
105104
"ember-cli-dependency-checker": "^3.2.0",
106105
"ember-cli-inject-live-reload": "^2.1.0",
@@ -143,7 +142,8 @@
143142
"release-it-lerna-changelog": "^3.1.0",
144143
"sinon": "^11.1.1",
145144
"typedoc": "^0.21.5",
146-
"typescript": "^4.3.4"
145+
"typescript": "^4.3.4",
146+
"webpack": "^5.70.0"
147147
},
148148
"engines": {
149149
"node": "10.* || >= 12"

tests/integration/component-test.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ module('Integration | Component | element-query', function (hooks) {
4747
// eslint-disable-next-line @typescript-eslint/no-misused-promises
4848
test('calls the onResize callback', async function (this: TestContextCustom, assert) {
4949
let callCount = 0;
50+
let callCountOld = 0;
5051
this.callback = sinon.spy(() => callCount++);
5152

5253
await render(hbs`
@@ -64,12 +65,12 @@ module('Integration | Component | element-query', function (hooks) {
6465
m = 'Element is rendered';
6566
assert.ok(true, m);
6667

67-
await waitUntil(() => callCount === 1);
68+
await waitUntil(() => callCount > callCountOld);
6869

6970
m = 'Callback called once';
7071
assert.ok(true, m);
7172

72-
assert.deepEqual(this.callback.firstCall.args, [
73+
assert.deepEqual(this.callback.lastCall.args, [
7374
{
7475
element,
7576
width: 300,
@@ -106,14 +107,15 @@ module('Integration | Component | element-query', function (hooks) {
106107
},
107108
]);
108109

110+
callCountOld = callCount;
109111
element.style.width = '400px';
110112

111-
await waitUntil(() => callCount === 2);
113+
await waitUntil(() => callCount > callCountOld);
112114

113115
m = 'Callback called twice';
114116
assert.ok(true, m);
115117

116-
assert.deepEqual(this.callback.secondCall.args, [
118+
assert.deepEqual(this.callback.lastCall.args, [
117119
{
118120
element,
119121
width: 400,
@@ -186,6 +188,7 @@ module('Integration | Component | element-query', function (hooks) {
186188
// eslint-disable-next-line @typescript-eslint/no-misused-promises
187189
test('stops calling the onResize callback after updating isDisabled after rendering', async function (this: TestContextCustom, assert) {
188190
let callCount = 0;
191+
let callCountOld = 0;
189192
this.callback = sinon.spy(() => callCount++);
190193
this.set('isDisabled', false);
191194

@@ -205,7 +208,7 @@ module('Integration | Component | element-query', function (hooks) {
205208
m = 'Element is rendered';
206209
assert.ok(true, m);
207210

208-
await waitUntil(() => callCount === 1);
211+
await waitUntil(() => callCount > callCountOld);
209212

210213
m = 'Callback called once';
211214
assert.ok(true, m);
@@ -249,12 +252,13 @@ module('Integration | Component | element-query', function (hooks) {
249252

250253
this.set('isDisabled', true);
251254

255+
callCountOld = callCount;
252256
element.style.width = '400px';
253257

254258
await pause(500);
255259

256260
m = 'Call count';
257-
assert.equal(callCount, 1, m);
261+
assert.ok(callCount === callCountOld, m);
258262

259263
m = 'Attr `at-s` presence';
260264
assert.equal(element.getAttribute('at-s'), null, m);

tests/integration/modifier-test.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ module('Integration | Modifier | element-query', function (hooks) {
4949
// eslint-disable-next-line @typescript-eslint/no-misused-promises
5050
test('calls the onResize callback', async function (this: TestContextCustom, assert) {
5151
let callCount = 0;
52+
let callCountOld = 0;
5253
this.callback = sinon.spy(() => callCount++);
5354

5455
await render(hbs`
@@ -67,13 +68,13 @@ module('Integration | Modifier | element-query', function (hooks) {
6768
m = 'Element is rendered';
6869
assert.ok(true, m);
6970

70-
await waitUntil(() => callCount === 1);
71+
await waitUntil(() => callCount > callCountOld);
7172

7273
m = 'Callback called once';
7374
assert.ok(true, m);
7475

7576
sinon.assert.calledWithExactly(
76-
this.callback.firstCall,
77+
this.callback.lastCall,
7778
sinon.match({
7879
element,
7980
width: 300,
@@ -98,16 +99,17 @@ module('Integration | Modifier | element-query', function (hooks) {
9899
})
99100
);
100101

102+
callCountOld = callCount;
101103
element.style.width = '400px';
102104

103-
await waitUntil(() => callCount === 2);
105+
await waitUntil(() => callCount > callCountOld);
104106

105107
m = 'Callback called twice';
106108
assert.ok(true, m);
107109

108110
// prettier-ignore
109111
sinon.assert.calledWithMatch(
110-
this.callback.secondCall,
112+
this.callback.lastCall,
111113
{
112114
element,
113115
width: 400,
@@ -168,6 +170,7 @@ module('Integration | Modifier | element-query', function (hooks) {
168170
// eslint-disable-next-line @typescript-eslint/no-misused-promises
169171
test('stops calling the onResize callback after updating isDisabled after rendering', async function (this: TestContextCustom, assert) {
170172
let callCount = 0;
173+
let callCountOld = 0;
171174
this.callback = sinon.spy(() => callCount++);
172175
this.set('isDisabled', false);
173176

@@ -187,7 +190,7 @@ module('Integration | Modifier | element-query', function (hooks) {
187190
m = 'Element is rendered';
188191
assert.ok(true, m);
189192

190-
await waitUntil(() => callCount === 1);
193+
await waitUntil(() => callCount > callCountOld);
191194

192195
m = 'Callback called once';
193196
assert.ok(true, m);
@@ -220,12 +223,13 @@ module('Integration | Modifier | element-query', function (hooks) {
220223

221224
this.set('isDisabled', true);
222225

226+
callCountOld = callCount;
223227
element.style.width = '400px';
224228

225229
await pause(500);
226230

227231
m = 'Call count';
228-
assert.equal(callCount, 1, m);
232+
assert.ok(callCount === callCountOld, m);
229233

230234
m = 'Attr `at-s` presence';
231235
assert.equal(element.getAttribute('at-s'), null, m);

0 commit comments

Comments
 (0)