even simplier tests

This commit is contained in:
Damian Lesiuk 2025-10-01 21:59:27 +02:00
parent 50b6351b39
commit 97c365cb05
5 changed files with 48 additions and 108 deletions

View file

@ -27,7 +27,7 @@ class SharedLink {
required this.expiresAt,
required this.key,
required this.showMetadata,
required this.slug,
this.slug,
required this.type,
});

View file

@ -98,5 +98,6 @@ String? punycodeDecodeUrl(String? serverUrl) {
/// - If slug is present: 's/${sharedLink.slug}'
/// - Otherwise: 'share/${sharedLink.key}'
String getShareUrlPath(SharedLink sharedLink) {
return sharedLink.slug != null ? 's/${sharedLink.slug}' : 'share/${sharedLink.key}';
final slug = sharedLink.slug?.trim();
return slug?.isNotEmpty == true ? 's/$slug' : 'share/${sharedLink.key}';
}

View file

@ -80,7 +80,7 @@ void main() {
clipboardCapturer = ClipboardCapturer();
setupClipboardMock(clipboardCapturer);
setupDefaultMockResponses(mockSharedLinkService);
setupMockResponse(mockSharedLinkService, 'new-slug');
});
tearDown(() {
@ -90,53 +90,45 @@ void main() {
});
group('SharedLinkEditPage Tests', () {
testWidgets('copies URL with slug to clipboard after link creation', (tester) async {
testWidgets('copies correct URL for links with slug', (tester) async {
await pumpSharedLinkEditPage(tester, container, albumId: 'album-1');
await createSharedLink(tester);
final copyButton = find.byIcon(Icons.copy);
await tester.tap(copyButton);
await tester.tap(find.byIcon(Icons.copy));
await tester.pumpAndSettle();
expect(clipboardCapturer.text, 'https://demo.immich.app/s/new-slug');
});
testWidgets('copies URL without slug to clipboard after link creation', (tester) async {
setupMockResponseForLinkWithoutSlug(mockSharedLinkService);
testWidgets('copies correct URL for links without slug', (tester) async {
setupMockResponse(mockSharedLinkService, '');
await pumpSharedLinkEditPage(tester, container, albumId: 'album-1');
await createSharedLink(tester);
final copyButton = find.byIcon(Icons.copy);
await tester.tap(copyButton);
await tester.tap(find.byIcon(Icons.copy));
await tester.pumpAndSettle();
expect(clipboardCapturer.text, 'https://demo.immich.app/share/new-key');
});
testWidgets('handles empty external domain by using server endpoint', (tester) async {
setupEmptyExternalDomain(mockServerInfoNotifier);
testWidgets('uses server endpoint when external domain is empty', (tester) async {
setupServerInfo(mockServerInfoNotifier, '');
await pumpSharedLinkEditPage(tester, container, albumId: 'album-1');
await createSharedLink(tester);
final copyButton = find.byIcon(Icons.copy);
await tester.tap(copyButton);
await tester.tap(find.byIcon(Icons.copy));
await tester.pumpAndSettle();
expect(clipboardCapturer.text, 'https://demo.immich.app/s/new-slug');
});
testWidgets('uses custom domain when external domain is set', (tester) async {
final mockServerInfoWithCustomDomain = createMockServerInfo(externalDomain: 'https://custom-immich.com');
mockServerInfoNotifier.state = mockServerInfoWithCustomDomain;
testWidgets('uses custom external domain when set', (tester) async {
setupServerInfo(mockServerInfoNotifier, 'https://custom-immich.com');
await pumpSharedLinkEditPage(tester, container, albumId: 'album-1');
await createSharedLink(tester);
final copyButton = find.byIcon(Icons.copy);
await tester.tap(copyButton);
await tester.tap(find.byIcon(Icons.copy));
await tester.pumpAndSettle();
expect(clipboardCapturer.text, 'https://custom-immich.com/s/new-slug');
});
});

View file

@ -47,7 +47,7 @@ void main() {
mockSharedLinksNotifier = MockSharedLinksNotifier();
clipboardCapturer = ClipboardCapturer();
setupDefaultServerInfo(mockServerInfoNotifier);
setupServerInfo(mockServerInfoNotifier, 'https://example.com');
mockSharedLinksNotifier.state = const AsyncValue.data([]);
overrides = [
@ -68,62 +68,51 @@ void main() {
});
group('SharedLinkItem Tests', () {
testWidgets('copies URL with slug to clipboard', (tester) async {
testWidgets('copies URL with slug', (tester) async {
await tester.pumpConsumerWidget(Scaffold(body: SharedLinkItem(sharedLinkWithSlug)), overrides: overrides);
final copyButton = find.byIcon(Icons.copy_outlined);
await tester.tap(copyButton);
await tester.tap(find.byIcon(Icons.copy_outlined));
await tester.pumpAndSettle();
expect(clipboardCapturer.text, 'https://example.com/s/test-slug');
});
testWidgets('copies URL without slug to clipboard', (tester) async {
testWidgets('copies URL without slug', (tester) async {
await tester.pumpConsumerWidget(Scaffold(body: SharedLinkItem(sharedLinkWithoutSlug)), overrides: overrides);
final copyButton = find.byIcon(Icons.copy_outlined);
await tester.tap(copyButton);
await tester.tap(find.byIcon(Icons.copy_outlined));
await tester.pumpAndSettle();
expect(clipboardCapturer.text, 'https://example.com/share/test-key-2');
});
testWidgets('handles empty external domain by using server URL', (tester) async {
setupEmptyExternalDomain(mockServerInfoNotifier);
testWidgets('falls back to server URL when external domain is empty', (tester) async {
setupServerInfo(mockServerInfoNotifier, '');
await Store.put(StoreKey.serverEndpoint, 'http://example.com');
await tester.pumpConsumerWidget(Scaffold(body: SharedLinkItem(sharedLinkWithSlug)), overrides: overrides);
final copyButton = find.byIcon(Icons.copy_outlined);
await tester.tap(copyButton);
await tester.tap(find.byIcon(Icons.copy_outlined));
await tester.pumpAndSettle();
expect(clipboardCapturer.text, 'http://example.com/s/test-slug');
});
testWidgets('shows snackbar on successful copy', (tester) async {
testWidgets('shows success message on copy', (tester) async {
await tester.pumpConsumerWidget(Scaffold(body: SharedLinkItem(sharedLinkWithSlug)), overrides: overrides);
final copyButton = find.byIcon(Icons.copy_outlined);
await tester.tap(copyButton);
await tester.tap(find.byIcon(Icons.copy_outlined));
await tester.pumpAndSettle();
expect(find.textContaining('copied'), findsOneWidget);
});
testWidgets('works with different shared links', (tester) async {
testWidgets('handles different link types correctly', (tester) async {
await tester.pumpConsumerWidget(Scaffold(body: SharedLinkItem(sharedLinkWithSlug)), overrides: overrides);
final copyButton = find.byIcon(Icons.copy_outlined);
await tester.tap(copyButton);
await tester.tap(find.byIcon(Icons.copy_outlined));
await tester.pumpAndSettle();
expect(clipboardCapturer.text, 'https://example.com/s/test-slug');
await tester.pumpConsumerWidget(Scaffold(body: SharedLinkItem(sharedLinkWithoutSlug)), overrides: overrides);
await tester.tap(copyButton);
await tester.tap(find.byIcon(Icons.copy_outlined));
await tester.pumpAndSettle();
expect(clipboardCapturer.text, 'https://example.com/share/test-key-2');
});
});

View file

@ -32,12 +32,10 @@ class MockSharedLinksNotifier extends StateNotifier<AsyncValue<List<SharedLink>>
MockSharedLinksNotifier() : super(const AsyncValue.loading());
}
final mockServerInfoNotifierProvider = Provider<ServerInfoNotifier>((ref) => MockServerInfoNotifier());
/// Creates a mock ServerInfo with customizable parameters for testing
/// Creates a mock ServerInfo for testing
ServerInfo createMockServerInfo({
String externalDomain = 'https://demo.immich.app',
String serverEndpoint = 'https://demo.immich.app',
}) {
return ServerInfo(
serverVersion: const ServerVersion(major: 1, minor: 0, patch: 0),
@ -57,34 +55,6 @@ ServerInfo createMockServerInfo({
);
}
/// Creates a mock album shared link with customizable parameters for testing
SharedLink createAlbumSharedLink({
String id = '1',
String title = 'Test Album',
String description = 'Test Description',
String key = 'test-key',
String? slug = 'test-slug',
bool allowUpload = true,
bool allowDownload = true,
bool showMetadata = true,
String? password,
}) {
return SharedLink(
id: id,
title: title,
description: description,
key: key,
slug: slug,
expiresAt: DateTime.now().add(const Duration(days: 1)),
allowUpload: allowUpload,
allowDownload: allowDownload,
showMetadata: showMetadata,
thumbAssetId: null,
password: password,
type: SharedLinkSource.album,
);
}
/// Creates a shared link with slug for testing
SharedLink createSharedLinkWithSlug() {
return SharedLink(
@ -121,20 +91,13 @@ SharedLink createSharedLinkWithoutSlug() {
);
}
/// Sets up default server info with external domain for testing
void setupDefaultServerInfo(MockServerInfoNotifier mockServerInfoNotifier) {
final mockServerInfo = createMockServerInfo(externalDomain: 'https://example.com');
mockServerInfoNotifier.state = mockServerInfo;
/// Sets up server info with external domain for testing
void setupServerInfo(MockServerInfoNotifier mockServerInfoNotifier, String domain) {
mockServerInfoNotifier.state = createMockServerInfo(externalDomain: domain);
}
/// Sets up empty external domain for testing
void setupEmptyExternalDomain(ServerInfoNotifier mockServerInfoNotifier) {
final mockServerInfoWithEmptyDomain = createMockServerInfo(externalDomain: '');
mockServerInfoNotifier.state = mockServerInfoWithEmptyDomain;
}
/// Sets up default mock responses for shared link service
void setupDefaultMockResponses(MockSharedLinkService mockSharedLinkService) {
/// Sets up mock response for shared link service
void setupMockResponse(MockSharedLinkService mockSharedLinkService, String slug) {
when(
() => mockSharedLinkService.createSharedLink(
albumId: any(named: 'albumId'),
@ -146,25 +109,20 @@ void setupDefaultMockResponses(MockSharedLinkService mockSharedLinkService) {
password: any(named: 'password'),
expiresAt: any(named: 'expiresAt'),
),
).thenAnswer(
(_) async => createAlbumSharedLink(id: 'new-link-id', title: 'New Link', key: 'new-key', slug: 'new-slug'),
);
}
/// Sets up mock response for link without slug
void setupMockResponseForLinkWithoutSlug(MockSharedLinkService mockSharedLinkService) {
when(
() => mockSharedLinkService.createSharedLink(
albumId: any(named: 'albumId'),
assetIds: any(named: 'assetIds'),
showMeta: any(named: 'showMeta'),
allowDownload: any(named: 'allowDownload'),
allowUpload: any(named: 'allowUpload'),
description: any(named: 'description'),
password: any(named: 'password'),
expiresAt: any(named: 'expiresAt'),
),
).thenAnswer((_) async => createAlbumSharedLink(id: 'new-link-id', title: 'New Link', key: 'new-key', slug: null));
).thenAnswer((_) async => SharedLink(
id: 'new-link-id',
title: 'New Link',
description: 'Test Description',
key: 'new-key',
slug: slug.isEmpty ? null : slug,
expiresAt: DateTime.now().add(const Duration(days: 1)),
allowUpload: true,
allowDownload: true,
showMetadata: true,
thumbAssetId: null,
password: null,
type: SharedLinkSource.album,
));
}
/// Test utility to capture clipboard operations for verification