Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow the dialog methods to take in extra parameters #8084

Merged
merged 4 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 30 additions & 55 deletions core/dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,30 @@

// Former goog.module ID: Blockly.dialog

let alertImplementation = function (
message: string,
opt_callback?: () => void,
) {
window.alert(message);
if (opt_callback) {
opt_callback();
}
};

let confirmImplementation = function (
message: string,
callback: (result: boolean) => void,
) {
callback(window.confirm(message));
};

let promptImplementation = function (
message: string,
defaultValue: string,
callback: (result: string | null) => void,
) {
callback(window.prompt(message, defaultValue));
};

/**
* Wrapper to window.alert() that app developers may override via setAlert to
* provide alternatives to the modal browser window.
*
* @param message The message to display to the user.
* @param opt_callback The callback when the alert is dismissed.
*/
export function alert(message: string, opt_callback?: () => void) {
alertImplementation(message, opt_callback);
}
export let alert = (message: string, opt_callback?: () => void) => {
window.alert(message);
if (opt_callback) {
opt_callback();
}
};

/**
* Sets the function to be run when Blockly.dialog.alert() is called.
*
* @param alertFunction The function to be run.
* @see Blockly.dialog.alert
*/
export function setAlert(alertFunction: (p1: string, p2?: () => void) => void) {
alertImplementation = alertFunction;
export function setAlert(
alertFunction: (message: string, callback?: () => void) => void,
) {
alert = alertFunction;
}

/**
Expand All @@ -59,16 +39,12 @@ export function setAlert(alertFunction: (p1: string, p2?: () => void) => void) {
* @param message The message to display to the user.
* @param callback The callback for handling user response.
*/
export function confirm(message: string, callback: (p1: boolean) => void) {
TEST_ONLY.confirmInternal(message, callback);
}

/**
* Private version of confirm for stubbing in tests.
*/
function confirmInternal(message: string, callback: (p1: boolean) => void) {
confirmImplementation(message, callback);
}
export let confirm = (
message: string,
callback: (confirmed: boolean) => void,
) => {
callback(window.confirm(message));
};

/**
* Sets the function to be run when Blockly.dialog.confirm() is called.
Expand All @@ -77,9 +53,12 @@ function confirmInternal(message: string, callback: (p1: boolean) => void) {
* @see Blockly.dialog.confirm
*/
export function setConfirm(
confirmFunction: (p1: string, p2: (p1: boolean) => void) => void,
confirmFunction: (
message: string,
callback: (confirmed: boolean) => void,
) => void,
) {
confirmImplementation = confirmFunction;
confirm = confirmFunction;
}

/**
Expand All @@ -92,13 +71,13 @@ export function setConfirm(
* @param defaultValue The value to initialize the prompt with.
* @param callback The callback for handling user response.
*/
export function prompt(
export let prompt = (
message: string,
defaultValue: string,
callback: (p1: string | null) => void,
) {
promptImplementation(message, defaultValue, callback);
}
callback: (userInput: string | null) => void,
) => {
callback(window.prompt(message, defaultValue));
};

/**
* Sets the function to be run when Blockly.dialog.prompt() is called.
Expand All @@ -108,14 +87,10 @@ export function prompt(
*/
export function setPrompt(
promptFunction: (
p1: string,
p2: string,
p3: (p1: string | null) => void,
message: string,
defaultValue: string,
callback: (userInput: string | null) => void,
) => void,
) {
promptImplementation = promptFunction;
prompt = promptFunction;
}

export const TEST_ONLY = {
confirmInternal,
};
20 changes: 9 additions & 11 deletions tests/mocha/contextmenu_items_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,10 @@ suite('Context Menu Items', function () {
});

test('Deletes all blocks after confirming', function () {
// Mocks the confirmation dialog and calls the callback with 'true' simulating ok.
const confirmStub = sinon
.stub(Blockly.dialog.TEST_ONLY, 'confirmInternal')
.callsArgWith(1, true);
// Mocks the confirmation dialog and calls the callback with 'true'
// simulating ok.
const confirmStub = sinon.stub().callsArgWith(1, true);
Blockly.dialog.setConfirm(confirmStub);

this.workspace.newBlock('text');
this.workspace.newBlock('text');
Expand All @@ -337,9 +337,8 @@ suite('Context Menu Items', function () {

test('Does not delete blocks if not confirmed', function () {
// Mocks the confirmation dialog and calls the callback with 'false' simulating cancel.
const confirmStub = sinon
.stub(Blockly.dialog.TEST_ONLY, 'confirmInternal')
.callsArgWith(1, false);
const confirmStub = sinon.stub().callsArgWith(1, false);
Blockly.dialog.setConfirm(confirmStub);

this.workspace.newBlock('text');
this.workspace.newBlock('text');
Expand All @@ -350,10 +349,9 @@ suite('Context Menu Items', function () {
});

test('No dialog for single block', function () {
const confirmStub = sinon.stub(
Blockly.dialog.TEST_ONLY,
'confirmInternal',
);
const confirmStub = sinon.stub();
Blockly.dialog.setConfirm(confirmStub);

this.workspace.newBlock('text');
this.deleteOption.callback(this.scope);
this.clock.runAll();
Expand Down
58 changes: 58 additions & 0 deletions tests/mocha/dialog_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* @license
* Copyright 2024 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

suite.only('Dialog', function () {
teardown(function () {
sinon.restore();
});

suite('Prompt', function () {
test('setPrompt can take in a function with additional parameters', function () {
const spy = sinon.spy();
Blockly.dialog.setPrompt(spy);
const callback = () => {};

Blockly.dialog.prompt(
'message',
'defaultVal',
callback,
'extra parameter',
);

chai.assert.isTrue(
spy.calledWith('message', 'defaultVal', callback, 'extra parameter'),
);
});
});

suite('Confirm', function () {
test('setConfirm can take in a function with additional parameters', function () {
const spy = sinon.spy();
Blockly.dialog.setConfirm(spy);
const callback = () => {};

Blockly.dialog.confirm('message', callback, 'extra parameter');

chai.assert.isTrue(
spy.calledWith('message', callback, 'extra parameter'),
);
});
});

suite('Alert', function () {
test('setAlert can take in a function with additional parameters', function () {
const spy = sinon.spy();
Blockly.dialog.setAlert(spy);
const callback = () => {};

Blockly.dialog.alert('message', callback, 'extra parameter');

chai.assert.isTrue(
spy.calledWith('message', callback, 'extra parameter'),
);
});
});
});
1 change: 1 addition & 0 deletions tests/mocha/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import './contextmenu_items_test.js';
import './contextmenu_test.js';
import './cursor_test.js';
import './dialog_test.js';
import './dropdowndiv_test.js';
import './event_test.js';
import './event_block_change_test.js';
Expand Down
15 changes: 6 additions & 9 deletions tests/mocha/test_helpers/workspace.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,8 @@ export function testAWorkspace() {

test('deleteVariableById(id2) one usage', function () {
// Deleting variable one usage should not trigger confirm dialog.
const stub = sinon
.stub(Blockly.dialog.TEST_ONLY, 'confirmInternal')
.callsArgWith(1, true);
const stub = sinon.stub().callsArgWith(1, true);
Blockly.dialog.setConfirm(stub);
this.workspace.deleteVariableById('id2');

sinon.assert.notCalled(stub);
Expand All @@ -113,9 +112,8 @@ export function testAWorkspace() {

test('deleteVariableById(id1) multiple usages confirm', function () {
// Deleting variable with multiple usages triggers confirm dialog.
const stub = sinon
.stub(Blockly.dialog.TEST_ONLY, 'confirmInternal')
.callsArgWith(1, true);
const stub = sinon.stub().callsArgWith(1, true);
Blockly.dialog.setConfirm(stub);
this.workspace.deleteVariableById('id1');

sinon.assert.calledOnce(stub);
Expand All @@ -127,9 +125,8 @@ export function testAWorkspace() {

test('deleteVariableById(id1) multiple usages cancel', function () {
// Deleting variable with multiple usages triggers confirm dialog.
const stub = sinon
.stub(Blockly.dialog.TEST_ONLY, 'confirmInternal')
.callsArgWith(1, false);
const stub = sinon.stub().callsArgWith(1, false);
Blockly.dialog.setConfirm(stub);
this.workspace.deleteVariableById('id1');

sinon.assert.calledOnce(stub);
Expand Down