Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bitassets/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: bitassets
description: UI for Drivechain (BIP300/301) based sidechains
publish_to: "none" # Remove this line if you wish to publish to pub.dev

version: 1.0.152
version: 1.0.153

environment:
sdk: 3.11.0
Expand Down
40 changes: 10 additions & 30 deletions bitassets/test/test_utils.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import 'package:auto_route/auto_route.dart';
import 'package:bitassets/routing/router.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:get_it/get_it.dart';
import 'package:logger/logger.dart';
import 'package:sail_ui/pages/router.gr.dart';
import 'package:sail_ui/pages/sail_test_page.dart';
import 'package:sail_ui/sail_ui.dart';

import 'mocks/storage_mock.dart';
Expand All @@ -15,53 +12,30 @@ Future<void> _setDeviceSize() async {
await binding.setSurfaceSize(const Size(1200, 720));
}

Future<void> loadFonts() async {
final inter = rootBundle.load('./assets/fonts/Inter-Regular.ttf');
final fontLoader = FontLoader('Inter')..addFont(inter);
await fontLoader.load();
}

extension TestExtension on WidgetTester {
Future<void> pumpSailPage(
Widget child,
) async {
await _setDeviceSize();
await loadFonts();
await registerTestDependencies();

await pumpWidget(
SailApp(
dense: false,
builder: (context) {
final appRouter = GetIt.I.get<AppRouter>();

return MaterialApp.router(
routerDelegate: appRouter.delegate(
// ignore: deprecated_member_use
deepLinkBuilder: (_) => DeepLink([SailTestRoute(child: child)]),
),
routeInformationParser: appRouter.defaultRouteParser(),
title: 'BitAssets',
theme: ThemeData(
fontFamily: 'Inter',
),
);
return MaterialApp(home: SailTestPage(child: child));
},
initMethod: (_) async => (),
accentColor: SailColorScheme.black,
log: GetIt.I.get<Logger>(),
),
duration: const Duration(seconds: 10),
);
await pumpAndSettle();
await pump();
}
}

Future<void> registerTestDependencies() async {
if (!GetIt.I.isRegistered<AppRouter>()) {
GetIt.I.registerLazySingleton<AppRouter>(
() => AppRouter(),
);
}
final log = Logger();
if (!GetIt.I.isRegistered<Logger>()) {
GetIt.I.registerLazySingleton<Logger>(() => log);
Expand All @@ -86,6 +60,12 @@ Future<void> registerTestDependencies() async {
);
}

if (!GetIt.I.isRegistered<FormatterProvider>()) {
GetIt.I.registerLazySingleton<FormatterProvider>(
() => FormatterProvider(GetIt.I.get<SettingsProvider>()),
);
}

if (!GetIt.I.isRegistered<BinaryProvider>()) {
GetIt.I.registerLazySingleton<BinaryProvider>(
() => MockBinaryProvider(),
Expand Down
189 changes: 189 additions & 0 deletions bitassets/test/ui_integration_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:sail_ui/sail_ui.dart';

import 'test_utils.dart';

void main() {
TestWidgetsFlutterBinding.ensureInitialized({
'flutter.test.automatic_wait_for_timers': 'false',
});

group('UI Component Tests', () {
testWidgets('SailCard renders with title and content', (tester) async {
await tester.pumpSailPage(
SailCard(
title: 'BitAssets Portfolio',
subtitle: 'Digital asset management',
child: SailText.primary15('Card Content'),
),
);
await tester.pumpAndSettle();

expect(find.text('BitAssets Portfolio'), findsOneWidget);
expect(find.text('Digital asset management'), findsOneWidget);
expect(find.text('Card Content'), findsOneWidget);
});

testWidgets('SailColumn renders children vertically', (tester) async {
await tester.pumpSailPage(
SailColumn(
spacing: SailStyleValues.padding16,
children: [
SailText.primary15('First'),
SailText.primary15('Second'),
SailText.primary15('Third'),
],
),
);
await tester.pumpAndSettle();

final firstOffset = tester.getTopLeft(find.text('First'));
final secondOffset = tester.getTopLeft(find.text('Second'));
expect(secondOffset.dy, greaterThan(firstOffset.dy));
});

testWidgets('SailRow renders children horizontally', (tester) async {
await tester.pumpSailPage(
SailRow(
spacing: SailStyleValues.padding16,
children: [
SailText.primary15('Left'),
SailText.primary15('Right'),
],
),
);
await tester.pumpAndSettle();

final leftOffset = tester.getTopLeft(find.text('Left'));
final rightOffset = tester.getTopLeft(find.text('Right'));
expect(rightOffset.dx, greaterThan(leftOffset.dx));
});
});

group('Button Tests', () {
testWidgets('SailButton responds to tap', (tester) async {
bool wasPressed = false;

await tester.pumpSailPage(
SailButton(
label: 'Create Asset',
onPressed: () async {
wasPressed = true;
},
),
);
await tester.pumpAndSettle();

await tester.tap(find.byType(SailButton));
await tester.pumpAndSettle();

expect(wasPressed, isTrue);
});

testWidgets('SailButton loading state renders', (tester) async {
await tester.pumpSailPage(
SailButton(
label: 'Creating...',
loading: true,
onPressed: () async {},
),
);
await tester.pump();

expect(find.byType(SailButton), findsOneWidget);
});

testWidgets('Disabled SailButton does not trigger callback', (tester) async {
bool wasPressed = false;

await tester.pumpSailPage(
SailButton(
label: 'Disabled',
disabled: true,
onPressed: () async {
wasPressed = true;
},
),
);
await tester.pumpAndSettle();

await tester.tap(find.byType(SailButton));
await tester.pumpAndSettle();

expect(wasPressed, isFalse);
});
});

group('TextField Tests', () {
testWidgets('SailTextField accepts input', (tester) async {
final controller = TextEditingController();

await tester.pumpSailPage(
SailTextField(
controller: controller,
hintText: 'Enter asset ticker',
),
);
await tester.pumpAndSettle();

await tester.enterText(find.byType(TextField), 'MYASSET');
expect(controller.text, 'MYASSET');
});
});

group('Theme Tests', () {
testWidgets('Theme colors accessible from context', (tester) async {
await tester.pumpSailPage(
Builder(
builder: (context) {
final theme = SailTheme.of(context);
return Container(
color: theme.colors.background,
child: SailText.primary15('Themed'),
);
},
),
);
await tester.pumpAndSettle();

expect(find.text('Themed'), findsOneWidget);
});
});

group('Dropdown Tests', () {
testWidgets('SailDropdownButton renders with value', (tester) async {
await tester.pumpSailPage(
StatefulBuilder(
builder: (context, setState) => SailDropdownButton<String>(
value: 'token',
items: const [
SailDropdownItem(value: 'token', label: 'Token'),
SailDropdownItem(value: 'nft', label: 'NFT'),
],
onChanged: (value) {},
),
),
);
await tester.pumpAndSettle();

expect(find.text('Token'), findsOneWidget);
});
});

group('Checkbox Tests', () {
testWidgets('SailCheckbox renders', (tester) async {
await tester.pumpSailPage(
StatefulBuilder(
builder: (context, setState) => SailCheckbox(
value: false,
onChanged: (value) {},
),
),
);
await tester.pumpAndSettle();

expect(find.byType(SailCheckbox), findsOneWidget);
});
});
}
13 changes: 12 additions & 1 deletion bitassets/windows/runner/flutter_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,23 @@

#include "flutter/generated_plugin_registrant.h"
#include "desktop_multi_window/desktop_multi_window_plugin.h"
#include "url_launcher_windows/url_launcher_windows.h"

FlutterWindow::FlutterWindow(const flutter::DartProject& project)
: project_(project) {}

FlutterWindow::~FlutterWindow() {}

// Register only essential plugins for sub-windows.
// Some plugins (auto_updater, window_manager) have global state that crashes
// when registered multiple times in the same process.
void RegisterPluginsForSubWindow(flutter::PluginRegistry* registry) {
DesktopMultiWindowPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("DesktopMultiWindowPlugin"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
}

bool FlutterWindow::OnCreate() {
if (!Win32Window::OnCreate()) {
return false;
Expand All @@ -30,7 +41,7 @@ bool FlutterWindow::OnCreate() {
auto *flutter_view_controller =
reinterpret_cast<flutter::FlutterViewController *>(controller);
auto *registry = flutter_view_controller->engine();
RegisterPlugins(registry);
RegisterPluginsForSubWindow(registry);
});
SetChildContent(flutter_controller_->view()->GetNativeWindow());

Expand Down
2 changes: 1 addition & 1 deletion bitnames/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: bitnames
description: UI for Drivechain (BIP300/301) based sidechains
publish_to: "none" # Remove this line if you wish to publish to pub.dev

version: 1.0.151
version: 1.0.152

environment:
sdk: 3.11.0
Expand Down
Loading
Loading