refactor(app): share client and presentation scaffolds
This commit is contained in:
@@ -114,4 +114,32 @@ void main() {
|
||||
expect(activities.last.progress, 75);
|
||||
expect(activities.last.cancellable, isTrue);
|
||||
});
|
||||
|
||||
test('metadata edit preserves locked fields and removed tag wire format', () async {
|
||||
http.Request? captured;
|
||||
final client = makeClient((request) async {
|
||||
captured = request;
|
||||
return http.Response('', 200);
|
||||
});
|
||||
addTearDown(client.close);
|
||||
|
||||
final updated = await client.updateMetadata(
|
||||
sectionId: 1,
|
||||
ratingKey: 'item-id',
|
||||
typeNumber: 1,
|
||||
title: 'Renamed',
|
||||
tagChanges: {
|
||||
'genre': (current: ['Drama'], original: ['Drama', 'Science Fiction']),
|
||||
},
|
||||
);
|
||||
|
||||
expect(updated, isTrue);
|
||||
expect(captured?.method, 'PUT');
|
||||
expect(captured?.url.path, '/library/sections/1/all');
|
||||
expect(captured?.url.queryParameters, containsPair('title.value', 'Renamed'));
|
||||
expect(captured?.url.queryParameters, containsPair('title.locked', '1'));
|
||||
expect(captured?.url.queryParameters, containsPair('genre[0].tag.tag', 'Drama'));
|
||||
expect(captured?.url.queryParameters, containsPair('genre[].tag.tag-', 'Science%20Fiction'));
|
||||
expect(captured?.url.queryParameters, containsPair('genre.locked', '1'));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:plezy/services/settings_service.dart';
|
||||
import 'package:plezy/widgets/media_card_sliver_layout.dart';
|
||||
|
||||
void main() {
|
||||
Widget host({
|
||||
required ViewMode viewMode,
|
||||
required List<MediaCardSliverPosition> positions,
|
||||
Object? listEpoch,
|
||||
Object? gridEpoch,
|
||||
}) {
|
||||
return MaterialApp(
|
||||
home: CustomScrollView(
|
||||
slivers: [
|
||||
MediaCardSliverLayout(
|
||||
viewMode: viewMode,
|
||||
itemCount: 6,
|
||||
density: 100,
|
||||
padding: EdgeInsets.zero,
|
||||
listEpoch: listEpoch,
|
||||
gridEpochBuilder: gridEpoch == null ? null : (_) => gridEpoch,
|
||||
itemBuilder: (context, position) {
|
||||
positions.add(position);
|
||||
return SizedBox(key: ValueKey(position.index), height: 40, child: Text('${position.index}'));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('list mode exposes one-column card positions', (tester) async {
|
||||
final positions = <MediaCardSliverPosition>[];
|
||||
final epoch = Object();
|
||||
|
||||
await tester.pumpWidget(host(viewMode: ViewMode.list, positions: positions, listEpoch: epoch));
|
||||
|
||||
expect(find.byType(SliverList), findsOneWidget);
|
||||
expect(find.byType(SliverGrid), findsNothing);
|
||||
expect(positions, isNotEmpty);
|
||||
expect(positions.first.columnCount, 1);
|
||||
expect(positions.first.isFirstRow, isTrue);
|
||||
expect(positions.first.isFirstColumn, isTrue);
|
||||
expect(positions.first.disableScale, isTrue);
|
||||
expect(positions.first.layoutEpoch, same(epoch));
|
||||
});
|
||||
|
||||
testWidgets('grid mode exposes geometry-derived card positions', (tester) async {
|
||||
final positions = <MediaCardSliverPosition>[];
|
||||
final epoch = Object();
|
||||
|
||||
await tester.pumpWidget(host(viewMode: ViewMode.grid, positions: positions, gridEpoch: epoch));
|
||||
|
||||
expect(find.byType(SliverGrid), findsOneWidget);
|
||||
expect(find.byType(SliverList), findsNothing);
|
||||
expect(positions, isNotEmpty);
|
||||
final first = positions.first;
|
||||
expect(first.columnCount, greaterThan(1));
|
||||
expect(first.isGrid, isTrue);
|
||||
expect(first.isFirstRow, isTrue);
|
||||
expect(first.isFirstColumn, isTrue);
|
||||
expect(first.disableScale, isFalse);
|
||||
expect(first.layoutEpoch, same(epoch));
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:plezy/media/media_backend.dart';
|
||||
import 'package:plezy/media/media_hub.dart';
|
||||
import 'package:plezy/media/media_item.dart';
|
||||
import 'package:plezy/media/media_kind.dart';
|
||||
import 'package:plezy/widgets/tv_spotlight_scaffold.dart';
|
||||
|
||||
MediaItem _item(String id) => MediaItem(id: id, backend: MediaBackend.plex, kind: MediaKind.movie, title: id);
|
||||
|
||||
MediaHub _hub(String id, List<MediaItem> items) =>
|
||||
MediaHub(id: id, title: id, type: 'movie', size: items.length, items: items);
|
||||
|
||||
void main() {
|
||||
test('spotlight controller cancels an intermediate debounced selection', () async {
|
||||
final first = _item('first');
|
||||
final second = _item('second');
|
||||
final controller = TvSpotlightController(settleDelay: const Duration(milliseconds: 10));
|
||||
addTearDown(controller.dispose);
|
||||
controller.value = first;
|
||||
|
||||
controller.select(second);
|
||||
controller.select(first);
|
||||
await Future<void>.delayed(const Duration(milliseconds: 20));
|
||||
|
||||
expect(controller.value, same(first));
|
||||
});
|
||||
|
||||
test('spotlight controller resolves valid selection or first hub item', () {
|
||||
final first = _item('first');
|
||||
final second = _item('second');
|
||||
final controller = TvSpotlightController(settleDelay: Duration.zero);
|
||||
addTearDown(controller.dispose);
|
||||
final hubs = [
|
||||
_hub('one', [first]),
|
||||
_hub('two', [second]),
|
||||
];
|
||||
|
||||
expect(controller.resolve(hubs), same(first));
|
||||
controller.select(second);
|
||||
expect(controller.resolve(hubs), same(second));
|
||||
|
||||
controller.value = _item('removed');
|
||||
expect(controller.resolve(hubs), same(first));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user