~ knotless Search/
↑↓ move↵ open⇧↵ all results

grain.social/grain-ios

1 collaborator
0
1
main
99 lines · 3.3 KB Raw History
@testable import Grain
import SwiftUI
import XCTest

/// The app's top-level screens, none of which were reachable from the existing
/// suite. Rendering a screen also renders the cards, rows and strips it is
/// built from, so these cover a good deal more than the file they name.
@MainActor
final class ScreenRenderTests: GrainTestCase {
    private var account: TestAccount!

    /// Async overrides: the synchronous `setUp`/`tearDown` are nonisolated, so
    /// touching main-actor state from them warns.
    override func setUp() async throws {
        try await super.setUp()
        account = TestAccount()
    }

    override func tearDown() async throws {
        MockURLProtocol.handler = nil
        account.restore()
        try await super.tearDown()
    }

    // MARK: - Feed

    func testRendersFeed() {
        MockURLProtocol.respondWithJSON(Fixtures.feed)
        let env = TestEnvironment()
        ViewRender.render(FeedView(client: env.client).withTestEnvironment(env))
    }

    func testRendersFeedWhenItFailsToLoad() {
        MockURLProtocol.respondWithError(statusCode: 500)
        let env = TestEnvironment()
        ViewRender.render(FeedView(client: env.client).withTestEnvironment(env))
    }

    func testRendersFeedWhenEmpty() {
        MockURLProtocol.respondWithJSON(#"{"items": [], "cursor": null}"#)
        let env = TestEnvironment()
        ViewRender.render(FeedView(client: env.client).withTestEnvironment(env))
    }

    // MARK: - Search

    func testRendersSearch() {
        MockURLProtocol.respondWithJSON(Fixtures.feed)
        let env = TestEnvironment()
        ViewRender.render(SearchView(client: env.client).withTestEnvironment(env))
    }

    func testRendersSearchWhenItFailsToLoad() {
        MockURLProtocol.respondWithError(statusCode: 500)
        let env = TestEnvironment()
        ViewRender.render(SearchView(client: env.client).withTestEnvironment(env))
    }

    // MARK: - Notifications

    func testRendersNotifications() {
        MockURLProtocol.respondWithJSON(Fixtures.notifications)
        let env = TestEnvironment()
        let vm = NotificationsViewModel(client: env.client)
        ViewRender.render(
            NotificationsView(client: env.client, viewModel: vm).withTestEnvironment(env)
        )
    }

    func testRendersNotificationsWhenEmpty() {
        MockURLProtocol.respondWithJSON(#"{"notifications": [], "cursor": null}"#)
        let env = TestEnvironment()
        let vm = NotificationsViewModel(client: env.client)
        ViewRender.render(
            NotificationsView(client: env.client, viewModel: vm).withTestEnvironment(env)
        )
    }

    // MARK: - Settings

    func testRendersSettings() {
        MockURLProtocol.respondWithJSON("{}")
        let env = TestEnvironment()
        ViewRender.render(SettingsView(client: env.client).withTestEnvironment(env))
    }

    // MARK: - Tab tree

    /// MainTabView builds the whole signed-in tree, so this reaches the tab
    /// bar, the selected tab's screen and the shared chrome around them.
    func testRendersMainTabTree() {
        MockURLProtocol.respondWithJSON(Fixtures.feed)
        let env = TestEnvironment()
        ViewRender.render(
            MainTabView(pendingDeepLink: .constant(nil)).withTestEnvironment(env),
            settle: 0.2
        )
    }
}