create-esmx
Version:
A scaffold tool for creating Esmx projects
156 lines (155 loc) • 6 kB
JavaScript
import { existsSync } from "node:fs";
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { createProjectFromTemplate } from "./project.mjs";
import { getEsmxVersion } from "./template.mjs";
import { formatProjectName } from "./utils/index.mjs";
async function createTempDir(prefix = "esmx-unit-test-") {
return mkdtemp(join(tmpdir(), prefix));
}
async function cleanupTempDir(tmpDir) {
await rm(tmpDir, { recursive: true, force: true });
}
describe("project unit tests", () => {
let tmpDir;
beforeEach(async () => {
tmpDir = await createTempDir();
});
afterEach(async () => {
await cleanupTempDir(tmpDir);
});
it("should handle isDirectoryEmpty edge cases", async () => {
const hiddenFilesDir = join(tmpDir, "hidden-files-dir");
await mkdir(hiddenFilesDir, { recursive: true });
await writeFile(join(hiddenFilesDir, ".hidden-file"), "hidden content");
await writeFile(join(hiddenFilesDir, ".gitignore"), "node_modules/");
const projectNameInput = "hidden-files-dir";
const { name, root } = formatProjectName(projectNameInput, tmpDir);
await createProjectFromTemplate(root, "vue2-csr", tmpDir, false, {
projectName: name,
esmxVersion: getEsmxVersion(),
installCommand: "npm install",
devCommand: "npm run dev",
buildCommand: "npm run build",
startCommand: "npm start",
buildTypeCommand: "npm run build:type",
lintTypeCommand: "npm run lint:type"
});
expect(existsSync(join(hiddenFilesDir, "package.json"))).toBe(true);
});
it("should handle directory creation for nested paths", async () => {
const deepPath = join(
tmpDir,
"very",
"deep",
"nested",
"path",
"project"
);
const projectNameInput = "very/deep/nested/path/project";
const { name, root } = formatProjectName(projectNameInput, tmpDir);
await createProjectFromTemplate(root, "vue2-csr", tmpDir, false, {
projectName: name,
esmxVersion: getEsmxVersion(),
installCommand: "npm install",
devCommand: "npm run dev",
buildCommand: "npm run build",
startCommand: "npm start",
buildTypeCommand: "npm run build:type",
lintTypeCommand: "npm run lint:type"
});
expect(existsSync(deepPath)).toBe(true);
expect(existsSync(join(deepPath, "package.json"))).toBe(true);
});
it("should handle file copy with template variable replacement", async () => {
const projectPath = join(tmpDir, "variable-test");
const projectNameInput = "variable-test";
const { name, root } = formatProjectName(projectNameInput, tmpDir);
await createProjectFromTemplate(root, "vue2-csr", tmpDir, false, {
projectName: name,
esmxVersion: getEsmxVersion(),
installCommand: "npm install",
devCommand: "npm run dev",
buildCommand: "npm run build",
startCommand: "npm start",
buildTypeCommand: "npm run build:type",
lintTypeCommand: "npm run lint:type"
});
const packageJsonPath = join(projectPath, "package.json");
expect(existsSync(packageJsonPath)).toBe(true);
const packageContent = require("node:fs").readFileSync(
packageJsonPath,
"utf-8"
);
const packageJson = JSON.parse(packageContent);
expect(packageJson.name).toBe("variable-test");
});
it("should handle empty directory detection correctly", async () => {
const emptyDir = join(tmpDir, "empty-dir");
await mkdir(emptyDir, { recursive: true });
const projectNameInput = "empty-dir";
const { name, root } = formatProjectName(projectNameInput, tmpDir);
await createProjectFromTemplate(root, "vue2-csr", tmpDir, false, {
projectName: name,
esmxVersion: getEsmxVersion(),
installCommand: "npm install",
devCommand: "npm run dev",
buildCommand: "npm run build",
startCommand: "npm start",
buildTypeCommand: "npm run build:type",
lintTypeCommand: "npm run lint:type"
});
expect(existsSync(join(emptyDir, "package.json"))).toBe(true);
});
it("should handle mixed file types in directory", async () => {
const mixedDir = join(tmpDir, "mixed-dir");
await mkdir(mixedDir, { recursive: true });
await writeFile(join(mixedDir, ".dotfile"), "hidden");
await writeFile(join(mixedDir, "regular-file.txt"), "visible");
const projectNameInput = "mixed-dir";
const { name, root } = formatProjectName(projectNameInput, tmpDir);
await createProjectFromTemplate(
root,
"vue2-csr",
tmpDir,
true,
// force flag
{
projectName: name,
esmxVersion: getEsmxVersion(),
installCommand: "npm install",
devCommand: "npm run dev",
buildCommand: "npm run build",
startCommand: "npm start",
buildTypeCommand: "npm run build:type",
lintTypeCommand: "npm run lint:type"
}
);
expect(existsSync(join(mixedDir, "package.json"))).toBe(true);
});
it("should handle special characters in project names", async () => {
const specialNames = [
"project-with-dashes",
"project_with_underscores",
"project.with.dots"
];
for (const projectName of specialNames) {
const projectPath = join(tmpDir, projectName);
const { name, root } = formatProjectName(projectName, tmpDir);
await createProjectFromTemplate(root, "vue2-csr", tmpDir, false, {
projectName: name,
esmxVersion: getEsmxVersion(),
installCommand: "npm install",
devCommand: "npm run dev",
buildCommand: "npm run build",
startCommand: "npm start",
buildTypeCommand: "npm run build:type",
lintTypeCommand: "npm run lint:type"
});
expect(existsSync(projectPath)).toBe(true);
expect(existsSync(join(projectPath, "package.json"))).toBe(true);
}
});
});