remindwall / RWPureSwift / Tests / EditSettingsNewTests / Trackees / AddTrackeeTest.swift
Back to remindwall — Current RemindWall
import ComposableArchitecture
import Dao
import Testing
import DependenciesTestSupport
@testable import EditSettingsNew_Trackees
@MainActor
@Suite("AddTrackee Feature Tests", .dependency(\.uuid, .incrementing))
struct AddTrackeeTests {
@Test("Set name and save trackee")
func setAndSave() async {
@Dependency(\.uuid) var uuid
let testTrackee = Trackee(id: Trackee.ID(uuid()), name: "")
let store = TestStore(initialState: AddTrackeeFeature.State(trackee: testTrackee)) {
AddTrackeeFeature()
}
await store.send(.setName("Bob")){
$0.trackee.name = "Bob"
}
await store.send(.saveButtonTapped)
await store.receive(\.delegate.saveTrackee, Trackee(id: testTrackee.id, name: "Bob"))
}
@Test("Cancel button dismisses without saving")
func cancelButtonTapped() async {
@Dependency(\.uuid) var uuid
let testTrackee = Trackee(id: Trackee.ID(uuid()), name: "")
let store = TestStore(initialState: AddTrackeeFeature.State(trackee: testTrackee)) {
AddTrackeeFeature()
} withDependencies: {
$0.dismiss = DismissEffect { }
}
await store.send(.cancelButtonTapped)
// Verify no delegate actions are sent
}
@Test("Save button sends delegate action with current trackee state")
func saveButtonSendsCurrentState() async {
@Dependency(\.uuid) var uuid
let testTrackee = Trackee(id: Trackee.ID(uuid()), name: "Initial Name")
let store = TestStore(initialState: AddTrackeeFeature.State(trackee: testTrackee)) {
AddTrackeeFeature()
}
await store.send(.saveButtonTapped)
await store.receive(\.delegate.saveTrackee, Trackee(id: testTrackee.id, name: "Initial Name"))
}
@Test("Multiple name changes update state correctly")
func multipleNameChanges() async {
@Dependency(\.uuid) var uuid
let testTrackee = Trackee(id: Trackee.ID(uuid()), name: "")
let store = TestStore(initialState: AddTrackeeFeature.State(trackee: testTrackee)) {
AddTrackeeFeature()
} withDependencies: {
$0.uuid = .incrementing
}
await store.send(.setName("Alice")){
$0.trackee.name = "Alice"
}
await store.send(.setName("Bob")){
$0.trackee.name = "Bob"
}
await store.send(.setName("Charlie")){
$0.trackee.name = "Charlie"
}
await store.send(.saveButtonTapped)
await store.receive(\.delegate.saveTrackee, Trackee(id: testTrackee.id, name: "Charlie"))
}
@Test("Save empty name trackee")
func saveEmptyName() async {
@Dependency(\.uuid) var uuid
let testTrackee = Trackee(id: Trackee.ID(uuid()), name: "")
let store = TestStore(initialState: AddTrackeeFeature.State(trackee: testTrackee)) {
AddTrackeeFeature()
}
await store.send(.saveButtonTapped)
await store.receive(\.delegate.saveTrackee, Trackee(id: testTrackee.id, name: ""))
}
@Test("Set name with special characters")
func setNameWithSpecialCharacters() async {
@Dependency(\.uuid) var uuid
let testTrackee = Trackee(id: Trackee.ID(uuid()), name: "")
let store = TestStore(initialState: AddTrackeeFeature.State(trackee: testTrackee)) {
AddTrackeeFeature()
}
let specialName = "Test 123 !@#$%^&*()"
await store.send(.setName(specialName)){
$0.trackee.name = specialName
}
await store.send(.saveButtonTapped)
await store.receive(\.delegate.saveTrackee, Trackee(id: testTrackee.id, name: specialName))
}
@Test("Set name with emoji")
func setNameWithEmoji() async {
@Dependency(\.uuid) var uuid
let testTrackee = Trackee(id: Trackee.ID(uuid()), name: "")
let store = TestStore(initialState: AddTrackeeFeature.State(trackee: testTrackee)) {
AddTrackeeFeature()
}
let emojiName = "🐶 Max"
await store.send(.setName(emojiName)){
$0.trackee.name = emojiName
}
await store.send(.saveButtonTapped)
await store.receive(\.delegate.saveTrackee, Trackee(id: testTrackee.id, name: emojiName))
}
@Test("Delegate actions do not cause side effects")
func delegateActionsNoSideEffects() async {
@Dependency(\.uuid) var uuid
let testTrackee = Trackee(id: Trackee.ID(uuid()), name: "Test")
let store = TestStore(initialState: AddTrackeeFeature.State(trackee: testTrackee)) {
AddTrackeeFeature()
}
// Sending delegate actions directly should have no effect
await store.send(.delegate(.saveTrackee(testTrackee)))
}
@Test("keypadAppendCharacter appends characters to build name")
func keypadAppendCharacter() async {
@Dependency(\.uuid) var uuid
let testTrackee = Trackee(id: Trackee.ID(uuid()), name: "")
let store = TestStore(initialState: AddTrackeeFeature.State(trackee: testTrackee)) {
AddTrackeeFeature()
}
await store.send(.keypadAppendCharacter("B")) {
$0.trackee.name = "B"
}
await store.send(.keypadAppendCharacter("o")) {
$0.trackee.name = "Bo"
}
await store.send(.keypadAppendCharacter("b")) {
$0.trackee.name = "Bob"
}
await store.send(.saveButtonTapped)
await store.receive(\.delegate.saveTrackee, Trackee(id: testTrackee.id, name: "Bob"))
}
@Test("keypadDeleteCharacter removes last character")
func keypadDeleteCharacter() async {
@Dependency(\.uuid) var uuid
let testTrackee = Trackee(id: Trackee.ID(uuid()), name: "Bob")
let store = TestStore(initialState: AddTrackeeFeature.State(trackee: testTrackee)) {
AddTrackeeFeature()
}
await store.send(.keypadDeleteCharacter) {
$0.trackee.name = "Bo"
}
await store.send(.keypadDeleteCharacter) {
$0.trackee.name = "B"
}
}
@Test("keypadDeleteCharacter on empty name is no-op")
func keypadDeleteCharacterEmpty() async {
@Dependency(\.uuid) var uuid
let testTrackee = Trackee(id: Trackee.ID(uuid()), name: "")
let store = TestStore(initialState: AddTrackeeFeature.State(trackee: testTrackee)) {
AddTrackeeFeature()
}
await store.send(.keypadDeleteCharacter)
}
@Test("Long name can be set and saved")
func setLongName() async {
@Dependency(\.uuid) var uuid
let testTrackee = Trackee(id: Trackee.ID(uuid()), name: "")
let store = TestStore(initialState: AddTrackeeFeature.State(trackee: testTrackee)) {
AddTrackeeFeature()
}
let longName = String(repeating: "A", count: 1000)
await store.send(.setName(longName)){
$0.trackee.name = longName
}
await store.send(.saveButtonTapped)
await store.receive(\.delegate.saveTrackee, Trackee(id: testTrackee.id, name: longName))
}
}