Files
create-better-t-stack/apps/cli/test/frontend.test.ts
2025-09-14 11:29:01 +05:30

455 lines
11 KiB
TypeScript

import { describe, it } from "vitest";
import {
expectError,
expectSuccess,
runTRPCTest,
type TestConfig,
} from "./test-utils";
describe("Frontend Configurations", () => {
describe("Single Frontend Options", () => {
const singleFrontends = [
"tanstack-router",
"react-router",
"tanstack-start",
"next",
"nuxt",
"native-nativewind",
"native-unistyles",
"svelte",
"solid",
] satisfies ReadonlyArray<
| "tanstack-router"
| "react-router"
| "tanstack-start"
| "next"
| "nuxt"
| "native-nativewind"
| "native-unistyles"
| "svelte"
| "solid"
>;
for (const frontend of singleFrontends) {
it(`should work with ${frontend}`, async () => {
const config: TestConfig = {
projectName: `${frontend}-app`,
frontend: [frontend],
install: false,
};
// Set compatible defaults based on frontend
if (frontend === "solid") {
// Solid is not compatible with Convex backend
config.backend = "hono";
config.runtime = "bun";
config.database = "sqlite";
config.orm = "drizzle";
config.auth = "none";
config.api = "orpc"; // tRPC not supported with solid
config.addons = ["none"];
config.examples = ["none"];
config.dbSetup = "none";
config.webDeploy = "none";
config.serverDeploy = "none";
} else if (["nuxt", "svelte"].includes(frontend)) {
config.backend = "hono";
config.runtime = "bun";
config.database = "sqlite";
config.orm = "drizzle";
config.auth = "none";
config.api = "orpc"; // tRPC not supported with nuxt/svelte
config.addons = ["none"];
config.examples = ["none"];
config.dbSetup = "none";
config.webDeploy = "none";
config.serverDeploy = "none";
} else {
config.backend = "hono";
config.runtime = "bun";
config.database = "sqlite";
config.orm = "drizzle";
config.auth = "none";
config.api = "trpc";
config.addons = ["none"];
config.examples = ["none"];
config.dbSetup = "none";
config.webDeploy = "none";
config.serverDeploy = "none";
}
const result = await runTRPCTest(config);
expectSuccess(result);
});
}
});
describe("Frontend Compatibility with API", () => {
it("should work with React frontends + tRPC", async () => {
const result = await runTRPCTest({
projectName: "react-trpc",
frontend: ["tanstack-router"],
api: "trpc",
backend: "hono",
runtime: "bun",
database: "sqlite",
orm: "drizzle",
auth: "none",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
webDeploy: "none",
serverDeploy: "none",
install: false,
});
expectSuccess(result);
});
it("should fail with Nuxt + tRPC", async () => {
const result = await runTRPCTest({
projectName: "nuxt-trpc-fail",
frontend: ["nuxt"],
api: "trpc",
backend: "hono",
runtime: "bun",
database: "sqlite",
orm: "drizzle",
auth: "none",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
webDeploy: "none",
serverDeploy: "none",
expectError: true,
});
expectError(result, "tRPC API is not supported with 'nuxt' frontend");
});
it("should fail with Svelte + tRPC", async () => {
const result = await runTRPCTest({
projectName: "svelte-trpc-fail",
frontend: ["svelte"],
api: "trpc",
backend: "hono",
runtime: "bun",
database: "sqlite",
orm: "drizzle",
auth: "none",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
webDeploy: "none",
serverDeploy: "none",
expectError: true,
});
expectError(result, "tRPC API is not supported with 'svelte' frontend");
});
it("should fail with Solid + tRPC", async () => {
const result = await runTRPCTest({
projectName: "solid-trpc-fail",
frontend: ["solid"],
api: "trpc",
backend: "hono",
runtime: "bun",
database: "sqlite",
orm: "drizzle",
auth: "none",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
webDeploy: "none",
serverDeploy: "none",
expectError: true,
});
expectError(result, "tRPC API is not supported with 'solid' frontend");
});
it("should work with non-React frontends + oRPC", async () => {
const frontends = ["nuxt", "svelte", "solid"] as const;
for (const frontend of frontends) {
const result = await runTRPCTest({
projectName: `${frontend}-orpc`,
frontend: [frontend],
api: "orpc",
backend: "hono",
runtime: "bun",
database: "sqlite",
orm: "drizzle",
auth: "none",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
webDeploy: "none",
serverDeploy: "none",
install: false,
});
expectSuccess(result);
}
});
});
describe("Frontend Compatibility with Backend", () => {
it("should fail Solid + Convex", async () => {
const result = await runTRPCTest({
projectName: "solid-convex-fail",
frontend: ["solid"],
backend: "convex",
runtime: "none",
database: "none",
orm: "none",
auth: "none",
api: "none",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
webDeploy: "none",
serverDeploy: "none",
expectError: true,
});
expectError(
result,
"The following frontends are not compatible with '--backend convex': solid. Please choose a different frontend or backend.",
);
});
it("should work with React frontends + Convex", async () => {
const result = await runTRPCTest({
projectName: "react-convex",
frontend: ["tanstack-router"],
backend: "convex",
runtime: "none",
database: "none",
orm: "none",
auth: "clerk",
api: "none",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
webDeploy: "none",
serverDeploy: "none",
install: false,
});
expectSuccess(result);
});
});
describe("Frontend Compatibility with Auth", () => {
it("should fail incompatible frontends with Clerk + Convex", async () => {
const incompatibleFrontends = ["nuxt", "svelte", "solid"] as const;
for (const frontend of incompatibleFrontends) {
const result = await runTRPCTest({
projectName: `${frontend}-clerk-convex-fail`,
frontend: [frontend],
backend: "convex",
runtime: "none",
database: "none",
orm: "none",
auth: "clerk",
api: "none",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
webDeploy: "none",
serverDeploy: "none",
expectError: true,
});
expectError(result, "Clerk authentication is not compatible");
}
});
it("should work with compatible frontends + Clerk + Convex", async () => {
const compatibleFrontends = [
"tanstack-router",
"react-router",
"tanstack-start",
"next",
] as const;
for (const frontend of compatibleFrontends) {
const result = await runTRPCTest({
projectName: `${frontend}-clerk-convex`,
frontend: [frontend],
backend: "convex",
runtime: "none",
database: "none",
orm: "none",
auth: "clerk",
api: "none",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
webDeploy: "none",
serverDeploy: "none",
install: false,
});
expectSuccess(result);
}
});
});
describe("Multiple Frontend Constraints", () => {
it("should fail with multiple web frontends", async () => {
const result = await runTRPCTest({
projectName: "multiple-web-fail",
frontend: ["tanstack-router", "react-router"],
backend: "hono",
runtime: "bun",
database: "sqlite",
orm: "drizzle",
auth: "none",
api: "trpc",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
webDeploy: "none",
serverDeploy: "none",
expectError: true,
});
expectError(result, "Cannot select multiple web frameworks");
});
it("should fail with multiple native frontends", async () => {
const result = await runTRPCTest({
projectName: "multiple-native-fail",
frontend: ["native-nativewind", "native-unistyles"],
backend: "hono",
runtime: "bun",
database: "sqlite",
orm: "drizzle",
auth: "none",
api: "trpc",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
webDeploy: "none",
serverDeploy: "none",
expectError: true,
});
expectError(result, "Cannot select multiple native frameworks");
});
it("should work with one web + one native frontend", async () => {
const result = await runTRPCTest({
projectName: "web-native-combo",
frontend: ["tanstack-router", "native-nativewind"],
backend: "hono",
runtime: "bun",
database: "sqlite",
orm: "drizzle",
auth: "none",
api: "trpc",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
webDeploy: "none",
serverDeploy: "none",
install: false,
});
expectSuccess(result);
});
});
describe("Frontend with None Option", () => {
it("should work with frontend none", async () => {
const result = await runTRPCTest({
projectName: "no-frontend",
frontend: ["none"],
backend: "hono",
runtime: "bun",
database: "sqlite",
orm: "drizzle",
auth: "none",
api: "trpc",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
webDeploy: "none",
serverDeploy: "none",
install: false,
});
expectSuccess(result);
});
it("should fail with none + other frontends", async () => {
const result = await runTRPCTest({
projectName: "none-with-other-fail",
frontend: ["none", "tanstack-router"],
backend: "hono",
runtime: "bun",
database: "sqlite",
orm: "drizzle",
auth: "none",
api: "trpc",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
webDeploy: "none",
serverDeploy: "none",
expectError: true,
});
expectError(result, "Cannot combine 'none' with other frontend options");
});
});
describe("Web Deploy Constraints", () => {
it("should work with web frontend + web deploy", async () => {
const result = await runTRPCTest({
projectName: "web-deploy",
frontend: ["tanstack-router"],
webDeploy: "wrangler",
backend: "hono",
runtime: "bun",
database: "sqlite",
orm: "drizzle",
auth: "none",
api: "trpc",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
serverDeploy: "none",
install: false,
});
expectSuccess(result);
});
it("should fail with web deploy but no web frontend", async () => {
const result = await runTRPCTest({
projectName: "web-deploy-no-frontend-fail",
frontend: ["native-nativewind"],
webDeploy: "wrangler",
backend: "hono",
runtime: "bun",
database: "sqlite",
orm: "drizzle",
auth: "none",
api: "trpc",
addons: ["none"],
examples: ["none"],
dbSetup: "none",
serverDeploy: "none",
expectError: true,
});
expectError(result, "'--web-deploy' requires a web frontend");
});
});
});