Skip to content

Commit 8392284

Browse files
committed
Introduce new dialog box with "No, never ask me again" option
1 parent ae320d0 commit 8392284

2 files changed

Lines changed: 88 additions & 0 deletions

File tree

extensions/ql-vscode/src/helpers.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,46 @@ export function isWorkspaceFolderOnDisk(
256256
return workspaceFolder.uri.scheme === "file";
257257
}
258258

259+
/**
260+
* Opens a modal dialog for the user to make a choice between yes/no/never be asked again.
261+
*
262+
* @param message The message to show.
263+
* @param modal If true (the default), show a modal dialog box, otherwise dialog is non-modal and can
264+
* be closed even if the user does not make a choice.
265+
* @param yesTitle The text in the box indicating the affirmative choice.
266+
* @param noTitle The text in the box indicating the negative choice.
267+
* @param neverTitle The text in the box indicating the opt out choice.
268+
*
269+
* @return
270+
* `Yes` if the user clicks 'Yes',
271+
* `No` if the user clicks 'No' or cancels the dialog,
272+
* `No, and never ask me again` if the user clicks 'No, and never ask me again',
273+
* `undefined` if the dialog is closed without the user making a choice.
274+
*/
275+
export async function showNeverAskAgainDialog(
276+
message: string,
277+
modal = true,
278+
yesTitle = "Yes",
279+
noTitle = "No",
280+
neverAskAgainTitle = "No, and never ask me again",
281+
): Promise<string | undefined> {
282+
const yesItem = { title: yesTitle, isCloseAffordance: true };
283+
const noItem = { title: noTitle, isCloseAffordance: false };
284+
const neverAskAgainItem = {
285+
title: neverAskAgainTitle,
286+
isCloseAffordance: false,
287+
};
288+
const chosenItem = await Window.showInformationMessage(
289+
message,
290+
{ modal },
291+
yesItem,
292+
noItem,
293+
neverAskAgainItem,
294+
);
295+
296+
return chosenItem?.title;
297+
}
298+
259299
/** Gets all active workspace folders that are on the filesystem. */
260300
export function getOnDiskWorkspaceFoldersObjects() {
261301
const workspaceFolders = workspace.workspaceFolders ?? [];

extensions/ql-vscode/test/vscode-tests/no-workspace/helpers.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
showBinaryChoiceDialog,
3737
showBinaryChoiceWithUrlDialog,
3838
showInformationMessageWithAction,
39+
showNeverAskAgainDialog,
3940
walkDirectory,
4041
} from "../../../src/helpers";
4142
import { reportStreamProgress } from "../../../src/progress";
@@ -528,6 +529,53 @@ describe("helpers", () => {
528529
expect(showInformationMessageSpy).toHaveBeenCalledTimes(5);
529530
});
530531
});
532+
533+
describe("showNeverAskAgainDialog", () => {
534+
let showInformationMessageSpy: jest.SpiedFunction<
535+
typeof window.showInformationMessage
536+
>;
537+
538+
beforeEach(() => {
539+
showInformationMessageSpy = jest
540+
.spyOn(window, "showInformationMessage")
541+
.mockResolvedValue(undefined);
542+
});
543+
544+
const resolveArg =
545+
(index: number) =>
546+
(...args: any[]) =>
547+
Promise.resolve(args[index]);
548+
549+
const title =
550+
"We've noticed you don't have a CodeQL pack available to analyze this database. Can we set up a query pack for you?";
551+
552+
it("should show a binary choice dialog and return `Yes`", async () => {
553+
// pretend user chooses 'Yes'
554+
const yesItem = resolveArg(2);
555+
showInformationMessageSpy.mockImplementationOnce(yesItem);
556+
557+
const answer = await showNeverAskAgainDialog(title);
558+
expect(answer).toBe("Yes");
559+
});
560+
561+
it("should show a binary choice dialog and return `No`", async () => {
562+
// pretend user chooses 'No'
563+
const noItem = resolveArg(3);
564+
showInformationMessageSpy.mockImplementationOnce(noItem);
565+
566+
const answer = await showNeverAskAgainDialog(title);
567+
expect(answer).toBe("No");
568+
});
569+
570+
it("should show a binary choice dialog and return `No, and never ask me again`", async () => {
571+
// pretend user chooses 'No, and never ask me again'
572+
const neverAskAgainItem = resolveArg(4);
573+
showInformationMessageSpy.mockImplementationOnce(neverAskAgainItem);
574+
575+
const answer = await showNeverAskAgainDialog(title);
576+
expect(answer).toBe("No, and never ask me again");
577+
});
578+
});
531579
});
532580

533581
describe("walkDirectory", () => {

0 commit comments

Comments
 (0)