Files
plezy/test/widgets/oauth_proxy_dialog_test.dart
edde746 f1d4be70e2 feat(trackers): show a QR code in every tracker sign-in dialog and fit them on TV screens
Every tracker auth dialog (Trakt/Simkl/MDBList device-code and MAL/AniList
OAuth proxy) now shares the same PendingAuthDialog affordances: a QR code for
the sign-in URL, a large copyable URL with the scheme stripped, the browser
launch button (hidden on Apple TV, which has no browser), and the polling
spinner. On wide viewports (TV logical 960x540, desktop, phone landscape) the
QR pane sits beside the instructions so the dialog no longer clips on tvOS,
and the content is scrollable as an overflow safety net. Device activation
codes scale down instead of wrapping.
2026-08-10 08:33:11 +02:00

68 lines
2.5 KiB
Dart

import 'dart:ui' show SemanticsAction, Tristate;
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:plezy/i18n/strings.g.dart';
import 'package:plezy/services/trackers/oauth_proxy_client.dart';
import 'package:plezy/widgets/oauth_proxy_dialog.dart';
import 'package:qr_flutter/qr_flutter.dart';
void main() {
setUpAll(() => LocaleSettings.setLocaleSync(AppLocale.en));
const start = OAuthProxyStart(session: 'session-token', url: 'https://example.com/oauth/start', expiresIn: 600);
testWidgets('copy control exposes the OAuth URL as its value', (tester) async {
final semantics = tester.ensureSemantics();
tester.view.devicePixelRatio = 1;
tester.view.physicalSize = const Size(1024, 768);
addTearDown(tester.view.resetDevicePixelRatio);
addTearDown(tester.view.resetPhysicalSize);
await tester.pumpWidget(
MaterialApp(
home: OAuthProxyDialog(start: start, serviceName: 'Example', onCancel: () {}),
),
);
final finder = find.bySemanticsLabel(t.services.pendingAuth.copyUrl);
expect(finder, findsOneWidget);
final data = tester.getSemantics(finder).getSemanticsData();
expect(data.value, start.url);
expect(data.flagsCollection.isButton, isTrue);
expect(data.flagsCollection.isEnabled, Tristate.isTrue);
expect(data.hasAction(SemanticsAction.tap), isTrue);
expect(find.bySemanticsLabel(start.url), findsNothing);
semantics.dispose();
});
testWidgets('always shows a QR code encoding the sign-in URL', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: OAuthProxyDialog(start: start, serviceName: 'Example', onCancel: () {}),
),
);
expect(find.byType(QrImageView), findsOneWidget);
expect(find.text('example.com/oauth/start'), findsOneWidget);
});
testWidgets('fits within a tvOS-sized 960x540 logical viewport without overflowing', (tester) async {
tester.view.devicePixelRatio = 1;
tester.view.physicalSize = const Size(960, 540);
addTearDown(tester.view.resetDevicePixelRatio);
addTearDown(tester.view.resetPhysicalSize);
await tester.pumpWidget(
MaterialApp(
home: OAuthProxyDialog(start: start, serviceName: 'Example', onCancel: () {}),
),
);
// Wide layout: QR beside the instructions, dialog fully on screen.
final dialogRect = tester.getRect(find.byType(AlertDialog));
expect(dialogRect.height, lessThanOrEqualTo(540));
expect(tester.takeException(), isNull);
});
}