// Doc-help wiring guard — a page help button must open the RIGHT // topic. Every `showFaiDoc(context, '')` call in lib/ needs: // // 1. a registered _DocEntry (exposed as kKnownDocSlugs), and // 2. the backing assets assets/docs/.md + _de.md. // // Without this, a slug with no entry silently fell back to the // first doc ('architecture'): the Federation and Runs help buttons // opened the architecture sheet even though federation.md/runs.md // existed — the author wrote the docs, set the icon, but never // wired the catalog, and nothing caught it. This test catches that // whole class (per the no-bugfix-without-a-guard rule). import 'dart:io'; import 'package:flutter_test/flutter_test.dart'; import 'package:chain_studio/pages/welcome.dart' show kKnownDocSlugs; void main() { final callSlugs = _showFaiDocSlugsInLib(); test('lib/ actually calls showFaiDoc somewhere (sanity)', () { expect( callSlugs, isNotEmpty, reason: 'no showFaiDoc calls found — did the scan regex go stale?', ); }); test('every showFaiDoc slug is registered in the doc catalog', () { final unregistered = callSlugs.difference(kKnownDocSlugs); expect( unregistered, isEmpty, reason: 'These slugs are opened by a help button but have no _DocEntry, ' 'so they silently fall back to the wrong topic. Register them in ' '_kDocs (lib/pages/welcome.dart): $unregistered', ); }); test('every registered doc slug has both locale assets', () { final missing = []; for (final slug in kKnownDocSlugs) { for (final path in ['assets/docs/$slug.md', 'assets/docs/${slug}_de.md']) { if (!File(path).existsSync()) missing.add(path); } } expect( missing, isEmpty, reason: 'Registered doc slugs missing their markdown assets: $missing', ); }); } /// Scan lib/ for `showFaiDoc(context, 'slug')` and collect the slugs. Set _showFaiDocSlugsInLib() { final re = RegExp(r'''showFaiDoc\(\s*context\s*,\s*['"]([a-z0-9_-]+)['"]'''); final slugs = {}; final dir = Directory('lib'); for (final f in dir.listSync(recursive: true).whereType()) { if (!f.path.endsWith('.dart')) continue; for (final m in re.allMatches(f.readAsStringSync())) { slugs.add(m.group(1)!); } } return slugs; }