fix(mobile): sync album and asset activity state when add/remove asset level activity (#23484)

* fix; sync album-asset state when remove activity

* make build

* fix: support adding case

* make build

* Update mobile/lib/providers/activity.provider.dart

Co-authored-by: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>

* fix: add missing import for collection package

* make build

---------

Co-authored-by: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>
This commit is contained in:
idubnori
2025-11-11 04:25:43 +09:00
committed by GitHub
parent 8de6ec1a1b
commit cb6d81771d
3 changed files with 118 additions and 23 deletions

View File

@@ -33,6 +33,7 @@ final _activities = [
void main() {
late ActivityServiceMock activityMock;
late ActivityStatisticsMock activityStatisticsMock;
late ActivityStatisticsMock albumActivityStatisticsMock;
late ProviderContainer container;
late AlbumActivityProvider provider;
late ListenerMock<AsyncValue<List<Activity>>> listener;
@@ -44,17 +45,23 @@ void main() {
setUp(() async {
activityMock = ActivityServiceMock();
activityStatisticsMock = ActivityStatisticsMock();
albumActivityStatisticsMock = ActivityStatisticsMock();
container = TestUtils.createContainer(
overrides: [
activityServiceProvider.overrideWith((ref) => activityMock),
activityStatisticsProvider('test-album', 'test-asset').overrideWith(() => activityStatisticsMock),
activityStatisticsProvider('test-album').overrideWith(() => albumActivityStatisticsMock),
],
);
// Mock values
when(() => activityStatisticsMock.build(any(), any())).thenReturn(0);
when(() => albumActivityStatisticsMock.build(any())).thenReturn(0);
when(
() => activityMock.getAllActivities('test-album', assetId: 'test-asset'),
).thenAnswer((_) async => [..._activities]);
when(() => activityMock.getAllActivities('test-album')).thenAnswer((_) async => [..._activities]);
// Init and wait for providers future to complete
provider = albumActivityProvider('test-album', 'test-asset');
@@ -89,6 +96,10 @@ void main() {
() => activityMock.addActivity('test-album', ActivityType.like, assetId: 'test-asset'),
).thenAnswer((_) async => AsyncData(like));
final albumProvider = albumActivityProvider('test-album');
container.read(albumProvider.notifier);
await container.read(albumProvider.future);
await container.read(provider.notifier).addLike();
verify(() => activityMock.addActivity('test-album', ActivityType.like, assetId: 'test-asset'));
@@ -99,6 +110,11 @@ void main() {
// Never bump activity count for new likes
verifyNever(() => activityStatisticsMock.addActivity());
verifyNever(() => albumActivityStatisticsMock.addActivity());
final albumActivities = container.read(albumProvider).requireValue;
expect(albumActivities, hasLength(5));
expect(albumActivities, contains(like));
});
test('Like failed', () async {
@@ -107,6 +123,10 @@ void main() {
() => activityMock.addActivity('test-album', ActivityType.like, assetId: 'test-asset'),
).thenAnswer((_) async => AsyncError(Exception('Mock'), StackTrace.current));
final albumProvider = albumActivityProvider('test-album');
container.read(albumProvider.notifier);
await container.read(albumProvider.future);
await container.read(provider.notifier).addLike();
verify(() => activityMock.addActivity('test-album', ActivityType.like, assetId: 'test-asset'));
@@ -114,6 +134,12 @@ void main() {
final activities = await container.read(provider.future);
expect(activities, hasLength(4));
expect(activities, isNot(contains(like)));
verifyNever(() => albumActivityStatisticsMock.addActivity());
final albumActivities = container.read(albumProvider).requireValue;
expect(albumActivities, hasLength(4));
expect(albumActivities, isNot(contains(like)));
});
});
@@ -130,6 +156,7 @@ void main() {
expect(activities, isNot(anyElement(predicate((Activity a) => a.id == '3'))));
verifyNever(() => activityStatisticsMock.removeActivity());
verifyNever(() => albumActivityStatisticsMock.removeActivity());
});
test('Remove Like failed', () async {
@@ -140,6 +167,9 @@ void main() {
final activities = await container.read(provider.future);
expect(activities, hasLength(4));
expect(activities, anyElement(predicate((Activity a) => a.id == '3')));
verifyNever(() => activityStatisticsMock.removeActivity());
verifyNever(() => albumActivityStatisticsMock.removeActivity());
});
test('Comment successfully removed', () async {
@@ -151,23 +181,35 @@ void main() {
expect(activities, isNot(anyElement(predicate((Activity a) => a.id == '1'))));
verify(() => activityStatisticsMock.removeActivity());
verify(() => albumActivityStatisticsMock.removeActivity());
});
test('Removes activity from album state when asset scoped', () async {
when(() => activityMock.removeActivity('3')).thenAnswer((_) async => true);
when(() => activityMock.getAllActivities('test-album')).thenAnswer((_) async => [..._activities]);
final albumProvider = albumActivityProvider('test-album');
container.read(albumProvider.notifier);
await container.read(albumProvider.future);
await container.read(provider.notifier).removeActivity('3');
final assetActivities = container.read(provider).requireValue;
final albumActivities = container.read(albumProvider).requireValue;
expect(assetActivities, hasLength(3));
expect(assetActivities, isNot(anyElement(predicate((Activity a) => a.id == '3'))));
expect(albumActivities, hasLength(3));
expect(albumActivities, isNot(anyElement(predicate((Activity a) => a.id == '3'))));
verify(() => activityMock.removeActivity('3'));
verifyNever(() => activityStatisticsMock.removeActivity());
verifyNever(() => albumActivityStatisticsMock.removeActivity());
});
});
group('addComment()', () {
late ActivityStatisticsMock albumActivityStatisticsMock;
setUp(() {
albumActivityStatisticsMock = ActivityStatisticsMock();
container = TestUtils.createContainer(
overrides: [
activityServiceProvider.overrideWith((ref) => activityMock),
activityStatisticsProvider('test-album', 'test-asset').overrideWith(() => activityStatisticsMock),
activityStatisticsProvider('test-album').overrideWith(() => albumActivityStatisticsMock),
],
);
});
test('Comment successfully added', () async {
final comment = Activity(
id: '5',
@@ -178,6 +220,10 @@ void main() {
assetId: 'test-asset',
);
final albumProvider = albumActivityProvider('test-album');
container.read(albumProvider.notifier);
await container.read(albumProvider.future);
when(
() => activityMock.addActivity(
'test-album',
@@ -206,6 +252,10 @@ void main() {
verify(() => activityStatisticsMock.addActivity());
verify(() => albumActivityStatisticsMock.addActivity());
final albumActivities = container.read(albumProvider).requireValue;
expect(albumActivities, hasLength(5));
expect(albumActivities, contains(comment));
});
test('Comment successfully added without assetId', () async {
@@ -225,6 +275,8 @@ void main() {
when(() => activityMock.getAllActivities('test-album')).thenAnswer((_) async => [..._activities]);
final albumProvider = albumActivityProvider('test-album');
container.read(albumProvider.notifier);
await container.read(albumProvider.future);
await container.read(albumProvider.notifier).addComment('Test-Comment');
verify(
@@ -258,6 +310,10 @@ void main() {
),
).thenAnswer((_) async => AsyncError(Exception('Error'), StackTrace.current));
final albumProvider = albumActivityProvider('test-album');
container.read(albumProvider.notifier);
await container.read(albumProvider.future);
await container.read(provider.notifier).addComment('Test-Comment');
final activities = await container.read(provider.future);
@@ -266,6 +322,10 @@ void main() {
verifyNever(() => activityStatisticsMock.addActivity());
verifyNever(() => albumActivityStatisticsMock.addActivity());
final albumActivities = container.read(albumProvider).requireValue;
expect(albumActivities, hasLength(4));
expect(albumActivities, isNot(contains(comment)));
});
});
}