nandi/frqpublic Fork 0
36bdfc5f7539b88587f3ce83e2701a6bc844f191
Commits
Clone
git clone https://git.rickub.com/nandi/frq.git
git clone ssh://git@rickub.com/nandi/frq.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

nim_layout_test.dart · 139 lines · 4.7 KBDart Blame HistoryRaw
Lay every screen out in a test, and fix what that found 36bdfc5 nandi yesterday1/// Every screen, laid out for real, at sizes that squeeze.
2///
3/// This is the test that was missing. `Cannot hit test a render box that has
4/// never been laid out` is what a failed layout looks like from the outside,
5/// and nothing automated ever laid the chat screen out — a GUI on Wayland
6/// cannot be clicked, so every check stopped at the room list while the
7/// biggest screen in the app went out unverified.
8///
9/// `tester.takeException()` is the whole point: a layout error is reported to
10/// FlutterError rather than thrown at the caller, so a test that only pumps
11/// and asserts on widgets passes while the screen is broken. These fail.
12///
13/// just test layout
14import 'package:flutter/material.dart';
15import 'package:flutter_test/flutter_test.dart';
16import 'package:frq_core/frq_core.dart' as core;
17import 'package:cljd_flutter/nim_renderer.dart';
18
19/// Phone, small desktop, and a deliberately cramped one. The head row of the
20/// chat screen asks for more than 360 points has, which is why it wraps.
21const sizes = <String, Size>{
22 'phone': Size(360, 690),
23 'desktop': Size(1280, 800),
24 'cramped': Size(300, 500),
25};
26
27Future<void> layOut(WidgetTester tester, Size size) async {
28 await tester.binding.setSurfaceSize(size);
29 addTearDown(() => tester.binding.setSurfaceSize(null));
30 await tester.pumpWidget(const NimApp());
31 await tester.pump();
32}
33
34/// Nothing went to FlutterError while that frame was built.
35void expectLaidOut(WidgetTester tester, String what) {
36 final e = tester.takeException();
37 expect(e, isNull, reason: '$what reported: $e');
38}
39
40void main() {
41 // No offline guard needed: `demoUi` sets the state directly and none of
42 // these dispatch `connect`, so nothing here opens a socket.
43
44 group('the connect screen', () {
45 for (final entry in sizes.entries) {
46 testWidgets('lays out at ${entry.key}', (tester) async {
47 core.resetUi();
48 await layOut(tester, entry.value);
49 expectLaidOut(tester, 'connect at ${entry.key}');
50 });
51 }
52
53 testWidgets('lays out in every auth mode', (tester) async {
54 for (final mode in ['guest', 'bluesky', 'app-password']) {
55 core.resetUi();
56 core.dispatch('mode.$mode');
57 await layOut(tester, sizes['phone']!);
58 expectLaidOut(tester, 'connect in $mode');
59 }
60 });
61 });
62
63 group('the chat screen', () {
64 // The one that was never laid out by anything automated.
65 for (final entry in sizes.entries) {
66 testWidgets('lays out at ${entry.key}', (tester) async {
67 core.demoUi();
68 await layOut(tester, entry.value);
69 expectLaidOut(tester, 'chat at ${entry.key}');
70 });
71 }
72
73 testWidgets('renders the conversation it was given', (tester) async {
74 core.demoUi();
75 await layOut(tester, sizes['desktop']!);
76 expect(find.text('hello there'), findsOneWidget);
77 expect(find.text('#test'), findsWidgets);
78 expectLaidOut(tester, 'chat content');
79 });
80
81 testWidgets('lays out with the people panel up', (tester) async {
82 core.demoUi();
83 core.dispatch('users.toggle');
84 await layOut(tester, sizes['desktop']!);
85 expectLaidOut(tester, 'chat with people');
86 });
87
88 testWidgets('lays out with every compose banner showing', (tester) async {
89 core.demoUi();
90 core.dispatch('reply.to:2');
91 await layOut(tester, sizes['phone']!);
92 expectLaidOut(tester, 'chat replying');
93
94 core.demoUi();
95 core.dispatch('edit.start:7');
96 await layOut(tester, sizes['phone']!);
97 expectLaidOut(tester, 'chat editing');
98 });
99
100 testWidgets('lays out when scrolled off the present', (tester) async {
101 core.demoUi();
102 core.dispatch('jump.present');
103 await layOut(tester, sizes['phone']!);
104 expectLaidOut(tester, 'chat jumping');
105 });
106 });
107
108 group('the chats list', () {
109 for (final entry in sizes.entries) {
110 testWidgets('lays out at ${entry.key}', (tester) async {
111 core.demoUi();
112 core.dispatch('screen.chats');
113 await layOut(tester, entry.value);
114 expectLaidOut(tester, 'chats at ${entry.key}');
115 });
116 }
117
118 testWidgets('lays out with a search term in the box', (tester) async {
119 core.demoUi();
120 core.dispatch('screen.chats');
121 core.dispatch('search.change', 'te');
122 await layOut(tester, sizes['phone']!);
123 expectLaidOut(tester, 'chats searching');
124 });
125 });
126
127 group('discover and settings', () {
128 for (final screen in ['discover', 'settings']) {
129 for (final entry in sizes.entries) {
130 testWidgets('$screen lays out at ${entry.key}', (tester) async {
131 core.demoUi();
132 core.dispatch('screen.$screen');
133 await layOut(tester, entry.value);
134 expectLaidOut(tester, '$screen at ${entry.key}');
135 });
136 }
137 }
138 });
139}