Skip to content

Commit 68c99d1

Browse files
authored
fix(mover): Pass drag delta to dragger.onDrag in pixels (#599)
* refactor(tests): export sendKeyAndWait and make it more flexible Change the signature of sendKeyAndWait: - Export it, so it can be used directly by tests. - Allow multiple keys to be specified. - Make times parameter optional (default 1). * test(Mover): Test unconstrained movement of unconnectable block This test currently fails due to issue #446. * fix(Mover): Pass drag delta to dragger.onDrag in pixels Fixes #446 * chore(tests): Fix lint * chore(tests): Fix nits for PR #599
1 parent 422dc28 commit 68c99d1

File tree

3 files changed

+92
-14
lines changed

3 files changed

+92
-14
lines changed

src/actions/mover.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ export class Mover {
302302

303303
info.dragger.onDrag(
304304
info.fakePointerEvent('pointermove', direction),
305-
info.totalDelta,
305+
info.totalDelta.clone().scale(workspace.scale),
306306
);
307307

308308
info.updateTotalDelta();
@@ -327,7 +327,10 @@ export class Mover {
327327
info.totalDelta.x += x * UNCONSTRAINED_MOVE_DISTANCE * workspace.scale;
328328
info.totalDelta.y += y * UNCONSTRAINED_MOVE_DISTANCE * workspace.scale;
329329

330-
info.dragger.onDrag(info.fakePointerEvent('pointermove'), info.totalDelta);
330+
info.dragger.onDrag(
331+
info.fakePointerEvent('pointermove'),
332+
info.totalDelta.clone().scale(workspace.scale),
333+
);
331334
this.scrollCurrentBlockIntoView(workspace);
332335
return true;
333336
}

test/webdriverio/test/move_test.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {
1313
tabNavigateToWorkspace,
1414
testFileLocations,
1515
testSetup,
16+
sendKeyAndWait,
17+
keyDown,
1618
} from './test_setup.js';
1719

1820
suite('Move tests', function () {
@@ -145,6 +147,62 @@ suite('Move tests', function () {
145147
await this.browser.keys(Key.Escape);
146148
}
147149
});
150+
151+
// When a top-level block with no previous, next or output
152+
// connections is subject to a constrained move, it should not move.
153+
//
154+
// This includes a regression test for issue #446 (fixed in PR #599)
155+
// where, due to an implementation error in Mover, constrained
156+
// movement following unconstrained movement would result in the
157+
// block unexpectedly moving (unless workspace scale was === 1).
158+
test('Constrained move of unattachable top-level block', async function () {
159+
// Block ID of an unconnectable block.
160+
const BLOCK = 'p5_setup_1';
161+
162+
// Scale workspace.
163+
await this.browser.execute(() => {
164+
(Blockly.getMainWorkspace() as Blockly.WorkspaceSvg).setScale(0.9);
165+
});
166+
167+
// Navigate to unconnectable block, get initial coords and start move.
168+
await tabNavigateToWorkspace(this.browser);
169+
await focusOnBlock(this.browser, BLOCK);
170+
const startCoordinate = await getCoordinate(this.browser, BLOCK);
171+
await this.browser.keys('m');
172+
173+
// Check constrained moves have no effect.
174+
await keyDown(this.browser, 5);
175+
const coordinate = await getCoordinate(this.browser, BLOCK);
176+
chai.assert.deepEqual(
177+
coordinate,
178+
startCoordinate,
179+
'constrained move should have no effect',
180+
);
181+
182+
// Unconstrained moves.
183+
await sendKeyAndWait(this.browser, [Key.Alt, Key.ArrowDown]);
184+
await sendKeyAndWait(this.browser, [Key.Alt, Key.ArrowRight]);
185+
const newCoordinate = await getCoordinate(this.browser, BLOCK);
186+
chai.assert.notDeepEqual(
187+
newCoordinate,
188+
startCoordinate,
189+
'unconstrained move should have effect',
190+
);
191+
192+
// Try multiple constrained moves, as first might (correctly) do nothing.
193+
for (let i = 0; i < 5; i++) {
194+
await keyDown(this.browser);
195+
const coordinate = await getCoordinate(this.browser, BLOCK);
196+
chai.assert.deepEqual(
197+
coordinate,
198+
newCoordinate,
199+
'constrained move after unconstrained move should have no effect',
200+
);
201+
}
202+
203+
// Abort move.
204+
await this.browser.keys(Key.Escape);
205+
});
148206
});
149207

150208
/**
@@ -218,3 +276,22 @@ function getConnectedBlockInfo(browser: Browser, id: string, index: number) {
218276
index,
219277
);
220278
}
279+
280+
/**
281+
* Given a block ID, get the coordinates of that block, as returned by
282+
* getRelativeTosSurfaceXY().
283+
*
284+
* @param browser The webdriverio browser session.
285+
* @param id The ID of the block having the connection we wish to examine.
286+
* @returns The coordinates of the block.
287+
*/
288+
function getCoordinate(
289+
browser: Browser,
290+
id: string,
291+
): Promise<Blockly.utils.Coordinate> {
292+
return browser.execute((id: string) => {
293+
const block = Blockly.getMainWorkspace().getBlockById(id);
294+
if (!block) throw new Error('block not found');
295+
return block.getRelativeToSurfaceXY();
296+
}, id);
297+
}

test/webdriverio/test/test_setup.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -416,8 +416,7 @@ export async function tabNavigateToWorkspace(
416416
* @param browser The active WebdriverIO Browser object.
417417
*/
418418
export async function tabNavigateForward(browser: WebdriverIO.Browser) {
419-
await browser.keys(webdriverio.Key.Tab);
420-
await browser.pause(PAUSE_TIME);
419+
await sendKeyAndWait(browser, webdriverio.Key.Tab);
421420
}
422421

423422
/**
@@ -426,8 +425,7 @@ export async function tabNavigateForward(browser: WebdriverIO.Browser) {
426425
* @param browser The active WebdriverIO Browser object.
427426
*/
428427
export async function tabNavigateBackward(browser: WebdriverIO.Browser) {
429-
await browser.keys([webdriverio.Key.Shift, webdriverio.Key.Tab]);
430-
await browser.pause(PAUSE_TIME);
428+
await sendKeyAndWait(browser, [webdriverio.Key.Shift, webdriverio.Key.Tab]);
431429
}
432430

433431
/**
@@ -471,20 +469,20 @@ export async function keyDown(browser: WebdriverIO.Browser, times = 1) {
471469
}
472470

473471
/**
474-
* Sends the specified key for the specified number of times, waiting between
475-
* each key press to allow changes to keep up.
472+
* Sends the specified key(s) for the specified number of times,
473+
* waiting between each key press to allow changes to keep up.
476474
*
477475
* @param browser The active WebdriverIO Browser object.
478-
* @param key The WebdriverIO representative key value to press.
479-
* @param times The number of times to repeat the key press.
476+
* @param keys The WebdriverIO representative key value(s) to press.
477+
* @param times The number of times to repeat the key press (default 1).
480478
*/
481-
async function sendKeyAndWait(
479+
export async function sendKeyAndWait(
482480
browser: WebdriverIO.Browser,
483-
key: string,
484-
times: number,
481+
keys: string | string[],
482+
times = 1,
485483
) {
486484
for (let i = 0; i < times; i++) {
487-
await browser.keys(key);
485+
await browser.keys(keys);
488486
await browser.pause(PAUSE_TIME);
489487
}
490488
}

0 commit comments

Comments
 (0)