Invite: just the link (password included), one Copy button, a note only when needed, other addresses behind a toggle
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5116923858
commit
cf61453e28
12 files changed
+179
-163
No files matched your search
@@ -56,16 +56,15 @@ void main() {
|
||||
expect(InviteLink.parse('starsync://a b:1'), isNull);
|
||||
});
|
||||
|
||||
test('the invite copies its link, the password only when asked; old apps still read the address', () {
|
||||
test('the invite is just its link, with the password when one is set', () {
|
||||
const invite = Invite(host: '192.168.1.20', port: 8080, name: "Bob's server", password: true, version: '1.3.2');
|
||||
expect(invite.text, contains('(ask me for the password)'));
|
||||
expect(invite.text, isNot(contains('pw=')));
|
||||
final withPw = invite.textWith(secret: 'hunter2');
|
||||
expect(withPw, isNot(contains('ask me')));
|
||||
expect(inviteIn(withPw)?.secret, 'hunter2');
|
||||
expect(inviteIn(withPw)?.name, "Bob's server");
|
||||
final link = invite.link(secret: 'hunter2');
|
||||
expect(link.uri, 'starsync://192.168.1.20:8080/?name=Bob%27s+server&pw=hunter2');
|
||||
expect(inviteIn(link.uri), link);
|
||||
expect(link.toString(), isNot(contains('hunter2')));
|
||||
expect(const Invite(host: '192.168.1.20', port: 8080).link().uri, 'starsync://192.168.1.20:8080');
|
||||
// A 1.3.x app pasting it into the Join card's address.
|
||||
expect(addressIn(withPw), (host: '192.168.1.20', port: '8080'));
|
||||
expect(addressIn(link.uri), (host: '192.168.1.20', port: '8080'));
|
||||
expect(invite.at('203.0.113.7').address, '203.0.113.7:8080');
|
||||
});
|
||||
|
||||
@@ -172,7 +171,7 @@ void main() {
|
||||
offers.fromClipboard('starsync://127.0.0.1:40000');
|
||||
expect(offers.offer.peek(), isNull);
|
||||
// What this app just copied is not offered back to it.
|
||||
const copied = 'Join me on Starsync: starsync://198.51.100.4:8080';
|
||||
const copied = 'starsync://198.51.100.4:8080';
|
||||
offers.copied(copied);
|
||||
offers.fromClipboard(copied);
|
||||
expect(offers.offer.peek(), isNull);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart' show SystemChannels;
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:signals/signals_flutter.dart' show signal;
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
@@ -301,13 +302,12 @@ void main() {
|
||||
expect(isFakeIp(InternetAddress('198.20.1.1').rawAddress), isFalse);
|
||||
});
|
||||
|
||||
test('an invite: the address, whether to ask for a password, the version; pasted back', () {
|
||||
test('an invite: the address, its link; pasted back', () {
|
||||
const invite = Invite(host: '192.168.1.20', port: 8080, password: true, version: '1.3.0');
|
||||
expect(invite.address, '192.168.1.20:8080');
|
||||
expect(invite.text,
|
||||
'Join me on Starsync: starsync://192.168.1.20:8080 (ask me for the password) · Starsync 1.3.0');
|
||||
expect(invite.link().uri, 'starsync://192.168.1.20:8080');
|
||||
expect(invite.fp, isNull, reason: 'reserved for pinned certificates');
|
||||
expect(addressIn(invite.text), (host: '192.168.1.20', port: '8080'));
|
||||
expect(addressIn(invite.link().uri), (host: '192.168.1.20', port: '8080'));
|
||||
expect(addressIn('vps.example.com:9000'), (host: 'vps.example.com', port: '9000'));
|
||||
expect(addressIn('[fe80::1]:8080'), (host: 'fe80::1', port: '8080'));
|
||||
expect(addressIn('just a host'), isNull);
|
||||
@@ -367,31 +367,51 @@ void main() {
|
||||
yours.reach.value = const InviteReach(local: ['192.168.1.20'], looking: true);
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 400));
|
||||
expect(find.text('192.168.1.20:8080'), findsOneWidget);
|
||||
expect(find.text('Looking up your internet address…'), findsOneWidget);
|
||||
expect(find.text('Copy invite link'), findsOneWidget);
|
||||
expect(find.byKey(const ValueKey('stop-sharing')), findsOneWidget);
|
||||
expect(find.textContaining('friends on your network'), findsOneWidget);
|
||||
// No password set: nothing to tick.
|
||||
expect(find.byKey(const ValueKey('invite-with-password')), findsNothing);
|
||||
// One address so far: nothing else to pick, nothing to say.
|
||||
expect(find.byKey(const ValueKey('invite-other-addresses')), findsNothing);
|
||||
expect(find.byKey(const ValueKey('invite-note')), findsNothing);
|
||||
|
||||
// Behind a router: the internet address first, with the forwarding
|
||||
// it needs; the home address stays a choice.
|
||||
// Behind a router: the internet address, one line on forwarding;
|
||||
// the home address waits behind Other addresses.
|
||||
yours.shared.value = const Invite(host: '203.0.113.7', port: 8080, version: '1.3.0');
|
||||
yours.reach.value = const InviteReach(public: '203.0.113.7', local: ['192.168.1.20']);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('203.0.113.7:8080'), findsOneWidget);
|
||||
expect(find.text('192.168.1.20:8080'), findsOneWidget);
|
||||
expect(find.textContaining('port 8080 is forwarded on your router to this computer (192.168.1.20)'),
|
||||
expect(find.text('Looking up your internet address…'), findsNothing);
|
||||
expect(find.text('Friends outside your home network need port 8080 forwarded to this computer.'),
|
||||
findsOneWidget);
|
||||
expect(find.text('192.168.1.20:8080'), findsNothing);
|
||||
Future<String?> copy() async {
|
||||
String? copied;
|
||||
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (call) async {
|
||||
if (call.method == 'Clipboard.setData') copied = (call.arguments as Map)['text'] as String;
|
||||
return null;
|
||||
});
|
||||
addTearDown(() => tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null));
|
||||
await tester.tap(find.byKey(const ValueKey('copy-invite')));
|
||||
await tester.pumpAndSettle();
|
||||
return copied;
|
||||
}
|
||||
|
||||
// Just the link, nothing around it.
|
||||
expect(await copy(), matches(RegExp(r'^starsync://203\.0\.113\.7:8080(/\?name=\S+)?$')));
|
||||
|
||||
await tester.tap(find.byKey(const ValueKey('invite-other-addresses')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('203.0.113.7:8080'), findsOneWidget);
|
||||
await tester.tap(find.text('192.168.1.20:8080'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.textContaining('friends on your network'), findsOneWidget);
|
||||
expect(find.byKey(const ValueKey('invite-note')), findsNothing, reason: 'home network picked');
|
||||
expect(await copy(), startsWith('starsync://192.168.1.20:8080'));
|
||||
|
||||
// No internet address found: say what friends elsewhere need.
|
||||
// No internet address found: one line saying so.
|
||||
yours.reach.value = const InviteReach(local: ['192.168.1.20']);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.textContaining('VPS'), findsOneWidget);
|
||||
expect(find.textContaining("Couldn't find your internet address"), findsOneWidget);
|
||||
expect(_graph.notifier.toasts.peek().map((t) => t.text), contains('Invite link copied'));
|
||||
await tester.pump(const Duration(seconds: 6)); // the toasts go
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import 'package:starsync/src/session/session_coordinator.dart';
|
||||
import 'package:starsync/src/state/server_isolate.dart';
|
||||
import 'package:sync_relay_server/server.dart' show SyncServer;
|
||||
|
||||
import 'package:starsync/src/session/invite.dart' show InviteLink;
|
||||
import 'package:starsync/src/session/navigation.dart' show Place;
|
||||
|
||||
import 'test_graph.dart';
|
||||
@@ -166,6 +167,11 @@ void main() {
|
||||
final invite = await yours.invite();
|
||||
expect(invite.port, port);
|
||||
expect(invite.password, isTrue);
|
||||
// The link is the key: the password it was shared with, even when
|
||||
// the setting changes later.
|
||||
graph.forms.form.hostSecret = 'changed';
|
||||
expect(InviteLink.parse(yours.inviteLink(invite))?.secret, 'pw');
|
||||
graph.forms.form.hostSecret = 'pw';
|
||||
expect(yours.shared.peek(), invite);
|
||||
expect(identical(await yours.invite(), invite), isTrue, reason: 'already shared: the same invite');
|
||||
|
||||
|
||||
Reference in new issue
Block a user