Files
Prisma/test/backend/pawchive_sync_test.dart
T

270 lines
8.4 KiB
Dart

import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:gel_rule_app/backend/models/favorite_artist_item.dart';
import 'package:gel_rule_app/backend/models/pawchive_account.dart';
import 'package:gel_rule_app/backend/services/pawchive_sync_service.dart';
import 'package:gel_rule_app/backend/services/settings_service.dart';
class _FakeAdapter implements HttpClientAdapter {
_FakeAdapter(this.handler);
final Future<ResponseBody> Function(RequestOptions options) handler;
@override
Future<ResponseBody> fetch(
RequestOptions options,
Stream<dynamic>? requestStream,
Future<void>? cancelFuture,
) {
return handler(options);
}
@override
void close({bool force = false}) {}
}
void main() {
group('FavoriteArtistItem Tests', () {
test('roundtrip serialization and key generation', () {
const item = FavoriteArtistItem(
id: '12345',
service: 'fanbox',
providerId: 'pawchive',
name: 'CoolArtist',
avatarUrl: 'https://pawchive.pw/icons/fanbox/12345',
);
expect(item.key, equals('pawchive:fanbox:12345'));
expect(item.isEmpty, isFalse);
final json = item.toJson();
final restored = FavoriteArtistItem.fromJson(json);
expect(restored.key, equals(item.key));
expect(restored.name, equals('CoolArtist'));
expect(restored.avatarUrl, equals('https://pawchive.pw/icons/fanbox/12345'));
expect(restored == item, isTrue);
});
test('empty factory behaves correctly', () {
const empty = FavoriteArtistItem.empty();
expect(empty.isEmpty, isTrue);
expect(empty.key, equals('::'));
});
});
group('PawchiveAccount Tests', () {
test('roundtrip serialization and copyWith', () {
final now = DateTime(2026, 9, 4, 12, 0, 0);
final account = PawchiveAccount(
id: 'tester',
username: 'Tester',
sessionCookie: 'eySessionToken123',
baseUrl: 'https://pawchive.pw',
createdAt: now,
lastSyncedAt: now,
isActive: true,
syncedArtistsCount: 15,
);
final json = account.toJson();
final restored = PawchiveAccount.fromJson(json);
expect(restored.id, equals('tester'));
expect(restored.username, equals('Tester'));
expect(restored.sessionCookie, equals('eySessionToken123'));
expect(restored.isActive, isTrue);
expect(restored.syncedArtistsCount, equals(15));
expect(restored == account, isTrue);
final updated = account.copyWith(isActive: false, syncedArtistsCount: 20);
expect(updated.isActive, isFalse);
expect(updated.syncedArtistsCount, equals(20));
expect(updated.id, equals('tester'));
});
});
group('AppSettings Pawchive integration tests', () {
test('serializes and parses pawchive accounts correctly', () {
final acc1 = PawchiveAccount(
id: 'user1',
username: 'User1',
sessionCookie: 'token1',
createdAt: DateTime(2026, 9, 1),
isActive: true,
syncedArtistsCount: 5,
);
final acc2 = PawchiveAccount(
id: 'user2',
username: 'User2',
sessionCookie: 'token2',
createdAt: DateTime(2026, 9, 2),
isActive: false,
syncedArtistsCount: 10,
);
final settings = AppSettings.defaults.copyWith(
pawchiveAccounts: [
jsonEncode(acc1.toJson()),
jsonEncode(acc2.toJson()),
],
);
expect(settings.parsedPawchiveAccounts.length, equals(2));
expect(settings.activePawchiveAccount?.id, equals('user1'));
final json = settings.toJson();
final restored = AppSettings.fromJson(json);
expect(restored.parsedPawchiveAccounts.length, equals(2));
expect(restored.activePawchiveAccount?.username, equals('User1'));
});
});
group('PawchiveSyncService Tests', () {
test('fetchRemoteFavoriteArtists parses server response correctly', () async {
final dio = Dio();
dio.httpClientAdapter = _FakeAdapter((options) async {
if (options.path.endsWith('/account/favorites') &&
options.queryParameters['type'] == 'artist') {
final cookie = options.headers['Cookie'] as String?;
expect(cookie, contains('session=test_cookie_123'));
final payload = jsonEncode([
{
'id': '98765',
'service': 'fanbox',
'name': 'AlphaCreator',
'updated': '2026-09-04T10:00:00.000Z',
},
{
'id': '43210',
'service': 'patreon',
'name': 'BetaCreator',
'updated': '2026-09-03T15:00:00.000Z',
},
]);
return ResponseBody.fromString(
payload,
200,
headers: {
Headers.contentTypeHeader: [Headers.jsonContentType],
},
);
}
return ResponseBody.fromString('Not found', 404);
});
final service = PawchiveSyncService(dio: dio);
final items = await service.fetchRemoteFavoriteArtists(
baseUrl: 'https://pawchive.pw',
sessionCookie: 'session=test_cookie_123;',
);
expect(items.length, equals(2));
expect(items[0].id, equals('98765'));
expect(items[0].service, equals('fanbox'));
expect(items[0].name, equals('AlphaCreator'));
expect(items[0].avatarUrl, equals('https://pawchive.pw/icons/fanbox/98765'));
expect(items[1].id, equals('43210'));
expect(items[1].service, equals('patreon'));
expect(items[1].name, equals('BetaCreator'));
});
test('syncAccountFavorites merges remote artists into AppSettings', () async {
final dio = Dio();
dio.httpClientAdapter = _FakeAdapter((options) async {
final payload = jsonEncode([
{
'id': 'remote_1',
'service': 'fanbox',
'name': 'RemoteArtistOne',
},
{
'id': 'existing_local',
'service': 'patreon',
'name': 'AlreadyPresent',
},
]);
return ResponseBody.fromString(
payload,
200,
headers: {
Headers.contentTypeHeader: [Headers.jsonContentType],
},
);
});
final service = PawchiveSyncService(dio: dio);
const existingItem = FavoriteArtistItem(
id: 'existing_local',
service: 'patreon',
providerId: 'pawchive',
name: 'AlreadyPresent',
);
final initialSettings = AppSettings.defaults.copyWith(
favoriteArtists: [jsonEncode(existingItem.toJson())],
);
final account = PawchiveAccount(
id: 'myuser',
username: 'myuser',
sessionCookie: 'cookie123',
createdAt: DateTime.now(),
);
final result = await service.syncAccountFavorites(
account: account,
settings: initialSettings,
);
expect(result.isSuccess, isTrue);
expect(result.totalSyncedCount, equals(2));
expect(result.newlyAddedToLocal, equals(1)); // remote_1 added, existing_local skipped
expect(result.updatedSettings.favoriteArtists.length, equals(2));
});
test('toggleRemoteFavorite sends POST and DELETE successfully', () async {
var lastMethod = '';
var lastPath = '';
final dio = Dio();
dio.httpClientAdapter = _FakeAdapter((options) async {
lastMethod = options.method;
lastPath = options.path;
return ResponseBody.fromString('ok', 200);
});
final service = PawchiveSyncService(dio: dio);
final account = PawchiveAccount(
id: 'user1',
username: 'user1',
sessionCookie: 'session=abc',
createdAt: DateTime.now(),
);
final addResult = await service.toggleRemoteFavorite(
account: account,
service: 'fanbox',
artistId: '12345',
isFavorite: true,
);
expect(addResult, isTrue);
expect(lastMethod, equals('POST'));
expect(lastPath, equals('https://pawchive.pw/favorites/creator/fanbox/12345'));
final removeResult = await service.toggleRemoteFavorite(
account: account,
service: 'fanbox',
artistId: '12345',
isFavorite: false,
);
expect(removeResult, isTrue);
expect(lastMethod, equals('DELETE'));
expect(lastPath, equals('https://pawchive.pw/favorites/creator/fanbox/12345'));
});
});
}