658 lines
21 KiB
TypeScript
658 lines
21 KiB
TypeScript
import { expect, test, beforeEach, afterEach } from 'bun:test'
|
|
import { initRenderer, reverseDir, SchemaMismatchError } from "./index";
|
|
import { z } from "zod"
|
|
import { mkdtempSync, rmSync, existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs"
|
|
import { basename, join } from "node:path"
|
|
import { tmpdir } from "node:os"
|
|
|
|
const ifExampleSchema = z.object({
|
|
web: z.boolean(),
|
|
header: z.object({
|
|
render: z.boolean(),
|
|
text: z.string()
|
|
})
|
|
})
|
|
|
|
let tmp: string
|
|
|
|
beforeEach(() => {
|
|
tmp = mkdtempSync(join(tmpdir(), "tdir-test-"))
|
|
})
|
|
|
|
afterEach(() => {
|
|
rmSync(tmp, { recursive: true, force: true })
|
|
})
|
|
|
|
test("createRenderer validates schema matches templates", () => {
|
|
const createRenderer = initRenderer("./testdata/if_example")
|
|
expect(() => createRenderer(ifExampleSchema)).not.toThrow()
|
|
expect(() => createRenderer(z.object({ web: z.boolean() }))).toThrow(SchemaMismatchError)
|
|
expect(() => createRenderer(z.object({
|
|
web: z.string(),
|
|
header: z.object({ render: z.boolean(), text: z.string() })
|
|
}))).toThrow(SchemaMismatchError)
|
|
})
|
|
|
|
test("render validates context via zod", () => {
|
|
const createRenderer = initRenderer("./testdata/if_example")
|
|
const render = createRenderer(ifExampleSchema)
|
|
expect(() => render(tmp, {} as any)).toThrow(z.ZodError)
|
|
expect(() => render(tmp, { web: "nope" } as any)).toThrow(z.ZodError)
|
|
expect(() => render(tmp, { web: true, header: { render: true } } as any)).toThrow(z.ZodError)
|
|
})
|
|
|
|
test("renders with web=true, header rendered", () => {
|
|
const createRenderer = initRenderer("./testdata/if_example")
|
|
const render = createRenderer(ifExampleSchema)
|
|
render(tmp, { web: true, header: { render: true, text: "My Title" } })
|
|
|
|
const outFile = join(tmp, "web", "if_example.html")
|
|
expect(existsSync(outFile)).toBe(true)
|
|
|
|
const content = readFileSync(outFile, "utf-8")
|
|
expect(content).toContain("My Title")
|
|
expect(content).toContain("<head>")
|
|
expect(content).toContain("<body>")
|
|
})
|
|
|
|
test("render can write a reverse map", () => {
|
|
const createRenderer = initRenderer("./testdata/if_example")
|
|
const render = createRenderer(ifExampleSchema)
|
|
render(tmp, { web: true, header: { render: true, text: "My Title" } }, { reverseMap: true })
|
|
|
|
const manifest = JSON.parse(readFileSync(join(tmp, ".tdir-map.json"), "utf-8"))
|
|
expect(manifest.version).toBe(1)
|
|
expect(manifest.tokens["My Title"]).toContain("<@var(context.header.text)>")
|
|
|
|
const file = manifest.files.find((entry: any) => entry.outputPath === join("web", "if_example.html"))
|
|
expect(file).toBeDefined()
|
|
expect(file.tokens).toContainEqual({
|
|
kind: "conditional",
|
|
result: expect.stringContaining("<@var(context.header.text)>"),
|
|
token: expect.stringContaining("<@if(context.header.render)>"),
|
|
outputPath: join("web", "if_example.html"),
|
|
templatePath: join("<@if(context.web)>web", "if_example.html"),
|
|
range: expect.any(Object),
|
|
activeRange: expect.any(Object),
|
|
before: expect.any(String),
|
|
after: expect.any(String),
|
|
})
|
|
expect(file.tokens).toContainEqual({
|
|
kind: "content",
|
|
result: "My Title",
|
|
token: "<@var(context.header.text)>",
|
|
contextPath: "header.text",
|
|
outputPath: join("web", "if_example.html"),
|
|
templatePath: join("<@if(context.web)>web", "if_example.html"),
|
|
range: expect.any(Object),
|
|
})
|
|
})
|
|
|
|
test("reverse map records path variable tokens", () => {
|
|
const createRenderer = initRenderer("./testdata/var_in_path")
|
|
const render = createRenderer(z.object({
|
|
web: z.object({
|
|
create: z.boolean(),
|
|
dir: z.string()
|
|
}),
|
|
header: z.object({
|
|
render: z.boolean(),
|
|
text: z.string()
|
|
})
|
|
}))
|
|
render(tmp,{
|
|
web: {
|
|
create: true,
|
|
dir: "web"
|
|
},
|
|
header: {
|
|
render: false,
|
|
text: "test"
|
|
}
|
|
}, { reverseMap: "meta/reverse-map.json" })
|
|
|
|
const manifest = JSON.parse(readFileSync(join(tmp, "meta", "reverse-map.json"), "utf-8"))
|
|
expect(manifest.tokens["web"]).toContain("<@var(context.web.dir)>")
|
|
const pathFile = manifest.files.find((entry: any) => entry.outputPath === "web")
|
|
expect(pathFile.tokens).toContainEqual({
|
|
kind: "path",
|
|
result: "web",
|
|
token: "<@var(context.web.dir)>",
|
|
contextPath: "web.dir",
|
|
outputPath: "web",
|
|
templatePath: "<@if(context.web.create)><@var(context.web.dir)>",
|
|
})
|
|
})
|
|
|
|
test("reverseDir rebuilds templates from rendered output and map", () => {
|
|
const createRenderer = initRenderer("./testdata/if_example")
|
|
const render = createRenderer(ifExampleSchema)
|
|
const templateOut = join(tmp, "template")
|
|
const renderedOut = join(tmp, "rendered")
|
|
|
|
render(renderedOut, { web: true, header: { render: true, text: "My Title" } }, { reverseMap: true })
|
|
writeFileSync(join(renderedOut, "web", "if_example.html"), [
|
|
"<document>",
|
|
" <head> My Title </head>",
|
|
" <body>",
|
|
" <main>Edited rendered output</main>",
|
|
" </body>",
|
|
"</document>",
|
|
].join("\n"))
|
|
|
|
const result = reverseDir(renderedOut, templateOut)
|
|
expect(result.filesWritten).toBe(1)
|
|
expect(result.warnings).toEqual([])
|
|
|
|
const reversed = readFileSync(join(templateOut, "<@if(context.web)>web", "if_example.html"), "utf-8")
|
|
expect(reversed).toContain("<@if(context.header.render)>")
|
|
expect(reversed).toContain("<@endif>")
|
|
expect(reversed).toContain("<@var(context.header.text)>")
|
|
expect(reversed).toContain("Edited rendered output")
|
|
})
|
|
|
|
test("reverseDir restores files skipped by path conditionals", () => {
|
|
const createRenderer = initRenderer("./testdata/file_if")
|
|
const render = createRenderer(z.object({
|
|
web: z.boolean(),
|
|
file: z.boolean(),
|
|
text: z.string()
|
|
}))
|
|
const renderedOut = join(tmp, "rendered")
|
|
const templateOut = join(tmp, "template")
|
|
|
|
render(renderedOut,{
|
|
web: true,
|
|
file: false,
|
|
text: "test"
|
|
}, { reverseMap: true })
|
|
|
|
expect(existsSync(join(renderedOut, "web", "example.txt"))).toBe(false)
|
|
|
|
const result = reverseDir(renderedOut, templateOut)
|
|
expect(result.filesWritten).toBe(1)
|
|
const restoredPath = join(templateOut, "<@if(context.web)>web", "<@if(context.file)>example.txt")
|
|
expect(existsSync(restoredPath)).toBe(true)
|
|
expect(readFileSync(restoredPath, "utf-8")).toContain("<@var(context.text)>")
|
|
})
|
|
|
|
test("reverseDir supports custom map paths", () => {
|
|
const createRenderer = initRenderer("./testdata/var_in_path")
|
|
const render = createRenderer(z.object({
|
|
web: z.object({
|
|
create: z.boolean(),
|
|
dir: z.string()
|
|
}),
|
|
header: z.object({
|
|
render: z.boolean(),
|
|
text: z.string()
|
|
})
|
|
}))
|
|
const renderedOut = join(tmp, "rendered")
|
|
const templateOut = join(tmp, "template")
|
|
|
|
render(renderedOut,{
|
|
web: {
|
|
create: true,
|
|
dir: "web"
|
|
},
|
|
header: {
|
|
render: true,
|
|
text: "test"
|
|
}
|
|
}, { reverseMap: "meta/reverse-map.json" })
|
|
|
|
const result = reverseDir(renderedOut, templateOut, { mapPath: "meta/reverse-map.json" })
|
|
expect(result.filesWritten).toBe(1)
|
|
expect(existsSync(join(templateOut, "<@if(context.web.create)><@var(context.web.dir)>", "var_in_path_example.html"))).toBe(true)
|
|
})
|
|
|
|
test("reverseDir only includes new rendered files matching include globs", () => {
|
|
const createRenderer = initRenderer("./testdata/var_in_path")
|
|
const render = createRenderer(z.object({
|
|
web: z.object({
|
|
create: z.boolean(),
|
|
dir: z.string()
|
|
}),
|
|
header: z.object({
|
|
render: z.boolean(),
|
|
text: z.string()
|
|
})
|
|
}))
|
|
const renderedOut = join(tmp, "rendered")
|
|
const templateOut = join(tmp, "template")
|
|
const ignoredOut = join(tmp, "ignored-template")
|
|
|
|
render(renderedOut,{
|
|
web: {
|
|
create: true,
|
|
dir: "components"
|
|
},
|
|
header: {
|
|
render: true,
|
|
text: "test"
|
|
}
|
|
}, { reverseMap: true })
|
|
writeFileSync(join(renderedOut, "components", "new.ts"), "export const value = 1\n")
|
|
writeFileSync(join(renderedOut, "components", "title.ts"), "export const title = 'test'\n")
|
|
writeFileSync(join(renderedOut, "components", "debug.tmp"), "debug\n")
|
|
|
|
reverseDir(renderedOut, ignoredOut)
|
|
expect(existsSync(join(ignoredOut, "<@if(context.web.create)><@var(context.web.dir)>", "new.ts"))).toBe(false)
|
|
|
|
const result = reverseDir(renderedOut, templateOut, { include: ["components/**/*.ts"] })
|
|
expect(result.filesWritten).toBe(3)
|
|
expect(existsSync(join(templateOut, "<@if(context.web.create)><@var(context.web.dir)>", "new.ts"))).toBe(true)
|
|
expect(readFileSync(join(templateOut, "<@if(context.web.create)><@var(context.web.dir)>", "title.ts"), "utf-8")).toContain("<@var(context.header.text)>")
|
|
expect(existsSync(join(templateOut, "<@if(context.web.create)><@var(context.web.dir)>", "debug.tmp"))).toBe(false)
|
|
})
|
|
|
|
test("reverseDir can write templates inside rendered output without including its own writes", () => {
|
|
const createRenderer = initRenderer("./testdata/if_example")
|
|
const render = createRenderer(ifExampleSchema)
|
|
const renderedOut = join(tmp, "rendered")
|
|
render(renderedOut, { web: true, header: { render: true, text: "My Title" } }, { reverseMap: true })
|
|
writeFileSync(join(renderedOut, "new.html"), "<main>new</main>\n")
|
|
|
|
const result = reverseDir(renderedOut, join(renderedOut, "reversed"), { include: ["**/*"] })
|
|
expect(result.warnings).toEqual([])
|
|
expect(existsSync(join(renderedOut, "reversed", "<@if(context.web)>web", "if_example.html"))).toBe(true)
|
|
expect(existsSync(join(renderedOut, "reversed", "new.html"))).toBe(true)
|
|
expect(existsSync(join(renderedOut, "reversed", "reversed", "new.html"))).toBe(false)
|
|
})
|
|
|
|
test("wrong schema throws error",() => {
|
|
const createRenderer = initRenderer("./testdata/if_example")
|
|
expect(() => createRenderer(z.object({
|
|
web: z.string(),
|
|
header: z.object({
|
|
render: z.string(),
|
|
text: z.boolean()
|
|
})
|
|
}))).toThrow(new SchemaMismatchError({message: 'expected z.boolean() but schema has z.string()', path: 'web'}))
|
|
})
|
|
|
|
test("wrong schema throws error",() => {
|
|
const createRenderer = initRenderer("./testdata/if_example")
|
|
expect(() => createRenderer(z.object({
|
|
web: z.boolean(),
|
|
header: z.object({
|
|
render: z.string(),
|
|
text: z.boolean()
|
|
})
|
|
}))).toThrow(new SchemaMismatchError({message: 'expected z.boolean() but schema has z.string()', path: 'header.render'}))
|
|
})
|
|
|
|
test("wrong schema throws error",() => {
|
|
const createRenderer = initRenderer("./testdata/if_example")
|
|
expect(() => createRenderer(z.object({
|
|
web: z.boolean(),
|
|
header: z.object({
|
|
render: z.boolean(),
|
|
text: z.boolean()
|
|
})
|
|
}))).toThrow(new SchemaMismatchError({message: 'expected z.string() but schema has z.boolean()', path: 'header.text'}))
|
|
})
|
|
|
|
test("renders with web=true, header not rendered", () => {
|
|
const createRenderer = initRenderer("./testdata/if_example")
|
|
const render = createRenderer(ifExampleSchema)
|
|
render(tmp, { web: true, header: { render: false, text: "Ignored" } })
|
|
|
|
const outFile = join(tmp, "web", "if_example.html")
|
|
expect(existsSync(outFile)).toBe(true)
|
|
|
|
const content = readFileSync(outFile, "utf-8")
|
|
expect(content).not.toContain("Ignored")
|
|
expect(content).not.toContain("<head>")
|
|
expect(content).toContain("<body>")
|
|
})
|
|
|
|
test("renders with web=false, skips directory", () => {
|
|
const createRenderer = initRenderer("./testdata/if_example")
|
|
const render = createRenderer(ifExampleSchema)
|
|
render(tmp, { web: false, header: { render: true, text: "Hello" } })
|
|
|
|
expect(existsSync(join(tmp, "web"))).toBe(false)
|
|
})
|
|
|
|
test("vars in path are added to schema",() => {
|
|
const createRenderer = initRenderer("./testdata/var_in_path")
|
|
expect(() => createRenderer(z.object({
|
|
web: z.boolean(),
|
|
header: z.object({
|
|
render: z.boolean(),
|
|
text: z.boolean()
|
|
})
|
|
}))).toThrow(new SchemaMismatchError({message: 'expected z.object() but schema has z.boolean()', path: 'web'}))
|
|
})
|
|
|
|
test("vars in path renders correctrly",() => {
|
|
const createRenderer = initRenderer("./testdata/var_in_path")
|
|
const render = createRenderer(z.object({
|
|
web: z.object({
|
|
create: z.boolean(),
|
|
dir: z.string()
|
|
}),
|
|
header: z.object({
|
|
render: z.boolean(),
|
|
text: z.string()
|
|
})
|
|
}))
|
|
render(tmp,{
|
|
web: {
|
|
create: true,
|
|
dir: "web"
|
|
},
|
|
header: {
|
|
render: false,
|
|
text: "test"
|
|
}
|
|
})
|
|
expect(existsSync(join(tmp, "web"))).toBe(true)
|
|
const outFile = join(tmp, "web", "var_in_path_example.html")
|
|
expect(existsSync(outFile)).toBe(true)
|
|
|
|
const content = readFileSync(outFile, "utf-8")
|
|
expect(content).not.toContain("Ignored")
|
|
expect(content).not.toContain("<head>")
|
|
expect(content).toContain("<body>")
|
|
})
|
|
|
|
test("vars in path renders correctrly",() => {
|
|
const createRenderer = initRenderer("./testdata/var_in_path")
|
|
const render = createRenderer(z.object({
|
|
web: z.object({
|
|
create: z.boolean(),
|
|
dir: z.string()
|
|
}),
|
|
header: z.object({
|
|
render: z.boolean(),
|
|
text: z.string()
|
|
})
|
|
}))
|
|
render(tmp,{
|
|
web: {
|
|
create: true,
|
|
dir: "test"
|
|
},
|
|
header: {
|
|
render: true,
|
|
text: "test"
|
|
}
|
|
})
|
|
expect(existsSync(join(tmp, "test"))).toBe(true)
|
|
const outFile = join(tmp, "test", "var_in_path_example.html")
|
|
expect(existsSync(outFile)).toBe(true)
|
|
|
|
const content = readFileSync(outFile, "utf-8")
|
|
expect(content).toContain("test")
|
|
expect(content).toContain("<head>")
|
|
expect(content).toContain("<body>")
|
|
})
|
|
|
|
test("nested if dir renders correctly",() => {
|
|
const createRenderer = initRenderer("./testdata/nested_if_dir")
|
|
const render = createRenderer(z.object({
|
|
web: z.boolean(),
|
|
webnested: z.boolean()
|
|
}))
|
|
render(tmp,{
|
|
web: true,
|
|
webnested: true
|
|
})
|
|
expect(existsSync(join(tmp, "web"))).toBe(true)
|
|
})
|
|
|
|
test("nested if dir renders correctly",() => {
|
|
const createRenderer = initRenderer("./testdata/nested_if_dir_named")
|
|
const render = createRenderer(z.object({
|
|
web: z.boolean(),
|
|
webnested: z.boolean()
|
|
}))
|
|
render(tmp,{
|
|
web: true,
|
|
webnested: true
|
|
})
|
|
expect(existsSync(join(tmp, "nested" , "web"))).toBe(true)
|
|
})
|
|
|
|
test("multiple dirs 1 var",() => {
|
|
const createRenderer = initRenderer("./testdata/multi_dir_one_var")
|
|
const render = createRenderer(z.object({
|
|
web: z.boolean(),
|
|
}))
|
|
render(tmp,{
|
|
web: true,
|
|
})
|
|
expect(existsSync(join(tmp, "dir1"))).toBe(true)
|
|
expect(existsSync(join(tmp, "dir2"))).toBe(true)
|
|
expect(existsSync(join(tmp, "dir1", "dir1n"))).toBe(true)
|
|
})
|
|
|
|
test("file if",() => {
|
|
const createRenderer = initRenderer("./testdata/file_if")
|
|
const render = createRenderer(z.object({
|
|
web: z.boolean(),
|
|
file: z.boolean(),
|
|
text: z.string()
|
|
}))
|
|
render(tmp,{
|
|
web: true,
|
|
file: true,
|
|
text: "test"
|
|
})
|
|
expect(existsSync(join(tmp, "web"))).toBe(true)
|
|
const outFile = join(tmp, "web", "example.txt")
|
|
expect(existsSync(outFile)).toBe(true)
|
|
|
|
const content = readFileSync(outFile, "utf-8")
|
|
expect(content).toContain("test")
|
|
})
|
|
|
|
test("no endif should throw",() => {
|
|
expect(() => initRenderer("./testdata/no_end_if")).toThrow("test.txt")
|
|
})
|
|
|
|
test("path vars cannot write outside target",() => {
|
|
const createRenderer = initRenderer("./testdata/var_in_path")
|
|
const sentinel = join(tmp, "keep.txt")
|
|
const outsideName = `${basename(tmp)}-outside`
|
|
const outsidePath = join(tmp, "..", outsideName)
|
|
writeFileSync(sentinel, "keep")
|
|
const render = createRenderer(z.object({
|
|
web: z.object({
|
|
create: z.boolean(),
|
|
dir: z.string()
|
|
}),
|
|
header: z.object({
|
|
render: z.boolean(),
|
|
text: z.string()
|
|
})
|
|
}))
|
|
|
|
expect(() => render(tmp,{
|
|
web: {
|
|
create: true,
|
|
dir: `../${outsideName}`
|
|
},
|
|
header: {
|
|
render: false,
|
|
text: "test"
|
|
}
|
|
})).toThrow()
|
|
expect(existsSync(outsidePath)).toBe(false)
|
|
expect(existsSync(sentinel)).toBe(true)
|
|
})
|
|
|
|
test("refuses overlapping source and target directories",() => {
|
|
const source = join(tmp, "template")
|
|
const target = join(source, "out")
|
|
mkdirSync(source, { recursive: true })
|
|
writeFileSync(join(source, "test.txt"), "test")
|
|
|
|
const createRenderer = initRenderer(source)
|
|
const render = createRenderer(z.object({}))
|
|
expect(() => render(target, {})).toThrow()
|
|
})
|
|
|
|
test("binary files are copied without text rendering",() => {
|
|
const source = join(tmp, "template")
|
|
const target = join(tmp, "out")
|
|
mkdirSync(source, { recursive: true })
|
|
const binary = Buffer.from([0, 255, 1, 2, 3])
|
|
writeFileSync(join(source, "asset.bin"), binary)
|
|
|
|
const createRenderer = initRenderer(source)
|
|
const render = createRenderer(z.object({}))
|
|
render(target, {})
|
|
|
|
expect(readFileSync(join(target, "asset.bin"))).toEqual(binary)
|
|
})
|
|
|
|
test("conflicting template variable types should throw",() => {
|
|
const source = join(tmp, "template")
|
|
mkdirSync(source, { recursive: true })
|
|
writeFileSync(join(source, "test.txt"), [
|
|
"<@if(context.test)>",
|
|
"<@endif>",
|
|
"<@var(context.test)>"
|
|
].join("\n"))
|
|
|
|
const createRenderer = initRenderer(source)
|
|
expect(() => createRenderer(z.object({
|
|
test: z.boolean(),
|
|
}))).toThrow()
|
|
})
|
|
|
|
test("if elseif else",() => {
|
|
const createRenderer = initRenderer("./testdata/if_elseif_else_in_file")
|
|
const render = createRenderer(z.object({
|
|
test: z.boolean(),
|
|
test2: z.boolean()
|
|
}))
|
|
render(tmp,{
|
|
test: true,
|
|
test2: true
|
|
})
|
|
let outFile = join(tmp, "test.txt")
|
|
expect(existsSync(outFile)).toBe(true)
|
|
|
|
let content = readFileSync(outFile, "utf-8")
|
|
expect(content).toContain("test")
|
|
render(tmp,{
|
|
test: false,
|
|
test2: true
|
|
})
|
|
outFile = join(tmp, "test.txt")
|
|
expect(existsSync(outFile)).toBe(true)
|
|
|
|
content = readFileSync(outFile, "utf-8")
|
|
expect(content).toContain("test2")
|
|
render(tmp,{
|
|
test: false,
|
|
test2: false
|
|
})
|
|
outFile = join(tmp, "test.txt")
|
|
expect(existsSync(outFile)).toBe(true)
|
|
|
|
content = readFileSync(outFile, "utf-8")
|
|
expect(content).toContain("test3")
|
|
})
|
|
|
|
test("if eq in path", () => {
|
|
const createRenderer = initRenderer("./testdata/eq_in_path")
|
|
const render = createRenderer(z.object({test: z.string()}))
|
|
render(tmp,{test:"test"})
|
|
expect(existsSync(join(tmp,"test"))).toBe(true)
|
|
render(tmp,{test:"foo"})
|
|
expect(existsSync(join(tmp,"test"))).toBe(false)
|
|
})
|
|
|
|
test("if neq in file", () => {
|
|
const createRenderer = initRenderer("./testdata/neq_in_file")
|
|
expect(() => createRenderer(z.object({test: z.boolean()}))).toThrow(SchemaMismatchError)
|
|
const render = createRenderer(z.object({test: z.string()}))
|
|
|
|
render(tmp,{test:"foo"})
|
|
expect(readFileSync(join(tmp,"test.txt"), "utf-8")).toContain("not-test")
|
|
|
|
render(tmp,{test:"test"})
|
|
expect(readFileSync(join(tmp,"test.txt"), "utf-8")).toContain("test")
|
|
expect(readFileSync(join(tmp,"test.txt"), "utf-8")).not.toContain("not-test")
|
|
})
|
|
|
|
test("if neq in path", () => {
|
|
const createRenderer = initRenderer("./testdata/neq_in_path")
|
|
const render = createRenderer(z.object({test: z.string()}))
|
|
render(tmp,{test:"foo"})
|
|
expect(existsSync(join(tmp,"not-test"))).toBe(true)
|
|
render(tmp,{test:"test"})
|
|
expect(existsSync(join(tmp,"not-test"))).toBe(false)
|
|
})
|
|
|
|
test("if neq multiline block", () => {
|
|
const createRenderer = initRenderer("./testdata/neq_multiline_block")
|
|
const render = createRenderer(z.object({
|
|
project: z.object({
|
|
frontend: z.string()
|
|
})
|
|
}))
|
|
|
|
render(tmp,{project:{frontend:"react"}})
|
|
expect(readFileSync(join(tmp,"test.txt"), "utf-8")).toContain("bun dev")
|
|
|
|
render(tmp,{project:{frontend:"none"}})
|
|
expect(readFileSync(join(tmp,"test.txt"), "utf-8")).not.toContain("bun dev")
|
|
})
|
|
|
|
test("and or in file", () => {
|
|
const createRenderer = initRenderer("./testdata/and_or_in_file")
|
|
expect(() => createRenderer(z.object({
|
|
enabled: z.boolean(),
|
|
fallback: z.boolean(),
|
|
kind: z.boolean()
|
|
}))).toThrow(SchemaMismatchError)
|
|
|
|
const render = createRenderer(z.object({
|
|
enabled: z.boolean(),
|
|
fallback: z.boolean(),
|
|
kind: z.string()
|
|
}))
|
|
|
|
render(tmp,{enabled:true, fallback:false, kind:"web"})
|
|
let content = readFileSync(join(tmp,"test.txt"), "utf-8")
|
|
expect(content).toContain("and")
|
|
expect(content).toContain("or")
|
|
expect(content).toContain("nested")
|
|
|
|
render(tmp,{enabled:false, fallback:true, kind:"web"})
|
|
content = readFileSync(join(tmp,"test.txt"), "utf-8")
|
|
expect(content).toContain("not-and")
|
|
expect(content).toContain("not-or")
|
|
expect(content).toContain("nested")
|
|
|
|
render(tmp,{enabled:false, fallback:true, kind:"docs"})
|
|
content = readFileSync(join(tmp,"test.txt"), "utf-8")
|
|
expect(content).toContain("not-and")
|
|
expect(content).toContain("or")
|
|
expect(content).toContain("nested")
|
|
})
|
|
|
|
test("and or in path", () => {
|
|
const createRenderer = initRenderer("./testdata/and_or_in_path")
|
|
const render = createRenderer(z.object({
|
|
enabled: z.boolean(),
|
|
kind: z.string()
|
|
}))
|
|
|
|
render(tmp,{enabled:true, kind:"web"})
|
|
expect(existsSync(join(tmp,"match"))).toBe(true)
|
|
|
|
render(tmp,{enabled:true, kind:"docs"})
|
|
expect(existsSync(join(tmp,"match"))).toBe(true)
|
|
|
|
render(tmp,{enabled:false, kind:"docs"})
|
|
expect(existsSync(join(tmp,"match"))).toBe(false)
|
|
})
|