diff --git a/pkg/api/resolve_release_test.go b/pkg/api/resolve_release_test.go new file mode 100644 index 00000000..d31fbd00 --- /dev/null +++ b/pkg/api/resolve_release_test.go @@ -0,0 +1,36 @@ +package api + +import ( + "net/http" + "path/filepath" + "testing" + + "github.com/GopeedLab/gopeed/pkg/base" + "github.com/GopeedLab/gopeed/pkg/download" + restmodel "github.com/GopeedLab/gopeed/pkg/rest/model" +) + +func TestCancelledTorrentPreviewCanBeResolvedAgain(t *testing.T) { + d := download.NewDownloader(&download.DownloaderConfig{StorageDir: t.TempDir(), TempDir: t.TempDir()}) + if err := d.Setup(); err != nil { + t.Fatal(err) + } + defer d.Close() + service, err := NewService(d) + if err != nil { + t.Fatal(err) + } + path, err := filepath.Abs("../../internal/protocol/bt/testdata/test.torrent") + if err != nil { + t.Fatal(err) + } + req := &restmodel.ResolveTask{Req: &base.Request{URL: path}} + first := serviceTestRequest[*download.ResolveResult](t, service, http.MethodPost, "/api/v1/resolve", req) + serviceTestRequest[any](t, service, http.MethodDelete, "/api/v1/resolve/"+first.ID, nil) + // Release is idempotent, including an old window disposing after Create. + serviceTestRequest[any](t, service, http.MethodDelete, "/api/v1/resolve/"+first.ID, nil) + second := serviceTestRequest[*download.ResolveResult](t, service, http.MethodPost, "/api/v1/resolve", req) + if second.Res.Hash != first.Res.Hash { + t.Fatalf("different torrent after release: %v", second) + } +} diff --git a/ui/flutter/test/features/tasks/presentation/resolve_download_dialog_test.dart b/ui/flutter/test/features/tasks/presentation/resolve_download_dialog_test.dart index d484ab83..e4c2abfe 100644 --- a/ui/flutter/test/features/tasks/presentation/resolve_download_dialog_test.dart +++ b/ui/flutter/test/features/tasks/presentation/resolve_download_dialog_test.dart @@ -64,6 +64,38 @@ Future open( } void main() { + testWidgets('cancel releases a ready preview resource', (tester) async { + final released = []; + final registry = CapabilityRegistry(createAppCapabilityCodecs()) + ..bind(GopeedMethods.resolve, (_) => resolved('ready-rid')) + ..bind(const RpcMethod('gopeed.releaseResolve'), (id) { + released.add(id); + return const RpcUnit(); + }); + await open(tester, [pending('torrent')], registry); + await tester.pumpAndSettle(); + await tester.tap(find.byKey(const ValueKey('resolve-cancel-button'))); + await tester.pumpAndSettle(); + expect(released, contains('ready-rid')); + }); + + testWidgets('cancel releases a late preview result', (tester) async { + final response = Completer(); + final released = []; + final registry = CapabilityRegistry(createAppCapabilityCodecs()) + ..bind(GopeedMethods.resolve, (_) => response.future) + ..bind(const RpcMethod('gopeed.releaseResolve'), (id) { + released.add(id); + return const RpcUnit(); + }); + await open(tester, [pending('torrent')], registry); + await tester.tap(find.byKey(const ValueKey('resolve-close-button'))); + await tester.pumpAndSettle(); + response.complete(resolved('late-rid')); + await tester.pumpAndSettle(); + expect(released, contains('late-rid')); + }); + for (final width in [390.0, 700.0, 1024.0]) { testWidgets('file list fits and exposes ready selections at width $width', (tester) async { final registry = CapabilityRegistry(createAppCapabilityCodecs())