From d3ca255939f5784d3d4abdb75884fde6c5054393 Mon Sep 17 00:00:00 2001 From: dadachi Date: Wed, 14 Oct 2026 06:10:02 +0900 Subject: [PATCH] Keep the shop detail's tag fetch out of the item tag list ItemTagRepository.fetchAll (the shop detail's fetch) stored its result in itemTags, the item tag list's pages. When it answered after the user had gone on to another shop's item tag list, that list showed the previous shop's tags. Seen on the iPhone against the local API: shop A's detail still loading while shop B's list opened left A's tags in B's list. The shop detail keeps the tags itself, so fetchAll now only returns them. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01K5hZEFqXhBsUQwSWsgR6eH --- .../Data/Repositories/ItemTagRepository.swift | 7 +++--- .../ItemTagRepositoryPaginationTest.swift | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/NativeAppTemplate/Data/Repositories/ItemTagRepository.swift b/NativeAppTemplate/Data/Repositories/ItemTagRepository.swift index 778b438..4351fc4 100644 --- a/NativeAppTemplate/Data/Repositories/ItemTagRepository.swift +++ b/NativeAppTemplate/Data/Repositories/ItemTagRepository.swift @@ -97,11 +97,12 @@ import SwiftUI } } + /// For the shop detail, which keeps the tags itself. `itemTags` is the item tag + /// list's pages, possibly of another shop the user opened while this was loading, + /// so it is left alone func fetchAll(shopId: String) async throws -> [ItemTag] { do { - let response = try await itemTagsService.allItemTags(shopId: shopId) - itemTags = response.itemTags - return itemTags + return try await itemTagsService.allItemTags(shopId: shopId).itemTags } catch { Failure .fetch(from: Self.self, reason: error.codedDescription) diff --git a/NativeAppTemplateTests/Data/Repositories/ItemTagRepositoryPaginationTest.swift b/NativeAppTemplateTests/Data/Repositories/ItemTagRepositoryPaginationTest.swift index 3ccc798..71e1791 100644 --- a/NativeAppTemplateTests/Data/Repositories/ItemTagRepositoryPaginationTest.swift +++ b/NativeAppTemplateTests/Data/Repositories/ItemTagRepositoryPaginationTest.swift @@ -177,6 +177,31 @@ struct ItemTagRepositoryPaginationTest { #expect(repository.state == .hasData) } + /// Shop A's detail screen fetches all of A's tags (fetchAll). When that answer + /// arrives after the user went on to shop B's item tag list, B's list must keep + /// B's tags; seen on the iPhone against the local API before the fix + @Test + func previousShopsDetailFetchDoesNotReplaceAnotherShopsList() async throws { + let releaseA = DispatchSemaphore(value: 0) + let server = try await Self.shopServer(releaseA: releaseA) + defer { server.stop() } + let repository = makeRepository(server) + + let detailFetch = Task { try await repository.fetchAll(shopId: "shop-A") } + await waitUntil { server.requests.count == 1 } + repository.reloadPage(shopId: "shop-B", page: 1) + await waitUntil(timeout: .seconds(10)) { repository.state == .hasData } + releaseA.signal() + let shopATags = try await detailFetch.value + + // The detail gets A's page 1 (a1, a2: shopServer's answer without a page) + #expect(shopATags.map(\.id) == ["a1", "a2"]) + // B's list is unchanged: b1 with B's meta + #expect(repository.itemTags.map(\.id) == ["b1"]) + #expect(repository.paginationMeta?.totalPages == 1) + #expect(repository.state == .hasData) + } + /// Shop A's next page arriving after the user opened shop B must not be /// appended to B's list @Test