Skip to content

Commit 6c0f92b

Browse files
committed
chore: Implement initial block navigation tests.
1 parent 2129bb4 commit 6c0f92b

File tree

4 files changed

+180
-5
lines changed

4 files changed

+180
-5
lines changed

test/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,9 @@ document.addEventListener('DOMContentLoaded', () => {
129129
addP5();
130130
createWorkspace();
131131
document.getElementById('run')?.addEventListener('click', runCode);
132+
// Add Blockly to the global scope so that test code can access it to
133+
// verify state after keypresses.
134+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
135+
// @ts-expect-error
136+
window.Blockly = Blockly;
132137
});

test/loadTestBlocks.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ const simpleCircle = {
190190
'STATEMENTS': {
191191
'block': {
192192
'type': 'p5_canvas',
193-
'id': 'spya_H-5F=K8+DhedX$y',
193+
'id': 'create_canvas_1',
194194
'deletable': false,
195195
'movable': false,
196196
'fields': {
@@ -200,12 +200,12 @@ const simpleCircle = {
200200
'next': {
201201
'block': {
202202
'type': 'p5_background_color',
203-
'id': 'i/Hvi~^DYffkN/WpT_Ck',
203+
'id': 'set_background_color_1',
204204
'inputs': {
205205
'COLOR': {
206206
'shadow': {
207207
'type': 'colour_picker',
208-
'id': 'B:zpi7kg+.GF_Dutd9GL',
208+
'id': 'set_background_color_1_color',
209209
'fields': {
210210
'COLOUR': '#9999ff',
211211
},
@@ -220,7 +220,7 @@ const simpleCircle = {
220220
},
221221
{
222222
'type': 'p5_draw',
223-
'id': '3iI4f%2#Gmk}=OjI7(8h',
223+
'id': 'draw_root',
224224
'x': 0,
225225
'y': 332,
226226
'deletable': false,
@@ -234,7 +234,7 @@ const simpleCircle = {
234234
'COLOR': {
235235
'shadow': {
236236
'type': 'colour_picker',
237-
'id': 'gq(POne}j:hVw%C3t{vx',
237+
'id': 'draw_circle_1_color',
238238
'fields': {
239239
'COLOUR': '#ffff00',
240240
},

test/webdriverio/test/basic_test.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
import * as chai from 'chai';
88
import * as Blockly from 'blockly';
99
import {
10+
focusWorkspace,
11+
setCurrentCursorNodeById,
12+
getCurrentCursorNodeFieldName,
13+
getCurrentCursorNodeId,
14+
getCurrentCursorNodeType,
1015
testSetup,
1116
testFileLocations,
1217
PAUSE_TIME,
@@ -47,4 +52,89 @@ suite('Keyboard navigation', function () {
4752
});
4853
chai.assert.equal(selectedId, 'draw_circle_1');
4954
});
55+
56+
test('Down from statement block selects next connection', async function () {
57+
await focusWorkspace(this.browser);
58+
await this.browser.pause(PAUSE_TIME);
59+
await setCurrentCursorNodeById(this.browser, 'create_canvas_1');
60+
await this.browser.pause(PAUSE_TIME);
61+
await this.browser.keys(Key.ArrowDown);
62+
await this.browser.pause(PAUSE_TIME);
63+
64+
chai.assert.equal(
65+
await getCurrentCursorNodeId(this.browser),
66+
'create_canvas_1',
67+
);
68+
chai.assert.equal(
69+
await getCurrentCursorNodeType(this.browser),
70+
Blockly.ASTNode.types.NEXT,
71+
);
72+
});
73+
74+
test("Up from statement block selects previous block's connection", async function () {
75+
await focusWorkspace(this.browser);
76+
await this.browser.pause(PAUSE_TIME);
77+
await setCurrentCursorNodeById(this.browser, 'set_background_color_1');
78+
await this.browser.pause(PAUSE_TIME);
79+
await this.browser.keys(Key.ArrowUp);
80+
await this.browser.pause(PAUSE_TIME);
81+
82+
chai.assert.equal(
83+
await getCurrentCursorNodeId(this.browser),
84+
'create_canvas_1',
85+
);
86+
chai.assert.equal(
87+
await getCurrentCursorNodeType(this.browser),
88+
Blockly.ASTNode.types.NEXT,
89+
);
90+
});
91+
92+
test('Down from parent block selects input connection', async function () {
93+
await focusWorkspace(this.browser);
94+
await this.browser.pause(PAUSE_TIME);
95+
await setCurrentCursorNodeById(this.browser, 'p5_setup_1');
96+
await this.browser.pause(PAUSE_TIME);
97+
await this.browser.keys(Key.ArrowDown);
98+
await this.browser.pause(PAUSE_TIME);
99+
100+
chai.assert.equal(await getCurrentCursorNodeId(this.browser), 'p5_setup_1');
101+
chai.assert.equal(
102+
await getCurrentCursorNodeType(this.browser),
103+
Blockly.ASTNode.types.INPUT,
104+
);
105+
});
106+
107+
test('Up from child block selects input connection', async function () {
108+
await focusWorkspace(this.browser);
109+
await this.browser.pause(PAUSE_TIME);
110+
await setCurrentCursorNodeById(this.browser, 'create_canvas_1');
111+
await this.browser.pause(PAUSE_TIME);
112+
await this.browser.keys(Key.ArrowUp);
113+
await this.browser.pause(PAUSE_TIME);
114+
115+
chai.assert.equal(await getCurrentCursorNodeId(this.browser), 'p5_setup_1');
116+
chai.assert.equal(
117+
await getCurrentCursorNodeType(this.browser),
118+
Blockly.ASTNode.types.INPUT,
119+
);
120+
});
121+
122+
test('Right from block selects field', async function () {
123+
await focusWorkspace(this.browser);
124+
await this.browser.pause(PAUSE_TIME);
125+
await setCurrentCursorNodeById(this.browser, 'create_canvas_1');
126+
await this.browser.pause(PAUSE_TIME);
127+
await this.browser.keys(Key.ArrowRight);
128+
await this.browser.pause(PAUSE_TIME);
129+
130+
chai.assert.equal(await getCurrentCursorNodeId(this.browser), 'create_canvas_1');
131+
chai.assert.equal(
132+
await getCurrentCursorNodeType(this.browser),
133+
Blockly.ASTNode.types.FIELD,
134+
);
135+
chai.assert.equal(
136+
await getCurrentCursorNodeFieldName(this.browser),
137+
'WIDTH',
138+
);
139+
});
50140
});

test/webdriverio/test/test_setup.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,86 @@ export async function getSelectedBlockId(browser: WebdriverIO.Browser) {
155155
});
156156
}
157157

158+
/**
159+
* Clicks in the workspace to focus it.
160+
*
161+
* @param browser The active WebdriverIO Browser object.
162+
*/
163+
export async function focusWorkspace(browser: WebdriverIO.Browser) {
164+
const workspaceElement = await browser.$(
165+
'#blocklyDiv > div > svg.blocklySvg > g',
166+
);
167+
await workspaceElement.click();
168+
}
169+
170+
/**
171+
* Select a block with the given id as the current cursor node.
172+
*
173+
* @param browser The active WebdriverIO Browser object.
174+
* @param blockId The id of the block to select.
175+
*/
176+
export async function setCurrentCursorNodeById(
177+
browser: WebdriverIO.Browser,
178+
blockId: string,
179+
) {
180+
return await browser.execute((blockId) => {
181+
const workspaceSvg = Blockly.getMainWorkspace() as Blockly.WorkspaceSvg;
182+
const rootBlock = workspaceSvg.getBlockById(blockId);
183+
workspaceSvg
184+
.getCursor()
185+
?.setCurNode(Blockly.ASTNode.createBlockNode(rootBlock!)!);
186+
}, blockId);
187+
}
188+
189+
/**
190+
* Get the ID of the block at the current cursor node.
191+
*
192+
* @param browser The active WebdriverIO Browser object.
193+
* @returns A Promise that resolves to the ID of the current cursor node.
194+
*/
195+
export async function getCurrentCursorNodeId(
196+
browser: WebdriverIO.Browser,
197+
): Promise<string | undefined> {
198+
return await browser.execute(() => {
199+
const workspaceSvg = Blockly.getMainWorkspace() as Blockly.WorkspaceSvg;
200+
return workspaceSvg.getCursor()?.getCurNode()?.getSourceBlock()?.id;
201+
});
202+
}
203+
204+
/**
205+
* Get the type of the current cursor node.
206+
*
207+
* @param browser The active WebdriverIO Browser object.
208+
* @returns A Promise that resolves to the type of the current cursor node.
209+
*/
210+
export async function getCurrentCursorNodeType(
211+
browser: WebdriverIO.Browser,
212+
): Promise<string | undefined> {
213+
return await browser.execute(() => {
214+
const workspaceSvg = Blockly.getMainWorkspace() as Blockly.WorkspaceSvg;
215+
return workspaceSvg.getCursor()?.getCurNode()?.getType();
216+
});
217+
}
218+
219+
/**
220+
* Get the field name of the current cursor node.
221+
*
222+
* @param browser The active WebdriverIO Browser object.
223+
* @returns A Promise that resolves to the field name of the current cursor node.
224+
*/
225+
export async function getCurrentCursorNodeFieldName(
226+
browser: WebdriverIO.Browser,
227+
): Promise<string | undefined> {
228+
return await browser.execute(() => {
229+
const workspaceSvg = Blockly.getMainWorkspace() as Blockly.WorkspaceSvg;
230+
const field = workspaceSvg
231+
.getCursor()
232+
?.getCurNode()
233+
?.getLocation() as Blockly.Field;
234+
return field.name;
235+
});
236+
}
237+
158238
export interface ElementWithId extends WebdriverIO.Element {
159239
id: string;
160240
}

0 commit comments

Comments
 (0)