184 lines
4.9 KiB
Dart
184 lines
4.9 KiB
Dart
import 'package:flutter/services.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:fruitshorts/core/data/models/drama.dart';
|
|
import 'package:fruitshorts/core/data/models/play_ticket.dart';
|
|
import 'package:fruitshorts/core/data/models/player_port.dart';
|
|
import 'package:fruitshorts/core/data/models/wallet.dart';
|
|
import 'package:fruitshorts/core/data/repositories/commerce_repository.dart';
|
|
import 'package:fruitshorts/core/data/repositories/playback_repository.dart';
|
|
import 'package:fruitshorts/core/data/services/android_picture_in_picture.dart';
|
|
import 'package:fruitshorts/core/data/services/playback_session.dart';
|
|
import 'package:fruitshorts/core/data/services/wallet_controller.dart';
|
|
import 'package:fruitshorts/pages/player/player_logic.dart';
|
|
import 'package:fruitshorts/pages/player/player_view.dart';
|
|
|
|
import '../support/fake_watch_history.dart';
|
|
|
|
const _lockedDrama = Drama(
|
|
id: 'locked',
|
|
title: 'Locked',
|
|
synopsis: 'synopsis',
|
|
posterUrl: '/files/locked.png',
|
|
episodes: [
|
|
Episode(
|
|
id: 'locked-1',
|
|
number: 1,
|
|
title: 'Locked episode',
|
|
isFree: false,
|
|
locked: true,
|
|
),
|
|
],
|
|
);
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
test('should_not_request_ticket_for_guest_on_locked_episode', () async {
|
|
final playback = FakePlaybackRepository();
|
|
final logic = _logic(playback, signedIn: false);
|
|
logic.attach(
|
|
const PlayerPage(drama: _lockedDrama, initialIndex: 0),
|
|
isMounted: () => true,
|
|
);
|
|
logic.start(
|
|
factory: (_) => _NoopPlayer(),
|
|
coordinator: PlaybackCoordinator(),
|
|
);
|
|
await _drain(logic);
|
|
|
|
expect(playback.requests, isEmpty);
|
|
expect(logic.session.isLocked, isTrue);
|
|
|
|
logic.dispose();
|
|
await _drain(logic);
|
|
});
|
|
|
|
test('should_request_ticket_after_user_is_signed_in', () async {
|
|
final playback = FakePlaybackRepository(
|
|
ticket: const PlayTicket(
|
|
episodeId: 'locked-1',
|
|
accessible: false,
|
|
accessType: PlayTicket.coinRequired,
|
|
unlockCoin: 30,
|
|
),
|
|
);
|
|
final logic = _logic(playback, signedIn: true);
|
|
logic.attach(
|
|
const PlayerPage(drama: _lockedDrama, initialIndex: 0),
|
|
isMounted: () => true,
|
|
);
|
|
logic.start(
|
|
factory: (_) => _NoopPlayer(),
|
|
coordinator: PlaybackCoordinator(),
|
|
);
|
|
await _drain(logic);
|
|
|
|
expect(playback.requests, ['locked-1']);
|
|
expect(logic.blockedEpisodeId, 'locked-1');
|
|
|
|
logic.dispose();
|
|
await _drain(logic);
|
|
});
|
|
|
|
test('should_resume_unlock_and_play_for_same_episode_after_login', () async {
|
|
var signedIn = false;
|
|
final playback = FakePlaybackRepository(
|
|
ticket: const PlayTicket(
|
|
episodeId: 'locked-1',
|
|
accessible: true,
|
|
accessType: 'ENTITLED',
|
|
playUrl: '/files/locked-1.mp4',
|
|
),
|
|
);
|
|
final logic = _logic(
|
|
playback,
|
|
signedIn: false,
|
|
isSignedIn: () => signedIn,
|
|
wallet: WalletController(_UnlockCommerceRepository()),
|
|
);
|
|
logic.attach(
|
|
const PlayerPage(drama: _lockedDrama, initialIndex: 0),
|
|
isMounted: () => true,
|
|
);
|
|
logic.start(
|
|
factory: (_) => _NoopPlayer(),
|
|
coordinator: PlaybackCoordinator(),
|
|
);
|
|
await _drain(logic);
|
|
|
|
expect(playback.requests, isEmpty);
|
|
expect(logic.blockedEpisodeId, 'locked-1');
|
|
|
|
signedIn = true;
|
|
final unlocked = await logic.unlockEpisode(0);
|
|
await _drain(logic);
|
|
|
|
expect(unlocked, isTrue);
|
|
expect(playback.requests, ['locked-1']);
|
|
expect(logic.session.active, isNotNull);
|
|
|
|
logic.dispose();
|
|
await _drain(logic);
|
|
});
|
|
}
|
|
|
|
PlayerLogic _logic(
|
|
PlaybackRepository playback, {
|
|
bool signedIn = true,
|
|
bool Function()? isSignedIn,
|
|
WalletController? wallet,
|
|
}) {
|
|
return PlayerLogic(
|
|
history: FakeWatchHistory(),
|
|
playback: playback,
|
|
wallet: wallet,
|
|
pictureInPicture: AndroidPictureInPicture(
|
|
channel: const MethodChannel('test/player_locked_auth_flow/pip'),
|
|
),
|
|
waitForFrame: () async {},
|
|
isSignedIn: isSignedIn ?? () => signedIn,
|
|
);
|
|
}
|
|
|
|
Future<void> _drain(PlayerLogic logic) async {
|
|
for (var attempt = 0; attempt < 4; attempt++) {
|
|
await pumpEventQueue();
|
|
await logic.session.playbackSettled;
|
|
await logic.session.preloadSettled;
|
|
}
|
|
}
|
|
|
|
class _NoopPlayer implements PlayerPort {
|
|
@override
|
|
Future<void> initialize() async {}
|
|
|
|
@override
|
|
Future<void> play() async {}
|
|
|
|
@override
|
|
Future<void> pause() async {}
|
|
|
|
@override
|
|
Future<void> dispose() async {}
|
|
}
|
|
|
|
class _UnlockCommerceRepository implements CommerceRepository {
|
|
@override
|
|
Future<WalletSnapshot> fetchWallet() async => const WalletSnapshot(
|
|
wallet: CoinWallet(
|
|
coinBalance: 100,
|
|
totalRechargedCoin: 0,
|
|
totalConsumedCoin: 0,
|
|
totalRefundedCoin: 0,
|
|
),
|
|
);
|
|
|
|
@override
|
|
Future<UnlockResult> unlock(String episodeId) async => const UnlockResult(
|
|
unlocked: true,
|
|
accessType: 'ENTITLED',
|
|
coinCost: 30,
|
|
coinBalance: 70,
|
|
);
|
|
}
|