{"id":2112,"url":"https://github.com/nalexn/ViewInspector","last_synced_at":"2025-08-02T23:31:37.023Z","repository":{"id":37602161,"uuid":"222102253","full_name":"nalexn/ViewInspector","owner":"nalexn","description":"Runtime introspection and unit testing of SwiftUI views","archived":false,"fork":false,"pushed_at":"2024-11-24T07:06:12.000Z","size":2010,"stargazers_count":2208,"open_issues_count":35,"forks_count":153,"subscribers_count":28,"default_branch":"0.10.1","last_synced_at":"2024-11-26T13:13:22.409Z","etag":null,"topics":["best-practices","runtime-typechecking","swift","swift5","swiftui","swiftui-views","unit-testing"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nalexn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["nalexn"],"custom":["https://venmo.com/nallexn"]}},"created_at":"2019-11-16T13:19:44.000Z","updated_at":"2024-11-26T11:57:28.000Z","dependencies_parsed_at":"2023-11-25T09:38:20.038Z","dependency_job_id":"88d27b12-ed8d-400d-9f13-34bece347df6","html_url":"https://github.com/nalexn/ViewInspector","commit_stats":{"total_commits":1075,"total_committers":49,"mean_commits":21.93877551020408,"dds":"0.40930232558139534","last_synced_commit":"95ef7e922bc3b30535cb55e9aec636876c5fa1e0"},"previous_names":[],"tags_count":76,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nalexn%2FViewInspector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nalexn%2FViewInspector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nalexn%2FViewInspector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nalexn%2FViewInspector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nalexn","download_url":"https://codeload.github.com/nalexn/ViewInspector/tar.gz/refs/heads/0.10.1","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228503095,"owners_count":17930509,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["best-practices","runtime-typechecking","swift","swift5","swiftui","swiftui-views","unit-testing"],"created_at":"2024-01-05T20:16:03.856Z","updated_at":"2024-12-06T17:30:35.292Z","avatar_url":"https://github.com/nalexn.png","language":"Swift","readme":"\u003ch1 align=\"center\"\u003eViewInspector 🕵️‍♂️ for SwiftUI\u003c/h1\u003e\n\n\u003cspan align=\"center\"\u003e\n  \n![Platform](https://img.shields.io/badge/platform-iOS%20%7C%20macOS%20%7C%20tvOS%20%7C%20watchOS%20%7C%20visionOS-lightgrey) [![Build Status](https://travis-ci.com/nalexn/ViewInspector.svg?branch=master)](https://travis-ci.com/nalexn/ViewInspector) [![codecov](https://codecov.io/gh/nalexn/ViewInspector/branch/master/graph/badge.svg)](https://codecov.io/gh/nalexn/ViewInspector)\n\n\u003c/span\u003e\n\n**ViewInspector** is a library for unit testing SwiftUI views.\nIt allows for traversing a view hierarchy at runtime providing direct access to the underlying `View` structs.\n\n## Why?\n\nSwiftUI view is a function of state. We could provide it with the input, but were unable to verify the output... Until now!\n\n## Helpful links\n\n* **[Inspection guide](guide.md)**\n* **[SwiftUI API coverage](readiness.md)**\n\n## Use cases\n\n### 1. Search the view of a specific type or condition\n\nUse one of the `find` functions to quickly locate a specific view or assert there are none of such:\n\n```swift\ntry sut.inspect().find(button: \"Back\")\n\ntry sut.inspect().findAll(ViewType.Text.self,\n                          where: { try $0.attributes().isBold() })\n```\n\nCheck out [this section](guide.md#dynamic-query-with-find) in the guide for the reference.\n\n### 2. Read the inner state of the standard views\n\nStandard SwiftUI views are no longer a black box:\n\n```swift\nlet sut = Text(\"Completed by \\(72.51, specifier: \"%.1f\")%\").font(.caption)\n\nlet string = try sut.inspect().text().string(locale: Locale(identifier: \"es\"))\nXCTAssertEqual(string, \"Completado por 72,5%\")\n\nXCTAssertEqual(try sut.inspect().text().attributes().font(), .caption)\n```\n\nEach view has its own set of inspectable parameters, you can refer to the [API coverage](readiness.md) document to see what's available for a particular SwiftUI view.\n\n### 3. Verify your custom view's state\n\nObtain a copy of your custom view with actual state and references from the hierarchy of any depth:\n\n```swift\nlet sut = try view.inspect().find(CustomView.self).actualView()\nXCTAssertTrue(sut.viewModel.isUserLoggedIn)\n```\n\nThe library can operate with various types of the view's state, such as `@Binding`, `@State`, `@ObservedObject` and `@EnvironmentObject`.\n\n### 4. Trigger side effects\n\nYou can simulate user interaction by programmatically triggering system-controls callbacks:\n\n```swift\ntry sut.inspect().find(button: \"Close\").tap()\n\nlet list = try view.inspect().list()\ntry list[5].view(RowItemView.self).callOnAppear()\n```\n\nThe library provides helpers for writing asynchronous tests for views with callbacks.\n\n## FAQs\n\n### Which views and modifiers are supported?\n\nCheck out the [API coverage](readiness.md). There is currently almost full support for SwiftUI v1 API, the v2 and v3 support is under active development.\n\n### Is it using private APIs?\n\n**ViewInspector** is using official Swift reflection API to dissect the view structures. So it'll be production-friendly even if you could somehow ship the test target to the production.\n\n### How do I add it to my Xcode project?\n\nAssure you're adding the framework to your unit-test target. **Do NOT** add it to the main build target.\n\n#### Swift Package Manager\n\n`https://github.com/nalexn/ViewInspector`\n\n#### Carthage\n\n`github \"nalexn/ViewInspector\"`\n\n#### CocoaPods\n\n`pod 'ViewInspector'`\n\n### How do I use it in my project?\n\nPlease refer to the [Inspection guide](guide.md). You can also check out my other [project](https://github.com/nalexn/clean-architecture-swiftui) that harnesses the **ViewInspector** for testing the entire UI.\n\n### Other questions, concerns or suggestions?\n\nPing me on [Twitter](https://twitter.com/nallexn) or just submit an issue or a pull request on Github.\n\n---\n\n[![blog](https://img.shields.io/badge/blog-github-blue)](https://nalexn.github.io/?utm_source=nalexn_github) [![venmo](https://img.shields.io/badge/%F0%9F%8D%BA-Venmo-brightgreen)](https://venmo.com/nallexn)\n","funding_links":["https://github.com/sponsors/nalexn","https://venmo.com/nallexn"],"categories":["Testing","Unit-testing","Swift","Samples","Libraries","📝 Articles","🌎 by the community","Test"],"sub_categories":["UI Testing","Content","Inspection","Unit Testing"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnalexn%2FViewInspector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnalexn%2FViewInspector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnalexn%2FViewInspector/lists"}