Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Sources/Atoms/Attribute/Refreshable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
/// }
/// ```
///
@available(*, deprecated, message: "`Refreshable` is deprecated. Use a custom refresh function or other alternatives instead.")
public protocol Refreshable where Self: Atom {
/// Refreshes and then return a result value.
///
Expand Down
1 change: 1 addition & 0 deletions Sources/Atoms/Attribute/Resettable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
/// }
/// ```
///
@available(*, deprecated, message: "`Resettable` is deprecated. Use a custom reset function or other alternatives instead.")
public protocol Resettable where Self: Atom {
/// Arbitrary reset method to be executed on atom reset.
///
Expand Down
2 changes: 2 additions & 0 deletions Sources/Atoms/Context/AtomContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ public protocol AtomContext {
/// - Parameter atom: An atom to refresh.
///
/// - Returns: The value after the refreshing associated with the given atom is completed.
@available(*, deprecated, message: "`Refreshable` is deprecated. Use a custom refresh function or other alternatives instead.")
@discardableResult
func refresh<Node: Refreshable>(_ atom: Node) async -> Node.Produced

Expand Down Expand Up @@ -136,6 +137,7 @@ public protocol AtomContext {
/// ```
///
/// - Parameter atom: An atom to reset.
@available(*, deprecated, message: "`Resettable` is deprecated. Use a custom reset function or other alternatives instead.")
func reset(_ atom: some Resettable)
}

Expand Down
2 changes: 2 additions & 0 deletions Sources/Atoms/Context/AtomCurrentContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ public struct AtomCurrentContext: AtomContext {
/// - Parameter atom: An atom to refresh.
///
/// - Returns: The value after the refreshing associated with the given atom is completed.
@available(*, deprecated, message: "`Refreshable` is deprecated. Use a custom refresh function or other alternatives instead.")
@inlinable
@discardableResult
public func refresh<Node: Refreshable>(_ atom: Node) async -> Node.Produced {
Expand Down Expand Up @@ -155,6 +156,7 @@ public struct AtomCurrentContext: AtomContext {
/// ```
///
/// - Parameter atom: An atom to reset.
@available(*, deprecated, message: "`Resettable` is deprecated. Use a custom reset function or other alternatives instead.")
@inlinable
public func reset(_ atom: some Resettable) {
_store.reset(atom)
Expand Down
2 changes: 2 additions & 0 deletions Sources/Atoms/Context/AtomTestContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ public struct AtomTestContext: AtomWatchableContext {
/// - Parameter atom: An atom to refresh.
///
/// - Returns: The value after the refreshing associated with the given atom is completed.
@available(*, deprecated, message: "`Refreshable` is deprecated. Use a custom refresh function or other alternatives instead.")
@inlinable
@discardableResult
public func refresh<Node: Refreshable>(_ atom: Node) async -> Node.Produced {
Expand Down Expand Up @@ -300,6 +301,7 @@ public struct AtomTestContext: AtomWatchableContext {
/// ```
///
/// - Parameter atom: An atom to reset.
@available(*, deprecated, message: "`Resettable` is deprecated. Use a custom reset function or other alternatives instead.")
@inlinable
public func reset(_ atom: some Resettable) {
_store.reset(atom)
Expand Down
2 changes: 2 additions & 0 deletions Sources/Atoms/Context/AtomTransactionContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ public struct AtomTransactionContext: AtomWatchableContext {
/// - Parameter atom: An atom to refresh.
///
/// - Returns: The value after the refreshing associated with the given atom is completed.
@available(*, deprecated, message: "`Refreshable` is deprecated. Use a custom refresh function or other alternatives instead.")
@inlinable
@discardableResult
public func refresh<Node: Refreshable>(_ atom: Node) async -> Node.Produced {
Expand Down Expand Up @@ -166,6 +167,7 @@ public struct AtomTransactionContext: AtomWatchableContext {
/// ```
///
/// - Parameter atom: An atom to reset.
@available(*, deprecated, message: "`Resettable` is deprecated. Use a custom reset function or other alternatives instead.")
@inlinable
public func reset(_ atom: some Resettable) {
_store.reset(atom)
Expand Down
2 changes: 2 additions & 0 deletions Sources/Atoms/Context/AtomViewContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ public struct AtomViewContext: AtomWatchableContext {
/// - Parameter atom: An atom to refresh.
///
/// - Returns: The value after the refreshing associated with the given atom is completed.
@available(*, deprecated, message: "`Refreshable` is deprecated. Use a custom refresh function or other alternatives instead.")
@inlinable
@discardableResult
public func refresh<Node: Refreshable>(_ atom: Node) async -> Node.Produced {
Expand Down Expand Up @@ -172,6 +173,7 @@ public struct AtomViewContext: AtomWatchableContext {
/// ```
///
/// - Parameter atom: An atom to reset.
@available(*, deprecated, message: "`Resettable` is deprecated. Use a custom reset function or other alternatives instead.")
@inlinable
public func reset(_ atom: some Resettable) {
_store.reset(atom)
Expand Down
2 changes: 2 additions & 0 deletions Sources/Atoms/Core/StoreContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ internal struct StoreContext {
return value
}

@available(*, deprecated)
@usableFromInline
func refresh<Node: Refreshable>(_ atom: Node) async -> Node.Produced {
let (key, _) = lookupAtomKeyAndOverride(of: atom)
Expand Down Expand Up @@ -199,6 +200,7 @@ internal struct StoreContext {
}
}

@available(*, deprecated)
@usableFromInline
func reset(_ atom: some Resettable) {
let (key, _) = lookupAtomKeyAndOverride(of: atom)
Expand Down
1 change: 1 addition & 0 deletions Tests/AtomsTests/Attribute/RefreshableTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import XCTest

@testable import Atoms

@available(*, deprecated)
final class RefreshableTests: XCTestCase {
@MainActor
func testCustomRefresh() async {
Expand Down
1 change: 1 addition & 0 deletions Tests/AtomsTests/Attribute/ResettableTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import XCTest

@testable import Atoms

@available(*, deprecated)
final class ResettableTests: XCTestCase {
@MainActor
func testCustomReset() {
Expand Down
2 changes: 2 additions & 0 deletions Tests/AtomsTests/Context/AtomCurrentContextTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ final class AtomCurrentContextTests: XCTestCase {
XCTAssertEqual(value, 100)
}

@available(*, deprecated)
@MainActor
func testCustomRefresh() async {
let atom = TestCustomRefreshableAtom { _ in
Expand Down Expand Up @@ -84,6 +85,7 @@ final class AtomCurrentContextTests: XCTestCase {
XCTAssertEqual(storeContext.read(dependency), 0)
}

@available(*, deprecated)
@MainActor
func testCustomReset() {
let store = AtomStore()
Expand Down
2 changes: 2 additions & 0 deletions Tests/AtomsTests/Context/AtomTestContextTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ final class AtomTestContextTests: XCTestCase {
XCTAssertEqual(updateCount, 1)
}

@available(*, deprecated)
@MainActor
func testCustomRefresh() async {
let atom = TestCustomRefreshableAtom { _ in
Expand Down Expand Up @@ -248,6 +249,7 @@ final class AtomTestContextTests: XCTestCase {
XCTAssertEqual(context.read(atom), 0)
}

@available(*, deprecated)
@MainActor
func testCustomReset() {
let atom = TestStateAtom(defaultValue: 0)
Expand Down
2 changes: 2 additions & 0 deletions Tests/AtomsTests/Context/AtomTransactionContextTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ final class AtomTransactionContextTests: XCTestCase {
XCTAssertEqual(context.watch(atom1).value, 100)
}

@available(*, deprecated)
@MainActor
func testCustomRefresh() async {
let atom0 = TestValueAtom(value: 0)
Expand Down Expand Up @@ -103,6 +104,7 @@ final class AtomTransactionContextTests: XCTestCase {
XCTAssertEqual(context.read(dependency), 0)
}

@available(*, deprecated)
@MainActor
func testCustomReset() {
let transactionAtom = TestValueAtom(value: 0)
Expand Down
2 changes: 2 additions & 0 deletions Tests/AtomsTests/Context/AtomViewContextTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ final class AtomViewContextTests: XCTestCase {
XCTAssertEqual(context.watch(atom).value, 100)
}

@available(*, deprecated)
@MainActor
func testCustomRefresh() async {
let atom = TestCustomRefreshableAtom { _ in
Expand Down Expand Up @@ -104,6 +105,7 @@ final class AtomViewContextTests: XCTestCase {
XCTAssertEqual(context.read(atom), 0)
}

@available(*, deprecated)
@MainActor
func testCustomReset() {
let store = AtomStore()
Expand Down
151 changes: 113 additions & 38 deletions Tests/AtomsTests/Core/StoreContextTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1213,7 +1213,7 @@ final class StoreContextTests: XCTestCase {
}
}

struct TestAtom: StateAtom, Refreshable, Resettable {
struct TestAtom: StateAtom {
let testEffect: TestEffect

var key: UniqueKey {
Expand All @@ -1224,14 +1224,6 @@ final class StoreContextTests: XCTestCase {
context.read(TestDependencyAtom())
}

func refresh(context: CurrentContext) async -> Int {
context.read(TestDependencyAtom())
}

func reset(context: CurrentContext) {
context.reset(TestDependencyAtom())
}

func effect(context: CurrentContext) -> some AtomEffect {
testEffect.initContext = context
return testEffect
Expand Down Expand Up @@ -1297,49 +1289,132 @@ final class StoreContextTests: XCTestCase {
let testAtom = TestAtom(testEffect: testEffect)
let testAsyncAtom = TestAsyncAtom(testEffect: testEffect)

func assert<Node: Atom>(
_ atom: Node,
_ expected: Node.Produced,
file: StaticString = #filePath,
line: UInt = #line
) where Node.Produced: Equatable {
func assert(file: StaticString = #filePath, line: UInt = #line) {
XCTAssertEqual(testEffect.value1, 1, file: file, line: line)
XCTAssertEqual(testEffect.value2, 1, file: file, line: line)
XCTAssertEqual(context.read(atom), expected, file: file, line: line)
}

_ = context.read(testAtom)
assert(testAtom, 1)
let value0 = context.read(testAtom)
assert()
XCTAssertEqual(value0, 1)

_ = context.watch(testAtom, subscriber: subscriber, subscription: Subscription())
assert(testAtom, 1)

_ = context.watch(testAsyncAtom, subscriber: subscriber, subscription: Subscription())
assert(testAsyncAtom, .suspending)
let value1 = context.watch(testAtom, subscriber: subscriber, subscription: Subscription())
assert()
XCTAssertEqual(value1, 1)

context.modify(testAtom) { $0 = 1 }
assert(testAtom, 1)
let value2 = context.watch(testAsyncAtom, subscriber: subscriber, subscription: Subscription())
assert()
XCTAssertEqual(value2, .suspending)

scopedContext.set(context.read(testAtom), for: testAtom)
assert(testAtom, 1)
scopedContext.set(1, for: testAtom)
assert()

scopedContext.modify(testAtom) { $0 = 1 }
assert(testAtom, 1)

_ = await scopedContext.refresh(testAtom)
assert(testAtom, 1)
assert()

_ = await scopedContext.refresh(testAsyncAtom)
assert(testAsyncAtom, .success(1))

scopedContext.reset(testAtom)
assert(testAtom, 1)
let value3 = await scopedContext.refresh(testAsyncAtom)
assert()
XCTAssertEqual(value3, .success(1))

scopedContext.reset(testAsyncAtom)
assert(testAsyncAtom, .suspending)
assert()

scopedContext.unwatch(testAtom, subscriber: subscriber)
assert(testAtom, 1)
assert()
}

@available(*, deprecated)
@MainActor
func testEffectCrossScopeBoundaryDeprecated() async {
struct TestDependencyAtom: ValueAtom, Hashable {
func value(context: Context) -> Int {
1
}
}

struct TestAtom: StateAtom, Refreshable, Resettable {
let testEffect: TestEffect

var key: UniqueKey {
UniqueKey()
}

func defaultValue(context: Context) -> Int {
context.watch(TestDependencyAtom())
}

func refresh(context: CurrentContext) async -> Int {
context.read(TestDependencyAtom())
}

func reset(context: CurrentContext) {
context.reset(TestDependencyAtom())
}

func effect(context: CurrentContext) -> some AtomEffect {
testEffect.initContext = context
return testEffect
}
}

final class TestEffect: AtomEffect {
var initContext: AtomCurrentContext?
var value1: Int?
var value2: Int?

func updateValues(context: Context) {
value1 = context.read(TestDependencyAtom())
value2 = initContext?.read(TestDependencyAtom())
}

func initialized(context: Context) {
updateValues(context: context)
}

func updated(context: Context) {
updateValues(context: context)
}

func released(context: Context) {
updateValues(context: context)
}
}

let subscriberState = SubscriberState()
let subscriber = Subscriber(subscriberState)
let store = AtomStore()
let rootScopeToken = ScopeKey.Token()
let scopeToken = ScopeKey.Token()
let context = StoreContext.root(store: store, scopeKey: rootScopeToken.key)
let scopedContext = context.scoped(
scopeID: ScopeID(DefaultScopeID()),
scopeKey: scopeToken.key,
observers: [],
overrideContainer: OverrideContainer()
.addingOverride(for: TestDependencyAtom()) { _ in
2
}
)
let testEffect = TestEffect()
let testAtom = TestAtom(testEffect: testEffect)

func assert(file: StaticString = #filePath, line: UInt = #line) {
XCTAssertEqual(testEffect.value1, 1, file: file, line: line)
XCTAssertEqual(testEffect.value2, 1, file: file, line: line)
}

let value0 = context.watch(testAtom, subscriber: subscriber, subscription: Subscription())
assert()
XCTAssertEqual(value0, 1)

let value1 = await scopedContext.refresh(testAtom)
assert()
XCTAssertEqual(value1, 1)

context.set(3, for: testAtom)
scopedContext.reset(testAtom)
assert()
XCTAssertEqual(context.read(testAtom), 1)
}

@MainActor
Expand Down
2 changes: 2 additions & 0 deletions Tests/AtomsTests/Utilities/TestAtom.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ struct TestAsyncPhaseAtom<Success, Failure: Error>: AsyncPhaseAtom, @unchecked S
}
}

@available(*, deprecated)
struct TestCustomRefreshableAtom<T: Sendable>: ValueAtom, Refreshable, @unchecked Sendable {
var getValue: (Context) -> T
var refresh: (CurrentContext) async -> T
Expand All @@ -112,6 +113,7 @@ struct TestCustomRefreshableAtom<T: Sendable>: ValueAtom, Refreshable, @unchecke
}
}

@available(*, deprecated)
struct TestCustomResettableAtom<T>: StateAtom, Resettable, @unchecked Sendable {
var defaultValue: (Context) -> T
var reset: (CurrentContext) -> Void
Expand Down