@ondeinference / onde / commits / 05439fb

Refactor Dart SDK tests for onde_inference 0.2.0 API

- Update widget test to verify root widget construction

keypair34 committed Apr 5, 2026 at 18:14 UTC 05439fb861bf4b645ce31aec85daac47e189d128
2 files changed +74 -83
sdk/dart/example/test/widget_test.dart
+9 -22
@@ -1,30 +1,17 @@
1 -// This is a basic Flutter widget test.
1 +// Copyright 2026 Onde Inference (Splitfire AB). All rights reserved.
2 +// Use of this source code is governed by the MIT license.
3 //
3 -// To perform an interaction with a widget in your test, use the WidgetTester
4 -// utility in the flutter_test package. For example, you can send tap and scroll
5 -// gestures. You can also use WidgetTester to find child widgets in the widget
6 -// tree, read text, and verify that the values of widget properties are correct.
7 -
8 -import 'package:flutter/material.dart';
4 import 'package:flutter_test/flutter_test.dart';
5
6 import 'package:onde_inference_example/main.dart';
7
8 void main() {
14 - testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 - // Build our app and trigger a frame.
16 - await tester.pumpWidget(const MyApp());
17 -
18 - // Verify that our counter starts at 0.
19 - expect(find.text('0'), findsOneWidget);
20 - expect(find.text('1'), findsNothing);
21 -
22 - // Tap the '+' icon and trigger a frame.
23 - await tester.tap(find.byIcon(Icons.add));
24 - await tester.pump();
25 -
26 - // Verify that our counter has incremented.
27 - expect(find.text('0'), findsNothing);
28 - expect(find.text('1'), findsOneWidget);
9 + testWidgets('OndeInferenceApp builds without crashing',
10 + (WidgetTester tester) async {
11 + // Verify the root widget can be constructed.
12 + // Full integration tests require the native inference library to be
13 + // compiled first — run `flutter build` or `cargo build` in sdk/dart/rust/
14 + // before running widget tests that exercise the engine.
15 + expect(const OndeInferenceApp(), isA<OndeInferenceApp>());
16 });
17 }
sdk/dart/test/dart_test.dart
+65 -61
@@ -6,39 +6,39 @@ import 'package:onde_inference/onde_inference.dart';
6
7 void main() {
8 group('OndeException', () {
9 - test('toString includes message', () {
10 - const e = OndeException('No model loaded');
11 - expect(e.toString(), contains('No model loaded'));
9 + test('toString includes error info', () {
10 + const e = OndeException(OndeError_NoModelLoaded());
11 + expect(e.toString(), contains('OndeException'));
12 });
13
14 test('equality', () {
15 - const a = OndeException('foo');
16 - const b = OndeException('foo');
17 - const c = OndeException('bar');
15 + const a = OndeException(OndeError_NoModelLoaded());
16 + const b = OndeException(OndeError_NoModelLoaded());
17 + const c = OndeException(OndeError_Cancelled());
18 expect(a, equals(b));
19 expect(a, isNot(equals(c)));
20 });
21 });
22
23 group('ChatRole', () {
24 - test('toString values', () {
25 - expect(ChatRole.system.toString(), 'system');
26 - expect(ChatRole.user.toString(), 'user');
27 - expect(ChatRole.assistant.toString(), 'assistant');
24 + test('name values', () {
25 + expect(ChatRole.system.name, 'system');
26 + expect(ChatRole.user.name, 'user');
27 + expect(ChatRole.assistant.name, 'assistant');
28 });
29 });
30
31 group('ChatMessage', () {
32 test('factory constructors set correct roles', () {
33 - expect(ChatMessage.system('Hi').role, ChatRole.system);
34 - expect(ChatMessage.user('Hi').role, ChatRole.user);
35 - expect(ChatMessage.assistant('Hi').role, ChatRole.assistant);
33 + expect(ChatMessageX.system('Hi').role, ChatRole.system);
34 + expect(ChatMessageX.user('Hi').role, ChatRole.user);
35 + expect(ChatMessageX.assistant('Hi').role, ChatRole.assistant);
36 });
37
38 test('equality', () {
39 - final a = ChatMessage.user('Hello');
40 - final b = ChatMessage.user('Hello');
41 - final c = ChatMessage.user('World');
39 + final a = ChatMessageX.user('Hello');
40 + final b = ChatMessageX.user('Hello');
41 + final c = ChatMessageX.user('World');
42 expect(a, equals(b));
43 expect(a, isNot(equals(c)));
44 });
@@ -46,28 +46,28 @@ void main() {
46
47 group('SamplingConfig', () {
48 test('defaultConfig preset', () {
49 - final s = SamplingConfig.defaultConfig();
49 + final s = SamplingConfigX.defaultConfig();
50 expect(s.temperature, 0.7);
51 expect(s.topP, 0.95);
52 - expect(s.maxTokens, 512);
52 + expect(s.maxTokens, BigInt.from(512));
53 });
54
55 test('deterministic preset', () {
56 - final s = SamplingConfig.deterministic();
56 + final s = SamplingConfigX.deterministic();
57 expect(s.temperature, 0.0);
58 - expect(s.maxTokens, 512);
58 + expect(s.maxTokens, BigInt.from(512));
59 expect(s.topP, isNull);
60 });
61
62 test('mobile preset', () {
63 - final s = SamplingConfig.mobile();
63 + final s = SamplingConfigX.mobile();
64 expect(s.temperature, 0.7);
65 expect(s.topP, 0.95);
66 - expect(s.maxTokens, 128);
66 + expect(s.maxTokens, BigInt.from(128));
67 });
68
69 test('copyWith overrides single field', () {
70 - final base = SamplingConfig.defaultConfig();
70 + final base = SamplingConfigX.defaultConfig();
71 final copy = base.copyWith(temperature: 0.3);
72 expect(copy.temperature, 0.3);
73 expect(copy.topP, base.topP);
@@ -76,19 +76,19 @@ void main() {
76
77 test('equality', () {
78 expect(
79 - SamplingConfig.deterministic(),
80 - equals(SamplingConfig.deterministic()),
79 + SamplingConfigX.deterministic(),
80 + equals(SamplingConfigX.deterministic()),
81 );
82 expect(
83 - SamplingConfig.deterministic(),
84 - isNot(equals(SamplingConfig.mobile())),
83 + SamplingConfigX.deterministic(),
84 + isNot(equals(SamplingConfigX.mobile())),
85 );
86 });
87 });
88
89 group('GgufModelConfig', () {
90 - test('stub factory functions return non-empty configs', () {
91 - final config1_5b = OndeInference.qwen251_5bConfig();
90 + test('factory functions return non-empty configs', () {
91 + final config1_5b = OndeInference.qwen2515bConfig();
92 expect(config1_5b.modelId, contains('1.5B'));
93 expect(config1_5b.files, isNotEmpty);
94 expect(config1_5b.displayName, isNotEmpty);
@@ -98,7 +98,7 @@ void main() {
98 expect(config3b.modelId, contains('3B'));
99 expect(config3b.files, isNotEmpty);
100
101 - final configCoder1_5b = OndeInference.qwen25Coder1_5bConfig();
101 + final configCoder1_5b = OndeInference.qwen25Coder15bConfig();
102 expect(configCoder1_5b.modelId, contains('Coder'));
103
104 final configCoder3b = OndeInference.qwen25Coder3bConfig();
@@ -110,11 +110,11 @@ void main() {
110
111 test('equality', () {
112 expect(
113 - OndeInference.qwen251_5bConfig(),
114 - equals(OndeInference.qwen251_5bConfig()),
113 + OndeInference.qwen2515bConfig(),
114 + equals(OndeInference.qwen2515bConfig()),
115 );
116 expect(
117 - OndeInference.qwen251_5bConfig(),
117 + OndeInference.qwen2515bConfig(),
118 isNot(equals(OndeInference.qwen253bConfig())),
119 );
120 });
@@ -129,24 +129,30 @@ void main() {
129 expect(EngineStatus.error.isReady, isFalse);
130 });
131
132 - test('toString values', () {
133 - expect(EngineStatus.unloaded.toString(), 'unloaded');
134 - expect(EngineStatus.loading.toString(), 'loading');
135 - expect(EngineStatus.ready.toString(), 'ready');
136 - expect(EngineStatus.generating.toString(), 'generating');
137 - expect(EngineStatus.error.toString(), 'error');
132 + test('name values', () {
133 + expect(EngineStatus.unloaded.name, 'unloaded');
134 + expect(EngineStatus.loading.name, 'loading');
135 + expect(EngineStatus.ready.name, 'ready');
136 + expect(EngineStatus.generating.name, 'generating');
137 + expect(EngineStatus.error.name, 'error');
138 });
139 });
140
141 group('EngineInfo', () {
142 test('equality', () {
143 - const a = EngineInfo(status: EngineStatus.unloaded, historyLength: 0);
144 - const b = EngineInfo(status: EngineStatus.unloaded, historyLength: 0);
145 - const c = EngineInfo(
143 + final a = EngineInfo(
144 + status: EngineStatus.unloaded,
145 + historyLength: BigInt.zero,
146 + );
147 + final b = EngineInfo(
148 + status: EngineStatus.unloaded,
149 + historyLength: BigInt.zero,
150 + );
151 + final c = EngineInfo(
152 status: EngineStatus.ready,
153 modelName: 'Qwen 2.5 3B',
154 approxMemory: '~1.93 GB',
149 - historyLength: 3,
155 + historyLength: BigInt.from(3),
156 );
157 expect(a, equals(b));
158 expect(a, isNot(equals(c)));
@@ -169,24 +175,23 @@ void main() {
175 text: 'Hi there!',
176 durationSecs: 1.5,
177 durationDisplay: '1.5s',
178 + finishReason: 'stop',
179 );
180 const b = InferenceResult(
181 text: 'Hi there!',
182 durationSecs: 1.5,
183 durationDisplay: '1.5s',
184 + finishReason: 'stop',
185 );
186 expect(a, equals(b));
187 });
188 });
189
182 - group('RustLib stub', () {
183 - test('init() is a safe no-op', () async {
184 - expect(RustLib.isInitialized, isFalse);
185 - await RustLib.init();
186 - expect(RustLib.isInitialized, isTrue);
187 - // Second call is also safe.
188 - await RustLib.init();
189 - expect(RustLib.isInitialized, isTrue);
190 + group('RustLib', () {
191 + test('instance is accessible before init', () {
192 + // instance is always non-null; initialization requires the native
193 + // library to be compiled first.
194 + expect(RustLib.instance, isNotNull);
195 });
196 });
197
@@ -197,26 +202,25 @@ void main() {
202
203 test('config factories return valid configs', () {
204 expect(OndeInference.defaultModelConfig().modelId, isNotEmpty);
200 - expect(OndeInference.qwen251_5bConfig().modelId, contains('1.5B'));
205 + expect(OndeInference.qwen2515bConfig().modelId, contains('1.5B'));
206 expect(OndeInference.qwen253bConfig().modelId, contains('3B'));
202 - expect(OndeInference.qwen25Coder1_5bConfig().modelId, contains('Coder'));
207 + expect(OndeInference.qwen25Coder15bConfig().modelId, contains('Coder'));
208 expect(OndeInference.qwen25Coder3bConfig().modelId, contains('Coder'));
209 });
210
211 test('sampling factories return correct presets', () {
212 expect(OndeInference.defaultSamplingConfig().temperature, 0.7);
213 expect(OndeInference.deterministicSamplingConfig().temperature, 0.0);
209 - expect(OndeInference.mobileSamplingConfig().maxTokens, 128);
214 + expect(
215 + OndeInference.mobileSamplingConfig().maxTokens,
216 + BigInt.from(128),
217 + );
218 });
219 });
220
213 - group('OndeChatEngine stub', () {
214 - test('create() throws UnimplementedError before codegen', () async {
215 - // RustLib.init() is already called above; init guard is met.
216 - await expectLater(
217 - OndeChatEngine.create(),
218 - throwsA(isA<UnimplementedError>()),
219 - );
221 + group('OndeChatEngine', () {
222 + test('constructor throws when library not initialized', () {
223 + expect(() => OndeChatEngine(), throwsA(anything));
224 });
225 });
226 }