qwen can use tests.
gui test is working.
|
|
@ -9,7 +9,7 @@
|
||||||
- `flutter pub get` --> `./flutterw pub get`
|
- `flutter pub get` --> `./flutterw pub get`
|
||||||
- `flutter run -d linux` --> `./flutterw run -d linux`
|
- `flutter run -d linux` --> `./flutterw run -d linux`
|
||||||
- See `./Makefile` for more examples.
|
- See `./Makefile` for more examples.
|
||||||
- If you are an agent, you may be also containerized. Try `distrobox-host-exec $(pwd)/flutterw`
|
- If you are an agent, you may be also containerized. If podman or docker is not available, try `distrobox-host-exec ./flutterw`
|
||||||
|
|
||||||
|
|
||||||
# MANDATORY WORKFLOW
|
# MANDATORY WORKFLOW
|
||||||
|
|
|
||||||
BIN
evaluation-2.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
evaluation-with-expression.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
evaluation.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
formula-list.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
import-from-dart-literal.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
import-preview.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
|
|
@ -443,17 +443,17 @@ class _FormulaEditorState extends State<FormulaEditor> {
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const Text('Base Unit', style: TextStyle(fontSize: 12)),
|
|
||||||
DropdownButtonFormField<String?>(
|
DropdownButtonFormField<String?>(
|
||||||
value: _getBaseUnit(variable.unit),
|
value: _getBaseUnit(variable.unit),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
|
labelText: "Base unit",
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 0),
|
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 0),
|
||||||
),
|
),
|
||||||
items: [
|
items: [
|
||||||
const DropdownMenuItem<String?>(
|
const DropdownMenuItem<String?>(
|
||||||
value: null,
|
value: null,
|
||||||
child: Text('None', style: TextStyle(fontSize: 14)),
|
child: Text('None', style: TextStyle(fontSize: 14)),
|
||||||
),
|
),
|
||||||
..._getAllBaseUnits().map((baseUnit) {
|
..._getAllBaseUnits().map((baseUnit) {
|
||||||
return DropdownMenuItem<String?>(
|
return DropdownMenuItem<String?>(
|
||||||
|
|
@ -476,11 +476,11 @@ class _FormulaEditorState extends State<FormulaEditor> {
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const Text('Derived Unit', style: TextStyle(fontSize: 12)),
|
|
||||||
DropdownButtonFormField<String?>(
|
DropdownButtonFormField<String?>(
|
||||||
value: variable.unit,
|
value: variable.unit,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
|
labelText: "Derived unit",
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 0),
|
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 0),
|
||||||
),
|
),
|
||||||
items: [
|
items: [
|
||||||
|
|
@ -546,11 +546,11 @@ class _FormulaEditorState extends State<FormulaEditor> {
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const Text('Base Unit', style: TextStyle(fontSize: 12)),
|
|
||||||
DropdownButtonFormField<String?>(
|
DropdownButtonFormField<String?>(
|
||||||
value: _getBaseUnit(_outputVariable.unit),
|
value: _getBaseUnit(_outputVariable.unit),
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
|
labelText: "Base unit",
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 0),
|
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 0),
|
||||||
),
|
),
|
||||||
items: [
|
items: [
|
||||||
|
|
@ -579,11 +579,11 @@ class _FormulaEditorState extends State<FormulaEditor> {
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const Text('Derived Unit', style: TextStyle(fontSize: 12)),
|
|
||||||
DropdownButtonFormField<String?>(
|
DropdownButtonFormField<String?>(
|
||||||
value: _outputVariable.unit,
|
value: _outputVariable.unit,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
|
labelText: "Derived unit",
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 0),
|
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 0),
|
||||||
),
|
),
|
||||||
items: [
|
items: [
|
||||||
|
|
|
||||||
|
|
@ -16,26 +16,28 @@ void main() async {
|
||||||
// Setup service locator and initialize the database
|
// Setup service locator and initialize the database
|
||||||
setupLocator();
|
setupLocator();
|
||||||
|
|
||||||
runApp(const MyApp());
|
var corpusFuture = loadCorpusFromDatabaseOrAssets();
|
||||||
|
|
||||||
|
runApp( MyApp(corpusFuture));
|
||||||
}
|
}
|
||||||
|
|
||||||
final GlobalKey<_CorpusLoaderState> corpusLoaderKey = GlobalKey<_CorpusLoaderState>();
|
final GlobalKey<_CorpusLoaderState> corpusLoaderKey = GlobalKey<_CorpusLoaderState>();
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
const MyApp({Key? key}) : super(key: key);
|
final Future<Corpus> corpusFuture;
|
||||||
|
MyApp(this.corpusFuture, {Key? key}) : super(key: key);
|
||||||
get corpusFuture => corpusLoaderKey.currentState?._corpusFuture;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
home: CorpusLoader(),
|
home: CorpusLoader(corpusFuture),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CorpusLoader extends StatefulWidget {
|
class CorpusLoader extends StatefulWidget {
|
||||||
CorpusLoader({Key? key}) : super(key: corpusLoaderKey);
|
final Future<Corpus> corpusFuture;
|
||||||
|
CorpusLoader(this.corpusFuture, {Key? key}) : super(key: corpusLoaderKey);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CorpusLoader> createState() => _CorpusLoaderState();
|
State<CorpusLoader> createState() => _CorpusLoaderState();
|
||||||
|
|
@ -44,11 +46,10 @@ class CorpusLoader extends StatefulWidget {
|
||||||
class _CorpusLoaderState extends State<CorpusLoader> {
|
class _CorpusLoaderState extends State<CorpusLoader> {
|
||||||
late Future<Corpus> _corpusFuture;
|
late Future<Corpus> _corpusFuture;
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_corpusFuture = loadCorpusFromDatabaseOrAssets();
|
_corpusFuture = widget.corpusFuture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleImport() {
|
void _handleImport() {
|
||||||
|
|
|
||||||
BIN
list-with-search.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
2
screenshots.org
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
[[file:evaluation-2.png]][[file:evaluation-with-expression.png]][[file:list-with-search.png]]
|
||||||
|
[[file:sharing-formula.png]][[file:import-from-dart-literal.png]][[file:import-preview.png]]
|
||||||
BIN
sharing-formula.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
44
test/app_test.dart
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:d4rt_formulas/defaults/default_corpus.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:d4rt_formulas/main.dart';
|
||||||
|
import 'package:d4rt_formulas/corpus.dart';
|
||||||
|
import 'package:d4rt_formulas/formula_models.dart';
|
||||||
|
import 'package:d4rt_formulas/database/database_service.dart';
|
||||||
|
import 'package:d4rt_formulas/service_locator.dart';
|
||||||
|
import 'package:get_it/get_it.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
testWidgets('selects first formula and opens editor from AppBar', (WidgetTester tester) async {
|
||||||
|
// Build the app
|
||||||
|
var corpus = await createDefaultCorpus();
|
||||||
|
var corpusCompleter = Completer<Corpus>();
|
||||||
|
corpusCompleter.complete(corpus);
|
||||||
|
var app = MyApp(corpusCompleter.future);
|
||||||
|
await tester.pumpWidget(app);
|
||||||
|
await tester.pump();
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 10));
|
||||||
|
|
||||||
|
// Verify FormulaList is shown
|
||||||
|
expect(find.byType(ListView), findsOneWidget);
|
||||||
|
|
||||||
|
// Find and tap the first formula in the list
|
||||||
|
final formulaTile = find.byType(ListTile).first;
|
||||||
|
expect(formulaTile, findsOneWidget);
|
||||||
|
await tester.tap(formulaTile);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
|
||||||
|
// Find and tap the edit icon in the AppBar
|
||||||
|
final editIcon = find.byIcon(Icons.edit);
|
||||||
|
expect(editIcon, findsOneWidget);
|
||||||
|
await tester.tap(editIcon);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// Verify FormulaEditor is shown
|
||||||
|
expect(find.text('Edit Formula'), findsOneWidget);
|
||||||
|
});
|
||||||
|
}
|
||||||