{"id":25776441,"url":"https://github.com/airbnb/okreplay","last_synced_at":"2025-09-04T17:14:17.384Z","repository":{"id":18135155,"uuid":"83379086","full_name":"airbnb/okreplay","owner":"airbnb","description":"📼 Record and replay OkHttp network interaction in your tests.","archived":false,"fork":false,"pushed_at":"2022-08-29T06:31:17.000Z","size":63162,"stargazers_count":785,"open_issues_count":23,"forks_count":71,"subscribers_count":27,"default_branch":"master","last_synced_at":"2025-05-13T09:06:39.173Z","etag":null,"topics":["android","espresso","networking","okhttp"],"latest_commit_sha":null,"homepage":"","language":"Groovy","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/airbnb.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}},"created_at":"2017-02-28T02:17:33.000Z","updated_at":"2025-04-06T13:58:13.000Z","dependencies_parsed_at":"2022-08-07T09:00:32.788Z","dependency_job_id":null,"html_url":"https://github.com/airbnb/okreplay","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/airbnb/okreplay","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/airbnb%2Fokreplay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/airbnb%2Fokreplay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/airbnb%2Fokreplay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/airbnb%2Fokreplay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/airbnb","download_url":"https://codeload.github.com/airbnb/okreplay/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/airbnb%2Fokreplay/sbom","scorecard":{"id":173402,"data":{"date":"2025-08-11","repo":{"name":"github.com/airbnb/okreplay","commit":"1e1805b2c0f8b33da13b7a56ee11296b83d8aa5b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":7,"reason":"Found 21/30 approved changesets -- score normalized to 7","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build_test.yml:1","Warn: no topLevel permission defined: .github/workflows/deploy_snapshot.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: gradle/wrapper/gradle-wrapper.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build_test.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/airbnb/okreplay/build_test.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/deploy_snapshot.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/airbnb/okreplay/deploy_snapshot.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/deploy_snapshot.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/airbnb/okreplay/deploy_snapshot.yml/master?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Security-Policy","score":9,"reason":"security policy file detected","details":["Info: security policy file detected: github.com/airbnb/.github/SECURITY.md:1","Info: Found linked content: github.com/airbnb/.github/SECURITY.md:1","Warn: One or no descriptive hints of disclosure, vulnerability, and/or timelines in security policy","Info: Found text in security policy: github.com/airbnb/.github/SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 28 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-16T17:08:03.982Z","repository_id":18135155,"created_at":"2025-08-16T17:08:03.982Z","updated_at":"2025-08-16T17:08:03.982Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273641927,"owners_count":25142257,"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","status":"online","status_checked_at":"2025-09-04T02:00:08.968Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["android","espresso","networking","okhttp"],"created_at":"2025-02-27T06:01:24.173Z","updated_at":"2025-09-04T17:14:17.314Z","avatar_url":"https://github.com/airbnb.png","language":"Groovy","funding_links":[],"categories":["测试"],"sub_categories":[],"readme":"# OkReplay\n\nAutomatically record and replay OkHttp network interaction through your Android application.\nThis project was based on the great [Betamax](https://github.com/betamaxteam/betamax) library - which was inspired by Ruby's awesome [VCR](https://relishapp.com/vcr/vcr/docs) gem.\n\n## Introduction\n\nYou don’t want 3rd party downtime, network issues or resource constraints (such as the Twitter API’s\nrate limit) to break your tests. Writing custom stub web server code and configuring the application\nto connect to a different URI when under test is tedious and might not accurately simulate the real\nservice.\n\nOkReplay aims to solve these problems by intercepting HTTP connections initiated by your application\nand replaying previously __recorded__ responses.\n\nThe first time a test annotated with `@OkReplay` is run, any HTTP traffic is recorded to a tape and\nsubsequent test runs will play back the recorded HTTP response from the tape without actually\nconnecting to the external server.\n\nOkReplay works with JUnit and Espresso. OkReplay can be used to test any Java or Android applications,\nprovided they are using an `OkHttpClient` to make requests.\n\nTapes are stored to disk as YAML files and can be modified (or even created) by hand and committed\nto your project’s source control repository so they can be shared by other members of your team and\nused by your CI server. Different tests can use different tapes to simulate various response conditions.\nEach tape can hold multiple request/response interactions. An example tape file can be found\n[here](https://github.com/airbnb/okreplay/blob/master/okreplay-tests/src/test/resources/okreplay/tapes/smoke_spec.yaml).\n\n## Usage\n\nOkReplay comes as an OkHttp `Interceptor`. When \"started\", responses are served from the `Tape` file\nwhen a match is found for the `MatchRule` and the `TapeMode` is readable. If the `Tape` is writable,\nresponses will be served from the network as usual and the interaction will be stored on a `Tape`.\n\nAdd the `OkReplayInterceptor` to your `OkHttpClient`:\n\n```java\nOkReplayInterceptor okReplayInterceptor = new OkReplayInterceptor();\nOkHttpClient client = new OkHttpClient.Builder()\n  .addInterceptor(okReplayInterceptor)\n  .build()\n```\n\nBy default the interceptor won't do anything unless it's explicitly started.\n\n### Espresso integration\n\nIn your instrumentation test class, add:\n\n```java\nprivate final ActivityTestRule\u003cMainActivity\u003e activityTestRule =\n      new ActivityTestRule\u003c\u003e(MainActivity.class);\n  private final OkReplayConfig configuration = new OkReplayConfig.Builder()\n      .tapeRoot(new AndroidTapeRoot(getContext(), getClass()))\n      .defaultMode(TapeMode.READ_WRITE) // or TapeMode.READ_ONLY\n      .sslEnabled(true)\n      .interceptor(okReplayInterceptor))\n      .build();\n  @Rule public final TestRule testRule =\n      new OkReplayRuleChain(configuration, activityTestRule).get();\n\n  @Test\n  @OkReplay\n  public void testFooBar() {\n    // write your test as usual...\n  }\n```\n\n**IMPORTANT**: If you already have one, remove the `@Rule` annotation from your `ActivityTestRule`.\n\n### Gradle plugin integration\n\nAdd the classpath and apply the plugin in your build.config:\n\n```groovy\nbuildscript {\n  repositories {\n    maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }\n  }\n  dependencies {\n    classpath 'com.airbnb.okreplay:gradle-plugin:1.5.0'\n  }\n}\n\napply plugin: 'okreplay'\n\n```\n\nYou should now see these two tasks when you run `./gradlew tasks`:\n\n```\nclearDebugOkReplayTapes - Remove OkReplay tapes from the device\npullDebugOkReplayTapes - Pull OkReplay tapes from the device\n```\n\n## Download\n\nDownload [the latest JAR][2] or grab via Maven:\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.airbnb.okreplay\u003c/groupId\u003e\n  \u003cartifactId\u003eokreplay\u003c/artifactId\u003e\n  \u003cversion\u003e1.5.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\nor Gradle:\n```groovy\ndebugImplementation 'com.airbnb.okreplay:okreplay:1.5.0'\nreleaseImplementation 'com.airbnb.okreplay:noop:1.5.0'\nandroidTestImplementation 'com.airbnb.okreplay:espresso:1.5.0'\n```\n\nSnapshots of the development version are available in [Sonatype's `snapshots` repository][snap].\n\nLicense\n-------\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n [1]: http://airbnb.io/projects/okreplay/\n [2]: https://search.maven.org/remote_content?g=com.airbnb.okreplay\u0026a=okreplay\u0026v=LATEST\n [snap]: https://oss.sonatype.org/content/repositories/snapshots/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fairbnb%2Fokreplay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fairbnb%2Fokreplay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fairbnb%2Fokreplay/lists"}