Add Markdown HTML publication
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -34,7 +35,7 @@ func TestRunDryRunPrintsConfigSummary(t *testing.T) {
|
||||
for _, want := range []string{
|
||||
"Configured pipelines: 1",
|
||||
"- reports: source=local bundles=1 destinations=1",
|
||||
"bundle=. destination=archive action=publish_new",
|
||||
"bundle=. destination=archive action=publish_new outputs=report.md,summary.txt",
|
||||
} {
|
||||
if !strings.Contains(output, want) {
|
||||
t.Fatalf("Run() output = %q, want substring %q", output, want)
|
||||
@@ -72,6 +73,103 @@ func TestRunPublishesNewLocalBundle(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunPublishesHTMLOnly(t *testing.T) {
|
||||
sourceRoot := t.TempDir()
|
||||
destinationRoot := t.TempDir()
|
||||
writeSourceBundle(t, sourceRoot, "", testBundleOptions{})
|
||||
|
||||
err := Run(context.Background(), RunOptions{ConfigPath: writeLocalConfigWithPolicy(t, sourceRoot, destinationRoot, false, true)})
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
assertFileContains(t, filepath.Join(destinationRoot, "report.html"), "<h1>Report</h1>")
|
||||
if _, err := os.Stat(filepath.Join(destinationRoot, "report.md")); !os.IsNotExist(err) {
|
||||
t.Fatalf("report.md stat error = %v, want not exist", err)
|
||||
}
|
||||
destinationState := readStateFile(t, filepath.Join(destinationRoot, ".distributor.json"))
|
||||
if got, want := len(destinationState.Outputs), 1; got != want {
|
||||
t.Fatalf("state output count = %d, want %d", got, want)
|
||||
}
|
||||
output := destinationState.Outputs[0]
|
||||
if output.Kind != state.OutputKindGenerated || output.Transform != "markdown_to_html" || output.Path != "report.html" || output.SourcePath != "report.md" {
|
||||
t.Fatalf("generated output metadata = %#v", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunPublishesSourceAndHTML(t *testing.T) {
|
||||
sourceRoot := t.TempDir()
|
||||
destinationRoot := t.TempDir()
|
||||
writeSourceBundle(t, sourceRoot, "", testBundleOptions{})
|
||||
|
||||
err := Run(context.Background(), RunOptions{ConfigPath: writeLocalConfigWithPolicy(t, sourceRoot, destinationRoot, true, true)})
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
assertFile(t, filepath.Join(destinationRoot, "report.md"), "# Report\nSunny.\n")
|
||||
assertFileContains(t, filepath.Join(destinationRoot, "report.html"), "<p>Sunny.</p>")
|
||||
assertFile(t, filepath.Join(destinationRoot, "summary.txt"), "Summary\n")
|
||||
destinationState := readStateFile(t, filepath.Join(destinationRoot, ".distributor.json"))
|
||||
if got, want := len(destinationState.Outputs), 3; got != want {
|
||||
t.Fatalf("state output count = %d, want %d", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunDoesNotMutateSourceBundle(t *testing.T) {
|
||||
sourceRoot := t.TempDir()
|
||||
destinationRoot := t.TempDir()
|
||||
writeSourceBundle(t, sourceRoot, "", testBundleOptions{})
|
||||
sourcePath := filepath.Join(sourceRoot, "report.md")
|
||||
before, err := os.ReadFile(sourcePath)
|
||||
if err != nil {
|
||||
t.Fatalf("read source before: %v", err)
|
||||
}
|
||||
|
||||
err = Run(context.Background(), RunOptions{ConfigPath: writeLocalConfigWithPolicy(t, sourceRoot, destinationRoot, true, true)})
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
after, err := os.ReadFile(sourcePath)
|
||||
if err != nil {
|
||||
t.Fatalf("read source after: %v", err)
|
||||
}
|
||||
if string(after) != string(before) {
|
||||
t.Fatalf("source changed from %q to %q", before, after)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunFailsOnOutputPathCollision(t *testing.T) {
|
||||
sourceRoot := t.TempDir()
|
||||
destinationRoot := t.TempDir()
|
||||
writeSourceBundle(t, sourceRoot, "", testBundleOptions{ExtraFiles: []testFile{{Path: "report.html", Data: "<p>source html</p>\n"}}})
|
||||
|
||||
err := Run(context.Background(), RunOptions{ConfigPath: writeLocalConfigWithPolicy(t, sourceRoot, destinationRoot, true, true)})
|
||||
if err == nil || !strings.Contains(err.Error(), "destination output path collision") {
|
||||
t.Fatalf("Run() error = %v, want collision", err)
|
||||
}
|
||||
if entries, err := os.ReadDir(destinationRoot); err != nil || len(entries) != 0 {
|
||||
t.Fatalf("destination entries = %v err=%v, want empty", entries, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunDryRunReportsGeneratedOutputs(t *testing.T) {
|
||||
sourceRoot := t.TempDir()
|
||||
destinationRoot := t.TempDir()
|
||||
writeSourceBundle(t, sourceRoot, "", testBundleOptions{})
|
||||
|
||||
var stdout bytes.Buffer
|
||||
err := Run(context.Background(), RunOptions{
|
||||
ConfigPath: writeLocalConfigWithPolicy(t, sourceRoot, destinationRoot, false, true),
|
||||
DryRun: true,
|
||||
Stdout: &stdout,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
if !strings.Contains(stdout.String(), "outputs=report.html") {
|
||||
t.Fatalf("stdout = %q, want generated output path", stdout.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunSkipsWhenDestinationStateMatches(t *testing.T) {
|
||||
sourceRoot := t.TempDir()
|
||||
destinationRoot := t.TempDir()
|
||||
@@ -194,8 +292,14 @@ func TestRunDryRunDoesNotWrite(t *testing.T) {
|
||||
}
|
||||
|
||||
type testBundleOptions struct {
|
||||
ID string
|
||||
Created time.Time
|
||||
ID string
|
||||
Created time.Time
|
||||
ExtraFiles []testFile
|
||||
}
|
||||
|
||||
type testFile struct {
|
||||
Path string
|
||||
Data string
|
||||
}
|
||||
|
||||
func writeSourceBundle(t *testing.T, root, relative string, opts testBundleOptions) bundle.Manifest {
|
||||
@@ -217,6 +321,12 @@ func writeSourceBundle(t *testing.T, root, relative string, opts testBundleOptio
|
||||
{path: "report.md", data: "# Report\nSunny.\n"},
|
||||
{path: "summary.txt", data: "Summary\n"},
|
||||
}
|
||||
for _, extra := range opts.ExtraFiles {
|
||||
files = append(files, struct {
|
||||
path string
|
||||
data string
|
||||
}{path: extra.Path, data: extra.Data})
|
||||
}
|
||||
manifestFiles := make([]bundle.ManifestFile, 0, len(files))
|
||||
for _, file := range files {
|
||||
if err := os.WriteFile(filepath.Join(bundleRoot, filepath.FromSlash(file.path)), []byte(file.data), 0o600); err != nil {
|
||||
@@ -248,6 +358,19 @@ func writeSourceBundle(t *testing.T, root, relative string, opts testBundleOptio
|
||||
|
||||
func writeLocalConfig(t *testing.T, sourceRoot, destinationRoot string) string {
|
||||
t.Helper()
|
||||
return writeLocalConfigWithPolicy(t, sourceRoot, destinationRoot, true, false)
|
||||
}
|
||||
|
||||
func writeLocalConfigWithPolicy(t *testing.T, sourceRoot, destinationRoot string, publishSource, publishHTML bool) string {
|
||||
t.Helper()
|
||||
transformConfig := ""
|
||||
if publishHTML {
|
||||
transformConfig = `
|
||||
transform:
|
||||
markdown_to_html:
|
||||
enabled: true
|
||||
mode: sidecar`
|
||||
}
|
||||
return writeConfigFile(t, `
|
||||
pipelines:
|
||||
- id: reports
|
||||
@@ -259,8 +382,8 @@ pipelines:
|
||||
backend: local
|
||||
path: `+destinationRoot+`
|
||||
publish:
|
||||
source: true
|
||||
html: false
|
||||
source: `+fmt.Sprintf("%t", publishSource)+`
|
||||
html: `+fmt.Sprintf("%t", publishHTML)+transformConfig+`
|
||||
`)
|
||||
}
|
||||
|
||||
@@ -341,3 +464,14 @@ func assertFile(t *testing.T, path, want string) {
|
||||
t.Fatalf("%s = %q, want %q", path, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func assertFileContains(t *testing.T, path, want string) {
|
||||
t.Helper()
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatalf("read file %s: %v", path, err)
|
||||
}
|
||||
if !strings.Contains(string(data), want) {
|
||||
t.Fatalf("%s = %q, want substring %q", path, data, want)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user