Skip to content

Commit 3a53af9

Browse files
authored
fix: Ensure FieldImage is clickable when appropriate (#9063)
* fix: Ensure FieldImage is clickable when valid. * chore: Add new tests for FieldImage.isClickable().
1 parent a1cbdd9 commit 3a53af9

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

core/field_image.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,17 @@ export class FieldImage extends Field<string> {
212212
}
213213
}
214214

215+
/**
216+
* Check whether this field should be clickable.
217+
*
218+
* @returns Whether this field is clickable.
219+
*/
220+
isClickable(): boolean {
221+
// Images are only clickable if they have a click handler and fulfill the
222+
// contract to be clickable: enabled and attached to an editable block.
223+
return super.isClickable() && !!this.clickHandler;
224+
}
225+
215226
/**
216227
* If field click is called, and click handler defined,
217228
* call the handler.

tests/mocha/field_image_test.js

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
suite('Image Fields', function () {
2121
setup(function () {
2222
sharedTestSetup.call(this);
23+
this.workspace = Blockly.inject('blocklyDiv');
2324
});
2425
teardown(function () {
2526
sharedTestTeardown.call(this);
@@ -237,5 +238,114 @@ suite('Image Fields', function () {
237238
assert.isTrue(field.getFlipRtl());
238239
});
239240
});
241+
suite('isClickable', function () {
242+
setup(function () {
243+
this.onClick = function () {
244+
console.log('on click');
245+
};
246+
this.setUpBlockWithFieldImages = function () {
247+
const blockJson = {
248+
'type': 'text',
249+
'id': 'block_id',
250+
'x': 0,
251+
'y': 0,
252+
'fields': {
253+
'TEXT': '',
254+
},
255+
};
256+
Blockly.serialization.blocks.append(blockJson, this.workspace);
257+
return this.workspace.getBlockById('block_id');
258+
};
259+
this.extractFieldImage = function (block) {
260+
const fields = Array.from(block.getFields());
261+
// Sanity check (as a precondition).
262+
assert.strictEqual(fields.length, 3);
263+
const imageField = fields[0];
264+
// Sanity check (as a precondition).
265+
assert.isTrue(imageField instanceof Blockly.FieldImage);
266+
return imageField;
267+
};
268+
});
269+
270+
test('Unattached field without click handler returns false', function () {
271+
const field = new Blockly.FieldImage('src', 10, 10, null);
272+
273+
const isClickable = field.isClickable();
274+
275+
assert.isFalse(isClickable);
276+
});
277+
test('Unattached field with click handler returns false', function () {
278+
const field = new Blockly.FieldImage('src', 10, 10, this.onClick);
279+
280+
const isClickable = field.isClickable();
281+
282+
assert.isFalse(isClickable);
283+
});
284+
test('For attached but disabled field without click handler returns false', function () {
285+
const block = this.setUpBlockWithFieldImages();
286+
const field = this.extractFieldImage(block);
287+
field.setEnabled(false);
288+
289+
const isClickable = field.isClickable();
290+
291+
assert.isFalse(isClickable);
292+
});
293+
test('For attached but disabled field with click handler returns false', function () {
294+
const block = this.setUpBlockWithFieldImages();
295+
const field = this.extractFieldImage(block);
296+
field.setEnabled(false);
297+
field.setOnClickHandler(this.onClick);
298+
299+
const isClickable = field.isClickable();
300+
301+
assert.isFalse(isClickable);
302+
});
303+
test('For attached, enabled, but not editable field without click handler returns false', function () {
304+
const block = this.setUpBlockWithFieldImages();
305+
const field = this.extractFieldImage(block);
306+
block.setEditable(false);
307+
308+
const isClickable = field.isClickable();
309+
310+
assert.isFalse(isClickable);
311+
});
312+
test('For attached, enabled, but not editable field with click handler returns false', function () {
313+
const block = this.setUpBlockWithFieldImages();
314+
const field = this.extractFieldImage(block);
315+
block.setEditable(false);
316+
field.setOnClickHandler(this.onClick);
317+
318+
const isClickable = field.isClickable();
319+
320+
assert.isFalse(isClickable);
321+
});
322+
test('For attached, enabled, editable field without click handler returns false', function () {
323+
const block = this.setUpBlockWithFieldImages();
324+
const field = this.extractFieldImage(block);
325+
326+
const isClickable = field.isClickable();
327+
328+
assert.isFalse(isClickable);
329+
});
330+
test('For attached, enabled, editable field with click handler returns true', function () {
331+
const block = this.setUpBlockWithFieldImages();
332+
const field = this.extractFieldImage(block);
333+
field.setOnClickHandler(this.onClick);
334+
335+
const isClickable = field.isClickable();
336+
337+
assert.isTrue(isClickable);
338+
});
339+
test('For attached, enabled, editable field with removed click handler returns false', function () {
340+
const block = this.setUpBlockWithFieldImages();
341+
const field = this.extractFieldImage(block);
342+
field.setOnClickHandler(this.onClick);
343+
field.setOnClickHandler(null);
344+
345+
const isClickable = field.isClickable();
346+
347+
assert.isFalse(isClickable);
348+
});
349+
});
240350
});
241351
});

0 commit comments

Comments
 (0)