diff --git a/extensions/ql-vscode/src/remote-queries/repository-selection.ts b/extensions/ql-vscode/src/remote-queries/repository-selection.ts index e2bac681fe6..cf0c5f488f9 100644 --- a/extensions/ql-vscode/src/remote-queries/repository-selection.ts +++ b/extensions/ql-vscode/src/remote-queries/repository-selection.ts @@ -52,6 +52,10 @@ export async function getRepositorySelection(): Promise { return { repositoryLists: [quickpick.repositoryList] }; } else if (quickpick?.useCustomRepo) { const customRepo = await getCustomRepo(); + if (customRepo === undefined) { + // The user cancelled, do nothing. + throw new UserCancellationException('No repositories selected', true); + } if (!customRepo || !REPO_REGEX.test(customRepo)) { throw new UserCancellationException('Invalid repository format. Please enter a valid repository in the format / (e.g. github/codeql)'); } @@ -59,6 +63,10 @@ export async function getRepositorySelection(): Promise { return { repositories: [customRepo] }; } else if (quickpick?.useAllReposOfOwner) { const owner = await getOwner(); + if (owner === undefined) { + // The user cancelled, do nothing. + throw new UserCancellationException('No repositories selected', true); + } if (!owner || !OWNER_REGEX.test(owner)) { throw new Error(`Invalid user or organization: ${owner}`); } @@ -197,6 +205,6 @@ async function getCustomRepo(): Promise { async function getOwner(): Promise { return await window.showInputBox({ title: 'Enter a GitHub user or organization', - ignoreFocusOut: true, + ignoreFocusOut: true }); } diff --git a/extensions/ql-vscode/src/vscode-tests/no-workspace/remote-queries/repository-selection.test.ts b/extensions/ql-vscode/src/vscode-tests/no-workspace/remote-queries/repository-selection.test.ts index d85fe904634..be136607eb1 100644 --- a/extensions/ql-vscode/src/vscode-tests/no-workspace/remote-queries/repository-selection.test.ts +++ b/extensions/ql-vscode/src/vscode-tests/no-workspace/remote-queries/repository-selection.test.ts @@ -100,7 +100,9 @@ describe('repository selection', async () => { ['top_100'] ); }); + }); + describe('custom owner', async () => { // Test the owner regex in various "good" cases const goodOwners = [ 'owner', @@ -146,6 +148,18 @@ describe('repository selection', async () => { await expect(mod.getRepositorySelection()).to.be.rejectedWith(Error, `Invalid user or organization: ${owner}`); }); }); + + it('should be ok for the user to change their mind', async () => { + quickPickSpy.resolves( + { useAllReposOfOwner: true } + ); + getRemoteRepositoryListsSpy.returns({}); + + // The user pressed escape to cancel the operation + showInputBoxSpy.resolves(undefined); + + await expect(mod.getRepositorySelection()).to.be.rejectedWith(UserCancellationException, 'No repositories selected'); + }); }); describe('custom repo', async () => { @@ -196,6 +210,18 @@ describe('repository selection', async () => { await expect(mod.getRepositorySelection()).to.be.rejectedWith(UserCancellationException, 'Invalid repository format'); }); }); + + it('should be ok for the user to change their mind', async () => { + quickPickSpy.resolves( + { useCustomRepo: true } + ); + getRemoteRepositoryListsSpy.returns({}); + + // The user pressed escape to cancel the operation + showInputBoxSpy.resolves(undefined); + + await expect(mod.getRepositorySelection()).to.be.rejectedWith(UserCancellationException, 'No repositories selected'); + }); }); describe('external repository lists file', async () => {