1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:railway_clean_ip_scanner/app/controller.dart';
import 'package:railway_clean_ip_scanner/main.dart';
import 'package:railway_clean_ip_scanner/ui/widgets.dart';
import '../fakes.dart';
void _useDesktopSize(WidgetTester tester) {
tester.view.physicalSize = const Size(1280, 1400);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
}
AppController _controller(FakeEngine engine) {
final c = AppController(engine: engine);
c.animatedAurora = false;
return c;
}
void main() {
testWidgets('empty state renders the title, status and empty results text', (tester) async {
_useDesktopSize(tester);
final c = _controller(FakeEngine());
addTearDown(c.dispose);
await tester.pumpWidget(ScannerApp(controller: c));
await tester.pump();
expect(find.text('Twilight edition'), findsOneWidget);
expect(find.text('Ready'), findsOneWidget);
expect(find.text('Start scan'), findsOneWidget);
expect(find.text('Made by arblant & Muse'), findsOneWidget);
expect(
find.text('PC port by arblant — based on the Android app by Unknown37841 (MIT)'),
findsOneWidget,
);
expect(find.text('No clean IPs yet'), findsOneWidget);
expect(
find.text('Start a scan. Every IP is verified through a real tunnel, and the fastest ones appear here, ranked.'),
findsOneWidget,
);
expect(find.text('Copy top 5'), findsOneWidget);
expect(find.text('Build configs'), findsOneWidget);
});
testWidgets('starting a scan without a config shows the paste-first toast', (tester) async {
_useDesktopSize(tester);
final c = _controller(FakeEngine());
addTearDown(c.dispose);
await tester.pumpWidget(ScannerApp(controller: c));
await tester.pump();
await tester.tap(find.text('Start scan'));
await tester.pump();
await tester.pump(const Duration(milliseconds: 400));
expect(find.text('Paste a VLESS config first to load your server'), findsOneWidget);
expect(
find.text('Please paste a VLESS config above to load your server.'),
findsOneWidget,
);
});
testWidgets('results show the fastest card and the ranked list', (tester) async {
_useDesktopSize(tester);
final engine = FakeEngine(scanResults: [ok('10.0.0.1', 90), ok('10.0.0.2', 240)]);
final c = _controller(engine);
addTearDown(c.dispose);
await c.parseLink(sampleLink);
await tester.pumpWidget(ScannerApp(controller: c));
await tester.runAsync(() => c.toggleScan());
await tester.pump();
expect(find.text('FASTEST'), findsOneWidget);
expect(find.text('TOP PICK'), findsOneWidget);
expect(find.text('STABLE'), findsOneWidget);
expect(find.text('Clean IPs'), findsOneWidget);
expect(find.text('by delay'), findsOneWidget);
expect(find.text('01'), findsNothing);
expect(find.text('02'), findsOneWidget);
expect(find.text('90 ms'), findsWidgets);
expect(find.text('240 ms'), findsOneWidget);
});
testWidgets('Build configs opens the workbench with the rows and actions', (tester) async {
_useDesktopSize(tester);
final engine = FakeEngine(scanResults: [ok('10.0.0.1', 90)]);
final c = _controller(engine);
addTearDown(c.dispose);
await c.parseLink(sampleLink);
await tester.pumpWidget(ScannerApp(controller: c));
await tester.runAsync(() => c.toggleScan());
await tester.pump();
await tester.tap(find.text('Build configs'));
await tester.pump();
await tester.pump(const Duration(milliseconds: 400));
expect(find.text('CONFIGS'), findsOneWidget);
expect(find.text('Top N'), findsOneWidget);
expect(find.text('Best for all'), findsOneWidget);
expect(find.text('Custom'), findsOneWidget);
expect(find.text('Test these'), findsOneWidget);
expect(find.text('Generate & copy'), findsOneWidget);
expect(find.text('01'), findsOneWidget);
await tester.scrollUntilVisible(
find.text('05'),
120,
scrollable: find.byType(Scrollable).last,
);
expect(find.text('05'), findsOneWidget);
expect(find.text('Only 1 clean IP found, so some configs will share one.'), findsOneWidget);
});
testWidgets('the workbench says to scan first when there are no results', (tester) async {
_useDesktopSize(tester);
final c = _controller(FakeEngine());
addTearDown(c.dispose);
await tester.pumpWidget(ScannerApp(controller: c));
await tester.pump();
await tester.tap(find.text('Build configs'));
await tester.pump();
await tester.pump(const Duration(milliseconds: 400));
expect(find.text('Scan first to build configs'), findsOneWidget);
});
testWidgets('there is no Parse button, and Paste parses the link at once', (tester) async {
_useDesktopSize(tester);
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (call) async {
if (call.method == 'Clipboard.getData') {
return <String, dynamic>{'text': sampleLink};
}
return null;
});
addTearDown(() => tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null));
final c = _controller(FakeEngine());
addTearDown(c.dispose);
await tester.pumpWidget(ScannerApp(controller: c));
await tester.pump();
expect(find.text('Parse'), findsNothing);
expect(find.text('Paste'), findsOneWidget);
await tester.tap(find.text('Paste'));
await tester.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 50)));
await tester.pump();
expect(c.uuid.text, isNotEmpty);
expect(c.parseHint, startsWith('Parsed VLESS'));
});
testWidgets('the idle ring shows 0 of 254 and the Ready status', (tester) async {
_useDesktopSize(tester);
final c = _controller(FakeEngine());
addTearDown(c.dispose);
await tester.pumpWidget(ScannerApp(controller: c));
await tester.pump(const Duration(milliseconds: 700));
expect(find.byType(ScanRing), findsOneWidget);
expect(find.text('of 254'), findsOneWidget);
expect(find.text('Ready'), findsOneWidget);
});
testWidgets('the layout fits a phone-sized window', (tester) async {
tester.view.physicalSize = const Size(390, 844);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
final c = _controller(FakeEngine());
addTearDown(c.dispose);
await tester.pumpWidget(ScannerApp(controller: c));
await tester.pump(const Duration(milliseconds: 700));
expect(tester.takeException(), isNull);
expect(find.text('Start scan'), findsOneWidget);
expect(find.text('Copy top 5'), findsOneWidget);
});
}