Skip to content

Commit 50f9580

Browse files
committed
Move prepareCodeTour to separate file
1 parent 7f3e960 commit 50f9580

File tree

5 files changed

+168
-163
lines changed

5 files changed

+168
-163
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { AppCommandManager } from "./common/commands";
2+
import { Uri, workspace } from "vscode";
3+
import { join } from "path";
4+
import { pathExists } from "fs-extra";
5+
import { isCodespacesTemplate } from "./config";
6+
import { showBinaryChoiceDialog } from "./common/vscode/dialog";
7+
import { extLogger } from "./common";
8+
9+
/**
10+
* Check if the current workspace is the CodeTour and open the workspace folder.
11+
* Without this, we can't run the code tour correctly.
12+
**/
13+
export async function prepareCodeTour(
14+
commandManager: AppCommandManager,
15+
): Promise<void> {
16+
if (workspace.workspaceFolders?.length) {
17+
const currentFolder = workspace.workspaceFolders[0].uri.fsPath;
18+
19+
const tutorialWorkspacePath = join(
20+
currentFolder,
21+
"tutorial.code-workspace",
22+
);
23+
const toursFolderPath = join(currentFolder, ".tours");
24+
25+
/** We're opening the tutorial workspace, if we detect it.
26+
* This will only happen if the following three conditions are met:
27+
* - the .tours folder exists
28+
* - the tutorial.code-workspace file exists
29+
* - the CODESPACES_TEMPLATE setting doesn't exist (it's only set if the user has already opened
30+
* the tutorial workspace so it's a good indicator that the user is in the folder but has ignored
31+
* the prompt to open the workspace)
32+
*/
33+
if (
34+
(await pathExists(tutorialWorkspacePath)) &&
35+
(await pathExists(toursFolderPath)) &&
36+
!isCodespacesTemplate()
37+
) {
38+
const answer = await showBinaryChoiceDialog(
39+
"We've detected you're in the CodeQL Tour repo. We will need to open the workspace file to continue. Reload?",
40+
);
41+
42+
if (!answer) {
43+
return;
44+
}
45+
46+
const tutorialWorkspaceUri = Uri.file(tutorialWorkspacePath);
47+
48+
void extLogger.log(
49+
`In prepareCodeTour() method, going to open the tutorial workspace file: ${tutorialWorkspacePath}`,
50+
);
51+
52+
await commandManager.execute("vscode.openFolder", tutorialWorkspaceUri);
53+
}
54+
}
55+
}

extensions/ql-vscode/src/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ import {
6262
showAndLogWarningMessage,
6363
tmpDir,
6464
tmpDirDisposal,
65-
prepareCodeTour,
6665
} from "./helpers";
66+
import { prepareCodeTour } from "./code-tour";
6767
import {
6868
showBinaryChoiceDialog,
6969
showInformationMessageWithAction,

extensions/ql-vscode/src/helpers.ts

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1-
import { ensureDirSync, pathExists, ensureDir, writeFile } from "fs-extra";
1+
import { ensureDirSync, ensureDir, writeFile } from "fs-extra";
22
import { join } from "path";
33
import { dirSync } from "tmp-promise";
4-
import { Uri, window as Window, workspace } from "vscode";
4+
import { Uri, window as Window } from "vscode";
55
import { CodeQLCliServer } from "./codeql-cli/cli";
66
import { UserCancellationException } from "./common/vscode/progress";
77
import { extLogger, OutputChannelLogger } from "./common";
88
import { QueryMetadata } from "./pure/interface-types";
99
import { telemetryListener } from "./telemetry";
1010
import { RedactableError } from "./pure/errors";
1111
import { isQueryLanguage, QueryLanguage } from "./common/query-language";
12-
import { isCodespacesTemplate } from "./config";
13-
import { AppCommandManager } from "./common/commands";
1412
import { getOnDiskWorkspaceFolders } from "./common/vscode/workspace-folders";
15-
import { showBinaryChoiceDialog } from "./common/vscode/dialog";
1613

1714
// Shared temporary folder for the extension.
1815
export const tmpDir = dirSync({
@@ -140,53 +137,6 @@ async function internalShowAndLog(
140137
return result;
141138
}
142139

143-
/** Check if the current workspace is the CodeTour and open the workspace folder.
144-
* Without this, we can't run the code tour correctly.
145-
**/
146-
export async function prepareCodeTour(
147-
commandManager: AppCommandManager,
148-
): Promise<void> {
149-
if (workspace.workspaceFolders?.length) {
150-
const currentFolder = workspace.workspaceFolders[0].uri.fsPath;
151-
152-
const tutorialWorkspacePath = join(
153-
currentFolder,
154-
"tutorial.code-workspace",
155-
);
156-
const toursFolderPath = join(currentFolder, ".tours");
157-
158-
/** We're opening the tutorial workspace, if we detect it.
159-
* This will only happen if the following three conditions are met:
160-
* - the .tours folder exists
161-
* - the tutorial.code-workspace file exists
162-
* - the CODESPACES_TEMPLATE setting doesn't exist (it's only set if the user has already opened
163-
* the tutorial workspace so it's a good indicator that the user is in the folder but has ignored
164-
* the prompt to open the workspace)
165-
*/
166-
if (
167-
(await pathExists(tutorialWorkspacePath)) &&
168-
(await pathExists(toursFolderPath)) &&
169-
!isCodespacesTemplate()
170-
) {
171-
const answer = await showBinaryChoiceDialog(
172-
"We've detected you're in the CodeQL Tour repo. We will need to open the workspace file to continue. Reload?",
173-
);
174-
175-
if (!answer) {
176-
return;
177-
}
178-
179-
const tutorialWorkspaceUri = Uri.file(tutorialWorkspacePath);
180-
181-
void extLogger.log(
182-
`In prepareCodeTour() method, going to open the tutorial workspace file: ${tutorialWorkspacePath}`,
183-
);
184-
185-
await commandManager.execute("vscode.openFolder", tutorialWorkspaceUri);
186-
}
187-
}
188-
}
189-
190140
/**
191141
* Finds the language that a query targets.
192142
* If it can't be autodetected, prompt the user to specify the language manually.
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import { Uri, window, workspace, WorkspaceFolder } from "vscode";
2+
import * as tmp from "tmp";
3+
import { join } from "path";
4+
import { mkdir, writeFile } from "fs-extra";
5+
6+
import { prepareCodeTour } from "../../../src/code-tour";
7+
import { Setting } from "../../../src/config";
8+
import { createMockCommandManager } from "../../__mocks__/commandsMock";
9+
10+
describe("prepareCodeTour", () => {
11+
let dir: tmp.DirResult;
12+
let showInformationMessageSpy: jest.SpiedFunction<
13+
typeof window.showInformationMessage
14+
>;
15+
16+
beforeEach(() => {
17+
dir = tmp.dirSync();
18+
19+
const mockWorkspaceFolders = [
20+
{
21+
uri: Uri.file(dir.name),
22+
name: "test",
23+
index: 0,
24+
},
25+
] as WorkspaceFolder[];
26+
27+
jest
28+
.spyOn(workspace, "workspaceFolders", "get")
29+
.mockReturnValue(mockWorkspaceFolders);
30+
31+
showInformationMessageSpy = jest
32+
.spyOn(window, "showInformationMessage")
33+
.mockResolvedValue({ title: "Yes" });
34+
});
35+
36+
afterEach(() => {
37+
dir.removeCallback();
38+
});
39+
40+
describe("if we're in the tour repo", () => {
41+
describe("if the workspace is not already open", () => {
42+
it("should open the tutorial workspace", async () => {
43+
// set up directory to have a 'tutorial.code-workspace' file
44+
const tutorialWorkspacePath = join(dir.name, "tutorial.code-workspace");
45+
await writeFile(tutorialWorkspacePath, "{}");
46+
47+
// set up a .tours directory to indicate we're in the tour codespace
48+
const tourDirPath = join(dir.name, ".tours");
49+
await mkdir(tourDirPath);
50+
51+
// spy that we open the workspace file by calling the 'vscode.openFolder' command
52+
const executeCommand = jest.fn();
53+
await prepareCodeTour(createMockCommandManager({ executeCommand }));
54+
55+
expect(showInformationMessageSpy).toHaveBeenCalled();
56+
expect(executeCommand).toHaveBeenCalledWith(
57+
"vscode.openFolder",
58+
expect.objectContaining({
59+
path: expect.stringMatching(/tutorial.code-workspace$/),
60+
}),
61+
);
62+
});
63+
});
64+
65+
describe("if the workspace is already open", () => {
66+
it("should not open the tutorial workspace", async () => {
67+
// Set isCodespacesTemplate to true to indicate the workspace has already been opened
68+
jest.spyOn(Setting.prototype, "getValue").mockReturnValue(true);
69+
70+
// set up directory to have a 'tutorial.code-workspace' file
71+
const tutorialWorkspacePath = join(dir.name, "tutorial.code-workspace");
72+
await writeFile(tutorialWorkspacePath, "{}");
73+
74+
// set up a .tours directory to indicate we're in the tour codespace
75+
const tourDirPath = join(dir.name, ".tours");
76+
await mkdir(tourDirPath);
77+
78+
// spy that we open the workspace file by calling the 'vscode.openFolder' command
79+
const executeCommand = jest.fn();
80+
await prepareCodeTour(createMockCommandManager({ executeCommand }));
81+
82+
expect(executeCommand).not.toHaveBeenCalled();
83+
});
84+
});
85+
});
86+
87+
describe("if we're in a different tour repo", () => {
88+
it("should not open the tutorial workspace", async () => {
89+
// set up a .tours directory
90+
const tourDirPath = join(dir.name, ".tours");
91+
await mkdir(tourDirPath);
92+
93+
// spy that we open the workspace file by calling the 'vscode.openFolder' command
94+
const executeCommand = jest.fn();
95+
await prepareCodeTour(createMockCommandManager({ executeCommand }));
96+
97+
expect(executeCommand).not.toHaveBeenCalled();
98+
});
99+
});
100+
101+
describe("if we're in a different repo with no tour", () => {
102+
it("should not open the tutorial workspace", async () => {
103+
// spy that we open the workspace file by calling the 'vscode.openFolder' command
104+
const executeCommand = jest.fn();
105+
await prepareCodeTour(createMockCommandManager({ executeCommand }));
106+
107+
expect(executeCommand).not.toHaveBeenCalled();
108+
});
109+
});
110+
});
Lines changed: 0 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,4 @@
1-
import { Uri, window, workspace, WorkspaceFolder } from "vscode";
2-
import * as tmp from "tmp";
3-
import { join } from "path";
4-
import { writeFile, mkdir } from "fs-extra";
5-
6-
import { prepareCodeTour } from "../../../src/helpers";
71
import { reportStreamProgress } from "../../../src/common/vscode/progress";
8-
import { Setting } from "../../../src/config";
9-
import { createMockCommandManager } from "../../__mocks__/commandsMock";
102

113
describe("helpers", () => {
124
it("should report stream progress", () => {
@@ -66,105 +58,3 @@ describe("helpers", () => {
6658
});
6759
});
6860
});
69-
70-
describe("prepareCodeTour", () => {
71-
let dir: tmp.DirResult;
72-
let showInformationMessageSpy: jest.SpiedFunction<
73-
typeof window.showInformationMessage
74-
>;
75-
76-
beforeEach(() => {
77-
dir = tmp.dirSync();
78-
79-
const mockWorkspaceFolders = [
80-
{
81-
uri: Uri.file(dir.name),
82-
name: "test",
83-
index: 0,
84-
},
85-
] as WorkspaceFolder[];
86-
87-
jest
88-
.spyOn(workspace, "workspaceFolders", "get")
89-
.mockReturnValue(mockWorkspaceFolders);
90-
91-
showInformationMessageSpy = jest
92-
.spyOn(window, "showInformationMessage")
93-
.mockResolvedValue({ title: "Yes" });
94-
});
95-
96-
afterEach(() => {
97-
dir.removeCallback();
98-
});
99-
100-
describe("if we're in the tour repo", () => {
101-
describe("if the workspace is not already open", () => {
102-
it("should open the tutorial workspace", async () => {
103-
// set up directory to have a 'tutorial.code-workspace' file
104-
const tutorialWorkspacePath = join(dir.name, "tutorial.code-workspace");
105-
await writeFile(tutorialWorkspacePath, "{}");
106-
107-
// set up a .tours directory to indicate we're in the tour codespace
108-
const tourDirPath = join(dir.name, ".tours");
109-
await mkdir(tourDirPath);
110-
111-
// spy that we open the workspace file by calling the 'vscode.openFolder' command
112-
const executeCommand = jest.fn();
113-
await prepareCodeTour(createMockCommandManager({ executeCommand }));
114-
115-
expect(showInformationMessageSpy).toHaveBeenCalled();
116-
expect(executeCommand).toHaveBeenCalledWith(
117-
"vscode.openFolder",
118-
expect.objectContaining({
119-
path: expect.stringMatching(/tutorial.code-workspace$/),
120-
}),
121-
);
122-
});
123-
});
124-
125-
describe("if the workspace is already open", () => {
126-
it("should not open the tutorial workspace", async () => {
127-
// Set isCodespacesTemplate to true to indicate the workspace has already been opened
128-
jest.spyOn(Setting.prototype, "getValue").mockReturnValue(true);
129-
130-
// set up directory to have a 'tutorial.code-workspace' file
131-
const tutorialWorkspacePath = join(dir.name, "tutorial.code-workspace");
132-
await writeFile(tutorialWorkspacePath, "{}");
133-
134-
// set up a .tours directory to indicate we're in the tour codespace
135-
const tourDirPath = join(dir.name, ".tours");
136-
await mkdir(tourDirPath);
137-
138-
// spy that we open the workspace file by calling the 'vscode.openFolder' command
139-
const executeCommand = jest.fn();
140-
await prepareCodeTour(createMockCommandManager({ executeCommand }));
141-
142-
expect(executeCommand).not.toHaveBeenCalled();
143-
});
144-
});
145-
});
146-
147-
describe("if we're in a different tour repo", () => {
148-
it("should not open the tutorial workspace", async () => {
149-
// set up a .tours directory
150-
const tourDirPath = join(dir.name, ".tours");
151-
await mkdir(tourDirPath);
152-
153-
// spy that we open the workspace file by calling the 'vscode.openFolder' command
154-
const executeCommand = jest.fn();
155-
await prepareCodeTour(createMockCommandManager({ executeCommand }));
156-
157-
expect(executeCommand).not.toHaveBeenCalled();
158-
});
159-
});
160-
161-
describe("if we're in a different repo with no tour", () => {
162-
it("should not open the tutorial workspace", async () => {
163-
// spy that we open the workspace file by calling the 'vscode.openFolder' command
164-
const executeCommand = jest.fn();
165-
await prepareCodeTour(createMockCommandManager({ executeCommand }));
166-
167-
expect(executeCommand).not.toHaveBeenCalled();
168-
});
169-
});
170-
});

0 commit comments

Comments
 (0)