Skip to content

Commit

Permalink
feat(vscode): implemented nearestChildDartFrogProjects (#1015)
Browse files Browse the repository at this point in the history
Co-authored-by: Renan <6718144+renancaraujo@users.noreply.github.com>
  • Loading branch information
alestiago and renancaraujo committed Sep 11, 2023
1 parent 4a79284 commit ceeb7ec
Show file tree
Hide file tree
Showing 2 changed files with 244 additions and 0 deletions.
184 changes: 184 additions & 0 deletions extensions/vscode/src/test/suite/utils/dart-frog-structure.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,190 @@ suite("nearestParentDartFrogProject", () => {
});
});

suite("nearestChildDartFrogProjects", () => {
let fsStub: any;
let nearestChildDartFrogProjects: any;

beforeEach(() => {
fsStub = {
existsSync: sinon.stub(),
readFileSync: sinon.stub(),
statSync: sinon.stub(),
readdirSync: sinon.stub(),
};

nearestChildDartFrogProjects = proxyquire(
"../../../utils/dart-frog-structure",
{
fs: fsStub,
}
).nearestChildDartFrogProjects;
});

afterEach(() => {
sinon.restore();
});

test("returns a single path when the file path is a Dart Frog project", () => {
const filePath = "/home/project";

const dartFrogPubspecRoutesPath = path.join(filePath, "routes");
const dartFrogPubspecPath = path.join(filePath, "pubspec.yaml");
fsStub.existsSync.withArgs(filePath).returns(true);
fsStub.statSync.withArgs(filePath).returns({
isDirectory: () => true,
});
fsStub.readdirSync.withArgs(filePath).returns([]);
fsStub.existsSync.withArgs(dartFrogPubspecRoutesPath).returns(true);
fsStub.existsSync.withArgs(dartFrogPubspecPath).returns(true);
fsStub.readFileSync
.withArgs(dartFrogPubspecPath, "utf-8")
.returns(validPubspecYaml);

const dartFrogProjects = nearestChildDartFrogProjects(filePath);

assert.deepEqual(dartFrogProjects, [filePath]);
});

test("returns the path to all the child Dart Frog projects", () => {
fsStub.existsSync.returns(false);

const filePath = "/home/project";
fsStub.existsSync.withArgs(filePath).returns(true);
fsStub.statSync.withArgs(filePath).returns({
isDirectory: () => true,
});
fsStub.readdirSync
.withArgs(filePath)
.returns(["file.dart", "frog1", "frog2", "subdirectory", "flutter"]);

const fileDartPath = "/home/project/file.dart";
fsStub.existsSync.withArgs(fileDartPath).returns(true);
fsStub.statSync.withArgs(fileDartPath).returns({
isDirectory: () => false,
});

const dartFrogPath1 = "/home/project/frog1";
const dartFrogPubspecRoutesPath1 = path.join(dartFrogPath1, "routes");
const dartFrogPubspecPath1 = path.join(dartFrogPath1, "pubspec.yaml");
fsStub.existsSync.withArgs(dartFrogPath1).returns(true);
fsStub.statSync.withArgs(dartFrogPath1).returns({
isDirectory: () => true,
});
fsStub.readdirSync.withArgs(dartFrogPath1).returns([]);
fsStub.existsSync.withArgs(dartFrogPubspecRoutesPath1).returns(true);
fsStub.existsSync.withArgs(dartFrogPubspecPath1).returns(true);
fsStub.readFileSync
.withArgs(dartFrogPubspecPath1, "utf-8")
.returns(validPubspecYaml);

const dartFrogPath2 = "/home/project/frog2";
const dartFrogPubspecRoutesPath2 = path.join(dartFrogPath2, "routes");
const dartFrogPubspecPath2 = path.join(dartFrogPath2, "pubspec.yaml");
fsStub.existsSync.withArgs(dartFrogPath2).returns(true);
fsStub.statSync.withArgs(dartFrogPath2).returns({
isDirectory: () => true,
});
fsStub.readdirSync.withArgs(dartFrogPath2).returns([]);
fsStub.existsSync.withArgs(dartFrogPubspecRoutesPath2).returns(true);
fsStub.existsSync.withArgs(dartFrogPubspecPath2).returns(true);
fsStub.readFileSync
.withArgs(dartFrogPubspecPath2, "utf-8")
.returns(validPubspecYaml);

const subdirectory = "/home/project/subdirectory";
fsStub.existsSync.withArgs(subdirectory).returns(true);
fsStub.statSync.withArgs(subdirectory).returns({
isDirectory: () => true,
});
fsStub.readdirSync.withArgs(subdirectory).returns(["frog3"]);

const dartFrogPath3 = "/home/project/subdirectory/frog3";
const dartFrogPubspecRoutesPath3 = path.join(dartFrogPath3, "routes");
const dartFrogPubspecPath3 = path.join(dartFrogPath3, "pubspec.yaml");
fsStub.existsSync.withArgs(dartFrogPath3).returns(true);
fsStub.statSync.withArgs(dartFrogPath3).returns({
isDirectory: () => true,
});
fsStub.readdirSync.withArgs(dartFrogPath3).returns([]);
fsStub.existsSync.withArgs(dartFrogPubspecRoutesPath3).returns(true);
fsStub.existsSync.withArgs(dartFrogPubspecPath3).returns(true);
fsStub.readFileSync
.withArgs(dartFrogPubspecPath3, "utf-8")
.returns(validPubspecYaml);

const flutterPath = "/home/project/flutter";
const flutterPubspecPath = path.join(flutterPath, "pubspec.yaml");
fsStub.existsSync.withArgs(flutterPath).returns(true);
fsStub.statSync.withArgs(flutterPath).returns({
isDirectory: () => true,
});
fsStub.readdirSync.withArgs(flutterPath).returns([]);
fsStub.existsSync.withArgs(flutterPubspecPath).returns(true);
fsStub.readFileSync
.withArgs(flutterPubspecPath, "utf-8")
.returns(invalidPubspecYaml);

const dartFrogProjects = nearestChildDartFrogProjects(filePath);

assert.deepEqual(dartFrogProjects, [
dartFrogPath1,
dartFrogPath2,
dartFrogPath3,
]);
});

suite("returns undefined", () => {
test("when path does not exist", () => {
const filePath = "/home/project/routes/animals/frog.dart";
fsStub.existsSync.withArgs(filePath).returns(false);

const result = nearestChildDartFrogProjects(filePath);

assert.equal(result, undefined);
});

test("when path is not a directory", () => {
const filePath = "/home/project/routes/animals/frog.dart";
fsStub.existsSync.withArgs(filePath).returns(true);
fsStub.statSync.withArgs(filePath).returns({
isDirectory: () => false,
});

const result = nearestChildDartFrogProjects(filePath);

assert.equal(result, undefined);
});

test("when subdirectory is not a Dart Frog project", () => {
const filePath = "/home/project";
fsStub.existsSync.withArgs(filePath).returns(true);
fsStub.statSync.withArgs(filePath).returns({
isDirectory: () => true,
});
fsStub.readdirSync.withArgs(filePath).returns(["frog"]);

const dartFrogPath = "/home/project/frog";
const dartFrogPubspecRoutesPath = path.join(dartFrogPath, "routes");
const dartFrogPubspecPath = path.join(dartFrogPath, "pubspec.yaml");
fsStub.existsSync.withArgs(dartFrogPath).returns(true);
fsStub.statSync.withArgs(dartFrogPath).returns({
isDirectory: () => true,
});
fsStub.readdirSync.withArgs(dartFrogPath).returns([]);
fsStub.existsSync.withArgs(dartFrogPubspecRoutesPath).returns(true);
fsStub.existsSync.withArgs(dartFrogPubspecPath).returns(true);
fsStub.readFileSync
.withArgs(dartFrogPubspecPath, "utf-8")
.returns(invalidPubspecYaml);

const result = nearestChildDartFrogProjects(filePath);

assert.equal(result, undefined);
});
});
});

suite("isDartFrogProject", () => {
let fsStub: any;
let isDartFrogProject: any;
Expand Down
60 changes: 60 additions & 0 deletions extensions/vscode/src/utils/dart-frog-structure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,66 @@ export function nearestParentDartFrogProject(
return undefined;
}

/**
* Finds all Dart Frog projects that are children of a directory.
*
* Nested Dart Frog projects are not considered. Therefore, if the
* {@link filePath} is a Dart Frog project, then only that project is reported.
* The same logic applies to subdirectories. If a subdirectory is also a Dart
* Frog project, then all of its subdirectories are ignored and only the
* shallowest Dart Frog project is reported.
*
* @param filePath The path to the directory to check for.
* @returns {Array<string> | undefined} A set of paths to Dart Frog projects
* that are children of the {@link filePath}, or `undefined` if there are no
* Dart Frog projects in the {@link filePath}.
*/
export function nearestChildDartFrogProjects(
filePath: string
): Array<string> | undefined {
if (!fs.existsSync(filePath) || !fs.statSync(filePath).isDirectory()) {
return undefined;
}

if (isDartFrogProject(filePath)) {
return [filePath];
}

const dartFrogProjects = new Set<string>();

let currentSubdirectories = fs
.readdirSync(filePath)
.map((file: string) => path.join(filePath, file))
.filter((file: string) => fs.statSync(file).isDirectory());

while (currentSubdirectories.length > 0) {
for (let i = 0; i < currentSubdirectories.length; i++) {
const subdirectory = currentSubdirectories[i];
if (isDartFrogProject(subdirectory)) {
dartFrogProjects.add(subdirectory);
currentSubdirectories.splice(i, 1);
i--;
}
}

const nextSubdirectories: string[] = [];
for (const subdirectory of currentSubdirectories) {
const subdirectorySubdirectories = fs
.readdirSync(subdirectory)
.map((file: string) => path.join(subdirectory, file))
.filter((file: string) => fs.statSync(file).isDirectory());
nextSubdirectories.push(...subdirectorySubdirectories);
}
currentSubdirectories = nextSubdirectories;
}

if (dartFrogProjects.size === 0) {
return undefined;
}

return Array.from(dartFrogProjects);
}

/**
* Determines if a {@link filePath} is a Dart Frog project.
*
Expand Down

0 comments on commit ceeb7ec

Please sign in to comment.