suite check: закрыты пробелы в проверках шапки, иерархии и словаря

- документ без темы: ошибка, если такой не один или если он несёт ключи слоя —
  иначе конвенция, потерявшая topic, молча лишалась всех проверок распространения
- иерархия заголовков: один заголовок первого уровня, без перескоков через уровень
- имя темы: латиница и пригодность для имени файла — ошибкой, kebab-case —
  предупреждением
- сценарные связки чужого словаря ловятся в начале строки, где их ставит
  сценарный блок, а не в середине фразы, где это чаще SQL
This commit is contained in:
av
2026-07-27 10:16:15 +03:00
parent b2d07ae55d
commit 51d2050200
5 changed files with 230 additions and 0 deletions
+60
View File
@@ -323,6 +323,66 @@ func TestChecks(t *testing.T) {
"Без явного смещения", "Смотри conventions/time.md. Без явного смещения", 1)
},
want: "the text holds the canon file path",
}, {
name: "document opens below level one",
setup: func(f files) {
f["conventions/time.md"] = strings.Replace(baseTime, "# Время", "## Время", 1)
},
want: "opens with a level-2 heading",
}, {
name: "second level-one heading",
setup: func(f files) {
f["conventions/time.md"] = baseTime + "\n# Ещё один заголовок\n\nПроза.\n"
},
want: "holds a second level-1 heading",
}, {
name: "heading skips a level",
setup: func(f files) {
f["conventions/time.md"] = strings.Replace(baseTime, "## Правила", "#### Правила", 1)
},
want: "skipping a level",
}, {
name: "scenario block opens with a foreign connective",
setup: func(f files) {
f["conventions/time.md"] = baseTime +
"\nWHEN зависимость недоступна\nТОГДА запись ERROR\n"
},
want: `the scenario block opens with WHEN from the "en" vocabulary`,
}, {
name: "topic name is not usable as a file name",
setup: func(f files) {
// A bare non-ASCII key TOML rejects on its own; a quoted one
// passes straight through, which is what the check is for.
f["suite.toml"] = strings.Replace(baseManifest, "time =", `"время" =`, 1)
f["conventions/time.md"] = strings.Replace(baseTime, "topic: time", "topic: время", 1)
},
want: "is not usable as a file name",
}, {
name: "topic name is not lower kebab-case",
setup: func(f files) {
f["suite.toml"] = strings.Replace(baseManifest, "time =", "Time_Zone =", 1)
f["conventions/time.md"] = strings.Replace(baseTime, "topic: time", "topic: Time_Zone", 1)
},
want: "is not lower kebab-case",
}, {
name: "a second document without a topic",
setup: func(f files) {
f["suite.toml"] = strings.Replace(baseManifest,
`TIME = "conventions/time.md"`,
`TIME = "conventions/time.md"`+"\nMETA = \"GUIDE.md\"\nRULE = \"conventions/rules.md\"", 1)
f["GUIDE.md"] = "---\nprefix: META\n---\n\n# Как мы ведём конвенции\n\n" + versionLine + "\n"
f["conventions/rules.md"] = "---\nprefix: RULE\n---\n\n# Правила\n\n" + versionLine + "\n"
},
want: "more than one document without a topic",
}, {
name: "document without a topic carries layer keys",
setup: func(f files) {
f["suite.toml"] = strings.Replace(baseManifest,
`TIME = "conventions/time.md"`,
`TIME = "conventions/time.md"`+"\nGTIM = \"conventions/go.md\"", 1)
f["conventions/go.md"] = "---\nprefix: GTIM\nlang: go\n---\n\n# Go\n\n" + versionLine + "\n"
},
want: "carries the keys of a layer",
}}
for _, tc := range cases {