This repository has been archived on 2026-10-29. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
EveFlutter/test/parity_smoke_test.dart
2026-07-10 09:57:05 +01:00

277 lines
8.3 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'package:eve_parity/main.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
late EveSurfaceState goldenState;
setUpAll(() async {
final regular = FontLoader('EveParity')
..addFont(rootBundle.load('assets/fonts/Roboto-Regular.ttf'))
..addFont(rootBundle.load('assets/fonts/Roboto-Bold.ttf'));
await regular.load();
goldenState = EveSurfaceState.fromJson(
jsonDecode(File('assets/current-surface.json').readAsStringSync())
as Map<String, dynamic>,
);
});
for (final viewport in _viewports) {
testWidgets('renders selected Eve parity fixture at ${viewport.id}', (
tester,
) async {
await tester.binding.setSurfaceSize(
Size(viewport.width, viewport.height),
);
addTearDown(() => tester.binding.setSurfaceSize(null));
await tester.pumpWidget(
MaterialApp(home: EveSurfaceView(state: goldenState)),
);
await tester.pump(const Duration(milliseconds: 100));
await tester.pumpAndSettle();
await tester.pumpAndSettle();
await tester.runAsync(() async {
await Future<void>.delayed(const Duration(milliseconds: 250));
});
await tester.pumpAndSettle();
expect(find.byType(EveSurfaceView), findsOneWidget);
if (fixtureId == 'cultui-inspector') {
expect(find.text('AETHERIC FIELD TESTER'), findsOneWidget);
expect(find.text('FOV'), findsOneWidget);
expect(find.text('THROTTLE DECAY'), findsOneWidget);
expect(find.text('FLOW SPEED'), findsOneWidget);
}
await expectLater(
find.byType(EveSurfaceView),
matchesGoldenFile('goldens/$fixtureId-${viewport.id}.png'),
);
});
}
test('parses embedded document slots for CultUI nested surfaces', () {
final node = EveNode.fromJson(const {
'id': 'test.slot',
'kind': 'surface.slot',
'props': {'presentationKind': 'inventory.dropdown'},
'embeddedDocuments': [
{
'slotId': 'inventory.dropdown',
'documentId': 'cultmesh://test/dropdown',
'schemaId': 'gamecult.eve.surface.v1',
'presentationKind': 'inventory.dropdown',
},
],
});
expect(node.embeddedDocuments, hasLength(1));
expect(node.embeddedDocuments.single.slotId, 'inventory.dropdown');
expect(
node.embeddedDocuments.single.documentId,
'cultmesh://test/dropdown',
);
});
test('embedded_surface_fixture_contract', () {
const json = <String, dynamic>{
'schema': 'gamecult.eve.surface.v1',
'surface': {
'root': {
'id': 'root',
'kind': 'surface.root',
'children': [
{
'id': 'slot',
'kind': 'surface.slot',
'embeddedDocuments': [
{
'slotId': 'inventory.dropdown',
'documentId': 'cultmesh://test/dropdown',
'schemaId': 'gamecult.eve.surface.v1',
'presentationKind': 'inventory.dropdown',
},
],
},
],
},
},
};
final surface = json['surface'] as Map<String, dynamic>;
final root = EveNode.fromJson(surface['root'] as Map<String, dynamic>);
final slot = root.children.singleWhere(
(node) => node.kind == 'surface.slot',
);
expect(json['schema'], 'gamecult.eve.surface.v1');
expect(slot.embeddedDocuments, hasLength(1));
expect(slot.embeddedDocuments.single.slotId, 'inventory.dropdown');
expect(slot.embeddedDocuments.single.schemaId, 'gamecult.eve.surface.v1');
expect(
slot.embeddedDocuments.single.presentationKind,
'inventory.dropdown',
);
});
testWidgets('emits a provider-routed Eve command intent', (tester) async {
final state = EveSurfaceState.fromJson(const {
'schema': 'gamecult.eve.surface.v1',
'providerId': 'world.example',
'surfaceId': 'world.example.surface',
'surface': {
'id': 'world.example.surface',
'root': {
'id': 'root',
'kind': 'surface',
'children': [
{
'id': 'focus',
'kind': 'control.button',
'props': {
'label': 'Focus Target',
'command': 'world.example.commands',
'commandId': 'world.example.focus',
'action': {'operation': 'focus_entity'},
},
},
],
},
},
});
final intents = <EveCommandIntent>[];
await tester.pumpWidget(
MaterialApp(
home: EveSurfaceView(
state: state,
commandSink: (intent, node) => intents.add(intent),
),
),
);
await tester.tap(find.text('Focus Target'));
await tester.pump();
expect(intents, hasLength(1));
expect(intents.single.schema, 'gamecult.eve.command_invocation.v1');
expect(intents.single.providerId, 'world.example');
expect(intents.single.surfaceId, 'world.example.surface');
expect(intents.single.command, 'world.example.commands');
expect(intents.single.commandId, 'world.example.focus');
expect(intents.single.clientId, 'flutter-parity');
expect(intents.single.payload['action']['operation'], 'focus_entity');
});
testWidgets('provider picker consumes conformance export providers', (
tester,
) async {
final catalog = EveProviderCatalog.fromConformanceExport(
_providerCatalogExport,
);
var selected = 'provider.alpha';
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: StatefulBuilder(
builder: (context, setState) {
return EveProviderPicker(
catalog: catalog,
selectedProviderId: selected,
onSelected: (providerId) {
setState(() => selected = providerId);
},
);
},
),
),
),
);
expect(catalog.providers, hasLength(2));
expect(catalog.findProvider('provider.beta')?.ownerRepo, 'PluginOwner');
expect(
catalog
.findProvider('provider.beta')
?.pluginRequirements
.map((requirement) => requirement.pluginId),
containsAll(['sai.vn', 'norn.graph', 'tex.math']),
);
expect(find.text('provider.alpha'), findsOneWidget);
await tester.tap(find.byType(DropdownButton<String>));
await tester.pumpAndSettle();
await tester.tap(find.text('provider.beta').last);
await tester.pumpAndSettle();
expect(selected, 'provider.beta');
});
}
const fixtureId = String.fromEnvironment(
'EVE_PARITY_FIXTURE',
defaultValue: 'cultui-inspector',
);
const _viewports = [
_Viewport('phone', 390, 844),
_Viewport('tablet', 768, 1024),
_Viewport('desktop', 1280, 720),
];
class _Viewport {
const _Viewport(this.id, this.width, this.height);
final String id;
final double width;
final double height;
}
const _providerCatalogExport = {
'schema': 'gamecult.eve.conformance_export.v1',
'providers': [
{
'providerId': 'provider.alpha',
'status': 'advertised',
'ownerRepo': 'ProviderAlpha',
'advertisementPath': 'provider-alpha.json',
'surfaces': ['provider.alpha.surface'],
'commands': ['provider.alpha.commands'],
'pluginRequirements': [],
},
{
'providerId': 'provider.beta',
'status': 'advertised',
'ownerRepo': 'PluginOwner',
'advertisementPath': 'provider-beta.json',
'surfaces': ['provider.beta.surface'],
'commands': ['provider.beta.act'],
'pluginRequirements': [
{
'surfaceId': 'sai.visual_novel.surface',
'pluginId': 'sai.vn',
'requiredCapabilities': [
'vn.stage',
'story.choose',
'story.continue',
'story.jump',
],
},
{
'surfaceId': 'sai.visual_novel.surface',
'pluginId': 'norn.graph',
'requiredCapabilities': ['embed.norn'],
},
{
'surfaceId': 'sai.visual_novel.surface',
'pluginId': 'tex.math',
'requiredCapabilities': ['embed.tex'],
},
],
},
],
};