{"action":"opened","number":1,"pull_request":{"url":"https://api.github.com/repos/mindbody/Kava/pulls/1","id":62949592,"html_url":"https://github.com/mindbody/Kava/pull/1","diff_url":"https://github.com/mindbody/Kava/pull/1.diff","patch_url":"https://github.com/mindbody/Kava/pull/1.patch","issue_url":"https://api.github.com/repos/mindbody/Kava/issues/1","number":1,"state":"open","locked":false,"title":"Add element interface library and core documentation","user":{"login":"Hammertime38","id":2295961,"avatar_url":"https://avatars.githubusercontent.com/u/2295961?v=3","gravatar_id":"","url":"https://api.github.com/users/Hammertime38","html_url":"https://github.com/Hammertime38","followers_url":"https://api.github.com/users/Hammertime38/followers","following_url":"https://api.github.com/users/Hammertime38/following{/other_user}","gists_url":"https://api.github.com/users/Hammertime38/gists{/gist_id}","starred_url":"https://api.github.com/users/Hammertime38/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Hammertime38/subscriptions","organizations_url":"https://api.github.com/users/Hammertime38/orgs","repos_url":"https://api.github.com/users/Hammertime38/repos","events_url":"https://api.github.com/users/Hammertime38/events{/privacy}","received_events_url":"https://api.github.com/users/Hammertime38/received_events","type":"User","site_admin":false},"body":"This is a hefty update, but it is aimed at the finish line on Kava's primary goals. Like Bumblebee and Ironhide, Kava is meant to be a POM _wrapper_ on the consumed test framework, facading system interactions into a highly-readable, concrete interface. In comparison, XCTest is not very readable when dealing with complex interactions, and the framework is as dynamic as you can get (every XCUIElement has methods for every possible interaction in the system). At this point, we will only be adding common interactions and Element subclasses, but this should handle 95% of any iOS application UI.\r\n\r\nThis framework leverages the hell out of generics, so I can clarify on a specific example within the `Tappable` class:\r\n\r\n```swift\r\n\r\nclass Tappable<TResultBlock: Block> : Element {\r\n\r\n    public typealias TResultBlockBuilder = (() -> TResultBlock)?\r\n\r\n    public func tap(constructingBlock builder: TResultBlockBuilder = nil) -> TResultBlock {\r\n        return self.tap(TResultBlock.self, constructingBlock: builder)\r\n    }\r\n\r\n    public func tap<TCustomResultBlock : Block>(result: TCustomResultBlock.Type, constructingBlock builder: (() -> TCustomResultBlock)? = nil) -> TCustomResultBlock {\r\n        self.backingElement.tap()\r\n        return self.parentBlock.scopeTo(TCustomResultBlock.self, builder: builder)\r\n    }\r\n    ...\r\n}\r\n```\r\n\r\nThese are what I'm referring to as \"element action signatures\". For every action, we are maximizing our usage of generics by using function overloads for generic type inference. The typealiases defined are inherited by subclasses, which further standardizes these signatures across all elements. All of that said, we give the caller complete control over the proceeding Block scope and the construction of that proceeding Block (if absolutely necessary for nested element groups), but in most cases, neither is specified. So, within a page object, if we have a button defined as follows:\r\n\r\n```swift\r\nclass LoginPage : PageBlock {\r\n    var loginButton: Tappable<HomePage> {\r\n        get {\r\n            return Tappable(parentBlock: self, backingElement: self.backingElement.buttons[0])\r\n    }\r\n}\r\n```\r\nWhen in the scope of a LoginPage, the caller then has access to:\r\n```swift\r\nloginPage.tap() // Retuns a HomePage\r\nloginPage.tap(LoginPage.self) // Returns a new LoginPage block\r\nloginPage.tap(LoginPage.self, constructingBlock: { () -> LoginPage in\r\n    return self\r\n}) // Returns the same LoginPage block\r\n```","created_at":"2016-03-15T17:55:40Z","updated_at":"2016-03-15T17:55:40Z","closed_at":null,"merged_at":null,"merge_commit_sha":null,"assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/mindbody/Kava/pulls/1/commits","review_comments_url":"https://api.github.com/repos/mindbody/Kava/pulls/1/comments","review_comment_url":"https://api.github.com/repos/mindbody/Kava/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mindbody/Kava/issues/1/comments","statuses_url":"https://api.github.com/repos/mindbody/Kava/statuses/3fd1e6f4f45d1df9fe4aafa738ed5ba11b050daf","head":{"label":"mindbody:add-interface-library","ref":"add-interface-library","sha":"3fd1e6f4f45d1df9fe4aafa738ed5ba11b050daf","user":{"login":"mindbody","id":1529724,"avatar_url":"https://avatars.githubusercontent.com/u/1529724?v=3","gravatar_id":"","url":"https://api.github.com/users/mindbody","html_url":"https://github.com/mindbody","followers_url":"https://api.github.com/users/mindbody/followers","following_url":"https://api.github.com/users/mindbody/following{/other_user}","gists_url":"https://api.github.com/users/mindbody/gists{/gist_id}","starred_url":"https://api.github.com/users/mindbody/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mindbody/subscriptions","organizations_url":"https://api.github.com/users/mindbody/orgs","repos_url":"https://api.github.com/users/mindbody/repos","events_url":"https://api.github.com/users/mindbody/events{/privacy}","received_events_url":"https://api.github.com/users/mindbody/received_events","type":"Organization","site_admin":false},"repo":{"id":52039864,"name":"Kava","full_name":"mindbody/Kava","owner":{"login":"mindbody","id":1529724,"avatar_url":"https://avatars.githubusercontent.com/u/1529724?v=3","gravatar_id":"","url":"https://api.github.com/users/mindbody","html_url":"https://github.com/mindbody","followers_url":"https://api.github.com/users/mindbody/followers","following_url":"https://api.github.com/users/mindbody/following{/other_user}","gists_url":"https://api.github.com/users/mindbody/gists{/gist_id}","starred_url":"https://api.github.com/users/mindbody/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mindbody/subscriptions","organizations_url":"https://api.github.com/users/mindbody/orgs","repos_url":"https://api.github.com/users/mindbody/repos","events_url":"https://api.github.com/users/mindbody/events{/privacy}","received_events_url":"https://api.github.com/users/mindbody/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mindbody/Kava","description":"A lightweight POM framework for Xcode UI Testing in Swift","fork":false,"url":"https://api.github.com/repos/mindbody/Kava","forks_url":"https://api.github.com/repos/mindbody/Kava/forks","keys_url":"https://api.github.com/repos/mindbody/Kava/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mindbody/Kava/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mindbody/Kava/teams","hooks_url":"https://api.github.com/repos/mindbody/Kava/hooks","issue_events_url":"https://api.github.com/repos/mindbody/Kava/issues/events{/number}","events_url":"https://api.github.com/repos/mindbody/Kava/events","assignees_url":"https://api.github.com/repos/mindbody/Kava/assignees{/user}","branches_url":"https://api.github.com/repos/mindbody/Kava/branches{/branch}","tags_url":"https://api.github.com/repos/mindbody/Kava/tags","blobs_url":"https://api.github.com/repos/mindbody/Kava/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mindbody/Kava/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mindbody/Kava/git/refs{/sha}","trees_url":"https://api.github.com/repos/mindbody/Kava/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mindbody/Kava/statuses/{sha}","languages_url":"https://api.github.com/repos/mindbody/Kava/languages","stargazers_url":"https://api.github.com/repos/mindbody/Kava/stargazers","contributors_url":"https://api.github.com/repos/mindbody/Kava/contributors","subscribers_url":"https://api.github.com/repos/mindbody/Kava/subscribers","subscription_url":"https://api.github.com/repos/mindbody/Kava/subscription","commits_url":"https://api.github.com/repos/mindbody/Kava/commits{/sha}","git_commits_url":"https://api.github.com/repos/mindbody/Kava/git/commits{/sha}","comments_url":"https://api.github.com/repos/mindbody/Kava/comments{/number}","issue_comment_url":"https://api.github.com/repos/mindbody/Kava/issues/comments{/number}","contents_url":"https://api.github.com/repos/mindbody/Kava/contents/{+path}","compare_url":"https://api.github.com/repos/mindbody/Kava/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mindbody/Kava/merges","archive_url":"https://api.github.com/repos/mindbody/Kava/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mindbody/Kava/downloads","issues_url":"https://api.github.com/repos/mindbody/Kava/issues{/number}","pulls_url":"https://api.github.com/repos/mindbody/Kava/pulls{/number}","milestones_url":"https://api.github.com/repos/mindbody/Kava/milestones{/number}","notifications_url":"https://api.github.com/repos/mindbody/Kava/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mindbody/Kava/labels{/name}","releases_url":"https://api.github.com/repos/mindbody/Kava/releases{/id}","deployments_url":"https://api.github.com/repos/mindbody/Kava/deployments","created_at":"2016-02-18T21:24:43Z","updated_at":"2016-02-19T22:08:20Z","pushed_at":"2016-03-15T17:55:41Z","git_url":"git://github.com/mindbody/Kava.git","ssh_url":"git@github.com:mindbody/Kava.git","clone_url":"https://github.com/mindbody/Kava.git","svn_url":"https://github.com/mindbody/Kava","homepage":null,"size":40,"stargazers_count":0,"watchers_count":0,"language":"Swift","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"mindbody:master","ref":"master","sha":"17c870d52099f7eac028f6b9f682da94d5f789d8","user":{"login":"mindbody","id":1529724,"avatar_url":"https://avatars.githubusercontent.com/u/1529724?v=3","gravatar_id":"","url":"https://api.github.com/users/mindbody","html_url":"https://github.com/mindbody","followers_url":"https://api.github.com/users/mindbody/followers","following_url":"https://api.github.com/users/mindbody/following{/other_user}","gists_url":"https://api.github.com/users/mindbody/gists{/gist_id}","starred_url":"https://api.github.com/users/mindbody/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mindbody/subscriptions","organizations_url":"https://api.github.com/users/mindbody/orgs","repos_url":"https://api.github.com/users/mindbody/repos","events_url":"https://api.github.com/users/mindbody/events{/privacy}","received_events_url":"https://api.github.com/users/mindbody/received_events","type":"Organization","site_admin":false},"repo":{"id":52039864,"name":"Kava","full_name":"mindbody/Kava","owner":{"login":"mindbody","id":1529724,"avatar_url":"https://avatars.githubusercontent.com/u/1529724?v=3","gravatar_id":"","url":"https://api.github.com/users/mindbody","html_url":"https://github.com/mindbody","followers_url":"https://api.github.com/users/mindbody/followers","following_url":"https://api.github.com/users/mindbody/following{/other_user}","gists_url":"https://api.github.com/users/mindbody/gists{/gist_id}","starred_url":"https://api.github.com/users/mindbody/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mindbody/subscriptions","organizations_url":"https://api.github.com/users/mindbody/orgs","repos_url":"https://api.github.com/users/mindbody/repos","events_url":"https://api.github.com/users/mindbody/events{/privacy}","received_events_url":"https://api.github.com/users/mindbody/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mindbody/Kava","description":"A lightweight POM framework for Xcode UI Testing in Swift","fork":false,"url":"https://api.github.com/repos/mindbody/Kava","forks_url":"https://api.github.com/repos/mindbody/Kava/forks","keys_url":"https://api.github.com/repos/mindbody/Kava/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mindbody/Kava/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mindbody/Kava/teams","hooks_url":"https://api.github.com/repos/mindbody/Kava/hooks","issue_events_url":"https://api.github.com/repos/mindbody/Kava/issues/events{/number}","events_url":"https://api.github.com/repos/mindbody/Kava/events","assignees_url":"https://api.github.com/repos/mindbody/Kava/assignees{/user}","branches_url":"https://api.github.com/repos/mindbody/Kava/branches{/branch}","tags_url":"https://api.github.com/repos/mindbody/Kava/tags","blobs_url":"https://api.github.com/repos/mindbody/Kava/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mindbody/Kava/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mindbody/Kava/git/refs{/sha}","trees_url":"https://api.github.com/repos/mindbody/Kava/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mindbody/Kava/statuses/{sha}","languages_url":"https://api.github.com/repos/mindbody/Kava/languages","stargazers_url":"https://api.github.com/repos/mindbody/Kava/stargazers","contributors_url":"https://api.github.com/repos/mindbody/Kava/contributors","subscribers_url":"https://api.github.com/repos/mindbody/Kava/subscribers","subscription_url":"https://api.github.com/repos/mindbody/Kava/subscription","commits_url":"https://api.github.com/repos/mindbody/Kava/commits{/sha}","git_commits_url":"https://api.github.com/repos/mindbody/Kava/git/commits{/sha}","comments_url":"https://api.github.com/repos/mindbody/Kava/comments{/number}","issue_comment_url":"https://api.github.com/repos/mindbody/Kava/issues/comments{/number}","contents_url":"https://api.github.com/repos/mindbody/Kava/contents/{+path}","compare_url":"https://api.github.com/repos/mindbody/Kava/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mindbody/Kava/merges","archive_url":"https://api.github.com/repos/mindbody/Kava/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mindbody/Kava/downloads","issues_url":"https://api.github.com/repos/mindbody/Kava/issues{/number}","pulls_url":"https://api.github.com/repos/mindbody/Kava/pulls{/number}","milestones_url":"https://api.github.com/repos/mindbody/Kava/milestones{/number}","notifications_url":"https://api.github.com/repos/mindbody/Kava/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mindbody/Kava/labels{/name}","releases_url":"https://api.github.com/repos/mindbody/Kava/releases{/id}","deployments_url":"https://api.github.com/repos/mindbody/Kava/deployments","created_at":"2016-02-18T21:24:43Z","updated_at":"2016-02-19T22:08:20Z","pushed_at":"2016-03-15T17:55:41Z","git_url":"git://github.com/mindbody/Kava.git","ssh_url":"git@github.com:mindbody/Kava.git","clone_url":"https://github.com/mindbody/Kava.git","svn_url":"https://github.com/mindbody/Kava","homepage":null,"size":40,"stargazers_count":0,"watchers_count":0,"language":"Swift","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mindbody/Kava/pulls/1"},"html":{"href":"https://github.com/mindbody/Kava/pull/1"},"issue":{"href":"https://api.github.com/repos/mindbody/Kava/issues/1"},"comments":{"href":"https://api.github.com/repos/mindbody/Kava/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/mindbody/Kava/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/mindbody/Kava/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mindbody/Kava/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/mindbody/Kava/statuses/3fd1e6f4f45d1df9fe4aafa738ed5ba11b050daf"}},"merged":false,"mergeable":null,"mergeable_state":"unknown","merged_by":null,"comments":0,"review_comments":0,"commits":11,"additions":651,"deletions":23,"changed_files":14}}