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
33 changes: 31 additions & 2 deletions Sources/Atoms/Context/AtomTestContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,24 @@ public struct AtomTestContext: AtomWatchableContext {
until predicate: @escaping (Node.Loader.Value) -> Bool
) async -> Bool {
await withTaskGroup(of: Bool.self) { group in
@MainActor
func check() -> Bool {
guard let value = lookup(atom) else {
return false
}

return predicate(value)
}

let updates = state.makeUpdateStream()

group.addTask { @MainActor in
guard !predicate(read(atom)) else {
guard !check() else {
return false
}

for await _ in updates {
if predicate(read(atom)) {
if check() {
return true
}
}
Expand Down Expand Up @@ -261,6 +270,25 @@ public struct AtomTestContext: AtomWatchableContext {
}
}

/// Returns the already cached value associated with a given atom without side effects.
///
/// This method returns the value only when it is already cached, otherwise, it returns `nil`.
/// It has no side effects such as the creation of new values or watching to atoms.
///
/// ```swift
/// let context = AtomTestContext()
/// if let text = context.lookup(TextAtom()) {
/// print(text) // Prints the cached value associated with `TextAtom`.
/// }
/// ```
///
/// - Parameter atom: An atom that associates the value.
///
/// - Returns: The already cached value associated with the given atom.
public func lookup<Node: Atom>(_ atom: Node) -> Node.Loader.Value? {
store.lookup(atom)
}

/// Unwatches the given atom and do not receive any more updates of it.
///
/// It simulates cases where other atoms or views no longer watches to the atom.
Expand Down Expand Up @@ -298,6 +326,7 @@ public struct AtomTestContext: AtomWatchableContext {
}

private extension AtomTestContext {
@MainActor
final class State {
let store = AtomStore()
let token = ScopeKey.Token()
Expand Down
9 changes: 9 additions & 0 deletions Sources/Atoms/Core/StoreContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,15 @@ internal struct StoreContext {
}
}

@usableFromInline
func lookup<Node: Atom>(_ atom: Node) -> Node.Loader.Value? {
let override = lookupOverride(of: atom)
let key = AtomKey(atom, overrideScopeKey: override?.scopeKey)
let cache = lookupCache(of: atom, for: key)

return cache?.value
}

@usableFromInline
func unwatch(_ atom: some Atom, container: SubscriptionContainer.Wrapper) {
let override = lookupOverride(of: atom)
Expand Down