diff options
| author | Christian Cleberg <[email protected]> | 2026-08-07 04:12:50 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-08-07 04:12:50 -0500 |
| commit | 1f8f651a9c2ac2d6be231ff9f71ee3bcce9936d8 (patch) | |
| tree | 25cf810fa0e9a0ab343b60b59c26d8cc096c9a98 /HutchTests | |
| parent | db40d346c28800a1eec384a5e4f3d7d090198e4d (diff) | |
| download | hutch-1f8f651a9c2ac2d6be231ff9f71ee3bcce9936d8.tar.gz hutch-1f8f651a9c2ac2d6be231ff9f71ee3bcce9936d8.tar.bz2 hutch-1f8f651a9c2ac2d6be231ff9f71ee3bcce9936d8.zip | |
Projects: discovery, create, edit, manage linked resources (#12, #13, #14, #15)
hub.sr.ht's GraphQL now exposes the project write API (create/update/
link/unlink) and a public `projects` discovery query, so these
previously-blocked issues can be built.
ProjectService gains: fetchPublicProjects (#12); createProject (#13);
updateProject with ProjectInput (#14); link/unlink for sources, trackers,
and mailing lists plus linkable-resource candidate fetches (#15); and hub
cache invalidation after every mutation.
UI: a Discover browser and a create form reached from the projects list;
an Edit form and a Manage Resources sheet on project detail, gated to
projects the user owns. Mutations degrade to a visible error if a field
isn't live yet.
Built against the master schema; live deployment on sr.ht/query is not yet
confirmed (introspection there requires a token).
Diffstat (limited to 'HutchTests')
| -rw-r--r-- | HutchTests/ProjectFormTests.swift | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/HutchTests/ProjectFormTests.swift b/HutchTests/ProjectFormTests.swift new file mode 100644 index 0000000..a4b4dfa --- /dev/null +++ b/HutchTests/ProjectFormTests.swift @@ -0,0 +1,39 @@ +import Foundation +import Testing +@testable import Hutch + +struct ProjectFormTests { + @Test + func parsesTagsSplittingAndTrimming() { + #expect(ProjectFormSheet.parseTags("swift, ios , ") == ["swift", "ios"]) + #expect(ProjectFormSheet.parseTags("a,b,c") == ["a", "b", "c"]) + } + + @Test + func parseTagsDeduplicatesCaseInsensitively() { + #expect(ProjectFormSheet.parseTags("Swift, swift, SWIFT") == ["Swift"]) + } + + @Test + func parseTagsEmptyInputYieldsEmpty() { + #expect(ProjectFormSheet.parseTags(" ").isEmpty) + #expect(ProjectFormSheet.parseTags("").isEmpty) + } + + @Test + func linkableResourceDisplayNameCombinesOwnerAndName() { + let resource = LinkableResource(rid: "r1", name: "hutch", ownerCanonicalName: "~alice", kind: .source) + #expect(resource.displayName == "~alice/hutch") + #expect(resource.id == "r1") + } + + @Test + func discoveredProjectIDMatchesProject() { + let project = Project( + metadata: .init(id: "p1", name: "Hutch", description: nil, website: nil, visibility: .publicVisibility, tags: [], updated: .now), + resources: .init(mailingLists: [], sources: [], trackers: [], isFullyLoaded: false) + ) + let discovered = DiscoveredProject(project: project, ownerCanonicalName: "~alice") + #expect(discovered.id == "p1") + } +} |
