package project_test import ( "strings" "testing" "git.vakhrushev.me/av/convy/internal/doc" "git.vakhrushev.me/av/convy/internal/lang" "git.vakhrushev.me/av/convy/internal/project" ) const versionLine = `Ключевые слова ДОЛЖЕН, НЕ ДОЛЖЕН, СЛЕДУЕТ, НЕ СЛЕДУЕТ, ДОПУСКАЕТСЯ и метки ПОЧЕМУ, ПРИМЕРЫ, МЕХАНИЗИРОВАНО и СНЯТО толкуются как описано в языке конвенций версии 1 — тогда и только тогда, когда написаны заглавными.` const baseLayer = `--- topic: time prefix: TIME --- # Время Как приложение записывает моменты. ` + versionLine + ` ## Правила ### TIME-1. Момент записывается в UTC **ДОЛЖЕН.** Момент времени записывается с суффиксом Z. **ПОЧЕМУ.** Без явного смещения не видно, в какой зоне запись сделана. ` const goLayer = `--- topic: time prefix: GTIM lang: go extends: arch/time.md --- # Время: реализация на Go Как базовый слой выполняется в Go-коде. ` + versionLine + ` ## Правила ### GTIM-1. «Сейчас» берётся у слоя хранилища **ДОЛЖЕН.** Текущее время приходит из ` + "`store.Now()`" + `. **ПОЧЕМУ.** Единая точка даёт гарантированный UTC. ` func layers(t *testing.T, bodies ...string) []*doc.Document { t.Helper() v, err := lang.Lookup(1, "ru") if err != nil { t.Fatal(err) } var out []*doc.Document for i, body := range bodies { d, err := doc.Parse("layer.md", body) if err != nil { t.Fatalf("layer %d: %v", i, err) } d.Blocks(v) out = append(out, d) } return out } func vocab(t *testing.T) lang.Vocabulary { t.Helper() v, err := lang.Lookup(1, "ru") if err != nil { t.Fatal(err) } return v } // A copy is one document rather than three files glued together: the first // layer is the document, and every layer after it is a section of it. func TestRenderMakesTheLayersSectionsOfOneDocument(t *testing.T) { body := project.Render("time", layers(t, baseLayer, goLayer), vocab(t)) for _, want := range []string{ "---\norigin: time\n---", "\n# Время\n", "\n## Правила\n", "\n### TIME-1. Момент записывается в UTC\n", "\n## Время: реализация на Go\n", "\n### Правила\n", "\n#### GTIM-1. «Сейчас» берётся у слоя хранилища\n", } { if !strings.Contains(body, want) { t.Errorf("the copy lacks %q:\n%s", want, body) } } if strings.Contains(body, "topic: time\nprefix:") { t.Errorf("the front matter of a layer travelled into the copy:\n%s", body) } if strings.Contains(body, "extends:") { t.Errorf("a path of the suite travelled into the copy:\n%s", body) } } // The line about the language is what makes a copy readable on its own, and // saying it three times over says nothing more than saying it once. func TestRenderNamesTheLanguageOnce(t *testing.T) { body := project.Render("time", layers(t, baseLayer, goLayer), vocab(t)) if n := strings.Count(body, "толкуются как описано"); n != 1 { t.Errorf("the language version line appears %d times:\n%s", n, body) } if !strings.Contains(body, "конвенций версии 1") { t.Errorf("the language version line is gone altogether:\n%s", body) } } // A single layer is not a special case: assembly out of one layer is a copy of // it, with no section headings invented around it. func TestRenderOfOneLayerKeepsItsLevels(t *testing.T) { body := project.Render("time", layers(t, baseLayer), vocab(t)) if !strings.Contains(body, "\n# Время\n") || !strings.Contains(body, "\n### TIME-1.") { t.Errorf("a single layer was restructured:\n%s", body) } if strings.Contains(body, "####") { t.Errorf("headings of a single layer were demoted:\n%s", body) } }