Skip to content

Commit 05114e4

Browse files
authored
feat(vscode): improved path resolution algorithm from command palette (#831)
1 parent ff7a5bb commit 05114e4

File tree

6 files changed

+287
-17
lines changed

6 files changed

+287
-17
lines changed

extensions/vscode/src/commands/new-middleware.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
const cp = require("child_process");
22

33
import { Uri, window, OpenDialogOptions, ProgressOptions } from "vscode";
4-
import { nearestDartFrogProject, normalizeRoutePath } from "../utils";
4+
import {
5+
nearestDartFrogProject,
6+
normalizeRoutePath,
7+
resolveDartFrogProjectPathFromWorkspace,
8+
} from "../utils";
59

610
/**
711
* Command to create a new middleware.
@@ -24,26 +28,30 @@ import { nearestDartFrogProject, normalizeRoutePath } from "../utils";
2428
* @param {Uri | undefined} uri
2529
*/
2630
export const newMiddleware = async (uri: Uri | undefined): Promise<void> => {
27-
let selectedUri;
31+
let selectedPath;
2832
if (uri === undefined) {
29-
selectedUri = await promptForTargetDirectory();
30-
if (selectedUri === undefined) {
33+
selectedPath = resolveDartFrogProjectPathFromWorkspace();
34+
35+
if (selectedPath === undefined) {
36+
selectedPath = await promptForTargetDirectory();
37+
}
38+
if (selectedPath === undefined) {
3139
window.showErrorMessage("Please select a valid directory");
3240
return;
3341
}
3442
} else {
35-
selectedUri = uri.fsPath;
43+
selectedPath = uri.fsPath;
3644
}
3745

38-
const dartFrogProjectPath = nearestDartFrogProject(selectedUri);
46+
const dartFrogProjectPath = nearestDartFrogProject(selectedPath);
3947
if (dartFrogProjectPath === undefined) {
4048
window.showErrorMessage(
4149
"No Dart Frog project found in the selected directory"
4250
);
4351
return;
4452
}
4553

46-
const routePath = normalizeRoutePath(selectedUri, dartFrogProjectPath);
54+
const routePath = normalizeRoutePath(selectedPath, dartFrogProjectPath);
4755

4856
const options: ProgressOptions = {
4957
location: 15,

extensions/vscode/src/commands/new-route.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ import {
77
OpenDialogOptions,
88
ProgressOptions,
99
} from "vscode";
10-
import { nearestDartFrogProject, normalizeRoutePath } from "../utils";
10+
import {
11+
nearestDartFrogProject,
12+
normalizeRoutePath,
13+
resolveDartFrogProjectPathFromWorkspace,
14+
} from "../utils";
1115

1216
/**
1317
* Command to create a new route.
@@ -30,18 +34,22 @@ import { nearestDartFrogProject, normalizeRoutePath } from "../utils";
3034
* @param {Uri | undefined} uri
3135
*/
3236
export const newRoute = async (uri: Uri | undefined): Promise<void> => {
33-
let selectedUri;
37+
let selectedPath;
3438
if (uri === undefined) {
35-
selectedUri = await promptForTargetDirectory();
36-
if (selectedUri === undefined) {
39+
selectedPath = resolveDartFrogProjectPathFromWorkspace();
40+
41+
if (selectedPath === undefined) {
42+
selectedPath = await promptForTargetDirectory();
43+
}
44+
if (selectedPath === undefined) {
3745
window.showErrorMessage("Please select a valid directory");
3846
return;
3947
}
4048
} else {
41-
selectedUri = uri.fsPath;
49+
selectedPath = uri.fsPath;
4250
}
4351

44-
const dartFrogProjectPath = nearestDartFrogProject(selectedUri);
52+
const dartFrogProjectPath = nearestDartFrogProject(selectedPath);
4553
if (dartFrogProjectPath === undefined) {
4654
window.showErrorMessage(
4755
"No Dart Frog project found in the selected directory"
@@ -50,7 +58,7 @@ export const newRoute = async (uri: Uri | undefined): Promise<void> => {
5058
}
5159

5260
const normalizedRoutePath = normalizeRoutePath(
53-
selectedUri,
61+
selectedPath,
5462
dartFrogProjectPath
5563
);
5664

extensions/vscode/src/test/suite/commands/new-middleware.test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ suite("new-middleware command", () => {
2727
utilsStub = {
2828
nearestDartFrogProject: sinon.stub(),
2929
normalizeRoutePath: sinon.stub(),
30+
resolveDartFrogProjectPathFromWorkspace: sinon.stub(),
3031
};
3132

3233
utilsStub.nearestDartFrogProject
@@ -50,8 +51,9 @@ suite("new-middleware command", () => {
5051
});
5152

5253
suite("file open dialog", () => {
53-
test("is shown when Uri is undefined", async () => {
54+
test("is shown when Uri is undefined and fails to resolve a path from workspace", async () => {
5455
vscodeStub.window.showOpenDialog.returns(Promise.resolve(undefined));
56+
utilsStub.resolveDartFrogProjectPathFromWorkspace.returns(undefined);
5557

5658
await command.newMiddleware();
5759

@@ -63,6 +65,16 @@ suite("new-middleware command", () => {
6365
});
6466
});
6567

68+
test("is not shown when Uri is undefined but resolves a path from workspace", async () => {
69+
utilsStub.resolveDartFrogProjectPathFromWorkspace.returns(
70+
validUri.fsPath
71+
);
72+
73+
await command.newMiddleware();
74+
75+
sinon.assert.notCalled(vscodeStub.window.showOpenDialog);
76+
});
77+
6678
test("is not shown when Uri is defined", async () => {
6779
await command.newMiddleware(invalidUri);
6880

extensions/vscode/src/test/suite/commands/new-route.test.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ suite("new-route command", () => {
3030
utilsStub = {
3131
nearestDartFrogProject: sinon.stub(),
3232
normalizeRoutePath: sinon.stub(),
33+
resolveDartFrogProjectPathFromWorkspace: sinon.stub(),
3334
};
3435

3536
utilsStub.nearestDartFrogProject
@@ -123,9 +124,10 @@ suite("new-route command", () => {
123124
});
124125

125126
suite("file open dialog", () => {
126-
test("is shown when Uri is undefined", async () => {
127+
test("is shown when Uri is undefined and fails to resolve a path from workspace", async () => {
127128
vscodeStub.window.showInputBox.returns(validRouteName);
128129
vscodeStub.window.showOpenDialog.returns(Promise.resolve(undefined));
130+
utilsStub.resolveDartFrogProjectPathFromWorkspace.returns(undefined);
129131

130132
await command.newRoute();
131133

@@ -137,6 +139,17 @@ suite("new-route command", () => {
137139
});
138140
});
139141

142+
test("is not shown when Uri is undefined but resolves a path from workspace", async () => {
143+
utilsStub.resolveDartFrogProjectPathFromWorkspace.returns(
144+
validUri.fsPath
145+
);
146+
utilsStub.normalizeRoutePath.returns("/");
147+
148+
await command.newRoute();
149+
150+
sinon.assert.notCalled(vscodeStub.window.showOpenDialog);
151+
});
152+
140153
test("is not shown when Uri is defined", async () => {
141154
vscodeStub.window.showInputBox.returns(validRouteName);
142155

extensions/vscode/src/test/suite/utils/dart-frog-structure.test.ts

Lines changed: 174 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ suite("nearestDartFrogProject", () => {
144144
const routesPath1 = path.join(dartFrogPath1, "routes");
145145
const pubspecPath1 = path.join(dartFrogPath1, "pubspec.yaml");
146146

147-
const dartFrogPath2 = "/home/user/Developer/myserver";
147+
const dartFrogPath2 = "home/user/Developer/myserver";
148148
const routesPath2 = path.join(dartFrogPath2, "routes");
149149
const pubspecPath2 = path.join(dartFrogPath2, "pubspec.yaml");
150150

@@ -276,6 +276,179 @@ suite("isDartFrogProject", () => {
276276
});
277277
});
278278

279+
suite("resolveDartFrogProjectPathFromWorkspace", () => {
280+
let vscodeStub: any;
281+
let resolveDartFrogProjectPathFromWorkspace: any;
282+
283+
beforeEach(() => {
284+
vscodeStub = {
285+
workspace: {
286+
workspaceFolders: sinon.stub(),
287+
},
288+
window: {
289+
activeTextEditor: sinon.stub(),
290+
},
291+
};
292+
293+
resolveDartFrogProjectPathFromWorkspace = proxyquire(
294+
"../../../utils/dart-frog-structure",
295+
{
296+
vscode: vscodeStub,
297+
}
298+
).resolveDartFrogProjectPathFromWorkspace;
299+
});
300+
301+
afterEach(() => {
302+
sinon.restore();
303+
});
304+
305+
test("returns the file path of the active route Dart file", () => {
306+
vscodeStub.window.activeTextEditor = {
307+
document: {
308+
uri: {
309+
fsPath: `home/user/routes/index.dart`,
310+
},
311+
},
312+
};
313+
314+
const result = resolveDartFrogProjectPathFromWorkspace(
315+
sinon.stub().returns("home/user/")
316+
);
317+
318+
sinon.assert.match(result, "home/user/routes/index.dart");
319+
});
320+
321+
suite("returns the directory path of the active workspace folder", () => {
322+
test("when there is no active text editor", () => {
323+
vscodeStub.window.activeTextEditor = undefined;
324+
vscodeStub.workspace.workspaceFolders = [
325+
{
326+
uri: {
327+
fsPath: `home/user/routes/animals`,
328+
},
329+
},
330+
];
331+
332+
const result = resolveDartFrogProjectPathFromWorkspace(
333+
sinon.stub().returns("home/user/")
334+
);
335+
336+
sinon.assert.match(result, "home/user/routes/animals");
337+
});
338+
339+
test("when the active text editor is not a route", () => {
340+
vscodeStub.window.activeTextEditor = {
341+
document: {
342+
uri: {
343+
fsPath: `home/user/pubspec.yaml`,
344+
},
345+
},
346+
};
347+
vscodeStub.workspace.workspaceFolders = [
348+
{
349+
uri: {
350+
fsPath: `home/user/`,
351+
},
352+
},
353+
];
354+
355+
const result = resolveDartFrogProjectPathFromWorkspace(
356+
sinon.stub().returns("home/user/")
357+
);
358+
359+
sinon.assert.match(result, "home/user/");
360+
});
361+
362+
test("when the active text editor is not a Dart route", () => {
363+
vscodeStub.window.activeTextEditor = {
364+
document: {
365+
uri: {
366+
fsPath: `home/user/routes/hello.yaml`,
367+
},
368+
},
369+
};
370+
vscodeStub.workspace.workspaceFolders = [
371+
{
372+
uri: {
373+
fsPath: `home/user/`,
374+
},
375+
},
376+
];
377+
378+
const result = resolveDartFrogProjectPathFromWorkspace(
379+
sinon.stub().returns("home/user/")
380+
);
381+
382+
sinon.assert.match(result, "home/user/");
383+
});
384+
385+
test("when the active text editor is not a Dart Frog project", () => {
386+
vscodeStub.window.activeTextEditor = {
387+
document: {
388+
uri: {
389+
fsPath: `/home/bin/routes/animals/frog.dart`,
390+
},
391+
},
392+
};
393+
vscodeStub.workspace.workspaceFolders = [
394+
{
395+
uri: {
396+
fsPath: `home/user/`,
397+
},
398+
},
399+
];
400+
401+
const nearestDartFrogProject = sinon.stub();
402+
nearestDartFrogProject
403+
.withArgs("/home/bin/routes/animals")
404+
.returns(undefined);
405+
nearestDartFrogProject.withArgs("home/user/").returns("home/user/");
406+
407+
const result = resolveDartFrogProjectPathFromWorkspace(
408+
nearestDartFrogProject
409+
);
410+
411+
sinon.assert.match(result, "home/user/");
412+
});
413+
});
414+
415+
suite("returns undefined", () => {
416+
test("when there is no active workspace folder nor text editor", () => {
417+
vscodeStub.window.activeTextEditor = undefined;
418+
vscodeStub.workspace.workspaceFolders = undefined;
419+
420+
const result = resolveDartFrogProjectPathFromWorkspace(
421+
sinon.stub().returns(undefined)
422+
);
423+
424+
sinon.assert.match(result, undefined);
425+
});
426+
427+
test("when there is not an active workspace folder nor text editor that are Dart Frog projects", () => {
428+
vscodeStub.window.activeTextEditor = {
429+
document: {
430+
uri: {
431+
fsPath: `home/user/routes/animals/frog.dart`,
432+
},
433+
},
434+
};
435+
vscodeStub.workspace.workspaceFolders = [
436+
{
437+
uri: {
438+
fsPath: `home/user/`,
439+
},
440+
},
441+
];
442+
443+
const result = resolveDartFrogProjectPathFromWorkspace(
444+
sinon.stub().returns(undefined)
445+
);
446+
447+
sinon.assert.match(result, undefined);
448+
});
449+
});
450+
});
451+
279452
/**
280453
* Example of a pubspec.yaml file that depends on Dart Frog.
281454
*

0 commit comments

Comments
 (0)