Four layers under app/test/:
* kernel/, extension/ — unit tests for every kernel service and
the extension contract. i18n fallback chain gets the full
matrix (exact/lang/default/placeholder, namespace isolation,
unknown namespace, interpolation). Theme resolver and
extension-manager topo sort covered.
* widgets/, builtin/ — widget tests for every primitive and each
Tier 0 built-in. Assertions reach into the Semantics node so
a missing label fails structurally, not visually.
* goldens/ — Alchemist + Ahem font for cross-platform pixel
stability; primitives only (button, tab bar, icon set). No
goldens for compositions — they'd churn through every tier.
* a11y/ — contract-level gate: semantic coverage walks the
built-in catalogue, contrast walks every token pair in every
bundled theme against WCAG-AA thresholds (catches real
regressions: the first run caught `tab.inactive_text` at 2.81
in summer-night), i18n coverage asserts every referenced key
exists in its catalog (exists-in-map, not "key == value" — too
ambiguous for keys that happen to equal their translation).
Helpers under helpers/: `KernelFixture.create()` boots a
KernelServices with in-memory stores + a FakeDaemonClient (no
socket, drivable connected-state), `widget_harness` wraps a
widget in the minimum tree that resolves theme + i18n.
Co-Authored-By: Claude <noreply@anthropic.com>
70 lines
1.9 KiB
Dart
70 lines
1.9 KiB
Dart
import 'package:clide_app/extension/extension.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
void main() {
|
|
group('ExtensionManifest.fromYamlString', () {
|
|
test('parses the minimum viable manifest', () {
|
|
final m = ExtensionManifest.fromYamlString('''
|
|
id: ext.postmeridiem.linear
|
|
title: Linear
|
|
version: 1.2.3
|
|
entry: main.lua
|
|
schema_version: 1
|
|
''');
|
|
expect(m.id, 'ext.postmeridiem.linear');
|
|
expect(m.title, 'Linear');
|
|
expect(m.version, '1.2.3');
|
|
expect(m.entry, 'main.lua');
|
|
expect(m.schemaVersion, 1);
|
|
expect(m.dependsOn, isEmpty);
|
|
});
|
|
|
|
test('title defaults to id when absent', () {
|
|
final m = ExtensionManifest.fromYamlString('id: ext.x');
|
|
expect(m.title, 'ext.x');
|
|
expect(m.version, '0.0.0');
|
|
expect(m.entry, 'extension.lua');
|
|
expect(m.schemaVersion, 1);
|
|
});
|
|
|
|
test('depends_on list is captured', () {
|
|
final m = ExtensionManifest.fromYamlString('''
|
|
id: ext.a
|
|
depends_on:
|
|
- builtin.git
|
|
- builtin.diff
|
|
''');
|
|
expect(m.dependsOn, ['builtin.git', 'builtin.diff']);
|
|
});
|
|
|
|
test('non-string depends_on entries are filtered out', () {
|
|
final m = ExtensionManifest.fromYamlString('''
|
|
id: ext.x
|
|
depends_on: [builtin.git, 42, builtin.diff]
|
|
''');
|
|
expect(m.dependsOn, ['builtin.git', 'builtin.diff']);
|
|
});
|
|
|
|
test('missing id throws FormatException', () {
|
|
expect(
|
|
() => ExtensionManifest.fromYamlString('title: Floating'),
|
|
throwsA(isA<FormatException>()),
|
|
);
|
|
});
|
|
|
|
test('empty id throws FormatException', () {
|
|
expect(
|
|
() => ExtensionManifest.fromYamlString('id: ""'),
|
|
throwsA(isA<FormatException>()),
|
|
);
|
|
});
|
|
|
|
test('non-map root throws FormatException', () {
|
|
expect(
|
|
() => ExtensionManifest.fromYamlString('- just a list'),
|
|
throwsA(isA<FormatException>()),
|
|
);
|
|
});
|
|
});
|
|
}
|