nandi/frqpublic Fork 0
408386015c3de0843f7d8d4c62a343ef2e6aea64
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.

live_ui.dart · 117 lines · 4.0 KBDart Blame HistoryRaw
The renderer, and a transport bug that took four tries 58e6c97 nandi yesterday1/// The whole stack, end to end: Nim's socket, Nim's state, Nim's screens.
2///
3/// Connects to a real freeq, waits for the room list to fill, opens a room and
4/// prints what the tree actually contains. Everything goes through the FFI, so
5/// what it proves is the same path the window uses.
6///
7/// Not in any test suite: it needs a network and a running freeq.
8///
9/// just nim-live
10import 'dart:io';
11import 'package:frq_core/frq_core.dart' as core;
12
13List<core.UiNode> find(core.UiNode n, String tag) =>
14 [if (n.tag == tag) n, for (final c in n.children) ...find(c, tag)];
15
16List<String> labels(core.UiNode n, String tag) =>
17 find(n, tag).map((e) => e.prop('label', '')).toList();
18
19Future<void> main(List<String> args) async {
20 final host = args.isNotEmpty ? args[0] : 'irc.freeq.at';
21 final nick = args.length > 1
22 ? args[1]
23 : 'frq-ui-${DateTime.now().millisecondsSinceEpoch % 10000}';
24
25 core.resetUi();
26 print('$host as $nick');
27
28 core.dispatch('nick.change', nick);
29 core.dispatch('host.change', host);
30 var tree = core.dispatch('connect');
31
32 final deadline = DateTime.now().add(const Duration(seconds: 25));
33 while (DateTime.now().isBefore(deadline)) {
34 await Future<void>.delayed(const Duration(milliseconds: 100));
35 tree = core.poll();
36 if (labels(tree, 'title').any((l) => l.startsWith('Logged in as'))) break;
37 final err = labels(tree, 'label').where((l) => l.startsWith(''));
38 if (err.isNotEmpty) {
39 print('${err.first}');
40 exit(1);
41 }
42 }
43
44 if (!labels(tree, 'title').any((l) => l.startsWith('Logged in as'))) {
45 print('✗ never reached the chats screen — still ${labels(tree, "title")}');
46 exit(1);
47 }
48 print('✓ chats screen: ${labels(tree, "title").first}');
49
50 // The room list, from the real server. Waited for rather than read on the
51 // instant we land: registration finishes before the JOIN echo that creates
52 // the buffer, so reading immediately is reading too early.
53 final roomsBy = DateTime.now().add(const Duration(seconds: 10));
54 var rooms = <String>[];
55 while (DateTime.now().isBefore(roomsBy)) {
56 await Future<void>.delayed(const Duration(milliseconds: 200));
57 tree = core.poll();
58 rooms = labels(tree, 'title-2');
59 if (rooms.isNotEmpty) break;
60 }
61 print('✓ rooms: $rooms');
62 if (rooms.isEmpty) {
63 print('✗ no rooms in the list');
64 exit(1);
65 }
66
67 // Open one and look at the conversation.
68 tree = core.dispatch('room.open:${rooms.first}');
69 await Future<void>.delayed(const Duration(seconds: 2));
70 tree = core.poll();
71
72 print('✓ chat screen: ${labels(tree, "title").first}');
73 final said = find(tree, 'text').map((e) => e.prop('text', '')).toList();
74 print('${said.length} text runs, ${find(tree, "link").length} links, '
75 '${find(tree, "avatar").length} avatars, '
76 '${find(tree, "reaction").length} reaction chips, '
77 '${find(tree, "separator").length} separators');
78 for (final line in said.take(6)) {
79 print(' | $line');
80 }
81
82 // Every tag the tree contains, so an unrendered one shows up here rather
83 // than as an orange box in the window.
84 final tags = <String>{};
85 void walk(core.UiNode n) {
86 tags.add(n.tag);
87 for (final c in n.children) {
88 walk(c);
89 }
90 }
91
92 walk(tree);
93 print('✓ tags in use: ${(tags.toList()..sort()).join(", ")}');
94
A sent message showed twice 9c1dfe9 nandi 19h ago95 // Send a line, and count how many times it comes back on screen.
96 //
97 // echo-message is negotiated, so the server returns every line this client
98 // sends — and showing both that and the local copy is what put every sent
99 // message on screen twice.
100 final marker = 'frq echo check ${DateTime.now().millisecondsSinceEpoch}';
101 core.dispatch('draft.change', marker);
102 core.dispatch('send');
103 await Future<void>.delayed(const Duration(seconds: 3));
104 tree = core.poll();
105 final copies = find(tree, 'text')
106 .where((e) => e.prop('text', '') == marker)
107 .length;
108 if (copies == 1) {
109 print('✓ sent line appears once');
110 } else {
111 print('✗ sent line appears $copies times');
112 exit(1);
113 }
114
The renderer, and a transport bug that took four tries 58e6c97 nandi yesterday115 core.dispatch('disconnect');
116 print('✓ disconnected');
117}