{"id":17269576,"url":"https://github.com/kanecheshire/peasy","last_synced_at":"2025-05-12T06:08:26.044Z","repository":{"id":36463600,"uuid":"224840670","full_name":"KaneCheshire/Peasy","owner":"KaneCheshire","description":"A pure Swift mock server for embedding and running directly within iOS/macOS UI tests. Easy peasy.","archived":false,"fork":false,"pushed_at":"2024-08-21T06:52:21.000Z","size":669,"stargazers_count":39,"open_issues_count":10,"forks_count":11,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-31T11:06:07.481Z","etag":null,"topics":["ios","macos","swift","xctest","xcui","xcuitest"],"latest_commit_sha":null,"homepage":null,"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/KaneCheshire.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-11-29T11:24:56.000Z","updated_at":"2024-12-11T21:32:55.000Z","dependencies_parsed_at":"2023-01-17T02:00:21.208Z","dependency_job_id":null,"html_url":"https://github.com/KaneCheshire/Peasy","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KaneCheshire%2FPeasy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KaneCheshire%2FPeasy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KaneCheshire%2FPeasy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/KaneCheshire%2FPeasy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/KaneCheshire","download_url":"https://codeload.github.com/KaneCheshire/Peasy/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238053527,"owners_count":19408705,"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":["ios","macos","swift","xctest","xcui","xcuitest"],"created_at":"2024-10-15T08:16:48.367Z","updated_at":"2025-02-10T04:12:41.582Z","avatar_url":"https://github.com/KaneCheshire.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Peasy\n\n[![Actions Status](https://github.com/kanecheshire/Peasy/workflows/Swift/badge.svg)](https://github.com/kanecheshire/Peasy/actions)\n[![Version](https://img.shields.io/cocoapods/v/Peasy.svg?style=flat)](http://cocoapods.org/pods/Peasy)\n[![License](https://img.shields.io/cocoapods/l/Peasy.svg?style=flat)](http://cocoapods.org/pods/Peasy)\n[![Platform](https://img.shields.io/cocoapods/p/Peasy.svg?style=flat)](http://cocoapods.org/pods/Peasy)\n\n[![Closed Issues](https://img.shields.io/github/issues-closed-raw/kanecheshire/Peasy)](https://github.com/KaneCheshire/Peasy/issues?q=is%3Aissue+is%3Aclosed)\n[![Open Issues](https://img.shields.io/github/issues-raw/kanecheshire/Peasy)](https://github.com/kanecheshire/Peasy/issues)\n\nA lightweight mock server written purely in Swift,\nthat you can run directly _in_ your UI tests, with no need for any external\nprocess to be spun up as part of the tests. 🎉\n\n- [Quick start](#quick-start)\n- [Starting \u0026 stopping the server](#starting-and-stopping-the-server)\n- [Configuring responses](#configuring-responses)\n- [Default \u0026 override responses](#default-and-override-responses)\n- [Delaying requests](#delaying-requests)\n- [Intercepting requests](#intercepting-requests)\n- [Wildcards \u0026 variables in paths](#wildcards-and-variables-in-paths)\n\n## Quick start\n\nSimply create and start a server in your tests, then tell it what to respond\nwith for requests:\n\n```swift\nimport XCTest\nimport Peasy\n\nclass MyUITest: XCTestCase {\n\n  let server = Server()\n\n  override func setUp() {\n    server.start() // Default port is 8880\n    let ok = Response(status: .ok)\n    server.respond(with: ok, when: .path(matches: \"/\"))\n  }\n\n  func test_someStuff() {\n    // Run your tests that cause the app to call http://localhost:8880/\n  }\n\n}\n```\n\n## Starting and stopping the server\n\nTo start a Peasy server, just call `start`:\n\n```swift\nlet server = Server()\nserver.start()\n```\n\nBy default, Peasy starts the server on whatever port is available on the system,\nbut you can override this and choose any specific port you want:\n\n```swift\nserver.start(port: 8080)\n```\n\n\u003e NOTE: Starting two servers on the same port is not supported and will fail.\n\n\u003e NOTE: iOS simulators share the same network as your Mac, so you can communicate\ndirectly with your Peasy server from Terminal, Safari or Postman on your Mac.\n\nTo stop a server (i.e. when tests finish), just call `stop`:\n\n```swift\nserver.stop()\n```\n\n## Configuring responses\n\nBy default Peasy doesn't know how to respond to any requests made to it.\n\nYou'll need to tell Peasy what to respond with, which you do by building up a set\nof rules that must be valid for an incoming request:\n\n```swift\nlet response = Response(status: .ok)\nserver.respond(with: response, when: .path(matches: \"/\"))\n```\n\nYou can provide multiple rules to filter responses further, for example, only matching\npaths `\"/\"` for `GET` requests:\n\n```swift\nserver.respond(with: response, when: .path(matches: \"/\"), .method(matches: .get))\n```\n\nNow, whenever Peasy receives a `GET` request matching the root path of `\"/\"`, it will respond\nwith an empty response of `200 OK`.\n\nIf none of Peasy's built in rules work for you, you can always provide a custom handler:\n\n```swift\nlet customRule: Rule = .custom { request in\n  return request.path.contains(\"/common/path\")\n}\nserver.respond(with: response, when: customRule)\n```\n\n## Default and override responses\n\nIt's common to want to set a \"default\" response to a request, but sometimes override\nit.\n\nFor example, in a UI test, you might want to set the default response as happy path, but then\ntest that if the request is made again what happens if you get a different response.\n\nPeasy supports this by allowing you to indicate whether a set of rules are removed after they're\nmatched with `removeAfterResponding`:\n\n```swift\nserver.respond(with: happyPathResponse, when: .path(matches: \"/api\")) // removeAfterResponding defaults to false, so this will persist\n\nserver.respond(with: unhappyPathResponse, when: .path(matches: \"/api\"), removeAfterResponding: true) // This will match before the happy path response and will be removed after responding\n```\n\nIn the case of multiple configurations matching a request (as above), Peasy will use the last set one (the unhappy path one above). Since we're also telling the unhappy path response to be removed after responding,\nPeasy will then carry on matching the first configuration (the happy path) until a new override response is set.\n\n## Delaying requests\n\nYou might want to slow responses down on your Peasy servers, for example to write a UI test to test what happens when a request times out.\n\nPeasy makes this really easy, just provide a TimeInterval when configuring your responses:\n\n```swift\nserver.respond(with: response, when: .path(matches: \"/api\"), delay: 60)\n```\n\nBy default, Peasy will respond immediately to requests you've told it to respond to. You must provide an explicit delay if you want a delay.\n\n## Intercepting requests\n\nThere might be times when you want to know when Peasy has received a request so you\nyou know how to respond or take some other action, like track certain requests (i.e. analytics).\n\nPeasy supports this by allowing you to provide a handler to return a response where the request is\nprovided to you as an argument:\n\n```swift\nvar analytics: [Request] = []\nserver.respond(with { request in\n  analytics.append(request)\n  return response\n}, when: .path(matches: \"/analytics-event\"))\n```\n\n## Wildcards and variables in paths\n\nIt's common to use wildcards and variables in paths that may be dynamic. Peasy supports\nthis by allowing you to indicate which parts of the path can be dynamic with the `:variable`\nsyntax:\n\n```swift\nserver.respond(with: response, when: .path(matches: \"/constant/:variable\"))\n```\n\nThe name after `:` can be anything you like, but that path component must exist otherwise\nthe rule will fail to match (i.e. `\"/constant/\"` is not valid, but `\"/constant/value\"` is).\n\nIf you want to get the value of a variable you can do so using a key-value subscript on the\nrequest:\n\n```swift\nserver.respond(with { request in\n  print(\"The value is\", request[\"variable\"])\n  return response\n}, when: .path(matches: \"/constant/:variable\"))\n```\n\n## FAQs\n\nQ: Does Peasy run on a real device?\n\nA: Yes! Peasy uses low level Darwin APIs built into the open-source bits of iOS and macOS.\n\n---\n\nQ: Can this ever break?\n\nA: Technically yeah, but these APIs have been around forever and haven't been deprecated.\n\n---\n\nQ: Can I use this in my app for the App Store?\n\nA: Peasy is designed for UI tests but also works in regular apps. Peasy doesn't use\nany private APIs, so shouldn't be rejected, but it will also depend on what you're using Peasy for.\n\n## Credits\n\nPeasy was hugely inspired by Envoy's Embassy server, but it does too much and\nis far too complicated for what I want to achieve. Peasy's interface is designed\nto be the simplest and most accessible it can be.\n\nWithout Envoy's hard work, Peasy would not exist.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkanecheshire%2Fpeasy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkanecheshire%2Fpeasy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkanecheshire%2Fpeasy/lists"}