Support dispatching pointer events in click tests (#4154)

* Add helpers for simulating mouse click.

* Update field and workspace click tests.
This commit is contained in:
Monica Kozbial
2020-08-11 11:17:33 -07:00
committed by GitHub
parent b24b2dabde
commit b0b3c67b90
4 changed files with 115 additions and 48 deletions

View File

@@ -15,9 +15,11 @@
"captureWarnings": true,
"createRenderedBlock": true,
"createTestBlock": true,
"defineBasicBlockWithField": true,
"defineRowBlock": true,
"defineStackBlock": true,
"defineStatementBlock": true,
"dispatchPointerEvent": true,
"createFireChangeListenerSpy": true,
"createGenUidStubWithReturns": true,
"getCategoryJSON": true,
@@ -25,8 +27,9 @@
"getXmlArray": true,
"sharedTestSetup": true,
"sharedTestTeardown": true,
"simulateClick": true,
"testAWorkspace": true,
"testHelpers" : true,
"testHelpers": true,
"workspaceTeardown": true
},
"rules": {

View File

@@ -11,77 +11,88 @@
'use strict';
suite('Gesture', function() {
function testGestureIsFieldClick(block, isFieldClick){
var field = block.getField('NAME');
var eventTarget = field.getClickTarget_();
chai.assert.exists(eventTarget,
'Precondition: missing click target for field');
dispatchPointerEvent(eventTarget, 'pointerdown');
var fieldWorkspace = field.sourceBlock_.workspace;
// Gestures triggered on flyouts are stored on targetWorkspace.
var gestureWorkspace = fieldWorkspace.targetWorkspace || fieldWorkspace;
var gesture = gestureWorkspace.currentGesture_;
chai.assert.exists(gesture, 'Gesture exists after pointerdown.');
var isFieldClickSpy = sinon.spy(gesture, 'isFieldClick_');
dispatchPointerEvent(eventTarget, 'pointerup');
dispatchPointerEvent(eventTarget, 'click');
sinon.assert.called(isFieldClickSpy);
chai.assert.isTrue(isFieldClickSpy.alwaysReturned(isFieldClick));
}
function getTopFlyoutBlock(flyout) {
return flyout.workspace_.topBlocks_[0];
}
setup(function() {
sharedTestSetup.call(this);
this.workspace = new Blockly.Workspace();
this.e = {};
defineBasicBlockWithField();
var toolbox = document.getElementById('gesture-test-toolbox');
this.workspace = Blockly.inject('blocklyDiv', {toolbox: toolbox});
});
teardown(function() {
sharedTestTeardown.call(this);
delete Blockly.Block['test_field_block'];
});
test('Constructor', function() {
var gesture = new Blockly.Gesture(this.e, this.workspace);
chai.assert.equal(gesture.mostRecentEvent_, this.e);
var e = { id: 'dummy_test_event'};
var gesture = new Blockly.Gesture(e, this.workspace);
chai.assert.equal(gesture.mostRecentEvent_, e);
chai.assert.equal(gesture.creatorWorkspace_, this.workspace);
});
test('Field click - Click in workspace', function() {
var block = new Blockly.Block(this.workspace);
var field = new Blockly.Field();
field.setSourceBlock(block);
field.showEditor_ = function() {};
var gesture = new Blockly.Gesture(this.e, this.workspace);
gesture.setStartField(field);
var block = this.workspace.newBlock('test_field_block');
block.initSvg();
block.render();
var isFieldClick = gesture.isFieldClick_();
chai.assert.isTrue(isFieldClick);
testGestureIsFieldClick(block, true);
});
function gestureIsFieldClick_InFlyoutHelper(flyout, expectedResult){
// Assign workspace flyout
this.workspace.flyout_ = flyout;
// Create a Field inside of a Block
var block = new Blockly.Block(this.workspace);
var field = new Blockly.Field();
field.setSourceBlock(block);
field.showEditor_ = function() {};
// Create gesture from the flyout
var gesture = new Blockly.Gesture(this.e, this.workspace.flyout_);
// Populate gesture with click start information
gesture.setStartField(field);
gesture.setStartFlyout_(this.workspace.flyout_);
var isFieldClick = gesture.isFieldClick_();
chai.assert.equal(isFieldClick, expectedResult);
}
test('Field click - Auto close flyout', function() {
var flyout = new Blockly.VerticalFlyout(new Blockly.Options({}));
flyout.autoClose = false;
gestureIsFieldClick_InFlyoutHelper.call(this, flyout, true);
var flyout = this.workspace.flyout_;
chai.assert.exists(this.workspace.flyout_,
'Precondition: missing flyout');
flyout.autoClose = true;
var block = getTopFlyoutBlock(flyout);
testGestureIsFieldClick(block, false);
});
test('Field click - Always open flyout', function() {
var flyout = new Blockly.VerticalFlyout(new Blockly.Options({}));
var flyout = this.workspace.flyout_;
chai.assert.exists(this.workspace.flyout_,
'Precondition: missing flyout');
flyout.autoClose = false;
gestureIsFieldClick_InFlyoutHelper.call(this, flyout, true);
var block = getTopFlyoutBlock(flyout);
testGestureIsFieldClick(block, true);
});
test('Workspace click in accessibility mode - moves the cursor', function() {
var event = {
shiftKey : true,
clientX : 10,
clientY : 10,
test('Shift click in accessibility mode - moves the cursor', function() {
this.workspace.keyboardAccessibilityMode = true;
};
var ws = Blockly.inject('blocklyDiv', {});
ws.keyboardAccessibilityMode = true;
var gesture = new Blockly.Gesture(event, ws);
gesture.doWorkspaceClick_(event);
var cursor = ws.getCursor();
chai.assert.equal(cursor.getCurNode().getType(), Blockly.ASTNode.types.WORKSPACE);
var eventTarget = this.workspace.svgGroup_;
simulateClick(eventTarget, {shiftKey: true});
var cursor = this.workspace.getCursor();
var cursorNode = cursor.getCurNode();
chai.assert.exists(cursorNode);
chai.assert.equal(cursorNode.getType(), Blockly.ASTNode.types.WORKSPACE);
});
});

View File

@@ -150,6 +150,10 @@
<block type="row_block"></block>
</xml>
<xml xmlns="https://developers.google.com/blockly/xml" id="gesture-test-toolbox" style="display: none">
<block type="test_field_block"></block>
</xml>
<script>
mocha.run(function(failures) {
var failureDiv = document.getElementById('failureCount');

View File

@@ -283,6 +283,19 @@ function defineStatementBlock() {
"helpUrl": ""
}]);
}
function defineBasicBlockWithField() {
Blockly.defineBlocksWithJsonArray([{
"type": "test_field_block",
"message0": "%1",
"args0": [
{
"type": "field_input",
"name": "NAME"
}
],
"output": null
}]);
}
function createTestBlock() {
return {
@@ -300,3 +313,39 @@ function createRenderedBlock(workspaceSvg, type) {
block.render();
return block;
}
/**
* Triggers pointer event on target.
* @param {!EventTarget} target The object receiving the event.
* @param {string} type The type of mouse event (eg: mousedown, mouseup,
* click).
* @param {Object<string, string>=} properties Properties to pass into event
* constructor.
*/
function dispatchPointerEvent(target, type, properties) {
const eventInitDict = {
cancelable: true,
bubbles: true,
isPrimary: true,
pressure: 0.5,
clientX: 10,
clientY: 10,
};
if (properties) {
Object.assign(eventInitDict, properties);
}
const event = new PointerEvent(type, eventInitDict);
target.dispatchEvent(event);
}
/**
* Simulates mouse click by triggering relevant mouse events.
* @param {!EventTarget} target The object receiving the event.
* @param {Object<string, string>=} properties Properties to pass into event
* constructor.
*/
function simulateClick(target, properties) {
dispatchPointerEvent(target, 'pointerdown', properties);
dispatchPointerEvent(target, 'pointerup', properties);
dispatchPointerEvent(target, 'click', properties);
}