Add support for checkbox with dialog.showMessageBox

This adds the `checkboxLabel` and `checkboxChecked` options to display a
checkbox in the message box. Fixes #6048.
This commit is contained in:
Birunthan Mohanathas 2017-02-06 15:35:36 +00:00 committed by Kevin Sawicki
parent 9163b601a4
commit c8c11e68c6
10 changed files with 155 additions and 61 deletions

View file

@ -47,6 +47,8 @@ void ShowMessageBox(int type,
const std::string& title, const std::string& title,
const std::string& message, const std::string& message,
const std::string& detail, const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon, const gfx::ImageSkia& icon,
atom::NativeWindow* window, atom::NativeWindow* window,
mate::Arguments* args) { mate::Arguments* args) {
@ -56,8 +58,8 @@ void ShowMessageBox(int type,
peek, peek,
&callback)) { &callback)) {
atom::ShowMessageBox(window, (atom::MessageBoxType)type, buttons, atom::ShowMessageBox(window, (atom::MessageBoxType)type, buttons,
default_id, cancel_id, options, title, default_id, cancel_id, options, title, message, detail,
message, detail, icon, callback); checkbox_label, checkbox_checked, icon, callback);
} else { } else {
int chosen = atom::ShowMessageBox(window, (atom::MessageBoxType)type, int chosen = atom::ShowMessageBox(window, (atom::MessageBoxType)type,
buttons, default_id, cancel_id, buttons, default_id, cancel_id,

View file

@ -38,14 +38,9 @@ void AtomJavaScriptDialogManager::RunJavaScriptDialog(
} }
atom::ShowMessageBox(NativeWindow::FromWebContents(web_contents), atom::ShowMessageBox(NativeWindow::FromWebContents(web_contents),
atom::MessageBoxType::MESSAGE_BOX_TYPE_NONE, atom::MessageBoxType::MESSAGE_BOX_TYPE_NONE, buttons, -1,
buttons, 0, atom::MessageBoxOptions::MESSAGE_BOX_NONE, "",
-1, base::UTF16ToUTF8(message_text), "", "", false,
0,
atom::MessageBoxOptions::MESSAGE_BOX_NONE,
"",
base::UTF16ToUTF8(message_text),
"",
gfx::ImageSkia(), gfx::ImageSkia(),
base::Bind(&OnMessageBoxCallback, callback)); base::Bind(&OnMessageBoxCallback, callback));
} }
@ -66,7 +61,9 @@ void AtomJavaScriptDialogManager::CancelDialogs(
// static // static
void AtomJavaScriptDialogManager::OnMessageBoxCallback( void AtomJavaScriptDialogManager::OnMessageBoxCallback(
const DialogClosedCallback& callback, int code) { const DialogClosedCallback& callback,
int code,
bool checkbox_checked) {
callback.Run(code == 0, base::string16()); callback.Run(code == 0, base::string16());
} }

View file

@ -32,7 +32,8 @@ class AtomJavaScriptDialogManager : public content::JavaScriptDialogManager {
private: private:
static void OnMessageBoxCallback(const DialogClosedCallback& callback, static void OnMessageBoxCallback(const DialogClosedCallback& callback,
int code); int code,
bool checkbox_checked);
}; };
} // namespace atom } // namespace atom

View file

@ -32,7 +32,8 @@ enum MessageBoxOptions {
MESSAGE_BOX_NO_LINK = 1 << 0, MESSAGE_BOX_NO_LINK = 1 << 0,
}; };
typedef base::Callback<void(int code)> MessageBoxCallback; typedef base::Callback<void(int code, bool checkbox_checked)>
MessageBoxCallback;
int ShowMessageBox(NativeWindow* parent_window, int ShowMessageBox(NativeWindow* parent_window,
MessageBoxType type, MessageBoxType type,
@ -54,6 +55,8 @@ void ShowMessageBox(NativeWindow* parent_window,
const std::string& title, const std::string& title,
const std::string& message, const std::string& message,
const std::string& detail, const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon, const gfx::ImageSkia& icon,
const MessageBoxCallback& callback); const MessageBoxCallback& callback);

View file

@ -36,8 +36,11 @@ class GtkMessageBox : public NativeWindowObserver {
const std::string& title, const std::string& title,
const std::string& message, const std::string& message,
const std::string& detail, const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon) const gfx::ImageSkia& icon)
: cancel_id_(cancel_id), : cancel_id_(cancel_id),
checkbox_checked_(false),
parent_(static_cast<NativeWindowViews*>(parent_window)) { parent_(static_cast<NativeWindowViews*>(parent_window)) {
// Create dialog. // Create dialog.
dialog_ = gtk_message_dialog_new( dialog_ = gtk_message_dialog_new(
@ -68,6 +71,18 @@ class GtkMessageBox : public NativeWindowObserver {
g_object_unref(pixbuf); g_object_unref(pixbuf);
} }
if (!checkbox_label.empty()) {
GtkWidget* message_area =
gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG(dialog_));
GtkWidget* check_button =
gtk_check_button_new_with_label(checkbox_label.c_str());
g_signal_connect(check_button, "toggled",
G_CALLBACK(OnCheckboxToggledThunk), this);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
checkbox_checked);
gtk_container_add(GTK_CONTAINER(message_area), check_button);
}
// Add buttons. // Add buttons.
for (size_t i = 0; i < buttons.size(); ++i) { for (size_t i = 0; i < buttons.size(); ++i) {
GtkWidget* button = gtk_dialog_add_button( GtkWidget* button = gtk_dialog_add_button(
@ -154,6 +169,7 @@ class GtkMessageBox : public NativeWindowObserver {
} }
CHROMEGTK_CALLBACK_1(GtkMessageBox, void, OnResponseDialog, int); CHROMEGTK_CALLBACK_1(GtkMessageBox, void, OnResponseDialog, int);
CHROMEGTK_CALLBACK_1(GtkMessageBox, void, OnCheckboxToggled, gpointer);
private: private:
atom::UnresponsiveSuppressor unresponsive_suppressor_; atom::UnresponsiveSuppressor unresponsive_suppressor_;
@ -161,6 +177,8 @@ class GtkMessageBox : public NativeWindowObserver {
// The id to return when the dialog is closed without pressing buttons. // The id to return when the dialog is closed without pressing buttons.
int cancel_id_; int cancel_id_;
bool checkbox_checked_;
NativeWindowViews* parent_; NativeWindowViews* parent_;
GtkWidget* dialog_; GtkWidget* dialog_;
MessageBoxCallback callback_; MessageBoxCallback callback_;
@ -172,12 +190,16 @@ void GtkMessageBox::OnResponseDialog(GtkWidget* widget, int response) {
gtk_widget_hide(dialog_); gtk_widget_hide(dialog_);
if (response < 0) if (response < 0)
callback_.Run(cancel_id_); callback_.Run(cancel_id_, checkbox_checked_);
else else
callback_.Run(response); callback_.Run(response, checkbox_checked_);
delete this; delete this;
} }
void GtkMessageBox::OnCheckboxToggled(GtkWidget* widget, gpointer data) {
checkbox_checked_ = GTK_TOGGLE_BUTTON(widget)->active;
}
} // namespace } // namespace
int ShowMessageBox(NativeWindow* parent, int ShowMessageBox(NativeWindow* parent,
@ -190,8 +212,9 @@ int ShowMessageBox(NativeWindow* parent,
const std::string& message, const std::string& message,
const std::string& detail, const std::string& detail,
const gfx::ImageSkia& icon) { const gfx::ImageSkia& icon) {
return GtkMessageBox(parent, type, buttons, default_id, cancel_id, return GtkMessageBox(parent, type, buttons, default_id, cancel_id, title,
title, message, detail, icon).RunSynchronous(); message, detail, "", false, icon)
.RunSynchronous();
} }
void ShowMessageBox(NativeWindow* parent, void ShowMessageBox(NativeWindow* parent,
@ -203,18 +226,22 @@ void ShowMessageBox(NativeWindow* parent,
const std::string& title, const std::string& title,
const std::string& message, const std::string& message,
const std::string& detail, const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon, const gfx::ImageSkia& icon,
const MessageBoxCallback& callback) { const MessageBoxCallback& callback) {
(new GtkMessageBox(parent, type, buttons, default_id, cancel_id, (new GtkMessageBox(parent, type, buttons, default_id, cancel_id, title,
title, message, detail, icon))->RunAsynchronous(callback); message, detail, checkbox_label, checkbox_checked, icon))
->RunAsynchronous(callback);
} }
void ShowErrorBox(const base::string16& title, const base::string16& content) { void ShowErrorBox(const base::string16& title, const base::string16& content) {
if (Browser::Get()->is_ready()) { if (Browser::Get()->is_ready()) {
GtkMessageBox(nullptr, MESSAGE_BOX_TYPE_ERROR, { "OK" }, -1, 0, "Error", GtkMessageBox(nullptr, MESSAGE_BOX_TYPE_ERROR, {"OK"}, -1, 0, "Error",
base::UTF16ToUTF8(title).c_str(), base::UTF16ToUTF8(title).c_str(),
base::UTF16ToUTF8(content).c_str(), base::UTF16ToUTF8(content).c_str(), "", false,
gfx::ImageSkia()).RunSynchronous(); gfx::ImageSkia())
.RunSynchronous();
} else { } else {
fprintf(stderr, fprintf(stderr,
ANSI_TEXT_BOLD ANSI_BACKGROUND_GRAY ANSI_TEXT_BOLD ANSI_BACKGROUND_GRAY

View file

@ -39,7 +39,7 @@
- (void)alertDidEnd:(NSAlert*)alert - (void)alertDidEnd:(NSAlert*)alert
returnCode:(NSInteger)returnCode returnCode:(NSInteger)returnCode
contextInfo:(void*)contextInfo { contextInfo:(void*)contextInfo {
callback_.Run(returnCode); callback_.Run(returnCode, alert.suppressionButton.state == NSOnState);
[alert_ release]; [alert_ release];
[self release]; [self release];
@ -60,6 +60,8 @@ NSAlert* CreateNSAlert(NativeWindow* parent_window,
const std::string& title, const std::string& title,
const std::string& message, const std::string& message,
const std::string& detail, const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon) { const gfx::ImageSkia& icon) {
// Ignore the title; it's the window title on other platforms and ignorable. // Ignore the title; it's the window title on other platforms and ignorable.
NSAlert* alert = [[NSAlert alloc] init]; NSAlert* alert = [[NSAlert alloc] init];
@ -95,6 +97,12 @@ NSAlert* CreateNSAlert(NativeWindow* parent_window,
[[ns_buttons objectAtIndex:default_id] setKeyEquivalent:@"\r"]; [[ns_buttons objectAtIndex:default_id] setKeyEquivalent:@"\r"];
} }
if (!checkbox_label.empty()) {
alert.showsSuppressionButton = YES;
alert.suppressionButton.title = base::SysUTF8ToNSString(checkbox_label);
alert.suppressionButton.state = checkbox_checked ? NSOnState : NSOffState;
}
if (!icon.isNull()) { if (!icon.isNull()) {
NSImage* image = skia::SkBitmapToNSImageWithColorSpace( NSImage* image = skia::SkBitmapToNSImageWithColorSpace(
*icon.bitmap(), base::mac::GetGenericRGBColorSpace()); *icon.bitmap(), base::mac::GetGenericRGBColorSpace());
@ -104,7 +112,7 @@ NSAlert* CreateNSAlert(NativeWindow* parent_window,
return alert; return alert;
} }
void SetReturnCode(int* ret_code, int result) { void SetReturnCode(int* ret_code, int result, bool checkbox_checked) {
*ret_code = result; *ret_code = result;
} }
@ -120,9 +128,8 @@ int ShowMessageBox(NativeWindow* parent_window,
const std::string& message, const std::string& message,
const std::string& detail, const std::string& detail,
const gfx::ImageSkia& icon) { const gfx::ImageSkia& icon) {
NSAlert* alert = CreateNSAlert( NSAlert* alert = CreateNSAlert(parent_window, type, buttons, default_id,
parent_window, type, buttons, default_id, title, message, title, message, detail, "", false, icon);
detail, icon);
// Use runModal for synchronous alert without parent, since we don't have a // Use runModal for synchronous alert without parent, since we don't have a
// window to wait for. // window to wait for.
@ -154,11 +161,13 @@ void ShowMessageBox(NativeWindow* parent_window,
const std::string& title, const std::string& title,
const std::string& message, const std::string& message,
const std::string& detail, const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon, const gfx::ImageSkia& icon,
const MessageBoxCallback& callback) { const MessageBoxCallback& callback) {
NSAlert* alert = CreateNSAlert( NSAlert* alert =
parent_window, type, buttons, default_id, title, message, CreateNSAlert(parent_window, type, buttons, default_id, title, message,
detail, icon); detail, checkbox_label, checkbox_checked, icon);
ModalDelegate* delegate = [[ModalDelegate alloc] initWithCallback:callback ModalDelegate* delegate = [[ModalDelegate alloc] initWithCallback:callback
andAlert:alert andAlert:alert
callEndModal:false]; callEndModal:false];

View file

@ -72,7 +72,7 @@ void MapToCommonID(const std::vector<base::string16>& buttons,
} }
} }
int ShowMessageBoxUTF16(HWND parent, int ShowTaskDialogUTF16(NativeWindow* parent,
MessageBoxType type, MessageBoxType type,
const std::vector<base::string16>& buttons, const std::vector<base::string16>& buttons,
int default_id, int default_id,
@ -81,6 +81,8 @@ int ShowMessageBoxUTF16(HWND parent,
const base::string16& title, const base::string16& title,
const base::string16& message, const base::string16& message,
const base::string16& detail, const base::string16& detail,
const base::string16& checkbox_label,
bool* checkbox_checked,
const gfx::ImageSkia& icon) { const gfx::ImageSkia& icon) {
TASKDIALOG_FLAGS flags = TASKDIALOG_FLAGS flags =
TDF_SIZE_TO_CONTENT | // Show all content. TDF_SIZE_TO_CONTENT | // Show all content.
@ -88,10 +90,14 @@ int ShowMessageBoxUTF16(HWND parent,
TASKDIALOGCONFIG config = { 0 }; TASKDIALOGCONFIG config = { 0 };
config.cbSize = sizeof(config); config.cbSize = sizeof(config);
config.hwndParent = parent;
config.hInstance = GetModuleHandle(NULL); config.hInstance = GetModuleHandle(NULL);
config.dwFlags = flags; config.dwFlags = flags;
if (parent) {
config.hwndParent =
static_cast<atom::NativeWindowViews*>(parent)->GetAcceleratedWidget();
}
if (default_id > 0) if (default_id > 0)
config.nDefaultButton = kIDStart + default_id; config.nDefaultButton = kIDStart + default_id;
@ -132,6 +138,14 @@ int ShowMessageBoxUTF16(HWND parent,
config.pszContent = detail.c_str(); config.pszContent = detail.c_str();
} }
if (!checkbox_label.empty()) {
config.pszVerificationText = checkbox_label.c_str();
if (checkbox_checked && *checkbox_checked) {
config.dwFlags |= TDF_VERIFICATION_FLAG_CHECKED;
}
}
// Iterate through the buttons, put common buttons in dwCommonButtons // Iterate through the buttons, put common buttons in dwCommonButtons
// and custom buttons in pButtons. // and custom buttons in pButtons.
std::map<int, int> id_map; std::map<int, int> id_map;
@ -151,7 +165,12 @@ int ShowMessageBoxUTF16(HWND parent,
} }
int id = 0; int id = 0;
TaskDialogIndirect(&config, &id, NULL, NULL); BOOL verificationFlagChecked = FALSE;
TaskDialogIndirect(&config, &id, nullptr, &verificationFlagChecked);
if (checkbox_checked) {
*checkbox_checked = verificationFlagChecked;
}
if (id_map.find(id) != id_map.end()) // common button. if (id_map.find(id) != id_map.end()) // common button.
return id_map[id]; return id_map[id];
else if (id >= kIDStart) // custom button. else if (id >= kIDStart) // custom button.
@ -160,6 +179,29 @@ int ShowMessageBoxUTF16(HWND parent,
return cancel_id; return cancel_id;
} }
int ShowTaskDialogUTF8(NativeWindow* parent,
MessageBoxType type,
const std::vector<std::string>& buttons,
int default_id,
int cancel_id,
int options,
const std::string& title,
const std::string& message,
const std::string& detail,
const std::string& checkbox_label,
bool* checkbox_checked,
const gfx::ImageSkia& icon) {
std::vector<base::string16> utf16_buttons;
for (const auto& button : buttons)
utf16_buttons.push_back(base::UTF8ToUTF16(button));
return ShowTaskDialogUTF16(
parent, type, utf16_buttons, default_id, cancel_id, options,
base::UTF8ToUTF16(title), base::UTF8ToUTF16(message),
base::UTF8ToUTF16(detail), base::UTF8ToUTF16(checkbox_label),
checkbox_checked, icon);
}
void RunMessageBoxInNewThread(base::Thread* thread, void RunMessageBoxInNewThread(base::Thread* thread,
NativeWindow* parent, NativeWindow* parent,
MessageBoxType type, MessageBoxType type,
@ -170,12 +212,16 @@ void RunMessageBoxInNewThread(base::Thread* thread,
const std::string& title, const std::string& title,
const std::string& message, const std::string& message,
const std::string& detail, const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon, const gfx::ImageSkia& icon,
const MessageBoxCallback& callback) { const MessageBoxCallback& callback) {
int result = ShowMessageBox(parent, type, buttons, default_id, int result = ShowTaskDialogUTF8(parent, type, buttons, default_id, cancel_id,
cancel_id, options, title, message, detail, icon); options, title, message, detail,
checkbox_label, &checkbox_checked, icon);
content::BrowserThread::PostTask( content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE, base::Bind(callback, result)); content::BrowserThread::UI, FROM_HERE,
base::Bind(callback, result, checkbox_checked));
content::BrowserThread::DeleteSoon( content::BrowserThread::DeleteSoon(
content::BrowserThread::UI, FROM_HERE, thread); content::BrowserThread::UI, FROM_HERE, thread);
} }
@ -192,25 +238,9 @@ int ShowMessageBox(NativeWindow* parent,
const std::string& message, const std::string& message,
const std::string& detail, const std::string& detail,
const gfx::ImageSkia& icon) { const gfx::ImageSkia& icon) {
std::vector<base::string16> utf16_buttons;
for (const auto& button : buttons)
utf16_buttons.push_back(base::UTF8ToUTF16(button));
HWND hwnd_parent = parent ?
static_cast<atom::NativeWindowViews*>(parent)->GetAcceleratedWidget() :
NULL;
atom::UnresponsiveSuppressor suppressor; atom::UnresponsiveSuppressor suppressor;
return ShowMessageBoxUTF16(hwnd_parent, return ShowTaskDialogUTF8(parent, type, buttons, default_id, cancel_id,
type, options, title, message, detail, "", nullptr, icon);
utf16_buttons,
default_id,
cancel_id,
options,
base::UTF8ToUTF16(title),
base::UTF8ToUTF16(message),
base::UTF8ToUTF16(detail),
icon);
} }
void ShowMessageBox(NativeWindow* parent, void ShowMessageBox(NativeWindow* parent,
@ -222,13 +252,15 @@ void ShowMessageBox(NativeWindow* parent,
const std::string& title, const std::string& title,
const std::string& message, const std::string& message,
const std::string& detail, const std::string& detail,
const std::string& checkbox_label,
bool checkbox_checked,
const gfx::ImageSkia& icon, const gfx::ImageSkia& icon,
const MessageBoxCallback& callback) { const MessageBoxCallback& callback) {
std::unique_ptr<base::Thread> thread( std::unique_ptr<base::Thread> thread(
new base::Thread(ATOM_PRODUCT_NAME "MessageBoxThread")); new base::Thread(ATOM_PRODUCT_NAME "MessageBoxThread"));
thread->init_com_with_mta(false); thread->init_com_with_mta(false);
if (!thread->Start()) { if (!thread->Start()) {
callback.Run(cancel_id); callback.Run(cancel_id, checkbox_checked);
return; return;
} }
@ -237,13 +269,14 @@ void ShowMessageBox(NativeWindow* parent,
FROM_HERE, FROM_HERE,
base::Bind(&RunMessageBoxInNewThread, base::Unretained(unretained), base::Bind(&RunMessageBoxInNewThread, base::Unretained(unretained),
parent, type, buttons, default_id, cancel_id, options, title, parent, type, buttons, default_id, cancel_id, options, title,
message, detail, icon, callback)); message, detail, checkbox_label, checkbox_checked, icon,
callback));
} }
void ShowErrorBox(const base::string16& title, const base::string16& content) { void ShowErrorBox(const base::string16& title, const base::string16& content) {
atom::UnresponsiveSuppressor suppressor; atom::UnresponsiveSuppressor suppressor;
ShowMessageBoxUTF16(NULL, MESSAGE_BOX_TYPE_ERROR, {}, -1, 0, 0, L"Error", ShowTaskDialogUTF16(nullptr, MESSAGE_BOX_TYPE_ERROR, {}, -1, 0, 0, L"Error",
title, content, gfx::ImageSkia()); title, content, L"", nullptr, gfx::ImageSkia());
} }
} // namespace atom } // namespace atom

View file

@ -122,6 +122,11 @@ will be passed via `callback(filename)`
* `title` String (optional) - Title of the message box, some platforms will not show it. * `title` String (optional) - Title of the message box, some platforms will not show it.
* `message` String - Content of the message box. * `message` String - Content of the message box.
* `detail` String (optional) - Extra information of the message. * `detail` String (optional) - Extra information of the message.
* `checkboxLabel` String (optional) - If provided, the message box will
include a checkbox with the given label. The checkbox state can be
inspected only when using `callback`.
* `checkboxChecked` Boolean (optional) - Initial checked state of the
checkbox. `false` by default.
* `icon` [NativeImage](native-image.md) (optional) * `icon` [NativeImage](native-image.md) (optional)
* `cancelId` Integer (optional) - The value will be returned when user cancels the dialog * `cancelId` Integer (optional) - The value will be returned when user cancels the dialog
instead of clicking the buttons of the dialog. By default it is the index instead of clicking the buttons of the dialog. By default it is the index
@ -135,6 +140,8 @@ will be passed via `callback(filename)`
set `noLink` to `true`. set `noLink` to `true`.
* `callback` Function (optional) * `callback` Function (optional)
* `response` Number - The index of the button that was clicked * `response` Number - The index of the button that was clicked
* `checkboxChecked` Boolean - The checked state of the checkbox if
`checkboxLabel` was set. Otherwise `false`.
Returns `Integer`, the index of the clicked button, if a callback is provided Returns `Integer`, the index of the clicked button, if a callback is provided
it returns undefined. it returns undefined.

View file

@ -178,7 +178,10 @@ module.exports = {
} }
} }
let {buttons, cancelId, defaultId, detail, icon, message, title, type} = options let {
buttons, cancelId, checkboxLabel, checkboxChecked, defaultId, detail,
icon, message, title, type
} = options
if (type == null) { if (type == null) {
type = 'none' type = 'none'
@ -217,6 +220,14 @@ module.exports = {
throw new TypeError('Detail must be a string') throw new TypeError('Detail must be a string')
} }
checkboxChecked = !!checkboxChecked
if (checkboxLabel == null) {
checkboxLabel = ''
} else if (typeof checkboxLabel !== 'string') {
throw new TypeError('checkboxLabel must be a string')
}
if (icon == null) { if (icon == null) {
icon = null icon = null
} }
@ -239,8 +250,8 @@ module.exports = {
const flags = options.noLink ? messageBoxOptions.noLink : 0 const flags = options.noLink ? messageBoxOptions.noLink : 0
return binding.showMessageBox(messageBoxType, buttons, defaultId, cancelId, return binding.showMessageBox(messageBoxType, buttons, defaultId, cancelId,
flags, title, message, detail, icon, window, flags, title, message, detail, checkboxLabel,
callback) checkboxChecked, icon, window, callback)
}, },
showErrorBox: function (...args) { showErrorBox: function (...args) {

View file

@ -59,6 +59,10 @@ describe('dialog module', () => {
assert.throws(() => { assert.throws(() => {
dialog.showMessageBox({detail: 3.14}) dialog.showMessageBox({detail: 3.14})
}, /Detail must be a string/) }, /Detail must be a string/)
assert.throws(() => {
dialog.showMessageBox({checkboxLabel: false})
}, /checkboxLabel must be a string/)
}) })
}) })