migration
This commit is contained in:
196
PediFoodsTests/SessionStateStoreTests.swift
Normal file
196
PediFoodsTests/SessionStateStoreTests.swift
Normal file
@@ -0,0 +1,196 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
@testable import PediFoods
|
||||
|
||||
@Test("makeUserKey prefers a non-empty profileId over email")
|
||||
func makeUserKeyPrefersProfileId() {
|
||||
let key = SessionStateStore.makeUserKey(profileId: "abc123", email: "user@example.com")
|
||||
#expect(key == "id:abc123")
|
||||
}
|
||||
|
||||
@Test("makeUserKey falls back to email when profileId is nil or blank")
|
||||
func makeUserKeyFallsBackToEmail() {
|
||||
#expect(SessionStateStore.makeUserKey(profileId: nil, email: "User@Example.com") == "email:user@example.com")
|
||||
#expect(SessionStateStore.makeUserKey(profileId: " ", email: "user@example.com") == "email:user@example.com")
|
||||
}
|
||||
|
||||
@Test("makeUserKey returns nil when both profileId and email are absent")
|
||||
func makeUserKeyNilWhenBothAbsent() {
|
||||
#expect(SessionStateStore.makeUserKey(profileId: nil, email: nil) == nil)
|
||||
#expect(SessionStateStore.makeUserKey(profileId: " ", email: " ") == nil)
|
||||
}
|
||||
|
||||
/// `SessionStateStore.defaults` is one shared static var - Swift Testing
|
||||
/// runs `@Test`s concurrently by default, so any test that swaps it would
|
||||
/// race every other test in this file. `.serialized` forces this suite's
|
||||
/// tests to run one at a time instead.
|
||||
@Suite(.serialized)
|
||||
struct SessionStateStorePersistenceTests {
|
||||
/// Points `SessionStateStore` at a throwaway, uniquely-named
|
||||
/// `UserDefaults` suite for the duration of one test, and restores
|
||||
/// `.standard` after. Internal (not private) so the cross-file
|
||||
/// extension in CartStateTests.swift can reuse it — both need to be
|
||||
/// in this same serialization domain, see that file's comment.
|
||||
func withIsolatedDefaults(_ body: () throws -> Void) rethrows {
|
||||
let suiteName = "SessionStateStoreTests.\(UUID().uuidString)"
|
||||
let suite = UserDefaults(suiteName: suiteName)!
|
||||
let previous = SessionStateStore.defaults
|
||||
SessionStateStore.defaults = suite
|
||||
defer {
|
||||
SessionStateStore.defaults = previous
|
||||
suite.removePersistentDomain(forName: suiteName)
|
||||
}
|
||||
try body()
|
||||
}
|
||||
|
||||
@Test("shouldPromptPushOptIn is true before the first prompt is ever recorded")
|
||||
func shouldPromptPushOptInTrueInitially() {
|
||||
withIsolatedDefaults {
|
||||
#expect(SessionStateStore.shouldPromptPushOptIn())
|
||||
}
|
||||
}
|
||||
|
||||
@Test("shouldPromptPushOptIn is false immediately after recording a prompt")
|
||||
func shouldPromptPushOptInFalseRightAfterRecording() {
|
||||
withIsolatedDefaults {
|
||||
SessionStateStore.recordPushOptInPrompted()
|
||||
#expect(SessionStateStore.shouldPromptPushOptIn() == false)
|
||||
}
|
||||
}
|
||||
|
||||
@Test("saveAddress/loadAddress round-trips every field")
|
||||
func addressRoundTrip() {
|
||||
withIsolatedDefaults {
|
||||
let state = AddressState(selectedId: "addr-1", display: "Rua A, 100", latitude: -23.5, longitude: -46.6)
|
||||
SessionStateStore.saveAddress(state)
|
||||
let loaded = SessionStateStore.loadAddress()
|
||||
#expect(loaded?.selectedId == "addr-1")
|
||||
#expect(loaded?.display == "Rua A, 100")
|
||||
#expect(loaded?.latitude == -23.5)
|
||||
}
|
||||
}
|
||||
|
||||
@Test("loadAddress substitutes a placeholder display string for an empty one")
|
||||
func addressLoadReplacesEmptyDisplay() {
|
||||
withIsolatedDefaults {
|
||||
SessionStateStore.saveAddress(AddressState(selectedId: nil, display: ""))
|
||||
#expect(SessionStateStore.loadAddress()?.display == "Defina seu endereco")
|
||||
}
|
||||
}
|
||||
|
||||
@Test("clearAddress removes a previously saved address")
|
||||
func addressClear() {
|
||||
withIsolatedDefaults {
|
||||
SessionStateStore.saveAddress(AddressState(selectedId: "addr-1", display: "Rua A"))
|
||||
SessionStateStore.clearAddress()
|
||||
#expect(SessionStateStore.loadAddress() == nil)
|
||||
}
|
||||
}
|
||||
|
||||
@Test("saveCart/loadCart round-trips items, addons, and total")
|
||||
func cartRoundTrip() {
|
||||
withIsolatedDefaults {
|
||||
let item = CartItemState(
|
||||
id: "item-1", productId: "p1", storeId: "s1", name: "Pizza",
|
||||
addons: [CartItemAddonState(id: "a1", name: "Extra cheese", quantity: 1, unitPrice: 3.0)],
|
||||
quantity: 2, unitPrice: 29.9
|
||||
)
|
||||
let cart = CartState(storeId: "s1", storeName: "Loja A", items: [item], total: 65.8)
|
||||
SessionStateStore.saveCart(cart)
|
||||
|
||||
let loaded = SessionStateStore.loadCart()
|
||||
#expect(loaded?.storeId == "s1")
|
||||
#expect(loaded?.items.first?.name == "Pizza")
|
||||
#expect(loaded?.items.first?.addons.first?.name == "Extra cheese")
|
||||
#expect(loaded?.total == 65.8)
|
||||
}
|
||||
}
|
||||
|
||||
@Test("clearCart removes a previously saved cart")
|
||||
func cartClear() {
|
||||
withIsolatedDefaults {
|
||||
SessionStateStore.saveCart(CartState(storeId: "s1", storeName: "Loja A", items: [], total: 0))
|
||||
SessionStateStore.clearCart()
|
||||
#expect(SessionStateStore.loadCart() == nil)
|
||||
}
|
||||
}
|
||||
|
||||
@Test("saveTrackedOrder inserts new orders at the front and updates existing ones in place")
|
||||
func trackedOrdersInsertAndUpdate() {
|
||||
withIsolatedDefaults {
|
||||
SessionStateStore.saveTrackedOrder(PublicOrderResult(id: "o1", status: "PENDING"))
|
||||
SessionStateStore.saveTrackedOrder(PublicOrderResult(id: "o2", status: "PENDING"))
|
||||
var orders = SessionStateStore.loadTrackedOrders()
|
||||
#expect(orders.map(\.id) == ["o2", "o1"])
|
||||
|
||||
SessionStateStore.saveTrackedOrder(PublicOrderResult(id: "o1", status: "COMPLETED"))
|
||||
orders = SessionStateStore.loadTrackedOrders()
|
||||
#expect(orders.map(\.id) == ["o2", "o1"])
|
||||
#expect(orders.first(where: { $0.id == "o1" })?.status == "COMPLETED")
|
||||
}
|
||||
}
|
||||
|
||||
@Test("loadTrackedOrder finds a specific order by id")
|
||||
func trackedOrderLookupById() {
|
||||
withIsolatedDefaults {
|
||||
SessionStateStore.saveTrackedOrder(PublicOrderResult(id: "o1", status: "PENDING"))
|
||||
#expect(SessionStateStore.loadTrackedOrder(orderId: "o1")?.status == "PENDING")
|
||||
#expect(SessionStateStore.loadTrackedOrder(orderId: "missing") == nil)
|
||||
}
|
||||
}
|
||||
|
||||
@Test("savePendingCartOrderId clears the value when given an empty string")
|
||||
func pendingCartOrderIdClearsOnEmptyString() {
|
||||
withIsolatedDefaults {
|
||||
SessionStateStore.savePendingCartOrderId("order-1")
|
||||
#expect(SessionStateStore.loadPendingCartOrderId() == "order-1")
|
||||
SessionStateStore.savePendingCartOrderId(" ")
|
||||
#expect(SessionStateStore.loadPendingCartOrderId() == nil)
|
||||
}
|
||||
}
|
||||
|
||||
@Test("saveOrderReview de-duplicates by orderId case- and whitespace-insensitively")
|
||||
func orderReviewDedupesByOrderId() {
|
||||
withIsolatedDefaults {
|
||||
let review1 = OrderReviewRecord(
|
||||
orderId: "Order-1", storeId: nil, shortId: nil, storeName: nil, storeLogoURL: nil,
|
||||
createdAt: nil, submittedAt: "2026-01-01", rating: 4, comment: "Good",
|
||||
orderPositiveTags: nil, orderImprovementTags: nil, deliverySentiment: nil,
|
||||
deliveryPositiveTags: nil, deliveryNegativeTags: nil, appNps: nil, platform: nil,
|
||||
editableUntil: nil, storeReplyUntil: nil, reviewWindowExpiresAt: nil,
|
||||
storeReplyMessage: nil, storeReplyAt: nil
|
||||
)
|
||||
SessionStateStore.saveOrderReview(review1)
|
||||
#expect(SessionStateStore.hasOrderReview(orderId: "order-1"))
|
||||
#expect(SessionStateStore.loadOrderReviews().count == 1)
|
||||
|
||||
let review2 = OrderReviewRecord(
|
||||
orderId: "order-1 ", storeId: nil, shortId: nil, storeName: nil, storeLogoURL: nil,
|
||||
createdAt: nil, submittedAt: "2026-01-02", rating: 5, comment: "Even better",
|
||||
orderPositiveTags: nil, orderImprovementTags: nil, deliverySentiment: nil,
|
||||
deliveryPositiveTags: nil, deliveryNegativeTags: nil, appNps: nil, platform: nil,
|
||||
editableUntil: nil, storeReplyUntil: nil, reviewWindowExpiresAt: nil,
|
||||
storeReplyMessage: nil, storeReplyAt: nil
|
||||
)
|
||||
SessionStateStore.saveOrderReview(review2)
|
||||
#expect(SessionStateStore.loadOrderReviews().count == 1)
|
||||
#expect(SessionStateStore.loadOrderReviews().first?.rating == 5)
|
||||
}
|
||||
}
|
||||
|
||||
@Test("saveOrderReviewDraft/loadOrderReviewDraft round-trips and clearOrderReviewDraft removes it")
|
||||
func orderReviewDraftRoundTripAndClear() {
|
||||
withIsolatedDefaults {
|
||||
let draft = OrderReviewDraftState(
|
||||
orderId: "o1", orderRate: 5, orderComment: "Great", orderPositiveTags: ["fast"],
|
||||
orderImprovementTags: [], deliverySentiment: "good", deliveryPositiveTags: [],
|
||||
deliveryNegativeTags: [], appNps: 9, platform: "ios"
|
||||
)
|
||||
SessionStateStore.saveOrderReviewDraft(draft)
|
||||
#expect(SessionStateStore.loadOrderReviewDraft(orderId: "o1")?.orderComment == "Great")
|
||||
|
||||
SessionStateStore.clearOrderReviewDraft(orderId: "o1")
|
||||
#expect(SessionStateStore.loadOrderReviewDraft(orderId: "o1") == nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user