{"id":13995467,"url":"https://github.com/paypal/Illuminator","last_synced_at":"2025-07-22T22:30:58.411Z","repository":{"id":26158470,"uuid":"29603811","full_name":"paypal/Illuminator","owner":"paypal","description":"iOS Automator","archived":true,"fork":false,"pushed_at":"2018-05-07T15:39:57.000Z","size":1103,"stargazers_count":39,"open_issues_count":8,"forks_count":19,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-06-13T07:46:19.466Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paypal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-01-21T18:11:05.000Z","updated_at":"2024-12-02T19:37:17.000Z","dependencies_parsed_at":"2022-08-20T23:10:31.842Z","dependency_job_id":null,"html_url":"https://github.com/paypal/Illuminator","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/paypal/Illuminator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paypal%2FIlluminator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paypal%2FIlluminator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paypal%2FIlluminator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paypal%2FIlluminator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paypal","download_url":"https://codeload.github.com/paypal/Illuminator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paypal%2FIlluminator/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266218474,"owners_count":23894473,"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":[],"created_at":"2024-08-09T14:03:25.536Z","updated_at":"2025-07-22T22:30:57.693Z","avatar_url":"https://github.com/paypal.png","language":"Swift","funding_links":[],"categories":["Swift"],"sub_categories":[],"readme":"# Illuminator\n\n[![CI Status](http://img.shields.io/travis/kviksilver/Illuminator.svg?style=flat)](https://travis-ci.org/kviksilver/Illuminator)\n[![Version](https://img.shields.io/cocoapods/v/Illuminator.svg?style=flat)](http://cocoapods.org/pods/Illuminator)\n[![License](https://img.shields.io/cocoapods/l/Illuminator.svg?style=flat)](http://cocoapods.org/pods/Illuminator)\n[![Platform](https://img.shields.io/cocoapods/p/Illuminator.svg?style=flat)](http://cocoapods.org/pods/Illuminator)\n\n# Illuminator makes your UI tests readable, reusable, and repairable\n\n## Readability\n\nWhere XCUITest generates a sequence of low-level element interactions, Illuminator tests are expressed as sequences of aptly-named (according to you, the developer) actions.  A detailed picture of what the test accomplishes should be apparent from the action names alone.\n\n```swift\n    func testWithIlluminator() {\n\n        initialState\n            .apply(wf.welcome.continueAsGuest())\n            .apply(wf.pushNotificationPermissions.decline())\n            .apply(wf.home.searchFor(\"table\"))\n            .apply(wf.browse.verifySubcategory(\"End tables\", expected: true))\n            .apply(wf.browse.verifySubcategory(\"Bobby tables\", expected: false))\n            .apply(wf.browse.openSubcategory(\"Coffee tables\"))\n            .apply(wf.browse.openProduct(atIndex: 3))\n            .apply(wf.productPage.addToCart(quantity: 2))\n            .apply(wf.welcomePopup.signIn())\n            .apply(wf.signInModal.submitCredentials(testAccount, password: testAccountPassword))\n            .apply(wf.cart.verifyTotalItems(2))\n            .apply(wf.cart.submitOrder())\n            .apply(wf.orderConfirmation.verifyIsActive())\n            .finish(self)\n    }\n```\n\n\n## Reusability\n\nYour tests don't need to explicitly check whether they're on the right screen before every UI element interaction; Illuminator does it for you.  Illuminator provides a system for grouping actions into the \"screens\" where they are available, and centralizes the logic for indicating when that screen is visible.\n\nIn the example above, `welcome`, `pushNotificationPermissions`, `home`, `browse`, `productPage`, `welcomePopup`, `signInModal`, `cart`, and `orderConfirmation` are the screens.  \n\nA sample app definition would include the following code:\n\n```swift\npublic typealias AppTestState = [String: String]\n\npublic struct WayfairTestApp: IlluminatorApplication {\n\n    var welcome: WelcomeScreen {\n        get {\n            return WelcomeScreen(testCaseWrapper: testCaseWrapper)\n        }\n    }\n\n    /// snip\n```\n\nAnd the definition of the welcome screen would include:\n\n```swift\npublic class WelcomeScreen: IlluminatorDelayedScreen\u003cAppTestState\u003e {\n        \n    public override var isActive: Bool {\n        return app.navigationBars[\"Welcome\"].exists\n    }\n\n     public func continueAsGuest() -\u003e IlluminatorActionGeneric\u003cAppTestState\u003e {\n        return makeAction() {\n            try self.app.buttons[\"Continue as Guest\"].ready().tap()\n        }\n    }\n\n    /// snip\n```\n\n\n## Repairability\n\nFailing XCTestcase test functions indicate the file and line of the failure.  That's not good enough.  Illuminator tests can indicate the file and line of the failure as well as a detailed description of the app state at the time of the failure.  For example, here is a sample of copy-pastable swift code generated by Illuminator between a test failure and the actual `XCFail()` call:\n\n```\napp.tabBars.elementBoundByIndex(0).buttons[\"Home\"]\napp.tabBars.elementBoundByIndex(0).buttons[\"Sales\"]\napp.tabBars.elementBoundByIndex(0).buttons[\"My Boards\"]\napp.tabBars.elementBoundByIndex(0).buttons[\"Account\"]\napp.tabBars.elementBoundByIndex(0).buttons[\"Cart\"]\napp.navigationBars[\"Welcome\"]\napp.navigationBars[\"Welcome\"].buttons[\"close\"]\napp.navigationBars[\"Welcome\"].staticTexts[\"Welcome\"]\napp.images[\"UniformCanvasLogo-Wayfair_US.jpg\"]\napp.staticTexts[\"Please Register or Sign In with your Wayfair.com account.\"]\napp.buttons[\"Register\"]\napp.buttons[\"Sign In\"]\napp.staticTexts[\"or\"]\n```\n\nOf course, this is ordinarily impossible.  Illuminator accomplishes this by meticulously working around XCUIElement operations that trigger immediate test failures (like XCUIElementQuery operations that return multiple elements or XCUIElement operations on nonexistent elements).  In the previous example, this was accomplished by Illuminator's `.ready()` function, which throws a catchable exception rather than trigger a test failure.\n\nBottom line?  In many cases you can repair broken CI tests without re-running the failing test in your IDE; just find the relevant element reference in the console output and copy/paste it into your screen or action as appropriate.\n\n\n## Documentation\n\nSee [Docs/](Docs/).\n\n\n## Usage\n\nTo run the example project, clone the repo, and run `pod install` from the Example directory first.\n\n## Installation\n\nIlluminator is available through [CocoaPods](http://cocoapods.org). To install\nit, simply add the following line to your Podfile:\n\n```ruby\npod \"Illuminator\"\n```\n\n## Authors\n\n* Ian Katz, ifreecarve@gmail.com\n* kviksilver, berceg@paypal.com\n\n## License\n\nIlluminator is available under the Apache 2.0 license. See the LICENSE.txt file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaypal%2FIlluminator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaypal%2FIlluminator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaypal%2FIlluminator/lists"}