From f86610b953056ec7b76ac1c247efb5db093b415f Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Mon, 8 Jan 2024 15:17:20 +0000 Subject: [PATCH 001/152] Removed updatecli workflow as it's running every hour and this doesn't seem necessary --- .github/workflows/updatecli.yaml | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 .github/workflows/updatecli.yaml diff --git a/.github/workflows/updatecli.yaml b/.github/workflows/updatecli.yaml deleted file mode 100644 index f3aafbcf..00000000 --- a/.github/workflows/updatecli.yaml +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: "Updatecli" - -on: - workflow_dispatch: - schedule: - # * is a special character in YAML so you have to quote this string - # trigger every hour the following pipeline - - cron: '0 * * * *' - -permissions: - contents: write - pull-requests: write - -jobs: - updatecli: - runs-on: ubuntu-latest - # Ensure we only run the following pipeline from main branch - # with a GITHUB_TOKEN that has "contents: write" permission - if: github.ref == 'refs/heads/main' - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Install Updatecli Binary - uses: updatecli/updatecli-action@v2 - - - name: Run Updatecli in enforce mode - run: "updatecli apply --config .github/updatecli/updatecli.d" - env: - GITHUB_ACTOR: ${{ github.actor }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 9ff751ce97772b36593691cba42fdc187f30ebd5 Mon Sep 17 00:00:00 2001 From: Mark Gerrard Date: Wed, 10 Jan 2024 10:08:01 +0000 Subject: [PATCH 002/152] Revert hacktober --- index.html | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/index.html b/index.html index 84a0a719..60320d44 100644 --- a/index.html +++ b/index.html @@ -133,31 +133,20 @@

-   Join us for Hacktoberfest 2023! -

-

Learn WireMock and contribute to open source

-

- - - -

+   + What's NEW? WireMock API Template Library

- This October we participate in Hacktoberfest - a global open source - hack fest. We invite you to join us, regardless of your profile and - technology stack. + Test against popular 3rd-party services in a few clicks!

- Adopt WireMock in your projects, contribute new features and fixes, - improve docs, create new demos and artwork, etc. + + +

- Learn More... + Browse our library of mock API templates and examples, find the API that you need, + and mock it in seconds - on your local machine or in the cloud. + Learn More...

From 57ef905c0df65c262f51e005d7eb6d8979d94a96 Mon Sep 17 00:00:00 2001 From: Mark Gerrard Date: Wed, 10 Jan 2024 17:24:30 +0000 Subject: [PATCH 003/152] update gem file --- Gemfile.lock | 2 -- 1 file changed, 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index b968d007..0f55380c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -108,7 +108,6 @@ GEM tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.4.2) - wdm (0.1.1) webrick (1.8.1) PLATFORMS @@ -126,7 +125,6 @@ DEPENDENCIES jemoji json (~> 1.8.6) nokogiri (>= 1.7.2) - wdm (~> 0.1.0) webrick (~> 1.7) BUNDLED WITH From dbbe4915348c047503d680479e1123feb2381960 Mon Sep 17 00:00:00 2001 From: Mark Gerrard Date: Wed, 10 Jan 2024 17:27:49 +0000 Subject: [PATCH 004/152] Fix ruby version --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c70aa783..1b957f7f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: - name: Setup Ruby uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0 with: - ruby-version: '2.7.6' # Not needed with a .ruby-version file + ruby-version: '2.7.2' # Not needed with a .ruby-version file bundler: '2.4.10' bundler-cache: false # runs 'bundle install' and caches installed gems automatically cache-version: 3 # Increment this number if you need to re-download cached gems From 7f6a970c635a92192870340a9b8f551e977134f6 Mon Sep 17 00:00:00 2001 From: Mark Gerrard Date: Wed, 10 Jan 2024 17:31:08 +0000 Subject: [PATCH 005/152] rubygems update --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b957f7f..d8eeef62 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,9 @@ jobs: id: pages uses: actions/configure-pages@v3 - name: Update RubyGems and Co - run: gem update --system + run: | + gem install rubygems-update --version 2.7.2 + gem update --system - name: Install Ruby Bundles run: bundle install - name: Build with Jekyll From 2bf1e08fcd968c3f6b39909d36f99c20fd65434a Mon Sep 17 00:00:00 2001 From: Mark Gerrard Date: Thu, 11 Jan 2024 10:23:39 +0000 Subject: [PATCH 006/152] Dont try to update rubygems itself as there seems to be a bug with updating it on this version of ruby --- .github/workflows/ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d8eeef62..891a5d68 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,9 +28,7 @@ jobs: id: pages uses: actions/configure-pages@v3 - name: Update RubyGems and Co - run: | - gem install rubygems-update --version 2.7.2 - gem update --system + run: gem update - name: Install Ruby Bundles run: bundle install - name: Build with Jekyll From dcbeeae4a493c1e3b887c70d37fbdff8784b6805 Mon Sep 17 00:00:00 2001 From: Mark Gerrard Date: Thu, 11 Jan 2024 10:46:59 +0000 Subject: [PATCH 007/152] Dont try to update rubygems itself as there seems to be a bug with updating it on this version of ruby --- .github/workflows/deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index adfb4b90..f108dd10 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -40,7 +40,7 @@ jobs: id: pages uses: actions/configure-pages@v3 - name: Update RubyGems and Co - run: gem update --system + run: gem update - name: Install Ruby Bundles run: bundle install - name: Build with Jekyll From 80d475c41bbc5e88557da4c071c6c0cc0abd4e3a Mon Sep 17 00:00:00 2001 From: Chris Dawkins Date: Thu, 11 Jan 2024 20:38:02 -0700 Subject: [PATCH 008/152] fix stub mapping http endpoint --- _docs/standalone/java-jar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/standalone/java-jar.md b/_docs/standalone/java-jar.md index fd949cff..9814c87a 100644 --- a/_docs/standalone/java-jar.md +++ b/_docs/standalone/java-jar.md @@ -212,7 +212,7 @@ You can create a stub mapping by posting to WireMock's HTTP API: ```bash $ curl -X POST \ --data '{ "request": { "url": "/get/this", "method": "GET" }, "response": { "status": 200, "body": "Here it is!\n" }}' \ -http://localhost:8080/__admin/mappings/new +http://localhost:8080/__admin/mappings ``` And then fetch it back: From 806af3da0f3ece02143bcb89b1eb2d195c4d36e6 Mon Sep 17 00:00:00 2001 From: Kyle Winkelman <39207896+kyle-winkelman@users.noreply.github.com> Date: Mon, 15 Jan 2024 09:40:16 -0600 Subject: [PATCH 009/152] Add extensionScanningEnabled option to @WireMockTest. (#242) --- _docs/junit-jupiter.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/_docs/junit-jupiter.md b/_docs/junit-jupiter.md index 2645fb75..0139f260 100644 --- a/_docs/junit-jupiter.md +++ b/_docs/junit-jupiter.md @@ -79,6 +79,18 @@ public class HttpsFixedPortDeclarativeWireMockTest { } ``` +### Enabling Extension Scanning + +When [extending WireMock via service loading](extending-wiremock.md#extension-registration-via-service-loading), it may +be helpful to have WireMock scan for extensions automatically via the `extensionScanningEnabled` parameter. + +```java +@WireMockTest(extensionScanningEnabled = true) +public class ExtensionScanningDeclarativeWireMockTest { + ... +} +``` + ## Advanced usage - programmatic Invoking the extension programmatically with `@RegisterExtension` allows you to run any number of WireMock instances and provides full control From 26137755e55d86b06beb751e435bbf32021645ba Mon Sep 17 00:00:00 2001 From: Prithvi Date: Tue, 16 Jan 2024 14:59:45 +0530 Subject: [PATCH 010/152] Added documentation for GET_OR_HEAD method (#246) Added documentation for GET_OR_HEAD method --- _docs/stubbing.md | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/_docs/stubbing.md b/_docs/stubbing.md index eb72e0c3..bf88eef5 100644 --- a/_docs/stubbing.md +++ b/_docs/stubbing.md @@ -133,8 +133,29 @@ stubFor(put("/status-only") More DSL examples [can be found here](https://github.com/tomakehurst/wiremock/tree/master/src/test/java/ignored/Examples.java#374). HTTP methods currently supported are: -`GET, POST, PUT, DELETE, HEAD, TRACE, OPTIONS`. You can specify `ANY` if -you want the stub mapping to match on any request method. +`GET, POST, PUT, DELETE, HEAD, TRACE, OPTIONS, GET_OR_HEAD`. You can specify `ANY` if +you want the stub mapping to match on any request method. `GET_OR_HEAD` is a special +method that could be used to match incoming requests for both `GET` or `HEAD` http +method. A ```HEAD``` request will result in the same behaviour expected from a web server i.e. +the ```Content-Type``` and ```Content-Length``` headers will be emitted but no response body. +A detailed guide about various HTTP methods can be found [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods). +```GET_OR_HEAD``` can be used the following way + +{% codetabs %} + +{% codetab Java %} + +```java +@Test +public void getOrHeadDemo() { + stubFor(getOrHead(urlEqualTo("/get-or-head-test")) + .willReturn(okJson("{\"key\": \"value\"}"))); + + assertThat(testClient.get("/get-or-head-test").statusCode(), is(200)); +} +``` + +{% endcodetab %} ### Setting the response status message From a4582306e05aa779a42923475df8058c181db4c2 Mon Sep 17 00:00:00 2001 From: Prithvi Date: Wed, 17 Jan 2024 16:34:03 +0530 Subject: [PATCH 011/152] Added closing endcode tabs (#250) --- _docs/stubbing.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/_docs/stubbing.md b/_docs/stubbing.md index bf88eef5..154b8b69 100644 --- a/_docs/stubbing.md +++ b/_docs/stubbing.md @@ -157,6 +157,8 @@ public void getOrHeadDemo() { {% endcodetab %} +{% endcodetabs %} + ### Setting the response status message In addition to the status code, the status message can optionally also From a8b0ba50af45380da36e9cea99b2212b1d6f1624 Mon Sep 17 00:00:00 2001 From: leeturner Date: Fri, 19 Jan 2024 11:54:40 +0000 Subject: [PATCH 012/152] Remove the hacktoberfest masthead notification from the notifications.js file. This is currently empty of notifications until we have something new to promote --- assets/js/notifications.js | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/assets/js/notifications.js b/assets/js/notifications.js index 64232636..35dccb97 100644 --- a/assets/js/notifications.js +++ b/assets/js/notifications.js @@ -1,22 +1,7 @@ var wiremock_notification_shown = localStorage.getItem( "wiremock_notification_shown", ); -var notifications = [ - { - content: { - title: - "Join us for Hacktoberfest 2023! " + - "Adopt WireMock in your projects and contribute to open source. " + - "Learn More", - }, - layout: { - style: "wiremock_notification_with_link", - position: "top", - className: "info", - autoHide: false, - }, - }, -]; +var notifications = []; if (wiremock_notification_shown == null) { localStorage.setItem("wiremock_notification_shown", true); From ee0fe0bd9cc540d269c2a8b4aa213d5e59454eaa Mon Sep 17 00:00:00 2001 From: Ethan Jones Date: Fri, 26 Jan 2024 12:36:54 -0500 Subject: [PATCH 013/152] Updating OSS vs WireMock Cloud --- home.html | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/home.html b/home.html index b8582b04..4ed6f24e 100644 --- a/home.html +++ b/home.html @@ -208,15 +208,16 @@

alt="wiremock cloud logo" class="logo" /> -

Hosted API mocking for everyone

- +

Rapidly create and Share API Mocks

+
    -
  • SaaS, nothing to install
  • -
  • For individuals, teams and enterprises
  • -
  • Intuitive web UI for developers
  • -
  • OpenAPI, Swagger and Postman import
  • -
  • NEW: Chaos Engineering
  • -
  • Generous free plan
  • +
  • Intuitive UI for complex API mock creation
  • +
  • WireMock-powered API productivity platform
  • +
  • Easy start with OpenAPI, Swagger, Postman imports
  • +
  • Pre-built templates for common industry APIs
  • +
  • Enhance API resilience with negative and chaos testing
  • +
  • Alerts for API mock and real API discrepancies
  • +
  • RBAC, security, and event logs
From f4e454f457692082e118c908533d6d33d8077e63 Mon Sep 17 00:00:00 2001 From: Kyle Winkelman Date: Wed, 17 Jan 2024 08:30:22 -0600 Subject: [PATCH 014/152] Allow matchesJsonSchema to be supplied as a json object. --- _docs/request-matching.md | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/_docs/request-matching.md b/_docs/request-matching.md index 73b06d58..eee3fd2e 100644 --- a/_docs/request-matching.md +++ b/_docs/request-matching.md @@ -800,7 +800,38 @@ stubFor( .willReturn(ok())); ``` -JSON: +JSON (supported in 3.4+): + +```json +{ + "request" : { + "urlPath" : "/schema-match", + "method" : "POST", + "bodyPatterns" : [ { + "matchesJsonSchema" : { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "schemaVersion" : "V202012" + } ] + }, + "response" : { + "status" : 200 + } +} +``` + +JSON with string literal: ```json { From cd0e7423d6bbedb8eac581f66202d061898b46cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20N=C3=BA=C3=B1ez=20Silva?= Date: Fri, 2 Feb 2024 17:50:35 +0100 Subject: [PATCH 015/152] Remove extra stubFor() in spring-boot example (#241) This commit removes an extra stubFor() in the code example. It was added twice by mistake and causes a compilation error. --- _docs/solutions/spring-boot.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_docs/solutions/spring-boot.md b/_docs/solutions/spring-boot.md index bb27b622..ebbb1439 100644 --- a/_docs/solutions/spring-boot.md +++ b/_docs/solutions/spring-boot.md @@ -37,14 +37,14 @@ class TodoControllerTests { void aTest() { // returns a URL to WireMockServer instance env.getProperty("user-client.url"); - wiremock.stubFor(stubFor(get("/todolist").willReturn(aResponse() + wiremock.stubFor(get("/todolist").willReturn(aResponse() .withHeader("Content-Type", "application/json") .withBody(""" [ { "id": 1, "userId": 1, "title": "my todo" }, ] """) - ))); + )); } } ``` From 0aa0eb836649c0a6bb8f6e1fc78a0d25cbe7bcb9 Mon Sep 17 00:00:00 2001 From: Prithvi Date: Fri, 2 Feb 2024 22:21:33 +0530 Subject: [PATCH 016/152] Corrected getRequestURI to url for wiremock server. (#243) --- _docs/quickstart/java-junit.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/quickstart/java-junit.md b/_docs/quickstart/java-junit.md index d9bc384a..b661057e 100644 --- a/_docs/quickstart/java-junit.md +++ b/_docs/quickstart/java-junit.md @@ -100,7 +100,7 @@ public void exampleTest() { // Setup HTTP POST request (with HTTP Client embedded in Java 11+) final HttpClient client = HttpClient.newBuilder().build(); final HttpRequest request = HttpRequest.newBuilder() - .uri(wiremockServer.getRequestURI("/my/resource")) + .uri(wiremockServer.url("/my/resource")) .header("Content-Type", "text/xml") .POST().build(); From 9973f3a32a7b6639c5166a77d348ec317ff35cd0 Mon Sep 17 00:00:00 2001 From: Dmitrii Khoziainov <87916143+dkhozyainov@users.noreply.github.com> Date: Fri, 2 Feb 2024 19:52:20 +0300 Subject: [PATCH 017/152] #2071 doc for GzipDisabled (#251) Co-authored-by: d.khoziainov --- _docs/stubbing.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/_docs/stubbing.md b/_docs/stubbing.md index 154b8b69..f23efdff 100644 --- a/_docs/stubbing.md +++ b/_docs/stubbing.md @@ -653,3 +653,20 @@ This can be changed by setting `duplicatePolicy` in the JSON to `IGNORE` or call If you want to ensure that the only stubs loaded after the import has completed are the ones it contains, you can set `"deleteAllNotInImport": true` in the JSON or call `deleteAllExistingStubsNotInImport()` on the Java builder. + +### Disabling Gzip at the ResponseDefinitionBuilder + +If you want to user Gzip disabled response option at the ResponseDefinitionBuilder level. +You can use `.withGzipDisabled(true)` + +```java + +wireMockServer.stubFor(get(urlEqualTo("/todo/items")) + .willReturn(aResponse() + .withStatus(200) + .withGzipDisabled(true) + .withBody( + "Here is some kind of response body" + + "Here is some kind of response body" + + "Here is some kind of response body"))); +``` From cf0b2b27b37763384ad392e9d85fa7d9519ac5fb Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Fri, 2 Feb 2024 16:54:44 +0000 Subject: [PATCH 018/152] Disabled automatic publishing of the site on push to main to avoid docs for releases features being released from PR merges --- .github/workflows/deploy.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index f108dd10..b641376f 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -2,8 +2,8 @@ name: Deploy Jekyll site to Pages on: # Runs on pushes targeting the default branch - push: - branches: ["main"] + # push: + # branches: ["main"] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: From 76e2f77d71673534f2f5e0e034e114f63abd68c9 Mon Sep 17 00:00:00 2001 From: Sam Williams <71648138+sam-williams-cko@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:55:43 +0000 Subject: [PATCH 019/152] Update stub mappings URL in administration.md (#255) * Update suggested URL in administration.md * Fix wording --- _docs/standalone/administration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/standalone/administration.md b/_docs/standalone/administration.md index ff573545..9a8ae8ad 100644 --- a/_docs/standalone/administration.md +++ b/_docs/standalone/administration.md @@ -10,7 +10,7 @@ You can find the key use-cases and the full specification below. ## Fetching all of your stub mappings (and checking WireMock is working) -A GET request to the root admin URL e.g `http://localhost:8080/__admin` +A GET request to the mappings admin URL e.g `http://localhost:8080/__admin/mappings` will return all currently registered stub mappings. This is a useful way to check whether WireMock is running on the host and port you expect. From d8eab7186c1fb4f2cba1a30fa5499e35918ff06d Mon Sep 17 00:00:00 2001 From: Ethan Jones Date: Sat, 10 Feb 2024 07:58:39 -0500 Subject: [PATCH 020/152] Updating OSS comparison --- index.html | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/index.html b/index.html index 60320d44..b977b61c 100644 --- a/index.html +++ b/index.html @@ -173,15 +173,16 @@

alt="wiremock cloud logo" class="logo" /> -

Hosted API mocking for everyone

- +

Rapidly create and Share API Mocks

+
    -
  • SaaS, nothing to install
  • -
  • For individuals, teams and enterprises
  • -
  • Intuitive web UI for developers
  • -
  • OpenAPI, Swagger and Postman import
  • -
  • NEW: Chaos Engineering
  • -
  • Generous free plan
  • +
  • Intuitive UI for complex API mock creation
  • +
  • For larger teams or API volume
  • +
  • Easy start with OpenAPI, Swagger, Postman imports
  • +
  • Pre-built templates for common industry APIs
  • +
  • Enhance API resilience with negative and chaos testing
  • +
  • Alerts for API mock and real API discrepancies
  • +
  • RBAC, security, and event logs
From 2c8c61cdb13ab52ca3c200d503cc981926166392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20N=C3=BA=C3=B1ez=20Silva?= Date: Fri, 2 Feb 2024 17:50:35 +0100 Subject: [PATCH 021/152] Remove extra stubFor() in spring-boot example (#241) This commit removes an extra stubFor() in the code example. It was added twice by mistake and causes a compilation error. --- _docs/solutions/spring-boot.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_docs/solutions/spring-boot.md b/_docs/solutions/spring-boot.md index bb27b622..ebbb1439 100644 --- a/_docs/solutions/spring-boot.md +++ b/_docs/solutions/spring-boot.md @@ -37,14 +37,14 @@ class TodoControllerTests { void aTest() { // returns a URL to WireMockServer instance env.getProperty("user-client.url"); - wiremock.stubFor(stubFor(get("/todolist").willReturn(aResponse() + wiremock.stubFor(get("/todolist").willReturn(aResponse() .withHeader("Content-Type", "application/json") .withBody(""" [ { "id": 1, "userId": 1, "title": "my todo" }, ] """) - ))); + )); } } ``` From 0e5cb6d7c311ae6366d72689a358e72e8164afbb Mon Sep 17 00:00:00 2001 From: Prithvi Date: Fri, 2 Feb 2024 22:21:33 +0530 Subject: [PATCH 022/152] Corrected getRequestURI to url for wiremock server. (#243) --- _docs/quickstart/java-junit.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/quickstart/java-junit.md b/_docs/quickstart/java-junit.md index d9bc384a..b661057e 100644 --- a/_docs/quickstart/java-junit.md +++ b/_docs/quickstart/java-junit.md @@ -100,7 +100,7 @@ public void exampleTest() { // Setup HTTP POST request (with HTTP Client embedded in Java 11+) final HttpClient client = HttpClient.newBuilder().build(); final HttpRequest request = HttpRequest.newBuilder() - .uri(wiremockServer.getRequestURI("/my/resource")) + .uri(wiremockServer.url("/my/resource")) .header("Content-Type", "text/xml") .POST().build(); From 47512db3a2ea649843777984fc9267a525a4c5dc Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Fri, 2 Feb 2024 16:54:44 +0000 Subject: [PATCH 023/152] Disabled automatic publishing of the site on push to main to avoid docs for releases features being released from PR merges --- .github/workflows/deploy.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index f108dd10..b641376f 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -2,8 +2,8 @@ name: Deploy Jekyll site to Pages on: # Runs on pushes targeting the default branch - push: - branches: ["main"] + # push: + # branches: ["main"] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: From 054bcddc10103a948ca43ef0102bf14f66aabf26 Mon Sep 17 00:00:00 2001 From: Sam Williams <71648138+sam-williams-cko@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:55:43 +0000 Subject: [PATCH 024/152] Update stub mappings URL in administration.md (#255) * Update suggested URL in administration.md * Fix wording --- _docs/standalone/administration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/standalone/administration.md b/_docs/standalone/administration.md index ff573545..9a8ae8ad 100644 --- a/_docs/standalone/administration.md +++ b/_docs/standalone/administration.md @@ -10,7 +10,7 @@ You can find the key use-cases and the full specification below. ## Fetching all of your stub mappings (and checking WireMock is working) -A GET request to the root admin URL e.g `http://localhost:8080/__admin` +A GET request to the mappings admin URL e.g `http://localhost:8080/__admin/mappings` will return all currently registered stub mappings. This is a useful way to check whether WireMock is running on the host and port you expect. From baaa2d5ebc1bee13f29f4d397d4b83da0b89316e Mon Sep 17 00:00:00 2001 From: Ethan Jones Date: Sat, 10 Feb 2024 07:58:39 -0500 Subject: [PATCH 025/152] Updating OSS comparison --- index.html | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/index.html b/index.html index 60320d44..b977b61c 100644 --- a/index.html +++ b/index.html @@ -173,15 +173,16 @@

alt="wiremock cloud logo" class="logo" /> -

Hosted API mocking for everyone

- +

Rapidly create and Share API Mocks

+
    -
  • SaaS, nothing to install
  • -
  • For individuals, teams and enterprises
  • -
  • Intuitive web UI for developers
  • -
  • OpenAPI, Swagger and Postman import
  • -
  • NEW: Chaos Engineering
  • -
  • Generous free plan
  • +
  • Intuitive UI for complex API mock creation
  • +
  • For larger teams or API volume
  • +
  • Easy start with OpenAPI, Swagger, Postman imports
  • +
  • Pre-built templates for common industry APIs
  • +
  • Enhance API resilience with negative and chaos testing
  • +
  • Alerts for API mock and real API discrepancies
  • +
  • RBAC, security, and event logs
From 0ea3a5263c27821fe1acf2b85a5e53c6fd98bd1a Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Fri, 16 Feb 2024 20:42:56 +0000 Subject: [PATCH 026/152] Updated WireMock version --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 0dc9f33e..d0d13d85 100644 --- a/_config.yml +++ b/_config.yml @@ -234,7 +234,7 @@ compress_html: ignore: envs: development -wiremock_version: 3.3.1 +wiremock_version: 3.4.0 wiremock_baseline: 3.x pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/ From 449c77145bce1c5b3082e99db4f435aaf60b506a Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Sat, 17 Feb 2024 11:16:15 +0000 Subject: [PATCH 027/152] Updated gRPC version --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index d0d13d85..3e36b254 100644 --- a/_config.yml +++ b/_config.yml @@ -238,7 +238,7 @@ wiremock_version: 3.4.0 wiremock_baseline: 3.x pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/ -grpc_extension_version: 0.4.0 +grpc_extension_version: 0.5.0 community_slack: join_url: https://slack.wiremock.org/ From 10b6e0fb3e94e47e6309fd2c8021db4e8de5d249 Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Mon, 19 Feb 2024 20:44:04 +0000 Subject: [PATCH 028/152] Bumped WireMock version to 3.4.1 --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 3e36b254..9c19b64a 100644 --- a/_config.yml +++ b/_config.yml @@ -234,7 +234,7 @@ compress_html: ignore: envs: development -wiremock_version: 3.4.0 +wiremock_version: 3.4.1 wiremock_baseline: 3.x pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/ From c9fe9e309dd1a1e55f8a47799000885bef2f66fc Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Mon, 19 Feb 2024 20:44:04 +0000 Subject: [PATCH 029/152] Bumped WireMock version to 3.4.1 --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 3e36b254..9c19b64a 100644 --- a/_config.yml +++ b/_config.yml @@ -234,7 +234,7 @@ compress_html: ignore: envs: development -wiremock_version: 3.4.0 +wiremock_version: 3.4.1 wiremock_baseline: 3.x pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/ From d3b86e5f79821fa7f82c18d3d00237ecb8e5f033 Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Fri, 23 Feb 2024 16:06:19 +0000 Subject: [PATCH 030/152] Bumped WireMock version to 3.4.2 --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 9c19b64a..7f1eb113 100644 --- a/_config.yml +++ b/_config.yml @@ -234,7 +234,7 @@ compress_html: ignore: envs: development -wiremock_version: 3.4.1 +wiremock_version: 3.4.2 wiremock_baseline: 3.x pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/ From 45e8c61eb2ba584aa3d86fa0296e34655836e77e Mon Sep 17 00:00:00 2001 From: leeturner Date: Thu, 29 Feb 2024 16:47:59 +0000 Subject: [PATCH 031/152] Add the mapping of the extensions folder in the docker volumes --- _docs/standalone/docker.md | 1 + 1 file changed, 1 insertion(+) diff --git a/_docs/standalone/docker.md b/_docs/standalone/docker.md index 2ebc00b4..70eff8d5 100644 --- a/_docs/standalone/docker.md +++ b/_docs/standalone/docker.md @@ -123,6 +123,7 @@ services: image: "wiremock/wiremock:latest" container_name: my_wiremock volumes: + - ./extensions:/var/wiremock/extensions - ./__files:/home/wiremock/__files - ./mappings:/home/wiremock/mappings entrypoint: ["/docker-entrypoint.sh", "--global-response-templating", "--disable-gzip", "--verbose"] From 4fabb2e4c63f43ed736a392b504ea4b7f3af1c73 Mon Sep 17 00:00:00 2001 From: leeturner Date: Thu, 29 Feb 2024 16:48:50 +0000 Subject: [PATCH 032/152] Give an example of how to disable response templating on a per stub basis. --- _docs/response-templating.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/_docs/response-templating.md b/_docs/response-templating.md index a724cda7..79a765d8 100644 --- a/_docs/response-templating.md +++ b/_docs/response-templating.md @@ -30,6 +30,24 @@ WireMockServer wm = See [the command line docs](../standalone/java-jar/#command-line-options) for the standalone equivalents of these parameters. +Response templating can also be disabled on a per-stub basis by adding the `disableBodyFileTemplating` parameter to the +`transformerParameters` object in the stub response definition. + +```json +{ + "request": { + "method": "GET", + "urlPath": "/test" + }, + "response": { + "status": 200, + "body": "Body content", + "transformerParameters": { + "disableBodyFileTemplating": true + } + } +} +``` ## Customising and extending the template engine From 4dd88ba4616ca46e61aeb7b9097d2652447351a8 Mon Sep 17 00:00:00 2001 From: leeturner Date: Mon, 4 Mar 2024 09:39:40 +0000 Subject: [PATCH 033/152] Clarify when response templating can be disabled on a per stub basis --- _docs/response-templating.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_docs/response-templating.md b/_docs/response-templating.md index 79a765d8..b943adea 100644 --- a/_docs/response-templating.md +++ b/_docs/response-templating.md @@ -30,8 +30,8 @@ WireMockServer wm = See [the command line docs](../standalone/java-jar/#command-line-options) for the standalone equivalents of these parameters. -Response templating can also be disabled on a per-stub basis by adding the `disableBodyFileTemplating` parameter to the -`transformerParameters` object in the stub response definition. +Response templating can also be disabled on a per-stub basis when using the `bodyFileName` element by adding the +`disableBodyFileTemplating` parameter to the `transformerParameters` object in the stub response definition. ```json { @@ -41,7 +41,7 @@ Response templating can also be disabled on a per-stub basis by adding the `disa }, "response": { "status": 200, - "body": "Body content", + "bodyFileName": "response.json", "transformerParameters": { "disableBodyFileTemplating": true } From 73c960ee7f49abcbdffa94c9179becb13c0586a4 Mon Sep 17 00:00:00 2001 From: Ethan Jones Date: Mon, 4 Mar 2024 11:33:36 -0500 Subject: [PATCH 034/152] Adding cloud callouts --- Gemfile.lock | 1 + _docs/download-and-installation.md | 3 ++- _docs/extensibility/filtering-requests.md | 2 ++ _docs/mock-api-templates.md | 2 ++ _docs/request-matching.md | 2 ++ _docs/simulating-faults.md | 2 ++ _docs/standalone.md | 2 ++ _docs/standalone/admin-api-reference.md | 2 ++ _docs/standalone/administration.md | 2 ++ _docs/standalone/docker.md | 2 ++ _docs/standalone/java-jar.md | 2 ++ _docs/verifying.md | 2 ++ _sass/_mocklab-popup.scss | 6 ++++++ 13 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0f55380c..dae010b3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -112,6 +112,7 @@ GEM PLATFORMS arm64-darwin-21 + arm64-darwin-23 x64-mingw32 x86_64-linux diff --git a/_docs/download-and-installation.md b/_docs/download-and-installation.md index 6c7fa81a..cf8138c1 100644 --- a/_docs/download-and-installation.md +++ b/_docs/download-and-installation.md @@ -14,7 +14,8 @@ redirect_from: - "/docs/download.html" - "/docs/download/" --- - + + ## Download options diff --git a/_docs/extensibility/filtering-requests.md b/_docs/extensibility/filtering-requests.md index 3bda7a62..5ccf6ec1 100644 --- a/_docs/extensibility/filtering-requests.md +++ b/_docs/extensibility/filtering-requests.md @@ -5,6 +5,8 @@ meta_title: Filtering and Modifying Requests description: Filtering and modifying requests via extensions --- + + Requests to both stubs and the admin API can be intercepted and either modified or halted with an immediate response. This supports a number of use cases including: authentication, URL rewriting and request header injection. diff --git a/_docs/mock-api-templates.md b/_docs/mock-api-templates.md index aa0dbc56..0a35ac0b 100644 --- a/_docs/mock-api-templates.md +++ b/_docs/mock-api-templates.md @@ -8,6 +8,8 @@ description: > that can be used with both WireMock or WireMock Cloud. --- + + The [library.wiremock.org](https://library.wiremock.org) site provides a catalog of API Templates that can be used with both [WireMock](https://wiremock.org/) or [WireMock Cloud](https://wiremock.io). diff --git a/_docs/request-matching.md b/_docs/request-matching.md index eee3fd2e..9d6a4e7c 100644 --- a/_docs/request-matching.md +++ b/_docs/request-matching.md @@ -6,6 +6,8 @@ toc_rank: 61 description: WireMock supports matching of requests to stubs and verification queries using the following attributes. --- + + WireMock enables flexible definition of a [mock API](/) by supporting rich matching of incoming requests. Stub matching and verification queries can use the following request attributes: - URL diff --git a/_docs/simulating-faults.md b/_docs/simulating-faults.md index fd2af476..dabac7f6 100644 --- a/_docs/simulating-faults.md +++ b/_docs/simulating-faults.md @@ -7,6 +7,8 @@ redirect_from: "/simulating-faults.html" description: One of the main reasons it’s beneficial to use web service fakes when testing is to inject faulty behaviour that might be difficult to get the real service to produce on demand. --- + + **One of the main reasons it's beneficial to use web service fakes when testing is to inject faulty behaviour that might be difficult to get the real service to produce on demand. In addition to being able to send diff --git a/_docs/standalone.md b/_docs/standalone.md index 5c731e2b..7c32cf43 100644 --- a/_docs/standalone.md +++ b/_docs/standalone.md @@ -10,6 +10,8 @@ description: > We provide the JAR file and Docker image distributions for it. --- + + WireMock can run as a standalone service, configured via the Java API, JSON over HTTP or JSON files. We provide the JAR file and Docker image distributions for it. diff --git a/_docs/standalone/admin-api-reference.md b/_docs/standalone/admin-api-reference.md index 8476f05e..e6280a40 100644 --- a/_docs/standalone/admin-api-reference.md +++ b/_docs/standalone/admin-api-reference.md @@ -10,6 +10,8 @@ redirect_from: - "/docs/api/" --- + + The WireMock admin API is described in [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md). The spec file plus an instance of Swagger UI can be accessed from a running WireMock instance under `/__admin/docs/`, e.g. `http://localhost:8080/__admin/docs/`. Below is the full API reference: diff --git a/_docs/standalone/administration.md b/_docs/standalone/administration.md index 9a8ae8ad..48f16271 100644 --- a/_docs/standalone/administration.md +++ b/_docs/standalone/administration.md @@ -5,6 +5,8 @@ meta_title: Administration API in WireMock Standalone | WireMock description: Provides tips on managing standalone WireMock servers --- + + WireMock Standalone offers the REST API for administration, troubleshooting and analysis purposes. You can find the key use-cases and the full specification below. diff --git a/_docs/standalone/docker.md b/_docs/standalone/docker.md index 2ebc00b4..d8fdb490 100644 --- a/_docs/standalone/docker.md +++ b/_docs/standalone/docker.md @@ -9,6 +9,8 @@ redirect_from: - "/docs/docker/" --- + + From version 2.31.0 WireMock has an [official Docker image](https://hub.docker.com/r/wiremock/wiremock). ## Getting started diff --git a/_docs/standalone/java-jar.md b/_docs/standalone/java-jar.md index 9814c87a..96a925f2 100644 --- a/_docs/standalone/java-jar.md +++ b/_docs/standalone/java-jar.md @@ -11,6 +11,8 @@ redirect_from: description: The WireMock server can be run in its own process, and configured via the Java API, JSON over HTTP or JSON files. --- + + The WireMock server can be run in its own process, and configured via the Java API, JSON over HTTP or JSON files. diff --git a/_docs/verifying.md b/_docs/verifying.md index 4aee216b..43fe5720 100644 --- a/_docs/verifying.md +++ b/_docs/verifying.md @@ -7,6 +7,8 @@ redirect_from: "/verifying.html" description: Verifying and querying requests relies on the request journal, which is an in-memory log of received requests. This can be disabled for load testing. --- + + The WireMock server records all requests it receives in memory (at least until it is [reset](../stubbing#reset)). This makes it possible to verify that a request matching a specific pattern was received, and also to fetch diff --git a/_sass/_mocklab-popup.scss b/_sass/_mocklab-popup.scss index f9af5ddc..785d7bf6 100644 --- a/_sass/_mocklab-popup.scss +++ b/_sass/_mocklab-popup.scss @@ -104,3 +104,9 @@ } } } + +div.cloud-callout { + background: rgba(255, 152, 0, .5); + padding: 1rem; + margin: 1rem 0 1rem 0; +} \ No newline at end of file From 52b39129f69d3eda2b9f2a70185421884e27e221 Mon Sep 17 00:00:00 2001 From: Ethan Jones Date: Mon, 4 Mar 2024 13:22:44 -0500 Subject: [PATCH 035/152] Updating to https --- _docs/download-and-installation.md | 2 +- _docs/extensibility/filtering-requests.md | 2 +- _docs/mock-api-templates.md | 2 +- _docs/request-matching.md | 2 +- _docs/simulating-faults.md | 2 +- _docs/standalone.md | 2 +- _docs/standalone/admin-api-reference.md | 2 +- _docs/standalone/administration.md | 2 +- _docs/standalone/docker.md | 2 +- _docs/standalone/java-jar.md | 2 +- _docs/verifying.md | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/_docs/download-and-installation.md b/_docs/download-and-installation.md index cf8138c1..b8c381f3 100644 --- a/_docs/download-and-installation.md +++ b/_docs/download-and-installation.md @@ -15,7 +15,7 @@ redirect_from: - "/docs/download/" --- - + ## Download options diff --git a/_docs/extensibility/filtering-requests.md b/_docs/extensibility/filtering-requests.md index 5ccf6ec1..1070daf2 100644 --- a/_docs/extensibility/filtering-requests.md +++ b/_docs/extensibility/filtering-requests.md @@ -5,7 +5,7 @@ meta_title: Filtering and Modifying Requests description: Filtering and modifying requests via extensions --- - + Requests to both stubs and the admin API can be intercepted and either modified or halted with an immediate response. This supports a number of use cases including: authentication, URL rewriting and request header injection. diff --git a/_docs/mock-api-templates.md b/_docs/mock-api-templates.md index 0a35ac0b..af643194 100644 --- a/_docs/mock-api-templates.md +++ b/_docs/mock-api-templates.md @@ -8,7 +8,7 @@ description: > that can be used with both WireMock or WireMock Cloud. --- - + The [library.wiremock.org](https://library.wiremock.org) site provides a catalog of API Templates that can be used with both diff --git a/_docs/request-matching.md b/_docs/request-matching.md index 9d6a4e7c..4a450fee 100644 --- a/_docs/request-matching.md +++ b/_docs/request-matching.md @@ -6,7 +6,7 @@ toc_rank: 61 description: WireMock supports matching of requests to stubs and verification queries using the following attributes. --- - + WireMock enables flexible definition of a [mock API](/) by supporting rich matching of incoming requests. Stub matching and verification queries can use the following request attributes: diff --git a/_docs/simulating-faults.md b/_docs/simulating-faults.md index dabac7f6..536ffc6d 100644 --- a/_docs/simulating-faults.md +++ b/_docs/simulating-faults.md @@ -7,7 +7,7 @@ redirect_from: "/simulating-faults.html" description: One of the main reasons it’s beneficial to use web service fakes when testing is to inject faulty behaviour that might be difficult to get the real service to produce on demand. --- - + **One of the main reasons it's beneficial to use web service fakes when testing is to inject faulty behaviour that might be difficult to get the diff --git a/_docs/standalone.md b/_docs/standalone.md index 7c32cf43..3ac15b47 100644 --- a/_docs/standalone.md +++ b/_docs/standalone.md @@ -10,7 +10,7 @@ description: > We provide the JAR file and Docker image distributions for it. --- - + WireMock can run as a standalone service, configured via the Java API, JSON over HTTP or JSON files. diff --git a/_docs/standalone/admin-api-reference.md b/_docs/standalone/admin-api-reference.md index e6280a40..2975a6f7 100644 --- a/_docs/standalone/admin-api-reference.md +++ b/_docs/standalone/admin-api-reference.md @@ -10,7 +10,7 @@ redirect_from: - "/docs/api/" --- - + The WireMock admin API is described in [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md). The spec file plus an instance of Swagger UI can be accessed from a running WireMock instance under `/__admin/docs/`, e.g. `http://localhost:8080/__admin/docs/`. diff --git a/_docs/standalone/administration.md b/_docs/standalone/administration.md index 48f16271..e733a3c9 100644 --- a/_docs/standalone/administration.md +++ b/_docs/standalone/administration.md @@ -5,7 +5,7 @@ meta_title: Administration API in WireMock Standalone | WireMock description: Provides tips on managing standalone WireMock servers --- - + WireMock Standalone offers the REST API for administration, troubleshooting and analysis purposes. You can find the key use-cases and the full specification below. diff --git a/_docs/standalone/docker.md b/_docs/standalone/docker.md index d8fdb490..2033f73b 100644 --- a/_docs/standalone/docker.md +++ b/_docs/standalone/docker.md @@ -9,7 +9,7 @@ redirect_from: - "/docs/docker/" --- - + From version 2.31.0 WireMock has an [official Docker image](https://hub.docker.com/r/wiremock/wiremock). diff --git a/_docs/standalone/java-jar.md b/_docs/standalone/java-jar.md index 96a925f2..7d6cde0c 100644 --- a/_docs/standalone/java-jar.md +++ b/_docs/standalone/java-jar.md @@ -11,7 +11,7 @@ redirect_from: description: The WireMock server can be run in its own process, and configured via the Java API, JSON over HTTP or JSON files. --- - + The WireMock server can be run in its own process, and configured via the Java API, JSON over HTTP or JSON files. diff --git a/_docs/verifying.md b/_docs/verifying.md index 43fe5720..fd6e5d09 100644 --- a/_docs/verifying.md +++ b/_docs/verifying.md @@ -7,7 +7,7 @@ redirect_from: "/verifying.html" description: Verifying and querying requests relies on the request journal, which is an in-memory log of received requests. This can be disabled for load testing. --- - + The WireMock server records all requests it receives in memory (at least until it is [reset](../stubbing#reset)). This makes it possible to verify that From 54353421402508cdce9dc9ae22c56e2e7b126298 Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Fri, 23 Feb 2024 16:06:19 +0000 Subject: [PATCH 036/152] Bumped WireMock version to 3.4.2 --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 9c19b64a..7f1eb113 100644 --- a/_config.yml +++ b/_config.yml @@ -234,7 +234,7 @@ compress_html: ignore: envs: development -wiremock_version: 3.4.1 +wiremock_version: 3.4.2 wiremock_baseline: 3.x pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/ From 9513bbbe1abb38ff4b42ad20be71ea706f174afc Mon Sep 17 00:00:00 2001 From: Ethan Date: Tue, 12 Mar 2024 08:46:28 -0400 Subject: [PATCH 037/152] Updating cloud callout messaging (#263) * Updating cloud callout messaging * Updating UTMs --------- Co-authored-by: Ethan Jones --- _docs/download-and-installation.md | 6 +++--- _docs/extensibility/filtering-requests.md | 2 +- _docs/mock-api-templates.md | 2 +- _docs/request-matching.md | 2 +- _docs/simulating-faults.md | 2 +- _docs/standalone.md | 2 +- _docs/standalone/admin-api-reference.md | 2 +- _docs/standalone/administration.md | 2 +- _docs/standalone/docker.md | 2 +- _docs/standalone/java-jar.md | 2 +- _docs/verifying.md | 2 +- _sass/_mocklab-popup.scss | 6 ++++++ 12 files changed, 19 insertions(+), 13 deletions(-) diff --git a/_docs/download-and-installation.md b/_docs/download-and-installation.md index b8c381f3..81cee1d8 100644 --- a/_docs/download-and-installation.md +++ b/_docs/download-and-installation.md @@ -1,4 +1,4 @@ ---- +open--- layout: docs title: Download and Installation meta_title: "How to Download and Install WireMock" @@ -14,8 +14,8 @@ redirect_from: - "/docs/download.html" - "/docs/download/" --- - - + + ## Download options diff --git a/_docs/extensibility/filtering-requests.md b/_docs/extensibility/filtering-requests.md index 1070daf2..2d3be6a4 100644 --- a/_docs/extensibility/filtering-requests.md +++ b/_docs/extensibility/filtering-requests.md @@ -5,7 +5,7 @@ meta_title: Filtering and Modifying Requests description: Filtering and modifying requests via extensions --- - + Requests to both stubs and the admin API can be intercepted and either modified or halted with an immediate response. This supports a number of use cases including: authentication, URL rewriting and request header injection. diff --git a/_docs/mock-api-templates.md b/_docs/mock-api-templates.md index af643194..3229a7d6 100644 --- a/_docs/mock-api-templates.md +++ b/_docs/mock-api-templates.md @@ -8,7 +8,7 @@ description: > that can be used with both WireMock or WireMock Cloud. --- - + The [library.wiremock.org](https://library.wiremock.org) site provides a catalog of API Templates that can be used with both diff --git a/_docs/request-matching.md b/_docs/request-matching.md index 4a450fee..8ca9ddf2 100644 --- a/_docs/request-matching.md +++ b/_docs/request-matching.md @@ -6,7 +6,7 @@ toc_rank: 61 description: WireMock supports matching of requests to stubs and verification queries using the following attributes. --- - + WireMock enables flexible definition of a [mock API](/) by supporting rich matching of incoming requests. Stub matching and verification queries can use the following request attributes: diff --git a/_docs/simulating-faults.md b/_docs/simulating-faults.md index 536ffc6d..458f7d65 100644 --- a/_docs/simulating-faults.md +++ b/_docs/simulating-faults.md @@ -7,7 +7,7 @@ redirect_from: "/simulating-faults.html" description: One of the main reasons it’s beneficial to use web service fakes when testing is to inject faulty behaviour that might be difficult to get the real service to produce on demand. --- - + **One of the main reasons it's beneficial to use web service fakes when testing is to inject faulty behaviour that might be difficult to get the diff --git a/_docs/standalone.md b/_docs/standalone.md index 3ac15b47..b539afcb 100644 --- a/_docs/standalone.md +++ b/_docs/standalone.md @@ -10,7 +10,7 @@ description: > We provide the JAR file and Docker image distributions for it. --- - + WireMock can run as a standalone service, configured via the Java API, JSON over HTTP or JSON files. diff --git a/_docs/standalone/admin-api-reference.md b/_docs/standalone/admin-api-reference.md index 2975a6f7..e0ee326c 100644 --- a/_docs/standalone/admin-api-reference.md +++ b/_docs/standalone/admin-api-reference.md @@ -10,7 +10,7 @@ redirect_from: - "/docs/api/" --- - + The WireMock admin API is described in [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md). The spec file plus an instance of Swagger UI can be accessed from a running WireMock instance under `/__admin/docs/`, e.g. `http://localhost:8080/__admin/docs/`. diff --git a/_docs/standalone/administration.md b/_docs/standalone/administration.md index e733a3c9..2197f2c1 100644 --- a/_docs/standalone/administration.md +++ b/_docs/standalone/administration.md @@ -5,7 +5,7 @@ meta_title: Administration API in WireMock Standalone | WireMock description: Provides tips on managing standalone WireMock servers --- - + WireMock Standalone offers the REST API for administration, troubleshooting and analysis purposes. You can find the key use-cases and the full specification below. diff --git a/_docs/standalone/docker.md b/_docs/standalone/docker.md index 2033f73b..4984a175 100644 --- a/_docs/standalone/docker.md +++ b/_docs/standalone/docker.md @@ -9,7 +9,7 @@ redirect_from: - "/docs/docker/" --- - + From version 2.31.0 WireMock has an [official Docker image](https://hub.docker.com/r/wiremock/wiremock). diff --git a/_docs/standalone/java-jar.md b/_docs/standalone/java-jar.md index 7d6cde0c..c02dee34 100644 --- a/_docs/standalone/java-jar.md +++ b/_docs/standalone/java-jar.md @@ -11,7 +11,7 @@ redirect_from: description: The WireMock server can be run in its own process, and configured via the Java API, JSON over HTTP or JSON files. --- - + The WireMock server can be run in its own process, and configured via the Java API, JSON over HTTP or JSON files. diff --git a/_docs/verifying.md b/_docs/verifying.md index fd6e5d09..c9abd2b3 100644 --- a/_docs/verifying.md +++ b/_docs/verifying.md @@ -7,7 +7,7 @@ redirect_from: "/verifying.html" description: Verifying and querying requests relies on the request journal, which is an in-memory log of received requests. This can be disabled for load testing. --- - + The WireMock server records all requests it receives in memory (at least until it is [reset](../stubbing#reset)). This makes it possible to verify that diff --git a/_sass/_mocklab-popup.scss b/_sass/_mocklab-popup.scss index 785d7bf6..270f88d5 100644 --- a/_sass/_mocklab-popup.scss +++ b/_sass/_mocklab-popup.scss @@ -103,6 +103,12 @@ color: $mocklab-dark-green; } } + + div.cloud-callout { + background: rgba(255, 152, 0, .5); + padding: 1rem; + margin: 1rem 0 1rem 0; + } } div.cloud-callout { From f2f24a39f22dfefa077dd2c7fa916b3d6f0d268a Mon Sep 17 00:00:00 2001 From: Mark Gerrard Date: Tue, 12 Mar 2024 13:38:16 +0000 Subject: [PATCH 038/152] fix: broken frontmatter --- _docs/download-and-installation.md | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/_docs/download-and-installation.md b/_docs/download-and-installation.md index 81cee1d8..d24f4247 100644 --- a/_docs/download-and-installation.md +++ b/_docs/download-and-installation.md @@ -1,18 +1,13 @@ -open--- +--- layout: docs title: Download and Installation meta_title: "How to Download and Install WireMock" toc_rank: 13 description: > - WireMock is available as a standalone service (for Docker of Java), Java library - and integrations for modern languages and technology stacks. -redirect_from: - - "/download.html" - - "/download/" - - "/downloads.html" - - "/downloads/" - - "/docs/download.html" - - "/docs/download/" +WireMock is available as a standalone service (for Docker of Java), Java library +and integrations for modern languages and technology stacks. +redirect_from: - "/download.html" - "/download/" - "/downloads.html" - "/downloads/" - "/docs/download.html" - "/docs/download/" + --- From f2c9cfe7e17183e50b389187a41c79dc36e09559 Mon Sep 17 00:00:00 2001 From: Mark Gerrard Date: Tue, 12 Mar 2024 13:38:16 +0000 Subject: [PATCH 039/152] fix: broken frontmatter --- _docs/download-and-installation.md | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/_docs/download-and-installation.md b/_docs/download-and-installation.md index 81cee1d8..d24f4247 100644 --- a/_docs/download-and-installation.md +++ b/_docs/download-and-installation.md @@ -1,18 +1,13 @@ -open--- +--- layout: docs title: Download and Installation meta_title: "How to Download and Install WireMock" toc_rank: 13 description: > - WireMock is available as a standalone service (for Docker of Java), Java library - and integrations for modern languages and technology stacks. -redirect_from: - - "/download.html" - - "/download/" - - "/downloads.html" - - "/downloads/" - - "/docs/download.html" - - "/docs/download/" +WireMock is available as a standalone service (for Docker of Java), Java library +and integrations for modern languages and technology stacks. +redirect_from: - "/download.html" - "/download/" - "/downloads.html" - "/downloads/" - "/docs/download.html" - "/docs/download/" + --- From f08b14a8e0b4e550b19f5250f20942af3808acc3 Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Thu, 28 Mar 2024 18:27:55 +0000 Subject: [PATCH 040/152] Updated WireMock version to 3.5.1 --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 7f1eb113..a14bb727 100644 --- a/_config.yml +++ b/_config.yml @@ -234,7 +234,7 @@ compress_html: ignore: envs: development -wiremock_version: 3.4.2 +wiremock_version: 3.5.1 wiremock_baseline: 3.x pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/ From dd5ef8c734933d599d84d5b786bbaf1cb568f483 Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Thu, 28 Mar 2024 18:27:55 +0000 Subject: [PATCH 041/152] Updated WireMock version to 3.5.1 --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 7f1eb113..a14bb727 100644 --- a/_config.yml +++ b/_config.yml @@ -234,7 +234,7 @@ compress_html: ignore: envs: development -wiremock_version: 3.4.2 +wiremock_version: 3.5.1 wiremock_baseline: 3.x pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/ From fd0ecb9838bd63a21906f21bdea2cfa02d814be4 Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Sat, 30 Mar 2024 22:17:25 +0000 Subject: [PATCH 042/152] Bumped WireMock version to 3.5.2 --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index a14bb727..6948fb12 100644 --- a/_config.yml +++ b/_config.yml @@ -234,7 +234,7 @@ compress_html: ignore: envs: development -wiremock_version: 3.5.1 +wiremock_version: 3.5.2 wiremock_baseline: 3.x pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/ From 26a712c73cc49febefe72533de2114114be94cad Mon Sep 17 00:00:00 2001 From: Tomas Bjerre Date: Tue, 2 Apr 2024 14:52:17 +0200 Subject: [PATCH 043/152] docs: wiremock-npm (#273) --- _docs/solutions/nodejs.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/_docs/solutions/nodejs.md b/_docs/solutions/nodejs.md index 47f9f867..0017b3ca 100644 --- a/_docs/solutions/nodejs.md +++ b/_docs/solutions/nodejs.md @@ -61,3 +61,11 @@ console.log(stubMappings); await wireMock.global.shutdown(); ``` + +## WireMock NPM package + +The WireMock NPM package is the WireMock standalone JAR packaged inside an NPM package. It has the exact same features as WireMock standalone and uses the same versioning. + +The main benefit of packaging it inside an NPM package is that the user will only need access to an NPM registry to use it. This is often the situation when working behind firewalls in organizations. + +- [GitHUb Repository](https://github.com/wiremock/wiremock-npm) From 222cd2d59c61b631d48f8af076ffc5d7e7ccdecd Mon Sep 17 00:00:00 2001 From: Lee Turner Date: Tue, 2 Apr 2024 13:53:02 +0100 Subject: [PATCH 044/152] Fix download page frontmatter formatting (#272) --- _docs/download-and-installation.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/_docs/download-and-installation.md b/_docs/download-and-installation.md index d24f4247..30507d5f 100644 --- a/_docs/download-and-installation.md +++ b/_docs/download-and-installation.md @@ -4,10 +4,15 @@ title: Download and Installation meta_title: "How to Download and Install WireMock" toc_rank: 13 description: > -WireMock is available as a standalone service (for Docker of Java), Java library -and integrations for modern languages and technology stacks. -redirect_from: - "/download.html" - "/download/" - "/downloads.html" - "/downloads/" - "/docs/download.html" - "/docs/download/" - + WireMock is available as a standalone service (for Docker of Java), Java library + and integrations for modern languages and technology stacks. +redirect_from: + - "/download.html" + - "/download/" + - "/downloads.html" + - "/downloads/" + - "/docs/download.html" + - "/docs/download/" --- From 48c07444f2b17479dabe26e5c8a004914668679d Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Tue, 2 Apr 2024 13:56:26 +0100 Subject: [PATCH 045/152] Switched download link on JAR page to canonical URL (rather than relying on redirect) --- _docs/standalone/java-jar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/standalone/java-jar.md b/_docs/standalone/java-jar.md index c02dee34..28dcbae0 100644 --- a/_docs/standalone/java-jar.md +++ b/_docs/standalone/java-jar.md @@ -16,7 +16,7 @@ description: The WireMock server can be run in its own process, and configured v The WireMock server can be run in its own process, and configured via the Java API, JSON over HTTP or JSON files. -Once you have [downloaded the standalone JAR](../../download) you can run it simply by doing this: +Once you have [downloaded the standalone JAR](../../download-and-installation/) you can run it simply by doing this: ```bash $ java -jar wiremock-standalone-{{ site.wiremock_version }}.jar From 6af58508591cd6f8027983a88a496b9796e8b44d Mon Sep 17 00:00:00 2001 From: cknoblauch Date: Tue, 2 Apr 2024 11:45:49 -0300 Subject: [PATCH 046/152] Update links to JUnit pages (#270) --- _docs/quickstart/java-junit.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/quickstart/java-junit.md b/_docs/quickstart/java-junit.md index b661057e..85c6309d 100644 --- a/_docs/quickstart/java-junit.md +++ b/_docs/quickstart/java-junit.md @@ -151,6 +151,6 @@ int httpsPort = wireMockRule.httpsPort(); ## Further reading - For more details on verifying requests and stubbing responses, see [Stubbing](../../stubbing) and [Verifying](../../verifying/) -- For more information on the JUnit rules see [The JUnit 4 Rule](../../junit-4/). +- For more information on the JUnit 5 Jupiter extension see [JUnit 5+ Jupiter](../../junit-jupiter/); for previous JUnit versions you can use [the JUnit 4 Rule](../../junit-extensions/). - For many more examples of JUnit tests check out the [WireMock's own acceptance tests](https://github.com/wiremock/wiremock/tree/master/src/test/java/com/github/tomakehurst/wiremock) From ebfe2b90d3f7cd340fb87b089509e896018e8c0e Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Tue, 2 Apr 2024 15:46:30 +0100 Subject: [PATCH 047/152] Re-added JUnit 4.x links (in addition to 5.x) --- _docs/quickstart/java-junit.md | 1 + 1 file changed, 1 insertion(+) diff --git a/_docs/quickstart/java-junit.md b/_docs/quickstart/java-junit.md index 85c6309d..3e989606 100644 --- a/_docs/quickstart/java-junit.md +++ b/_docs/quickstart/java-junit.md @@ -151,6 +151,7 @@ int httpsPort = wireMockRule.httpsPort(); ## Further reading - For more details on verifying requests and stubbing responses, see [Stubbing](../../stubbing) and [Verifying](../../verifying/) +- For more information on the JUnit 4 rules see [The JUnit 4 Rule](../../junit-4/). - For more information on the JUnit 5 Jupiter extension see [JUnit 5+ Jupiter](../../junit-jupiter/); for previous JUnit versions you can use [the JUnit 4 Rule](../../junit-extensions/). - For many more examples of JUnit tests check out the [WireMock's own acceptance tests](https://github.com/wiremock/wiremock/tree/master/src/test/java/com/github/tomakehurst/wiremock) From 2d63e8e9a62536a941ea7c5d7b096ebecdc28faa Mon Sep 17 00:00:00 2001 From: Robert Elliot Date: Tue, 2 Apr 2024 15:47:05 +0100 Subject: [PATCH 048/152] Document `options().withSupportedProxyEncodings` (#269) See https://github.com/wiremock/wiremock/pull/2646 --- _docs/configuration.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/_docs/configuration.md b/_docs/configuration.md index accf16a5..5f12cf4c 100644 --- a/_docs/configuration.md +++ b/_docs/configuration.md @@ -130,6 +130,11 @@ WireMock uses the trust store for three purposes: // The type of the CA key store .caKeystoreType("JKS") + +// Which proxy encodings to proxy through to the target if the request contains an Accept-Encoding header +// By default this is null, which means the header is sent to the target unchanged +// If there is an Accept-Encoding header on the request, and it does not contain any of the supported proxy encodings, the header is not sent to the target. +.withSupportedProxyEncodings("gzip", "deflate") ``` ## File locations From 672a66cd5b7d8740d5980b123876b14dba60d3ef Mon Sep 17 00:00:00 2001 From: Kyle Winkelman <39207896+kyle-winkelman@users.noreply.github.com> Date: Tue, 2 Apr 2024 09:49:37 -0500 Subject: [PATCH 049/152] Allow removal of headers from a proxied request. (#268) --- _docs/proxying.md | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/_docs/proxying.md b/_docs/proxying.md index 4bd01be1..26fa4ba8 100644 --- a/_docs/proxying.md +++ b/_docs/proxying.md @@ -102,7 +102,7 @@ the request to the destination: stubFor(get(urlMatching(".*")) .willReturn(aResponse() .proxiedFrom("http://otherhost.com") - .withAdditionalRequestHeader("User-Agent", "Mozilla/5.0 (iPhone; U; CPU iPhone)")); + .withAdditionalRequestHeader("User-Agent", "Mozilla/5.0 (iPhone; U; CPU iPhone)"))); ``` or @@ -124,6 +124,35 @@ or You can also add response headers via the same method as for non-proxy responses (see [Stubbing](../stubbing/)). +# Remove headers + +It is possible to configure the proxy to remove headers before forwarding the reques to the destination +([additional headers](#additional-headers) matching the removed headers will still be added). + +```java +stubFor(get(urlMatching(".*")) + .willReturn(aResponse() + .proxiedFrom("http://otherhost.com") + .withRemoveRequestHeader("User-Agent"))); +``` + +or + +```json +{ + "request": { + "method": "GET", + "urlPattern": ".*" + }, + "response": { + "proxyBaseUrl": "http://otherhost.com", + "removeProxyRequestHeaders": [ + "User-Agent" + ] + } +} +``` + ## Standalone shortcut It is possible to start the standalone running with the catch-all stub From 5269f371349e6d397a5398d3dff737e15019789d Mon Sep 17 00:00:00 2001 From: Kyle Winkelman <39207896+kyle-winkelman@users.noreply.github.com> Date: Tue, 2 Apr 2024 09:50:22 -0500 Subject: [PATCH 050/152] Optional default for SystemValueHelper. (#262) --- _docs/response-templating.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/_docs/response-templating.md b/_docs/response-templating.md index b943adea..48f7223d 100644 --- a/_docs/response-templating.md +++ b/_docs/response-templating.md @@ -927,12 +927,25 @@ Environment variables and system properties can be printed: {% raw %} ```handlebars +{{systemValue key='PATH'}} {{systemValue type='ENVIRONMENT' key='PATH'}} {{systemValue type='PROPERTY' key='os.path'}} ``` {% endraw %} +Since 3.5 a default value can be supplied: + +{% raw %} + +```handlebars +{{systemValue key='PATH' default='DEFAULT'}} +{{systemValue type='ENVIRONMENT' key='PATH' default='DEFAULT'}} +{{systemValue type='PROPERTY' key='os.path' default='DEFAULT'}} +``` + +{% endraw %} + If you want to add permitted extensions to your rule, then you can use the `ResponseTemplateTransformer` when constructing the response template extension. From cf1e62d51d2bca45c30d0a2a67ef9406db1a4e56 Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Tue, 2 Apr 2024 15:56:33 +0100 Subject: [PATCH 051/152] Fixed #274 - corrected interface name and some descriptive text in data provider doc --- _docs/extensibility/adding-template-model-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/extensibility/adding-template-model-data.md b/_docs/extensibility/adding-template-model-data.md index 7dc0f456..c4bb1be7 100644 --- a/_docs/extensibility/adding-template-model-data.md +++ b/_docs/extensibility/adding-template-model-data.md @@ -5,7 +5,7 @@ meta_title: Adding Template Model Data description: Adding extra elements to the template model during request processing --- -Extensions that implement the `TemplateHelperProviderExtension` interface provide additional Handlebars helpers to the templating system: +Extensions that implement the `TemplateModelDataProviderExtension` interface provide additional model elements to the templating system: ```java new WireMockServer(.extensions( From 04b80437e7f2e4c220b51cdd0a760d1cccdf280b Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Tue, 2 Apr 2024 16:06:09 +0100 Subject: [PATCH 052/152] Fixes #267 - wrong link on HTTPS trust example --- _docs/https.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/https.md b/_docs/https.md index 289c16c4..c4d0316f 100644 --- a/_docs/https.md +++ b/_docs/https.md @@ -76,4 +76,4 @@ HTTP port with a client that's expecting HTTPS (i.e. has `https://` in the URL). `org.apache.hc.core5.http.NoHttpResponseException: The target server failed to respond`: Could mean you've tried to connect to the HTTPS port with a client expecting HTTP. -`javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target`: You are using WireMock's default (self-signed) TLS certificate or another certificate that isn't signed by a CA. In this case you need to specifically configure your HTTP client to trust the certificate being presented, or to trust all certificates. Here is an example of [how to do this with the Apache HTTP client](https://github.com/tomakehurst/wiremock/blob/{{ site.wiremock_version }}/src/main/java/com/github/tomakehurst/wiremock/http/HttpClientFactory.java). +`javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target`: You are using WireMock's default (self-signed) TLS certificate or another certificate that isn't signed by a CA. In this case you need to specifically configure your HTTP client to trust the certificate being presented, or to trust all certificates. Here is an example of [how to do this with the Apache HTTP client](https://github.com/wiremock/wiremock/blob/3.4.2/src/main/java/com/github/tomakehurst/wiremock/http/HttpClientFactory.java#L207). From a499abc134fea0a6355ff913b4abd23042dc1ef3 Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Tue, 2 Apr 2024 16:08:32 +0100 Subject: [PATCH 053/152] Fixed #266 - typo in form param matching example --- _docs/request-matching.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/request-matching.md b/_docs/request-matching.md index 8ca9ddf2..b781ce70 100644 --- a/_docs/request-matching.md +++ b/_docs/request-matching.md @@ -107,7 +107,7 @@ Configuration file: ```java stubFor(post(urlPathEqualTo("/mock")) - .withFormParam("tool", equalTo("WireMock")) + .withFormParam("tool", equalTo("WireMock") ).willReturn(ok())); ``` From d39ab4a6cf6eab95c65479224142def0655077da Mon Sep 17 00:00:00 2001 From: Andriy Redko Date: Tue, 2 Apr 2024 12:59:25 -0400 Subject: [PATCH 054/152] Add Jetty 12 supporting documentation (#271) Signed-off-by: Andriy Redko --- _docs/getting-started.md | 1 + _docs/jetty-12.md | 62 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 _docs/jetty-12.md diff --git a/_docs/getting-started.md b/_docs/getting-started.md index 76c09df5..8b3bbbe3 100644 --- a/_docs/getting-started.md +++ b/_docs/getting-started.md @@ -18,6 +18,7 @@ At the moment, we provide the following quick starts for beginners: - [API Mocking with Java and JUnit 4](../quickstart/java-junit) - [Downloading and Installing WireMock](../download-and-installation) +- [Using WireMock with Jetty 12](../jetty-12) diff --git a/_docs/jetty-12.md b/_docs/jetty-12.md new file mode 100644 index 00000000..d4faa5bf --- /dev/null +++ b/_docs/jetty-12.md @@ -0,0 +1,62 @@ +--- +layout: docs +title: "Using WireMock with Jetty 12" +meta_title: Using WireMock with Jetty 12 | WireMock +description: WireMock ships with Jetty 11 by default but fully supports Jetty 12 as well. +--- + +WireMock ships with Jetty 11 by default but fully supports Jetty 12 as well with a new module `wiremock-jetty12`. In this tutorial we are going to see how Wiremock could be configured to use Jetty 12. + +## Prerequisites + +- Java 17 +- Maven or Gradle, recent versions +- A Java project, based on Maven or Gradle + +## Add WireMock Dependency to your project + +{% codetabs %} + +{% codetab Maven %} + +```xml + + org.wiremock + wiremock-jetty12 + {{ site.wiremock_version }} + test + +``` + +{% endcodetab %} + +{% codetab Gradle Groovy %} + +```groovy +testImplementation "org.wiremock:wiremock-jetty12:{{ site.wiremock_version }}" +``` + +{% endcodetab %} + +{% endcodetab %} + +## Limitations + +There are few limitations that usage of Jetty 12 is imposing with respect to stubbing behavior. + +- status message will not be returned to the client even if set by the stub explicitly + ```java + stubFor(get("/my/resource") + .willReturn(status(400) + .withStatusMessage("ERROR"))); + + URI uri = URI.create(wireMockRule.url("/my/resource")); + HttpURLConnection connection = (HttpURLConnection) uri.toURL ().openConnection (); + connection.setRequestMethod ("GET"); + + assertThat(connection.getResponseCode()).isEqualTo(400); + assertThat(connection.getResponseMessage()).isEqualTo("Bad Request"); /* the status message is not returned */ + ``` +- when using multipart form data, the body is not decoded into plain text in case of `base64` (or other encodings) + +- serving files from configured file locations always ends up with redirect when folder (without trailing `/`) is requested From e72b08369de1eb42d7d63377e6c51f5a67359bca Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Tue, 2 Apr 2024 18:16:08 +0100 Subject: [PATCH 055/152] Added Jetty 12 note on Spring page and Jetty 12 page to nav --- _data/doc-categories.yml | 1 + _docs/jetty-12.md | 2 +- _docs/solutions/spring-boot.md | 8 ++++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/_data/doc-categories.yml b/_data/doc-categories.yml index 2e6a15f4..7c1b1b0a 100644 --- a/_data/doc-categories.yml +++ b/_data/doc-categories.yml @@ -26,6 +26,7 @@ java: - java-usage - configuration - running-without-http-server + - jetty-12 - android stubbing-and-verifying: diff --git a/_docs/jetty-12.md b/_docs/jetty-12.md index d4faa5bf..3b012f9e 100644 --- a/_docs/jetty-12.md +++ b/_docs/jetty-12.md @@ -38,7 +38,7 @@ testImplementation "org.wiremock:wiremock-jetty12:{{ site.wiremock_version }}" {% endcodetab %} -{% endcodetab %} +{% endcodetabs %} ## Limitations diff --git a/_docs/solutions/spring-boot.md b/_docs/solutions/spring-boot.md index ebbb1439..8df521f4 100644 --- a/_docs/solutions/spring-boot.md +++ b/_docs/solutions/spring-boot.md @@ -59,6 +59,14 @@ See [Spring Cloud Contract WireMock](https://docs.spring.io/spring-cloud-contrac The article [Faking OAuth2 Single Sign-on in Spring](https://engineering.pivotal.io/post/faking_oauth_sso/) from Pivotal's blog shows how WireMock can be used to test Spring apps that use 3rd party OAuth2 login. + +## Jetty version issues when running WireMock and Spring together. + +WireMock's main artifact is built on Jetty 11, largely so that Java 11 support can be maintained. However, many Spring applications depend on Jetty 12 and the presence of both on the classpath causes WireMock to fail with a `ClassNotFoundException` or `NoClassDefFoundError` for Servlet API classes thrown during startup. + +To rectify this, WireMock now has a dedicated Jetty 12 artifact which can be added to your project's classpath. See the [Jetty 12 page](../../jetty-12/) for details. + + ## Useful pages - [WireMock on Java and JVM](../solutions/jvm) - Most of JVM generic solutions are applicable to Spring Boot development too From 850b87d049bd80bc446283caf6f8a2de0f99771a Mon Sep 17 00:00:00 2001 From: Mark Gerrard Date: Tue, 2 Apr 2024 18:20:57 +0100 Subject: [PATCH 056/152] fix broken code tabs (#275) --- _docs/quickstart/java-junit.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/quickstart/java-junit.md b/_docs/quickstart/java-junit.md index 3e989606..cfb7b924 100644 --- a/_docs/quickstart/java-junit.md +++ b/_docs/quickstart/java-junit.md @@ -47,7 +47,7 @@ like [Apache HttpClient](https://hc.apache.org/httpcomponents-client-5.2.x/#). {% endcodetab %} -{% codetab Gradle Groovy %} +{% codetab Gradle %} ```groovy testImplementation "org.wiremock:wiremock:{{ site.wiremock_version }}" From 5ea3b3fee2c8406a867097e89e7fcef439134a2b Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Tue, 2 Apr 2024 18:24:45 +0100 Subject: [PATCH 057/152] Fixed some broken tabs --- _docs/download-and-installation.md | 2 +- _docs/jetty-12.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/_docs/download-and-installation.md b/_docs/download-and-installation.md index 30507d5f..11943b0b 100644 --- a/_docs/download-and-installation.md +++ b/_docs/download-and-installation.md @@ -59,7 +59,7 @@ docker run -it --rm -p 8080:8080 --name wiremock \ {% endcodetab %} -{% codetab Gradle Groovy %} +{% codetab Gradle %} ```groovy testImplementation "org.wiremock:wiremock-standalone:{{ site.wiremock_version }}" diff --git a/_docs/jetty-12.md b/_docs/jetty-12.md index 3b012f9e..91769fe8 100644 --- a/_docs/jetty-12.md +++ b/_docs/jetty-12.md @@ -30,7 +30,7 @@ WireMock ships with Jetty 11 by default but fully supports Jetty 12 as well with {% endcodetab %} -{% codetab Gradle Groovy %} +{% codetab Gradle %} ```groovy testImplementation "org.wiremock:wiremock-jetty12:{{ site.wiremock_version }}" From 3e2a30cf5d7b6d23351514f19c13fb182f9b2c82 Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Wed, 3 Apr 2024 09:40:58 +0100 Subject: [PATCH 058/152] Added stub deletion docs --- _docs/stubbing.md | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/_docs/stubbing.md b/_docs/stubbing.md index f23efdff..c25af923 100644 --- a/_docs/stubbing.md +++ b/_docs/stubbing.md @@ -540,15 +540,29 @@ This feature is also available with the standard JAR. To use it, define the file ## Removing stubs -Stub mappings can be deleted via the Java API as follows: +Stub mappings can be deleted via the Java API, either by passing the stub object or the stub ID: ```java -StubMapping stubMapping = stubFor(get(urlEqualTo("/delete-me")) - .willReturn(aResponse().withStatus(200))); - -// Do things with the stub +UUID stubId = UUID.randomUUID(); +StubMapping stubMapping = stubFor(get("/delete-me") + .withId(stubId) + .willReturn(ok())); removeStub(stubMapping); + +// or + +removeStub(stubId); +``` + +Where stubs have metadata set on them this can be used to remove them: + +```java +stubFor(get("/delete-me") + .withMetadata(metadata().attr("tag", "payments")) + .willReturn(ok())); + +removeStubsByMetadata(matchingJsonPath("$.tag", equalTo("payments"))); ``` They can be deleted via the HTTP API by issuing a `DELETE` to `http://:/__admin/mappings/{id}` From 328b4a4de9dbee3e053503e490916862059b0ef5 Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Wed, 3 Apr 2024 09:45:56 +0100 Subject: [PATCH 059/152] Added docs for disabling HTTP/2 --- _docs/configuration.md | 14 ++++++++++++++ _docs/standalone/java-jar.md | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/_docs/configuration.md b/_docs/configuration.md index 5f12cf4c..d49400fc 100644 --- a/_docs/configuration.md +++ b/_docs/configuration.md @@ -98,6 +98,20 @@ WireMock uses the trust store for three purposes: 3. As a proxy, WireMock will trust a target server if it presents a public certificate in this trust store + +## HTTP/2 configuration + +HTTP/2 can be disabled separately for plain text (HTTP) and TLS (HTTPS): + +```java +// Disable HTTP/2 over HTTP +.http2PlainDisabled(true); + +// Disable HTTP/2 over HTTPS +.http2TlsDisabled(true); +``` + + ## Proxy settings ```java diff --git a/_docs/standalone/java-jar.md b/_docs/standalone/java-jar.md index 28dcbae0..cfb978b6 100644 --- a/_docs/standalone/java-jar.md +++ b/_docs/standalone/java-jar.md @@ -30,6 +30,10 @@ The following can optionally be specified on the command line: `--disable-http`: Disable the HTTP listener, option available only if HTTPS is enabled. +`--disable-http2-plain`: Disable HTTP/2 over plain text (HTTP). + +`--disable-http2-tls`: Disable HTTP/2 over TLS (HTTPS). + `--https-port`: If specified, enables HTTPS on the supplied port. Note: When you specify this parameter, WireMock will still, additionally, bind to an HTTP port (8080 by default). So when running multiple WireMock servers you will also need to specify the `--port` parameter in order to avoid conflicts. From 07fb97ce3af08e9d6794799adc19dcd9bb95b0b9 Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Thu, 4 Apr 2024 15:47:25 +0100 Subject: [PATCH 060/152] Added JWT doc --- _data/doc-categories.yml | 5 +++-- _docs/https.md | 4 ++-- _docs/jwt.md | 10 ++++++++++ 3 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 _docs/jwt.md diff --git a/_data/doc-categories.yml b/_data/doc-categories.yml index 7c1b1b0a..2f9e19a2 100644 --- a/_data/doc-categories.yml +++ b/_data/doc-categories.yml @@ -41,8 +41,8 @@ stubbing-and-verifying: - proxying - verifying -templating: - title: Templating +library: + title: Mock API Template Library link: /docs/mock-api-templates pages: - mock-api-templates @@ -60,6 +60,7 @@ protocols: - webhooks-and-callbacks - grpc - solutions/graphql + - jwt - https configuration: diff --git a/_docs/https.md b/_docs/https.md index c4d0316f..391940bd 100644 --- a/_docs/https.md +++ b/_docs/https.md @@ -1,7 +1,7 @@ --- layout: docs -title: Serving HTTPs -meta_title: Using WireMock with HTTPs using self-signed or custom certificates | WireMock +title: Serving HTTPS +meta_title: Using WireMock with HTTPS using self-signed or custom certificates | WireMock redirect_from: "/https.html" description: WireMock can optionally accept requests over HTTPS. By default it will serve its own self-signed TLS certificate. --- diff --git a/_docs/jwt.md b/_docs/jwt.md new file mode 100644 index 00000000..1bd3e9c0 --- /dev/null +++ b/_docs/jwt.md @@ -0,0 +1,10 @@ +--- +layout: docs +title: JSON Web Tokens (JWT) +meta_title: JSON Web Tokens +description: Generating JWTs and JWKSs +--- + +The JWT extension provides support for generating JWTs and corresponding JSON Web Key Sets (JWKS) in stub responses via response templating. + +For details see [the project's README](https://github.com/wiremock/wiremock-jwt-extension/blob/main/README.md). \ No newline at end of file From 0d24cbe2bab9c1bd65810cc77be4492fc0f88dec Mon Sep 17 00:00:00 2001 From: Ethan Jones Date: Sat, 6 Apr 2024 09:49:06 -0400 Subject: [PATCH 061/152] Making the Slack callout stronger --- Gemfile.lock | 1 + _includes/masthead.html | 2 +- index.html | 14 ++++---------- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0f55380c..dae010b3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -112,6 +112,7 @@ GEM PLATFORMS arm64-darwin-21 + arm64-darwin-23 x64-mingw32 x86_64-linux diff --git a/_includes/masthead.html b/_includes/masthead.html index e49257ec..d63b2104 100644 --- a/_includes/masthead.html +++ b/_includes/masthead.html @@ -66,7 +66,7 @@
- Go to WM Cloud + Try WireMock Cloud Free forever. No credit card needed
diff --git a/index.html b/index.html index 60320d44..9cac48a7 100644 --- a/index.html +++ b/index.html @@ -75,8 +75,7 @@

- Flexible API Mocking for Testing and - Development + Join The WireMock Community

@@ -115,19 +114,14 @@

-->

- WireMock is a tool for building mock APIs. Create stable development - environments, isolate yourself from flakey 3rd parties and simulate - APIs that don't exist yet. + WireMock is community-driven, with user-contributed documentation and an active Slack community where all ideas and questions are welcome.

- Documentation Slack CommunityJoin Us On Slack
From 5d837fc7a28e932c1f20c793e6a62055eaec4617 Mon Sep 17 00:00:00 2001 From: Ethan Jones Date: Sat, 6 Apr 2024 09:52:06 -0400 Subject: [PATCH 062/152] Revert "Making the Slack callout stronger" This reverts commit 0d24cbe2bab9c1bd65810cc77be4492fc0f88dec. --- Gemfile.lock | 1 - _includes/masthead.html | 2 +- index.html | 14 ++++++++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index dae010b3..0f55380c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -112,7 +112,6 @@ GEM PLATFORMS arm64-darwin-21 - arm64-darwin-23 x64-mingw32 x86_64-linux diff --git a/_includes/masthead.html b/_includes/masthead.html index d63b2104..e49257ec 100644 --- a/_includes/masthead.html +++ b/_includes/masthead.html @@ -66,7 +66,7 @@
- Try WireMock Cloud + Go to WM Cloud Free forever. No credit card needed
diff --git a/index.html b/index.html index 9cac48a7..60320d44 100644 --- a/index.html +++ b/index.html @@ -75,7 +75,8 @@

- Join The WireMock Community + Flexible API Mocking for Testing and + Development

@@ -114,14 +115,19 @@

-->

- WireMock is community-driven, with user-contributed documentation and an active Slack community where all ideas and questions are welcome. + WireMock is a tool for building mock APIs. Create stable development + environments, isolate yourself from flakey 3rd parties and simulate + APIs that don't exist yet.

+ Documentation Join Us On SlackSlack Community
From 59445a160c91820f6131972715f0481f0e19c6b7 Mon Sep 17 00:00:00 2001 From: Ethan Jones Date: Sat, 6 Apr 2024 09:55:29 -0400 Subject: [PATCH 063/152] Making the Slack callout stronger --- Gemfile.lock | 1 + _includes/masthead.html | 4 ++-- index.html | 28 +++++++++++----------------- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0f55380c..dae010b3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -112,6 +112,7 @@ GEM PLATFORMS arm64-darwin-21 + arm64-darwin-23 x64-mingw32 x86_64-linux diff --git a/_includes/masthead.html b/_includes/masthead.html index e49257ec..9577618d 100644 --- a/_includes/masthead.html +++ b/_includes/masthead.html @@ -66,7 +66,7 @@
- Go to WM Cloud + Try WireMock Cloud Free forever. No credit card needed
@@ -80,7 +80,7 @@
  • - Go to WM Cloud + Try WireMock Cloud
  • {% for menuItem in site.data.navigation.main %} diff --git a/index.html b/index.html index 60320d44..b1283b4d 100644 --- a/index.html +++ b/index.html @@ -75,8 +75,7 @@

    - Flexible API Mocking for Testing and - Development + Join The WireMock Community

    @@ -114,21 +113,16 @@

    -->

    -

    - WireMock is a tool for building mock APIs. Create stable development - environments, isolate yourself from flakey 3rd parties and simulate - APIs that don't exist yet. -

    - -
    - Documentation - Slack Community +

    + WireMock is community-driven, with user-contributed documentation and an active Slack community where all ideas and questions are welcome. +

    + +
    From 6be4a49ada438fcef6164d255f45bc7197922696 Mon Sep 17 00:00:00 2001 From: Ethan Jones Date: Mon, 8 Apr 2024 12:23:51 -0400 Subject: [PATCH 064/152] Fixing Gemfile issue --- Gemfile.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index dae010b3..0f55380c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -112,7 +112,6 @@ GEM PLATFORMS arm64-darwin-21 - arm64-darwin-23 x64-mingw32 x86_64-linux From 873aab5262b92c7e6731410b8d863908c58a8ac9 Mon Sep 17 00:00:00 2001 From: leeturner Date: Mon, 8 Apr 2024 21:19:43 +0100 Subject: [PATCH 065/152] fix: the link to the jvm page was broken, this fixes it --- _docs/solutions/spring-boot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/solutions/spring-boot.md b/_docs/solutions/spring-boot.md index 8df521f4..1d3754cc 100644 --- a/_docs/solutions/spring-boot.md +++ b/_docs/solutions/spring-boot.md @@ -69,4 +69,4 @@ To rectify this, WireMock now has a dedicated Jetty 12 artifact which can be add ## Useful pages -- [WireMock on Java and JVM](../solutions/jvm) - Most of JVM generic solutions are applicable to Spring Boot development too +- [WireMock on Java and JVM](../jvm) - Most of JVM generic solutions are applicable to Spring Boot development too From 3737bb2807b9803800f2db543359b3af0846f37a Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Wed, 17 Apr 2024 18:29:57 +0100 Subject: [PATCH 066/152] Updated WireMock version to 3.5.3 --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 6948fb12..013ac52a 100644 --- a/_config.yml +++ b/_config.yml @@ -234,7 +234,7 @@ compress_html: ignore: envs: development -wiremock_version: 3.5.2 +wiremock_version: 3.5.3 wiremock_baseline: 3.x pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/ From 8763b63f167e347f6927ac12d7360d31d4d1297c Mon Sep 17 00:00:00 2001 From: Ethan Jones Date: Thu, 18 Apr 2024 16:55:15 -0400 Subject: [PATCH 067/152] More cloud callouts in the docs + updating what's new on the homepage --- _docs/configuration.md | 2 ++ _docs/extending-wiremock.md | 2 ++ _docs/proxying.md | 2 ++ _docs/quickstart/java-junit.md | 2 ++ _docs/solutions/android.md | 3 +++ _docs/solutions/c_cpp.md | 2 ++ _docs/solutions/dotnet.md | 1 + _docs/solutions/golang.md | 2 ++ _docs/solutions/graphql.md | 2 ++ _docs/solutions/groovy.md | 2 ++ _docs/solutions/jvm.md | 2 ++ _docs/solutions/kotlin.md | 1 + _docs/solutions/kubernetes.md | 2 ++ _docs/solutions/nodejs.md | 2 ++ _docs/solutions/python.md | 1 + _docs/solutions/quarkus.md | 1 + _docs/solutions/rust.md | 2 ++ _docs/solutions/spring-boot.md | 4 ++++ _docs/solutions/testcontainers.md | 2 ++ _docs/stateful-behaviour.md | 2 ++ _docs/stubbing.md | 2 ++ index.html | 12 +++++------- 22 files changed, 46 insertions(+), 7 deletions(-) diff --git a/_docs/configuration.md b/_docs/configuration.md index d49400fc..69ec41c1 100644 --- a/_docs/configuration.md +++ b/_docs/configuration.md @@ -5,6 +5,8 @@ meta_title: Configuring WireMock in Java | WireMock description: Configuring WireMock progammatically in Java. --- + + Both `WireMockServer` and the `WireMockRule` take a configuration builder as the parameter to their constructor e.g. ```java diff --git a/_docs/extending-wiremock.md b/_docs/extending-wiremock.md index bebd4462..90e3576a 100644 --- a/_docs/extending-wiremock.md +++ b/_docs/extending-wiremock.md @@ -7,6 +7,8 @@ redirect_from: "/extending-wiremock.html" description: You can register the extension programmatically via its class name, class or an instance --- + + WireMock can be customised via a variety of extension points. Each extension point is defined by an interface that extends from `Extension` and extension implementations are loaded at startup time. diff --git a/_docs/proxying.md b/_docs/proxying.md index 26fa4ba8..0ff4f76c 100644 --- a/_docs/proxying.md +++ b/_docs/proxying.md @@ -7,6 +7,8 @@ redirect_from: "/proxying.html" description: Proxy responses are defined in exactly the same manner as stubs, meaning that the same request matching criteria can be used. --- + + WireMock has the ability to selectively proxy requests through to other hosts. This supports a proxy/intercept setup where requests are by default proxied to another (possibly real, live) service, but where diff --git a/_docs/quickstart/java-junit.md b/_docs/quickstart/java-junit.md index cfb7b924..270af2a4 100644 --- a/_docs/quickstart/java-junit.md +++ b/_docs/quickstart/java-junit.md @@ -5,6 +5,8 @@ meta_title: "API Mocking QuickStart with Java and JUnit 4 | WireMock" description: "Shows how to write your API Client first test with WireMock and JUnit" --- + + In this guide we will write an API Unit test with WireMock and JUnit 4. ## Prerequisites diff --git a/_docs/solutions/android.md b/_docs/solutions/android.md index 580b287d..488f93d4 100644 --- a/_docs/solutions/android.md +++ b/_docs/solutions/android.md @@ -8,6 +8,9 @@ redirect_from: "/docs/android.html" logo: /images/logos/technology/android.svg --- + + + ## Guide by Sam Edwards As documented by Sam Edwards in 2016, diff --git a/_docs/solutions/c_cpp.md b/_docs/solutions/c_cpp.md index 832036f9..d3e1460a 100644 --- a/_docs/solutions/c_cpp.md +++ b/_docs/solutions/c_cpp.md @@ -7,6 +7,8 @@ logo: /images/logos/technology/c.png og_image: solutions/testcontainers/testcontainers_c_opengraph.png --- + + ## Testcontainers for C/C++ module Testcontainers C diff --git a/_docs/solutions/dotnet.md b/_docs/solutions/dotnet.md index 81ac805e..a332c58c 100644 --- a/_docs/solutions/dotnet.md +++ b/_docs/solutions/dotnet.md @@ -6,6 +6,7 @@ description: "Additional solutions for WireMock when using .NET" logo: /images/logos/technology/dotnet.svg --- + ## WireMock.Net diff --git a/_docs/solutions/golang.md b/_docs/solutions/golang.md index 5e2b8c5a..78454888 100644 --- a/_docs/solutions/golang.md +++ b/_docs/solutions/golang.md @@ -10,6 +10,8 @@ redirect_from: hide-disclaimer: true --- + + ## Testcontainers module for Go The WireMock community provides a [Testcontainers for Go module](https://github.com/wiremock/wiremock-testcontainers-go) module diff --git a/_docs/solutions/graphql.md b/_docs/solutions/graphql.md index 24b0f91e..e25f55ce 100644 --- a/_docs/solutions/graphql.md +++ b/_docs/solutions/graphql.md @@ -11,6 +11,8 @@ redirect_from: hide-disclaimer: true --- + + ## WireMock Extension There is a [GraphQL extension for WireMock](https://github.com/wiremock/wiremock-graphql-extension) diff --git a/_docs/solutions/groovy.md b/_docs/solutions/groovy.md index 400f251c..11d3134d 100644 --- a/_docs/solutions/groovy.md +++ b/_docs/solutions/groovy.md @@ -6,6 +6,8 @@ description: "Additional solutions for WireMock when using Groovy" logo: /images/logos/technology/groovy.svg --- + + ## DSL Bindings There is a [Groovy DSL binding library](https://github.com/tomjankes/wiremock-groovy) diff --git a/_docs/solutions/jvm.md b/_docs/solutions/jvm.md index ff6c06d9..96c2b443 100644 --- a/_docs/solutions/jvm.md +++ b/_docs/solutions/jvm.md @@ -7,6 +7,8 @@ logo: /images/logos/technology/java.svg hide-disclaimer: true --- + + WireMock was originally created for Java development, and there are plenty of solutions when developing applications powered by the Java Virtual Machine. diff --git a/_docs/solutions/kotlin.md b/_docs/solutions/kotlin.md index 322b90d8..1fdb38bb 100644 --- a/_docs/solutions/kotlin.md +++ b/_docs/solutions/kotlin.md @@ -6,6 +6,7 @@ description: Additional solutions for WireMock when using Kotlin logo: /images/logos/technology/kotlin.svg --- + ## Kotlin DSL Bindings diff --git a/_docs/solutions/kubernetes.md b/_docs/solutions/kubernetes.md index 5e22728b..47bb695a 100644 --- a/_docs/solutions/kubernetes.md +++ b/_docs/solutions/kubernetes.md @@ -7,6 +7,8 @@ logo: /images/logos/technology/kubernetes.svg hide-disclaimer: true --- + + ## WireMock Helm Chart (Experimental) There is an [experimental Helm Chart](https://wiremock.github.io/helm-charts/) for WireMock. diff --git a/_docs/solutions/nodejs.md b/_docs/solutions/nodejs.md index 0017b3ca..1d8a6c9b 100644 --- a/_docs/solutions/nodejs.md +++ b/_docs/solutions/nodejs.md @@ -6,6 +6,8 @@ description: Additional solutions for WireMock when using Node.js logo: /images/logos/technology/nodejs.svg --- + + ## WireMock Captain WireMock Captain provides an easy interface for testing HTTP-based APIs. diff --git a/_docs/solutions/python.md b/_docs/solutions/python.md index 8f4f2f93..a57ce433 100644 --- a/_docs/solutions/python.md +++ b/_docs/solutions/python.md @@ -7,6 +7,7 @@ logo: /images/logos/technology/python.svg hide-disclaimer: true --- + ## Python WireMock diff --git a/_docs/solutions/quarkus.md b/_docs/solutions/quarkus.md index eb642a3d..b4360e88 100644 --- a/_docs/solutions/quarkus.md +++ b/_docs/solutions/quarkus.md @@ -6,6 +6,7 @@ description: "Additional solutions for WireMock when developing with Quarkus" logo: /images/logos/technology/quarkus.svg --- + ## WireMock Extension for Quarkus diff --git a/_docs/solutions/rust.md b/_docs/solutions/rust.md index 150db781..a2bceffc 100644 --- a/_docs/solutions/rust.md +++ b/_docs/solutions/rust.md @@ -6,6 +6,8 @@ description: "Additional solutions for WireMock when using Rust" logo: /images/logos/technology/rust.svg --- + + ## wiremock-rs. Server implementation in Rust [LukeMathWalker/wiremock-rs](https://github.com/LukeMathWalker/wiremock-rs) is an API Mock Server implementation in Rust. diff --git a/_docs/solutions/spring-boot.md b/_docs/solutions/spring-boot.md index 1d3754cc..9056da9c 100644 --- a/_docs/solutions/spring-boot.md +++ b/_docs/solutions/spring-boot.md @@ -9,6 +9,10 @@ redirect_from: logo: /images/logos/technology/spring.svg --- + + + + ## WireMock Spring Boot [WireMock Spring Boot](https://github.com/maciejwalkowiak/wiremock-spring-boot) diff --git a/_docs/solutions/testcontainers.md b/_docs/solutions/testcontainers.md index c1d5f83b..0925f66d 100644 --- a/_docs/solutions/testcontainers.md +++ b/_docs/solutions/testcontainers.md @@ -12,6 +12,8 @@ redirect_from: - "/testcontainers/" --- + + The WireMock community provides modules for [Testcontainers](https://testcontainers.com/). They allow provisioning the WireMock server as a standalone container within your tests, based on [WireMock Docker](https://github.com/wiremock/wiremock-docker). diff --git a/_docs/stateful-behaviour.md b/_docs/stateful-behaviour.md index d4a5838a..32ef3739 100644 --- a/_docs/stateful-behaviour.md +++ b/_docs/stateful-behaviour.md @@ -6,6 +6,8 @@ redirect_from: "/stateful-behaviour.html" description: Most web services tend to have some state, which changes as you and others interact with it. --- + + **Most web services tend to have some state, which changes as you and others interact with it. So it's pretty useful to be able to simulate this when you've swapped a real service for a test double.** diff --git a/_docs/stubbing.md b/_docs/stubbing.md index c25af923..f323c344 100644 --- a/_docs/stubbing.md +++ b/_docs/stubbing.md @@ -7,6 +7,8 @@ redirect_from: "/stubbing.html" description: A core feature of WireMock is the ability to return canned HTTP responses for requests matching criteria. These are described in detail in Request Matching. --- + + A core feature of WireMock [API mocking]({{ '/' | absolute_url }}) is the ability to return canned HTTP responses for requests matching criteria. These are described in detail in [Request Matching](../request-matching/). diff --git a/index.html b/index.html index a17ff7cd..b4c78882 100644 --- a/index.html +++ b/index.html @@ -128,19 +128,17 @@

      - What's NEW? WireMock API Template Library

    + What's NEW? OpenAPI Validation

    - Test against popular 3rd-party services in a few clicks! + Guarantee requests to your mock APIs match your specs.

    - - + +

    - Browse our library of mock API templates and examples, find the API that you need, - and mock it in seconds - on your local machine or in the cloud. - Learn More... + Stop faulty behavior from leaking into your production environments with OpenAPI validation on your mock API requests. Choose between hard and soft validation as needed. Learn more.

    From 960ea003fde3204c673dfdbb5352f0c4ef0d46a6 Mon Sep 17 00:00:00 2001 From: Ethan Jones Date: Fri, 19 Apr 2024 14:16:18 -0400 Subject: [PATCH 068/152] fixing broken image --- images/wiremock-cloud/openapivalidation.png | Bin 0 -> 64901 bytes index.html | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 images/wiremock-cloud/openapivalidation.png diff --git a/images/wiremock-cloud/openapivalidation.png b/images/wiremock-cloud/openapivalidation.png new file mode 100644 index 0000000000000000000000000000000000000000..e01efb9d0d108ec6a61bd90d9cf1c18808333a71 GIT binary patch literal 64901 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

    -

    From fa0cc7b167ca4201131e143063cfb2e5da242b69 Mon Sep 17 00:00:00 2001 From: Antonio Perez Dieppa Date: Tue, 23 Apr 2024 09:35:45 +0100 Subject: [PATCH 069/152] update wiremock version to 3.5.4 --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 013ac52a..269e7d3f 100644 --- a/_config.yml +++ b/_config.yml @@ -234,7 +234,7 @@ compress_html: ignore: envs: development -wiremock_version: 3.5.3 +wiremock_version: 3.5.4 wiremock_baseline: 3.x pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/ From f30c8e0bbe26e8a184299de4f5301f7fc3e5bb65 Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Thu, 25 Apr 2024 10:08:56 +0100 Subject: [PATCH 070/152] Added --supported-proxy-encodings doc --- _docs/standalone/java-jar.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_docs/standalone/java-jar.md b/_docs/standalone/java-jar.md index cfb978b6..c095e3c6 100644 --- a/_docs/standalone/java-jar.md +++ b/_docs/standalone/java-jar.md @@ -100,6 +100,10 @@ internet access via an opaque proxy). e.g. `--proxy-via webproxy.mycorp.com:8080`. Also supports proxy authentication, e.g. `--proxy-via http://username:password@webproxy.mycorp.com:8080/`. +`--supported-proxy-encodings`: The set of acceptable compression methods represented in the `accept-encoding` request header +sent by WireMock when proxying or recording expressed as a comma-separated list e.g `gzip,deflate`. This is particularly useful if you want to avoid recording e.g. brotli compresssed responses +that can't then be viewed in the request log or served with a different compression scheme on playback, which can be achieved via `--supported-proxy-encodings=identity`. + `--enable-browser-proxying`: Run as a browser proxy. See [Running as a browser proxy](../../proxying#running-as-a-browser-proxy). From 2774db8f74839b20387b20f9197e6fa7a13e32f1 Mon Sep 17 00:00:00 2001 From: Tomas Bjerre Date: Sun, 28 Apr 2024 09:05:19 +0200 Subject: [PATCH 071/152] docs: WireMock Pact --- _data/doc-categories.yml | 1 + _docs/solutions/jvm.md | 1 + _docs/solutions/pact.md | 176 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 _docs/solutions/pact.md diff --git a/_data/doc-categories.yml b/_data/doc-categories.yml index 2f9e19a2..abbae640 100644 --- a/_data/doc-categories.yml +++ b/_data/doc-categories.yml @@ -28,6 +28,7 @@ java: - running-without-http-server - jetty-12 - android + - pact stubbing-and-verifying: title: Stubbing & Verifying diff --git a/_docs/solutions/jvm.md b/_docs/solutions/jvm.md index 96c2b443..d647848b 100644 --- a/_docs/solutions/jvm.md +++ b/_docs/solutions/jvm.md @@ -66,5 +66,6 @@ sorted by alphabet: - [Clojure](https://docs.google.com/document/d/1TQccT9Bk-o2lvRVN8_mMaGttaOnwbYFLkn0DsmwGIOA/edit#heading=h.gvb3rxc1ab9p) - [Groovy](../groovy) - [Kotlin](../kotlin) +- [Pact](../pact) - [Scala](https://docs.google.com/document/d/1TQccT9Bk-o2lvRVN8_mMaGttaOnwbYFLkn0DsmwGIOA/edit#heading=h.gvb3rxc1ab9p) - [Spring Boot](../spring-boot) diff --git a/_docs/solutions/pact.md b/_docs/solutions/pact.md new file mode 100644 index 00000000..9ef7935d --- /dev/null +++ b/_docs/solutions/pact.md @@ -0,0 +1,176 @@ +--- +layout: solution +title: "Using WireMock with Pact" +meta_title: Running WireMock with Pact | WireMock +description: The recorded invocations on WireMock can be used to generate the JSON files that are needed to publish contracts to the Pactflow broker. +redirect_from: +- "/docs/pact.html" +--- + +## WireMock Pact + +WireMock Pact will get the requests from [WireMock](https://github.com/wiremock/wiremock/) and create [Pact JSON](https://docs.pact.io/) files on the filesystem. The Pact JSON can be published to a [Pactflow broker](https://test.pactflow.io/). + +WireMock Pact contains: + +- `wiremock-pact-lib` - *A library that can transform WireMock [ServeEvent](https://github.com/wiremock/wiremock/blob/master/src/main/java/com/github/tomakehurst/wiremock/stubbing/ServeEvent.java):s to Pact JSON.* +- `wiremock-pact-extension-junit5` - *A WireMock extension, and JUnit 5, that is intended to ease usage of the library.* +- `wiremock-pact-example-springboot-app` - *A SpringBoot application that shows how it can be used.* + +WireMock Pact is released to [Maven Central](https://central.sonatype.com/search?q=se.bjurr.wiremockpact). And [available on GitHub](https://github.com/wiremock/wiremock-pact). + +## Usage - Junit 5 + +The extension is both a WireMock extension and a JUnit 5 extension. When using [`wiremock-spring-boot`](https://wiremock.org/docs/solutions/spring-boot/) it can be configured like this in a base class of your tests: + +```java +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import com.maciejwalkowiak.wiremock.spring.ConfigureWireMock; +import com.maciejwalkowiak.wiremock.spring.EnableWireMock; +import com.maciejwalkowiak.wiremock.spring.WireMockConfigurationCustomizer; +import org.junit.jupiter.api.extension.RegisterExtension; +import se.bjurr.wiremockpact.wiremockpactextensionjunit5.WireMockPactExtension; +import se.bjurr.wiremockpact.wiremockpactlib.api.WireMockPactConfig; + +@EnableWireMock({ + @ConfigureWireMock( + name = "wiremock-service-name", + property = "wiremock.server.url", + stubLocation = "wiremock", + configurationCustomizers = {WireMockPactBaseTest.class}) +}) +public class WireMockPactBaseTest implements WireMockConfigurationCustomizer { + @RegisterExtension + static WireMockPactExtension WIREMOCK_PACT_EXTENSION = + new WireMockPactExtension( + WireMockPactConfig.builder() // + .setConsumerDefaultValue("WireMockPactExample") // + .setProviderDefaultValue("UnknownProvider") // + .setPactJsonFolder("src/test/resources/pact-json")); + + @Override + public void customize( + final WireMockConfiguration configuration, final ConfigureWireMock options) { + configuration.extensions(WIREMOCK_PACT_EXTENSION); + } +} +``` + +### Usage - Library + +It can be used as a library. + +```java +public class ExampleTest { + private static WireMockServer server; + private static WireMockPactApi wireMockPactApi; + + @BeforeAll + public static void beforeEach() throws IOException { + server = new WireMockServer(); + server.start(); + + stubFor( + post(anyUrl()) + .willReturn( + ok() + .withHeader("content-type", "application/json") + .withBody(""" + {"a":"b"} + """)) + .withMetadata( + new Metadata( + Map.of( + WireMockPactMetadata.METADATA_ATTR, + new WireMockPactMetadata() + .setProvider("some-specific-provider"))))); + + wireMockPactApi = + WireMockPactApi.create( + new WireMockPactConfig() + .setConsumerDefaultValue("my-service") + .setProviderDefaultValue("unknown-service") + .setPactJsonFolder("the/pact-json/folder")); + wireMockPactApi.clearAllSaved(); + } + + @Test + public void testInvoke() { + // Do stuff that invokes WireMock... + } + + @AfterAll + public static void after() { + for (final ServeEvent serveEvent : server.getAllServeEvents()) { + wireMockPactApi.addServeEvent(serveEvent); + } + // Save pact-json to folder given in WireMockPactApi + wireMockPactApi.saveAll(); + server.stop(); + } +} +``` + +### Mappings metadata - Set provider in mapping + +You can adjust any mappings file like this to specify the provider of a mapping in its [metadata](https://github.com/wiremock/spec/blob/main/wiremock/wiremock-admin-api/schemas/stub-mapping.yaml) field: + +```diff +{ + "id" : "d68fb4e2-48ed-40d2-bc73-0a18f54f3ece", + "request" : { + "urlPattern" : "/animals/1", + "method" : "GET" + }, + "response" : { + "status" : 202 + }, + "uuid" : "d68fb4e2-48ed-40d2-bc73-0a18f54f3ece", ++ "metadata": { ++ "wireMockPactSettings": { ++ "provider":"some-other-system" ++ } ++ } +} +``` + +Or programmatically: + +```java + stubFor( + post(anyUrl()) + .withMetadata( + new Metadata( + Map.of( + WireMockPactMetadata.METADATA_ATTR, + new WireMockPactMetadata() + .setProvider("some-specific-provider"))))); +``` + +### Publishing to Pact broker + +Pact has a [CLI tool](https://docs.pact.io/pact_broker/publishing_and_retrieving_pacts) that can be used for publishing the contracts. But it requires Ruby or Docker. If you don't have that, perhaps `curl` is an option. There is [a shell script here](https://github.com/tomasbjerre/pactflow-publish-sh) that can also be used [via NPM](https://www.npmjs.com/package/pactflow-publish-sh). + +You may want to use something like [git-changelog-command-line](https://github.com/tomasbjerre/git-changelog-command-line) to get the next version. + +There is a test-server at https://test.pactflow.io/ that can be accessed with user `dXfltyFMgNOFZAxr8io9wJ37iUpY42M` and password `O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1`. + +```sh +current_version=$(npx git-changelog-command-line \ + --patch-version-pattern "^fix.*" \ + --print-current-version) +git_hash=`git rev-parse --short HEAD` +participant_version_number="$current_version-$git_hash" + +npx pactflow-publish-sh \ + --username=dXfltyFMgNOFZAxr8io9wJ37iUpY42M \ + --password=O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1 \ + --pactflow-broker-url=https://test.pactflow.io/contracts/publish \ + --build-url=http://whatever/ \ + --pact-json-folder=wiremock-pact-example-springboot-app/src/test/resources/pact-json \ + --participant-version-number=$participant_version_number +``` + +## Useful pages + +- [WireMock on Java and JVM](../jvm) - Most of JVM generic solutions are applicable to Spring Boot development too From 8171b3d728bf01520a58b37912fe2226ba3e6d0d Mon Sep 17 00:00:00 2001 From: leeturner Date: Thu, 9 May 2024 14:56:58 +0100 Subject: [PATCH 072/152] Updated gRPC version --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 269e7d3f..2d81234f 100644 --- a/_config.yml +++ b/_config.yml @@ -238,7 +238,7 @@ wiremock_version: 3.5.4 wiremock_baseline: 3.x pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/ -grpc_extension_version: 0.5.0 +grpc_extension_version: 0.6.0 community_slack: join_url: https://slack.wiremock.org/ From 6e1366ef3dcee7d818a91f65be74664c79628af1 Mon Sep 17 00:00:00 2001 From: leeturner Date: Mon, 20 May 2024 16:42:22 +0100 Subject: [PATCH 073/152] Document new helper methods. This is a WIP as the arrayJoin helper will need to be updated with more examples of the prefix and suffix parameters --- _docs/response-templating.md | 93 ++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/_docs/response-templating.md b/_docs/response-templating.md index 48f7223d..0bbc7872 100644 --- a/_docs/response-templating.md +++ b/_docs/response-templating.md @@ -341,6 +341,30 @@ Variable assignment and number helpers are available: {% endraw %} +## Val helper + +The `val` helper can be used to access values or provide a default if the value is not present. It can also be used to +assign a value to a variable much like the `assign` helper. The main difference between `val` and `assign` is that `val` +will maintain the type of the date being assigned whereas `assign` will always assign a string. + +{% raw %} + +```handlebars +{{val request.query.search or='default'}} // the value of request.query.search or 'default' if it's not present +{{val request.query.search default='default'}} // the value of request.query.search or 'default' if it's not present +{{val request.query.search}} // the value of request.query.search or null if it's not present +{{val request.query.search or='default' assign='myVar'}} // assign the value of request.query.search or 'default' to myVar +{{val request.query.search assign='myVar'}} // assign the value of request.query.search to myVar + + +{{val (array 1 2 3) default='123'}} // [1, 2, 3] +{{val 'value for myVar' assign='myVar'}}{{myVar}} // value for myVar +{{val null or='other value for myVar' assign='myVar'}}{{myVar}} // other value for myVar +{{val 10 assign='myVar'}}{{#lt myVar 20}}Less Than{{else}}More Than{{/lt}} // Less Than +``` + +{% endraw %} + ## XPath helpers Additionally some helpers are available for working with JSON and XML. @@ -719,6 +743,75 @@ Providing no parameters will result in an empty array. {% endraw %} +## Array add & remove helpers +The `arrayAdd` and `arrayRemove` helpers can be used to add or remove elements from an array based on a position value +or the `start` or `end` keywords. If no position is specified, the element will be added or removed from the end of the +array. + +{% raw %} + +```handlebars +{{arrayAdd (array 1 'three') 2 position=1}} // [1, 2, three] +{{arrayAdd (array 1 'three') 2 position='start'}} // [2, 1, three] +{{arrayAdd (array 1 'three') 2 position='end'}} // [1, three, 2] +{{arrayAdd (array 1 'three') 2}} // [1, three, 2] + +{{arrayRemove (array 1 2 'three') position=1}} // [1, three] +{{arrayRemove (array 1 2 'three') position='start'}} // [2, three] +{{arrayRemove (array 1 2 'three') position='end'}} // [1, 2] +{{arrayRemove (array 1 2 'three')}} // [1, 2] +``` + +{% endraw %} + +## arrayJoin helper + +The `arrayJoin` helper will concatenate the values passed to it with the separator specified: + +{% raw %} + +```handlebars +{{arrayJoin ',' (array 'One' 'Two' 'Three')}} // One,Two,Three +{{arrayJoin ' - ' 'a' 'b' 'c'}} // a - b - c +{{arrayJoin ', ' (range 1 5)}} // 1, 2, 3, 4, 5 +{{arrayJoin (pickRandom ':') (array 'One' 'Two' 'Three')}} // One:Two:Three +{{arrayJoin '' (array 'W' 'i' 'r' 'e' 'M' 'o' 'c' 'k' ' ' 'R' 'o' 'c' 'k' 's')}} // WireMock Rocks +``` + +{% endraw %} + +You can also specify a `prefix` and `suffix` to be added to the start and end of the result: + +{% raw %} + +```handlebars +{{arrayJoin ',' (array 'One' 'Two' 'Three') prefix='[' suffix=']'}} // [One,Two,Three] +``` + +{% endraw %} + +The `arrayJoin` helper can also be used as a block helper: + +{% raw %} + +```handlebars +{{#parseJson 'myThings'}} +[ + { "id": 1, "name": "One" }, + { "id": 2, "name": "Two" }, + { "id": 3, "name": "Three" } +] +{{/parseJson}} +[{{#arrayJoin ',' myThings as |item|}} +{ +"name{{item.id}}": "{{item.name}}" +} +{{/arrayJoin}}] // [{ "name1": "One" }, { "name2": "Two" }, { "name3": "Three" }] +``` + +{% endraw %} + + ## Contains helper The `contains` helper returns a boolean value indicating whether the string or array passed as the first parameter From 01fcc2af2b0350bfc378f3473632a30964e2e3e2 Mon Sep 17 00:00:00 2001 From: leeturner Date: Mon, 20 May 2024 16:42:48 +0100 Subject: [PATCH 074/152] Document the new lifecycle methods in the Extension interface --- _docs/extending-wiremock.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_docs/extending-wiremock.md b/_docs/extending-wiremock.md index 90e3576a..be464785 100644 --- a/_docs/extending-wiremock.md +++ b/_docs/extending-wiremock.md @@ -28,6 +28,10 @@ At present, the following extension interfaces are available: The interfaces in this list ending with `V2` supercede deprecated equivalents with an older, more restrictive interface. Additionally `ServeEventListener` deprecates `PostServeAction`. +As of WireMock version `3.6.0`, the `Extension` interface has two new lifecycle methods called `start()` and `stop()`. +The `start()` method is called on each extension when the WireMock server first starts (just before the stub mappings +are loaded) and the `stop()` method is called when the server is stopped. This allows extensions to perform any +initialisation or cleanup tasks. ## Registering Extensions From aab7905be8386b0bd6663859f82c151fdd101889 Mon Sep 17 00:00:00 2001 From: leeturner Date: Tue, 21 May 2024 10:03:12 +0100 Subject: [PATCH 075/152] Add the prefix and suffix examples --- _docs/response-templating.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/_docs/response-templating.md b/_docs/response-templating.md index 0bbc7872..c7a281c3 100644 --- a/_docs/response-templating.md +++ b/_docs/response-templating.md @@ -786,6 +786,7 @@ You can also specify a `prefix` and `suffix` to be added to the start and end of ```handlebars {{arrayJoin ',' (array 'One' 'Two' 'Three') prefix='[' suffix=']'}} // [One,Two,Three] +{{arrayJoin ' * ' (array 1 2 3) prefix='(' suffix=')'}} // (1 * 2 * 3) ``` {% endraw %} @@ -807,6 +808,21 @@ The `arrayJoin` helper can also be used as a block helper: "name{{item.id}}": "{{item.name}}" } {{/arrayJoin}}] // [{ "name1": "One" }, { "name2": "Two" }, { "name3": "Three" }] + + +// or the same example with the prefix and suffix parameters +{{#parseJson 'myThings'}} + [ + { "id": 1, "name": "One" }, + { "id": 2, "name": "Two" }, + { "id": 3, "name": "Three" } + ] +{{/parseJson}} +{{#arrayJoin ',' myThings prefix='[' suffix=']' as |item|}} + { + "name{{item.id}}": "{{item.name}}" + } +{{/arrayJoin}} // [{ "name1": "One" }, { "name2": "Two" }, { "name3": "Three" }] ``` {% endraw %} From 464d0b34ac2271712021503a65ed3f23d4c9fe89 Mon Sep 17 00:00:00 2001 From: leeturner Date: Wed, 22 May 2024 14:47:50 +0100 Subject: [PATCH 076/152] Bumped WireMockk version to 3.6.0 --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 2d81234f..30b074cc 100644 --- a/_config.yml +++ b/_config.yml @@ -234,7 +234,7 @@ compress_html: ignore: envs: development -wiremock_version: 3.5.4 +wiremock_version: 3.6.0 wiremock_baseline: 3.x pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/ From d6bcb0940357323726e2c794dfb65e1f4de6b24b Mon Sep 17 00:00:00 2001 From: MuTalKing Date: Sun, 2 Jun 2024 01:28:48 +0300 Subject: [PATCH 077/152] Add new command line options description --- _docs/configuration.md | 11 +++++++++++ _docs/standalone/java-jar.md | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/_docs/configuration.md b/_docs/configuration.md index 69ec41c1..0a221745 100644 --- a/_docs/configuration.md +++ b/_docs/configuration.md @@ -294,3 +294,14 @@ To output all raw traffic to console use `ConsoleNotifyingWiremockNetworkTraffic If you would like to collect the traffic and for example add it to your acceptance test's output, you can use the `CollectingNetworkTrafficListener`. + +## HTTP Client +If you want to increase the proxying performance of wiremock you can enable Connection reuse and increse max Connections + +```java +// Maximum connections for Http Client +.maxHttpClientConnections(1000); +//Disable http connection reuse, `false` to enable +.disableConnectionReuse(true) +``` + diff --git a/_docs/standalone/java-jar.md b/_docs/standalone/java-jar.md index c095e3c6..dd74e7fd 100644 --- a/_docs/standalone/java-jar.md +++ b/_docs/standalone/java-jar.md @@ -195,6 +195,10 @@ The last of these will cause chunked encoding to be used only when a stub define `--filename-template`: Set filename template in handlebar format. For endpoint: `GET /pets/{id}` using the format: `{{{method}}}-{{{url}}}.json` output will be `get-pets-id.json`. Default format: `{{{method}}}-{{{path}}}-{{{id}}}.json` hence by default template filename will be: `get-pets-id-1.json`. Note: introduced in [3.0.0-beta-8](https://github.com/wiremock/wiremock/releases/tag/3.0.0-beta-8). +`--max-http-client-connections`: Maximum connections for Http Client. Defaults to 1000. + +`--disable-connection-reuse`: Disable http connection reuse. Defaults to `true` + `--help`: Show command line help ## Configuring WireMock using the Java client From c1ddb93ba81942e33e6d0352c3da1546430d657c Mon Sep 17 00:00:00 2001 From: Kyle Winkelman Date: Tue, 4 Jun 2024 11:29:54 -0500 Subject: [PATCH 078/152] Add custom content patterns. --- _data/doc-categories.yml | 3 +- _docs/extending-wiremock.md | 65 +++++++- .../extensibility/custom-content-matching.md | 150 ++++++++++++++++++ ...matching.md => custom-request-matching.md} | 2 +- 4 files changed, 210 insertions(+), 10 deletions(-) create mode 100644 _docs/extensibility/custom-content-matching.md rename _docs/extensibility/{custom-matching.md => custom-request-matching.md} (99%) diff --git a/_data/doc-categories.yml b/_data/doc-categories.yml index abbae640..222a0dd6 100644 --- a/_data/doc-categories.yml +++ b/_data/doc-categories.yml @@ -78,7 +78,8 @@ extensibility: - extending-wiremock - extensibility/filtering-requests - extensibility/transforming-responses - - extensibility/custom-matching + - extensibility/custom-request-matching + - extensibility/custom-content-matching - extensibility/listening-for-serve-events - extensibility/extending-the-admin-api - extensibility/adding-template-helpers diff --git a/_docs/extending-wiremock.md b/_docs/extending-wiremock.md index be464785..32b05311 100644 --- a/_docs/extending-wiremock.md +++ b/_docs/extending-wiremock.md @@ -19,7 +19,8 @@ At present, the following extension interfaces are available: * `ResponseTransformerV2`: Modify the response served to the client. See [Transforming responses](../extensibility/transforming-responses/). * `ServeEventListener`: Listen for events at various points in the request processing lifecycle. See [Listening for Serve Events](../extensibility/listening-for-serve-events/). * `AdminApiExtension`: Add admin API functions. See [Admin API Extensions](../extensibility/extending-the-admin-api/). -* `RequestMatcherExtension`: Implement custom request matching logic. See [Custom matching](../extensibility/custom-matching/). +* `RequestMatcherExtension`: Implement custom request matching logic. See [Custom Request Matching](../extensibility/custom-request-matching/). +* `ContentPatternExtension`: Implement custom content matching logic. See [Custom Content Matching](../extensibility/custom-content-matching/). * `GlobalSettingsListener`: Listen for changes to the settings object. See [Listening for Settings Changes](../extensibility/listening-for-settings-changes/). * `StubLifecycleListener`: Listen for changes to the stub mappings. See [Listening for Stub Changes](../extensibility/listening-for-stub-changes/). * `TemplateHelperProviderExtension`: Provide custom Handlebars helpers to the template engine. See [Adding Template Helpers](../extensibility/adding-template-helpers/). @@ -35,18 +36,35 @@ initialisation or cleanup tasks. ## Registering Extensions -You can directly register the extension programmatically via its class name, -class or an instance: +You can directly register the extension programmatically via its class name, class or an instance. +Server: ```java new WireMockServer(wireMockConfig() - .extensions("com.mycorp.BodyContentTransformer", "com.mycorp.HeaderMangler")); + .extensions("com.mycorp.ClassNameOne", "com.mycorp.ClassNameTwo") + .extensions(ClassOne.class, ClassTwo.class) + .extensions(new InstanceOne(), new InstanceTwo())); +``` -new WireMockServer(wireMockConfig() - .extensions(BodyContentTransformer.class, HeaderMangler.class)); +Client: +```java +// Only need to register extensions that change how a mapping is parsed/written (i.e. ContentPatternExtension). +WireMock.create() + .extensions("com.mycorp.ClassNameOne", "com.mycorp.ClassNameTwo") + .extensions(ClassOne.class, ClassTwo.class) + .extensions(new InstanceOne(), new InstanceTwo()) + .build(); +``` -new WireMockServer(wireMockConfig() - .extensions(new BodyContentTransformer(), new HeaderMangler())); +Extension: +```java +@RegisterExtension +static WireMockExtension wm = WireMockExtension.newInstance() + .options(wireMockConfig() + .extensions("com.mycorp.ClassNameOne", "com.mycorp.ClassNameTwo") + .extensions(ClassOne.class, ClassTwo.class) + .extensions(new InstanceOne(), new InstanceTwo())) + .build(); ``` See [Running as a Standalone Process](../running-standalone/) for details on running with extensions from the command line. @@ -76,11 +94,42 @@ Services currently available to extension factories are: * `Extensions`: the service for creating and providing extension implementations. * `TemplateEngine`: the Handlebars template engine. +For factories that register extensions that change how a mapping is parsed/written (i.e. ContentPatternExtension), must implement `ExtensionFactory#createForClient()` +to return those extension. + ## Extension registration via service loading Extensions that are packaged with the relevant [Java service loader framework](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html) metadata will be loaded automatically if they are placed on the classpath. +Server: +```java +new WireMockServer(wireMockConfig().extensionScanningEnabled(true)); +``` + +Client: +```java +WireMock.create() + .extensionScanningEnabled(true) + .build(); +``` + +Extension: +```java +@RegisterExtension +static WireMockExtension wm = WireMockExtension.newInstance() + .options(wireMockConfig() + .extensionScanningEnabled(true)) + .build(); + +// or + +@WireMockTest(extensionScanningEnabled = true) +public class MyTest { + ... +} +``` + See [https://github.com/wiremock/wiremock/tree/master/test-extension](https://github.com/wiremock/wiremock/tree/master/test-extension) for an example of such an extension. diff --git a/_docs/extensibility/custom-content-matching.md b/_docs/extensibility/custom-content-matching.md new file mode 100644 index 00000000..bea92da4 --- /dev/null +++ b/_docs/extensibility/custom-content-matching.md @@ -0,0 +1,150 @@ +--- +layout: docs +title: Custom Content Matching +meta_title: Adding custom content matchers +description: Adding custom content matchers via extensions +--- + +If WireMock's standard set of content matching strategies isn't sufficient, you can register one or more content +matcher classes containing your own logic. + +Custom content matchers can be attached directly to stubs via the Java API when using the local admin interface (by +calling `stubFor(...)` on `WireMockServer`, `WireMockExtension`, or `WireMockRule`). They can also be added via the +extension mechanism on a remote admin interface (by calling `extensions(...)` on `WireMockBuilder`). + +To create a custom content matcher extend `ContentPattern` or `StringValuePattern` (ensuring `Json.write(...)` +appropriately serializes your matcher and a `@JsonCreator` is defined): +```java +public class MagicBytesPattern extends ContentPattern { + + public enum Format { + GIF("47 49 46 38 37 61", "47 49 46 38 39 61"), + PNG("89 50 4E 47 0D 0A 1A 0A"), + ZIP("50 4B 03 04", "50 4B 05 06", "50 4B 07 08"); + + private final Set magicBytes; + + Format(String... magicBytes) { + HexFormat hexFormat = HexFormat.ofDelimiter(" "); + this.magicBytes = Stream.of(magicBytes).map(hexFormat::parseHex).collect(toSet()); + } + } + + private final Format format; + + @JsonCreator + public MagicBytesPattern(@JsonProperty("magicBytes") Format format) { + super(format.magicBytes.iterator().next()); + this.format = format; + } + + @Override + public String getName() { + return "magicBytes"; + } + + @Override + public String getExpected() { + return format.toString(); + } + + @Override + public MatchResult match(byte[] value) { + for (byte[] magicByte : format.magicBytes) { + if (value.length >= magicByte.length) { + boolean matches = true; + for (int i = 0; i < magicByte.length; i++) { + if (value[i] != magicByte[i]) { + matches = false; + break; + } + } + if (matches) { + return MatchResult.exactMatch(); + } + } + } + return MatchResult.noMatch(); + } + + public Format getMagicBytes() { + return format; + } +} +``` +```java +public class StartsWithMatcher extends StringValuePattern { + + @JsonCreator + public StartsWithMatcher(@JsonProperty("startsWith") String startsWith) { + super(startsWith); + } + + @Override + public MatchResult match(String value) { + return MatchResult.of(value.startsWith(expectedValue)); + } + + public String getStartsWith() { + return expectedValue; + } +} +``` + +Then, implement `ContentPatternExtension` giving the extension a unique name and identifying the class of your matcher: +```java +public class StartsWithPatternExtension implements ContentPatternExtension { + + @Override + public Class> getContentPatternClass() { + return StartsWithPattern.class; + } + + @Override + public String getName() { + return "starts-with-pattern"; + } +} +``` + +After the extension is properly registered, you can define a stub with it: + +{% codetabs %} + +{% codetab Java %} + +```java +stubFor( + post("/gif") + .withHeader("X-FileName", new StartsWithMatcher("gif")) + .withRequestBody(new MagicBytesPattern(MagicBytesPattern.Format.GIF)) + .willReturn(ok())); +``` + +{% endcodetab %} + +{% codetab JSON %} + +```json +{ + "request": { + "url": "/gif", + "method": "POST", + "headers": { + "X-FileName": { + "startsWith": "gif" + } + }, + "bodyPatterns": [{ + "magicBytes": "GIF" + }] + }, + "response": { + "status": 200 + } +} +``` + +{% endcodetab %} + +{% endcodetabs %} \ No newline at end of file diff --git a/_docs/extensibility/custom-matching.md b/_docs/extensibility/custom-request-matching.md similarity index 99% rename from _docs/extensibility/custom-matching.md rename to _docs/extensibility/custom-request-matching.md index 5099bde6..8f9bacd2 100644 --- a/_docs/extensibility/custom-matching.md +++ b/_docs/extensibility/custom-request-matching.md @@ -1,6 +1,6 @@ --- layout: docs -title: Custom Matching +title: Custom Request Matching meta_title: Adding custom request matchers description: Adding custom request matchers via extensions --- From 3cc3879580b2c9026db9d9f9f24ae626fe7d6e01 Mon Sep 17 00:00:00 2001 From: Ethan Date: Wed, 5 Jun 2024 01:23:53 -0700 Subject: [PATCH 079/152] Updagting the studio page (#286) Co-authored-by: Ethan Jones --- studio/index.html | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/studio/index.html b/studio/index.html index e7ccdb6e..b6747dd8 100644 --- a/studio/index.html +++ b/studio/index.html @@ -1,6 +1,6 @@ --- layout: default -title: WireMock Studio +title: WireMock Studio is now WireMock Cloud description: WireMock Studio is a tool for building and running mock APIs on your desktop or in your cluster. --- @@ -16,17 +16,15 @@

    -

    Studio

    +

    Cloud

    -

    is an IDE for your mock APIs.

    -

    is an IDE for your

    -

    mock APIs.

    +

    is an API productivity platform powered by WireMock.

    - It provides management of multiple mock APIs, support for Swagger, OpenAPI, Postman and JWT, and a full web UI that's accessible to non-coders. + WireMock Studio has been replaced by WireMock Cloud. From Git sync to API prototyping to chaos testing and more, WireMock Cloud brings the power of mocking to every stage of building your application.

    From 21ddc0da51b25355278fcb1c6864a5374185ef0c Mon Sep 17 00:00:00 2001 From: viktormelnychuk Date: Thu, 6 Jun 2024 20:33:29 +0300 Subject: [PATCH 080/152] update docs --- _docs/request-matching.md | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/_docs/request-matching.md b/_docs/request-matching.md index b781ce70..a0b2562d 100644 --- a/_docs/request-matching.md +++ b/_docs/request-matching.md @@ -987,6 +987,46 @@ The full list of comparison types used by default is as follows: `CHILD_LOOKUP` `ATTR_NAME_LOOKUP` +#### Same child nodes with different content +By default WireMock takes into account an order of identical child nodes. Meaning if actual request has different order of same node on same level than stub it won't be matched. +This can be changed by passing additional argument to the `equalToXml` method + +Java: + +```java + .withRequestBody(equalToXml("" + + " 1" + + " 2" + + "",false,true)) +``` +```json +{ + "request": { + ... + "bodyPatterns" : [ { + "equalToXml" : "Hello", + "ignoreOrderOfSameNode": true + } ] + ... + }, + ... +} +``` +This will make sure that stub above matches both of following requests: +```xml + + 2 + 1 + +``` +and +```xml + + 1 + 2 + +``` +If third argument is passed as `false` then first xml will not match the stub ### XPath Deems a match if the attribute value is valid XML and matches the XPath expression supplied. An XML document will be considered to match if any elements are returned by the XPath evaluation. WireMock delegates to Java's in-built XPath engine (via XMLUnit), therefore up to (at least) Java 8 it supports XPath version 1.0. From ca6fb47f73f00d2059f86779313d04935e79dee0 Mon Sep 17 00:00:00 2001 From: leeturner Date: Wed, 12 Jun 2024 18:42:50 +0100 Subject: [PATCH 081/152] Clarify the version of wiremock for the new helpers --- _docs/response-templating.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/_docs/response-templating.md b/_docs/response-templating.md index c7a281c3..369ea322 100644 --- a/_docs/response-templating.md +++ b/_docs/response-templating.md @@ -343,9 +343,10 @@ Variable assignment and number helpers are available: ## Val helper -The `val` helper can be used to access values or provide a default if the value is not present. It can also be used to -assign a value to a variable much like the `assign` helper. The main difference between `val` and `assign` is that `val` -will maintain the type of the date being assigned whereas `assign` will always assign a string. +Released in WireMock version `3.6.0`, the `val` helper can be used to access values or provide a default if the value +is not present. It can also be used to assign a value to a variable much like the `assign` helper. The main difference +between `val` and `assign` is that `val` will maintain the type of the date being assigned whereas `assign` will always +assign a string. {% raw %} @@ -744,9 +745,9 @@ Providing no parameters will result in an empty array. {% endraw %} ## Array add & remove helpers -The `arrayAdd` and `arrayRemove` helpers can be used to add or remove elements from an array based on a position value -or the `start` or `end` keywords. If no position is specified, the element will be added or removed from the end of the -array. +As of WireMock version `3.6.0`, the `arrayAdd` and `arrayRemove` helpers can be used to add or remove elements from an +array based on a position value or the `start` or `end` keywords. If no position is specified, the element will be +added or removed from the end of the array. {% raw %} @@ -766,7 +767,8 @@ array. ## arrayJoin helper -The `arrayJoin` helper will concatenate the values passed to it with the separator specified: +Released in WireMock version `3.6.0`, the `arrayJoin` helper will concatenate the values passed to it with the +separator specified: {% raw %} From 6b44a71de9b1fddf848638493565a93c3e488dc2 Mon Sep 17 00:00:00 2001 From: leeturner Date: Mon, 17 Jun 2024 17:50:38 +0100 Subject: [PATCH 082/152] Add the new request.id to the docs --- _docs/response-templating.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/_docs/response-templating.md b/_docs/response-templating.md index 369ea322..df1095bd 100644 --- a/_docs/response-templating.md +++ b/_docs/response-templating.md @@ -181,6 +181,8 @@ wm.stubFor(get(urlPathMatching("/static/.*")) The model of the request is supplied to the header and body templates. The following request attributes are available: +`request.id` - The unique ID of each request (introduced in WireMock version x.x.x) + `request.url` - URL path and query `request.path` - URL path. This can be referenced in full or it can be treated as an array of path segments (like below) e.g. `request.path.3`. From 85375bd75e90e5585c366603d12ad3c758236b22 Mon Sep 17 00:00:00 2001 From: viktormelnychuk Date: Wed, 19 Jun 2024 14:16:57 +0300 Subject: [PATCH 083/152] implement suggestion --- _docs/request-matching.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_docs/request-matching.md b/_docs/request-matching.md index a0b2562d..1a346a58 100644 --- a/_docs/request-matching.md +++ b/_docs/request-matching.md @@ -988,8 +988,8 @@ The full list of comparison types used by default is as follows: `ATTR_NAME_LOOKUP` #### Same child nodes with different content -By default WireMock takes into account an order of identical child nodes. Meaning if actual request has different order of same node on same level than stub it won't be matched. -This can be changed by passing additional argument to the `equalToXml` method +By default, WireMock takes into account an order of identical child nodes. Meaning if actual request has different order of same node on same level than stub it won't be matched. +As of WireMock version `3.7.0`, this can be changed by passing additional argument to the `equalToXml` method Java: @@ -1004,7 +1004,7 @@ Java: "request": { ... "bodyPatterns" : [ { - "equalToXml" : "Hello", + "equalToXml" : "12", "ignoreOrderOfSameNode": true } ] ... From 19b06ca48ac1a1eec47d7302487deb4f2f48b2fe Mon Sep 17 00:00:00 2001 From: Ethan Jones Date: Wed, 19 Jun 2024 12:14:22 -0400 Subject: [PATCH 084/152] Adding WM Live callout --- assets/js/notifications.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/assets/js/notifications.js b/assets/js/notifications.js index 35dccb97..09a1252d 100644 --- a/assets/js/notifications.js +++ b/assets/js/notifications.js @@ -1,7 +1,21 @@ var wiremock_notification_shown = localStorage.getItem( "wiremock_notification_shown", ); -var notifications = []; +var notifications = [ + { + content: { + title: + "Go beyond the basics of request matching with WireMock Live on July 18! " + + "Register now.", + }, + layout: { + style: "wiremock_notification_with_link", + position: "top", + className: "info", + autoHide: false, + }, + }, +]; if (wiremock_notification_shown == null) { localStorage.setItem("wiremock_notification_shown", true); From a780f85ed607fa9fdf5a11a345a97b21b4b45e77 Mon Sep 17 00:00:00 2001 From: leeturner Date: Thu, 20 Jun 2024 09:44:21 +0100 Subject: [PATCH 085/152] Update the version number that this will be released in --- _docs/response-templating.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_docs/response-templating.md b/_docs/response-templating.md index df1095bd..52c32fd6 100644 --- a/_docs/response-templating.md +++ b/_docs/response-templating.md @@ -181,7 +181,7 @@ wm.stubFor(get(urlPathMatching("/static/.*")) The model of the request is supplied to the header and body templates. The following request attributes are available: -`request.id` - The unique ID of each request (introduced in WireMock version x.x.x) +`request.id` - The unique ID of each request (introduced in WireMock version `3.7.0`) `request.url` - URL path and query From df50329c202f4536eff3766d4390030285b54b29 Mon Sep 17 00:00:00 2001 From: leeturner Date: Fri, 21 Jun 2024 15:32:21 +0100 Subject: [PATCH 086/152] Bumped WireMockk version to 3.7.0 --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index 30b074cc..e47b9b6e 100644 --- a/_config.yml +++ b/_config.yml @@ -234,7 +234,7 @@ compress_html: ignore: envs: development -wiremock_version: 3.6.0 +wiremock_version: 3.7.0 wiremock_baseline: 3.x pageEditPrefix: https://github.com/wiremock/wiremock.org/edit/main/ From bf9f7568fd4ee7b0f9fb4a396e959e9ae548d176 Mon Sep 17 00:00:00 2001 From: leeturner Date: Thu, 27 Jun 2024 10:13:45 +0100 Subject: [PATCH 087/152] Update to the new wiremock oss logo --- _includes/masthead.html | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/_includes/masthead.html b/_includes/masthead.html index 9577618d..65cb326c 100644 --- a/_includes/masthead.html +++ b/_includes/masthead.html @@ -1,15 +1,17 @@

    -   - What's NEW? OpenAPI Validation

    + Image of a loud speaker  + What's NEW? External data sources

    - Guarantee requests to your mock APIs match your specs. + Easily bring data from a CSV file into your mock API calls.

    - - + + Image of WireMock Cloud data sources

    - Stop faulty behavior from leaking into your production environments with OpenAPI validation on your mock API requests. Choose between hard and soft validation as needed. Learn more. + Using external data with WireMock Cloud mock servers lets you quickly bring updated test data without complex configuration, helping to guarantee your test sessions with our API mocks are realistic and simulate your application's production behavior. Learn more.

From 3d43c3d9c1514e781e923070a2b5e8397e31e98f Mon Sep 17 00:00:00 2001 From: leeturner Date: Wed, 3 Jul 2024 13:46:59 +0100 Subject: [PATCH 095/152] Reword whats new page --- index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 25338473..97307d41 100644 --- a/index.html +++ b/index.html @@ -130,7 +130,7 @@

Image of a loud speaker  What's NEW? External data sources

- Easily bring data from a CSV file into your mock API calls. + Easily use data from a CSV file into your mock API calls.

@@ -138,7 +138,7 @@

- Using external data with WireMock Cloud mock servers lets you quickly bring updated test data without complex configuration, helping to guarantee your test sessions with our API mocks are realistic and simulate your application's production behavior. Learn more. + Using external data with WireMock Cloud mock servers lets you quickly use updated test data without complex configuration, helping to guarantee your test sessions with our API mocks are realistic and simulate your application's production behavior. Learn more.

From 669d66ceca2d6c04ee686860ebdc21c61228c454 Mon Sep 17 00:00:00 2001 From: leeturner Date: Thu, 4 Jul 2024 09:49:12 +0100 Subject: [PATCH 096/152] Update the WireMock openapi with the latest updates from the main repo --- assets/js/wiremock-admin-api.json | 327 +++++++++++++++++++++-- swagger/examples/health.yaml | 5 + swagger/examples/record-spec.yaml | 2 +- swagger/schemas/health.yaml | 25 ++ swagger/schemas/request-pattern.yaml | 38 +++ swagger/schemas/response-definition.yaml | 5 + swagger/schemas/stub-mapping.yaml | 19 ++ swagger/wiremock-admin-api.yaml | 152 ++++++++++- 8 files changed, 549 insertions(+), 24 deletions(-) create mode 100644 swagger/examples/health.yaml create mode 100644 swagger/schemas/health.yaml diff --git a/assets/js/wiremock-admin-api.json b/assets/js/wiremock-admin-api.json index 929328a2..29cf743e 100644 --- a/assets/js/wiremock-admin-api.json +++ b/assets/js/wiremock-admin-api.json @@ -2,11 +2,12 @@ "openapi": "3.0.0", "info": { "title": "WireMock", - "version": "2.35.0" + "version": "3.8.0", + "description": "WireMock offers a REST API for administration, troubleshooting and analysis purposes" }, "externalDocs": { "description": "WireMock user documentation", - "url": "http://wiremock.org/docs/" + "url": "https://wiremock.org/docs/" }, "servers": [ { @@ -19,7 +20,7 @@ "description": "Operations on stub mappings", "externalDocs": { "description": "User documentation", - "url": "http://wiremock.org/docs/stubbing/" + "url": "https://wiremock.org/docs/stubbing/" } }, { @@ -27,7 +28,7 @@ "description": "Logged requests and responses received by the mock service", "externalDocs": { "description": "User documentation", - "url": "http://wiremock.org/docs/verifying/" + "url": "https://wiremock.org/docs/verifying/" } }, { @@ -35,7 +36,7 @@ "description": "Near misses allow querying of received requests or request patterns according to similarity", "externalDocs": { "description": "User documentation", - "url": "http://wiremock.org/docs/verifying/#near-misses" + "url": "https://wiremock.org/docs/verifying/#near-misses" } }, { @@ -43,7 +44,7 @@ "description": "Stub mapping record and snapshot functions", "externalDocs": { "description": "User documentation", - "url": "http://wiremock.org/docs/record-playback/" + "url": "https://wiremock.org/docs/record-playback/" } }, { @@ -51,9 +52,13 @@ "description": "Scenarios support modelling of stateful behaviour", "externalDocs": { "description": "User documentation", - "url": "http://wiremock.org/docs/stateful-behaviour/" + "url": "https://wiremock.org/docs/stateful-behaviour/" } }, + { + "name": "Files", + "description": "Manage the files used to support WireMock stubs" + }, { "name": "System", "description": "Global operations" @@ -62,6 +67,7 @@ "paths": { "/__admin/mappings": { "get": { + "operationId": "getAllStubMappings", "summary": "Get all stub mappings", "tags": [ "Stub Mappings" @@ -207,6 +213,13 @@ "type": "object", "description": "Extra request headers to send when proxying to another host." }, + "removeProxyRequestHeaders": { + "type": "array", + "description": "Request headers to remove when proxying to another host.", + "items": { + "type": "string" + } + }, "body": { "type": "string", "description": "The response body as a string. Only one of body, base64Body, jsonBody or bodyFileName may be specified." @@ -402,6 +415,7 @@ } }, "post": { + "operationId": "createNewStubMapping", "summary": "Create a new stub mapping", "tags": [ "Stub Mappings" @@ -519,6 +533,13 @@ "type": "object", "description": "Extra request headers to send when proxying to another host." }, + "removeProxyRequestHeaders": { + "type": "array", + "description": "Request headers to remove when proxying to another host.", + "items": { + "type": "string" + } + }, "body": { "type": "string", "description": "The response body as a string. Only one of body, base64Body, jsonBody or bodyFileName may be specified." @@ -778,6 +799,13 @@ "type": "object", "description": "Extra request headers to send when proxying to another host." }, + "removeProxyRequestHeaders": { + "type": "array", + "description": "Request headers to remove when proxying to another host.", + "items": { + "type": "string" + } + }, "body": { "type": "string", "description": "The response body as a string. Only one of body, base64Body, jsonBody or bodyFileName may be specified." @@ -932,6 +960,7 @@ } }, "delete": { + "operationId": "deleteAllStubMappings", "summary": "Delete all stub mappings", "tags": [ "Stub Mappings" @@ -945,6 +974,7 @@ }, "/__admin/mappings/reset": { "post": { + "operationId": "resetStubMappings", "summary": "Reset stub mappings", "description": "Restores stub mappings to the defaults defined back in the backing store", "tags": [ @@ -959,6 +989,7 @@ }, "/__admin/mappings/save": { "post": { + "operationId": "persistStubMappings", "summary": "Persist stub mappings", "description": "Save all persistent stub mappings to the backing store", "tags": [ @@ -973,6 +1004,7 @@ }, "/__admin/mappings/import": { "post": { + "operationId": "importStubMappings", "summary": "Import stub mappings", "description": "Import given stub mappings to the backing store", "tags": [ @@ -999,6 +1031,7 @@ } ], "get": { + "operationId": "getStubMappingById", "summary": "Get stub mapping by ID", "tags": [ "Stub Mappings" @@ -1118,6 +1151,13 @@ "type": "object", "description": "Extra request headers to send when proxying to another host." }, + "removeProxyRequestHeaders": { + "type": "array", + "description": "Request headers to remove when proxying to another host.", + "items": { + "type": "string" + } + }, "body": { "type": "string", "description": "The response body as a string. Only one of body, base64Body, jsonBody or bodyFileName may be specified." @@ -1275,6 +1315,7 @@ } }, "put": { + "operationId": "updateStubMapping", "summary": "Update a stub mapping", "tags": [ "Stub Mappings" @@ -1392,6 +1433,13 @@ "type": "object", "description": "Extra request headers to send when proxying to another host." }, + "removeProxyRequestHeaders": { + "type": "array", + "description": "Request headers to remove when proxying to another host.", + "items": { + "type": "string" + } + }, "body": { "type": "string", "description": "The response body as a string. Only one of body, base64Body, jsonBody or bodyFileName may be specified." @@ -1651,6 +1699,13 @@ "type": "object", "description": "Extra request headers to send when proxying to another host." }, + "removeProxyRequestHeaders": { + "type": "array", + "description": "Request headers to remove when proxying to another host.", + "items": { + "type": "string" + } + }, "body": { "type": "string", "description": "The response body as a string. Only one of body, base64Body, jsonBody or bodyFileName may be specified." @@ -1808,6 +1863,7 @@ } }, "delete": { + "operationId": "deleteStubMapping", "summary": "Delete a stub mapping", "tags": [ "Stub Mappings" @@ -1824,6 +1880,7 @@ }, "/__admin/mappings/find-by-metadata": { "post": { + "operationId": "findStubMappingsByMetadata", "description": "Find stubs by matching on their metadata", "tags": [ "Stub Mappings" @@ -2075,6 +2132,13 @@ "type": "object", "description": "Extra request headers to send when proxying to another host." }, + "removeProxyRequestHeaders": { + "type": "array", + "description": "Request headers to remove when proxying to another host.", + "items": { + "type": "string" + } + }, "body": { "type": "string", "description": "The response body as a string. Only one of body, base64Body, jsonBody or bodyFileName may be specified." @@ -2272,6 +2336,7 @@ }, "/__admin/mappings/remove-by-metadata": { "post": { + "operationId": "removeStubMappingsByMetadata", "summary": "Delete stub mappings matching metadata", "tags": [ "Stub Mappings" @@ -2412,6 +2477,7 @@ }, "/__admin/requests": { "get": { + "operationId": "getAllRequestsInJournal", "summary": "Get all requests in journal", "tags": [ "Requests" @@ -2533,6 +2599,7 @@ } }, "delete": { + "operationId": "deleteAllRequestsInJournal", "summary": "Delete all requests in journal", "tags": [ "Requests" @@ -2546,6 +2613,7 @@ }, "/__admin/requests/{requestId}": { "get": { + "operationId": "getRequestById", "summary": "Get request by ID", "tags": [ "Requests" @@ -2602,6 +2670,7 @@ } }, "delete": { + "operationId": "deleteRequestById", "summary": "Delete request by ID", "tags": [ "Requests" @@ -2627,6 +2696,7 @@ }, "/__admin/requests/reset": { "post": { + "operationId": "emptyRequestJournal", "deprecated": true, "summary": "Empty the request journal", "tags": [ @@ -2641,6 +2711,7 @@ }, "/__admin/requests/count": { "post": { + "operationId": "countRequestsByCriteria", "summary": "Count requests by criteria", "description": "Count requests logged in the journal matching the specified criteria", "tags": [ @@ -2758,6 +2829,7 @@ }, "/__admin/requests/remove": { "post": { + "operationId": "removeRequestsByCriteria", "summary": "Remove requests by criteria", "description": "Removed requests logged in the journal matching the specified criteria", "tags": [ @@ -2897,6 +2969,7 @@ }, "/__admin/requests/remove-by-metadata": { "post": { + "operationId": "removeRequestsByMetadata", "summary": "Delete requests mappings matching metadata", "tags": [ "Requests" @@ -3072,6 +3145,7 @@ }, "/__admin/requests/find": { "post": { + "operationId": "findRequestsByCriteria", "summary": "Find requests by criteria", "description": "Retrieve details of requests logged in the journal matching the specified criteria", "tags": [ @@ -3211,6 +3285,7 @@ }, "/__admin/requests/unmatched": { "get": { + "operationId": "findUnmatchedRequests", "summary": "Find unmatched requests", "description": "Get details of logged requests that weren't matched by any stub mapping", "tags": [ @@ -3260,6 +3335,7 @@ }, "/__admin/requests/unmatched/near-misses": { "get": { + "operationId": "retrieveNearMissesForUnmatchedRequests", "description": "Retrieve near-misses for all unmatched requests", "tags": [ "Near Misses" @@ -3354,6 +3430,7 @@ }, "/__admin/near-misses/request": { "post": { + "operationId": "findNearMissesForRequest", "summary": "Find near misses matching specific request", "description": "Find at most 3 near misses for closest stub mappings to the specified request", "tags": [ @@ -3512,6 +3589,7 @@ }, "/__admin/near-misses/request-pattern": { "post": { + "operationId": "findNearMissesForRequestPattern", "summary": "Find near misses matching request pattern", "description": "Find at most 3 near misses for closest logged requests to the specified request pattern", "tags": [ @@ -3697,6 +3775,7 @@ }, "/__admin/recordings/start": { "post": { + "operationId": "startRecording", "summary": "Start recording", "description": "Begin recording stub mappings", "tags": [ @@ -3947,14 +4026,14 @@ "targetBaseUrl": { "type": "string", "description": "Target URL when using the record and playback API", - "example": "http://examples.wiremockapi.cloud/" + "example": "https://example.wiremock.org" } } } ] }, "example": { - "targetBaseUrl": "http://examples.wiremockapi.cloud/", + "targetBaseUrl": "https://example.wiremock.org", "filters": { "urlPathPattern": "/api/.*", "method": "GET" @@ -3995,6 +4074,7 @@ }, "/__admin/recordings/stop": { "post": { + "operationId": "stopRecording", "summary": "Stop recording", "description": "End recording of stub mappings", "tags": [ @@ -4119,6 +4199,13 @@ "type": "object", "description": "Extra request headers to send when proxying to another host." }, + "removeProxyRequestHeaders": { + "type": "array", + "description": "Request headers to remove when proxying to another host.", + "items": { + "type": "string" + } + }, "body": { "type": "string", "description": "The response body as a string. Only one of body, base64Body, jsonBody or bodyFileName may be specified." @@ -4293,6 +4380,7 @@ }, "/__admin/recordings/status": { "get": { + "operationId": "getRecordingStatus", "summary": "Get recording status", "tags": [ "Recordings" @@ -4324,6 +4412,7 @@ }, "/__admin/recordings/snapshot": { "post": { + "operationId": "takeRecordingSnapshot", "summary": "Take a snapshot recording", "tags": [ "Recordings" @@ -4740,6 +4829,13 @@ "type": "object", "description": "Extra request headers to send when proxying to another host." }, + "removeProxyRequestHeaders": { + "type": "array", + "description": "Request headers to remove when proxying to another host.", + "items": { + "type": "string" + } + }, "body": { "type": "string", "description": "The response body as a string. Only one of body, base64Body, jsonBody or bodyFileName may be specified." @@ -4914,6 +5010,7 @@ }, "/__admin/scenarios": { "get": { + "operationId": "getAllScenarios", "summary": "Get all scenarios", "tags": [ "Scenarios" @@ -4973,6 +5070,7 @@ }, "/__admin/scenarios/reset": { "post": { + "operationId": "resetAllScenarios", "summary": "Reset the state of all scenarios", "tags": [ "Scenarios" @@ -4984,8 +5082,101 @@ } } }, + "/__admin/files": { + "get": { + "operationId": "getAllFileNames", + "summary": "Get all file names", + "tags": [ + "Files" + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "file1.json", + "file2.json", + "file3.txt" + ] + } + } + }, + "description": "All scenarios" + } + } + } + }, + "/__admin/files/{fileId}": { + "parameters": [ + { + "description": "The name of the file", + "in": "path", + "name": "fileId", + "required": true, + "example": "file1.json", + "schema": { + "type": "string" + } + } + ], + "get": { + "operationId": "getFileById", + "summary": "Get file by ID", + "tags": [ + "Files" + ], + "responses": { + "404": { + "description": "File not found" + }, + "200": { + "description": "The contents of the file" + } + } + }, + "put": { + "operationId": "updateFileById", + "summary": "Update or create a file", + "tags": [ + "Files" + ], + "requestBody": { + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "byte" + } + } + } + }, + "responses": { + "200": { + "description": "OK - contents of the request body as a string" + } + } + }, + "delete": { + "operationId": "deleteFileById", + "summary": "Delete a file if it exists", + "tags": [ + "Files" + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/__admin/settings": { "post": { + "operationId": "updateGlobalSettings", "summary": "Update global settings", "tags": [ "System" @@ -5063,6 +5254,7 @@ }, "/__admin/reset": { "post": { + "operationId": "resetMappingsAndJournal", "summary": "Reset mappings and request journal", "description": "Reset mappings to the default state and reset the request journal", "tags": [ @@ -5075,15 +5267,106 @@ } } }, - "/__admin/shutdown": { - "post": { - "description": "Shutdown the WireMock server", + "/__admin/shutdown" : { + "post" : { + "operationId" : "shutdownServer", + "summary" : "Shutdown the WireMock server", + "description" : "Shutdown the WireMock server", + "tags" : [ "System" ], + "responses" : { + "200" : { + "description" : "Server will be shut down" + } + } + } + }, + "/__admin/version": { + "get": { + "operationId": "getVersion", + "summary": "Return the version of the WireMock server", + "description": "Returns the version of the WireMock server", "tags": [ "System" ], "responses": { "200": { - "description": "Server will be shut down" + "description": "Successfully returned the version of the WireMock server", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "version": { + "type": "string", + "example": "3.8.0" + } + } + }, + "example": { + "version": "3.8.0" + } + } + } + } + } + } + }, + "/__admin/health": { + "get": { + "operationId": "getHealth", + "summary": "Return the health of the WireMock server", + "description": "Returns the health of the WireMock server", + "tags": [ + "System" + ], + "responses": { + "200": { + "description": "Successful health and uptime data", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "The status of the server", + "example": "healthy", + "enum": [ + "healthy", + "unhealthy" + ] + }, + "message": { + "type": "string", + "description": "Longer message regarding the status of the server", + "example": "Wiremock is ok" + }, + "version": { + "type": "string", + "description": "The WireMock version", + "example": "3.8.0" + }, + "upTimeInSeconds": { + "type": "integer", + "description": "How long the server has been running", + "example": 14355 + }, + "timestamp": { + "type": "string", + "description": "The current timestamp", + "example": "2024-07-03T13:16:06.172362Z" + } + } + }, + "example": { + "status": "healthy", + "message": "Wiremock is ok", + "version": "3.8.0", + "uptimeInSeconds": 14355, + "timestamp": "2024-07-03T13:16:06.172362Z" + } + } + } } } } @@ -5294,6 +5577,13 @@ "type": "object", "description": "Extra request headers to send when proxying to another host." }, + "removeProxyRequestHeaders": { + "type": "array", + "description": "Request headers to remove when proxying to another host.", + "items": { + "type": "string" + } + }, "body": { "type": "string", "description": "The response body as a string. Only one of body, base64Body, jsonBody or bodyFileName may be specified." @@ -5683,14 +5973,14 @@ "targetBaseUrl": { "type": "string", "description": "Target URL when using the record and playback API", - "example": "http://examples.wiremockapi.cloud/" + "example": "https://example.wiremock.org" } } } ] }, "example": { - "targetBaseUrl": "http://examples.wiremockapi.cloud/", + "targetBaseUrl": "https://example.wiremock.org", "filters": { "urlPathPattern": "/api/.*", "method": "GET" @@ -6131,6 +6421,13 @@ "type": "object", "description": "Extra request headers to send when proxying to another host." }, + "removeProxyRequestHeaders": { + "type": "array", + "description": "Request headers to remove when proxying to another host.", + "items": { + "type": "string" + } + }, "body": { "type": "string", "description": "The response body as a string. Only one of body, base64Body, jsonBody or bodyFileName may be specified." diff --git a/swagger/examples/health.yaml b/swagger/examples/health.yaml new file mode 100644 index 00000000..4c74d40e --- /dev/null +++ b/swagger/examples/health.yaml @@ -0,0 +1,5 @@ +status: "healthy" +message: "Wiremock is ok" +version: "3.8.0" +uptimeInSeconds: 14355 +timestamp: "2024-07-03T13:16:06.172362Z" \ No newline at end of file diff --git a/swagger/examples/record-spec.yaml b/swagger/examples/record-spec.yaml index 552de91f..660b9125 100644 --- a/swagger/examples/record-spec.yaml +++ b/swagger/examples/record-spec.yaml @@ -1,4 +1,4 @@ -targetBaseUrl: http://examples.wiremockapi.cloud/ +targetBaseUrl: http://example.mocklab.io filters: urlPathPattern: "/api/.*" method: GET diff --git a/swagger/schemas/health.yaml b/swagger/schemas/health.yaml new file mode 100644 index 00000000..cd0eb57f --- /dev/null +++ b/swagger/schemas/health.yaml @@ -0,0 +1,25 @@ +type: object +properties: + status: + type: string + example: "healthy" + description: "The status of the server" + enum: + - healthy + - unhealthy + message: + type: string + description: "Longer message regarding the status of the server" + example: "Wiremock is ok" + version: + type: string + description: "The WireMock version" + example: "3.8.0" + uptimeInSeconds: + type: integer + description: "How long the server has been running" + example: 14355 + timestamp: + type: string + description: "The current timestamp" + example: "2024-07-03T13:16:06.172362Z" diff --git a/swagger/schemas/request-pattern.yaml b/swagger/schemas/request-pattern.yaml index 628878f0..4035ff8e 100644 --- a/swagger/schemas/request-pattern.yaml +++ b/swagger/schemas/request-pattern.yaml @@ -8,6 +8,15 @@ example: method: POST url: /some/thing properties: + scheme: + type: string + description: The URI scheme + host: + type: object + description: 'URI host pattern to match against in the "": "" form' + port: + type: integer + description: The HTTP port number method: type: string description: The HTTP request method e.g. GET @@ -48,3 +57,32 @@ properties: description: 'Request body patterns to match against in the : { "": "" } form' items: type: object + customMatcher: + type: object + description: Custom request matcher to match against + properties: + name: + type: string + description: The matcher's name specified in the implementation of the matcher. + parameters: + type: object + multipartPatterns: + type: array + description: Multipart patterns to match against headers and body + items: + type: object + properties: + name: + type: string + matchingType: + type: string + default: ANY + enum: + - ALL + - ANY + headers: + type: object + bodyPatterns: + type: array + items: + type: object diff --git a/swagger/schemas/response-definition.yaml b/swagger/schemas/response-definition.yaml index e6a035f8..43bf4c58 100644 --- a/swagger/schemas/response-definition.yaml +++ b/swagger/schemas/response-definition.yaml @@ -13,6 +13,11 @@ allOf: additionalProxyRequestHeaders: type: object description: Extra request headers to send when proxying to another host. + removeProxyRequestHeaders: + type: array + description: Request headers to remove when proxying to another host. + items: + type: string body: type: string description: The response body as a string. Only one of body, base64Body, jsonBody or bodyFileName may be specified. diff --git a/swagger/schemas/stub-mapping.yaml b/swagger/schemas/stub-mapping.yaml index 16ed220f..176eafd9 100644 --- a/swagger/schemas/stub-mapping.yaml +++ b/swagger/schemas/stub-mapping.yaml @@ -32,6 +32,25 @@ properties: postServeActions: type: object description: A map of the names of post serve action extensions to trigger and their parameters. + serveEventListeners: + type: array + description: The list of serve event listeners + items: + type: object + properties: + name: + type: string + requestPhases: + type: array + items: + type: string + enum: + - BEFORE_MATCH + - AFTER_MATCH + - BEFORE_RESPONSE_SENT + - AFTER_COMPLETE + parameters: + type: object metadata: type: object description: Arbitrary metadata to be used for e.g. tagging, documentation. Can also be used to find and remove stubs. diff --git a/swagger/wiremock-admin-api.yaml b/swagger/wiremock-admin-api.yaml index a7d0a33b..f605ca3b 100644 --- a/swagger/wiremock-admin-api.yaml +++ b/swagger/wiremock-admin-api.yaml @@ -2,11 +2,12 @@ openapi: 3.0.0 info: title: WireMock - version: 2.35.0 + version: 3.8.0 + description: "WireMock offers a REST API for administration, troubleshooting and analysis purposes" externalDocs: description: WireMock user documentation - url: http://wiremock.org/docs/ + url: https://wiremock.org/docs/ servers: - url: / @@ -16,33 +17,36 @@ tags: description: Operations on stub mappings externalDocs: description: User documentation - url: http://wiremock.org/docs/stubbing/ + url: https://wiremock.org/docs/stubbing/ - name: Requests description: Logged requests and responses received by the mock service externalDocs: description: User documentation - url: http://wiremock.org/docs/verifying/ + url: https://wiremock.org/docs/verifying/ - name: Near Misses description: Near misses allow querying of received requests or request patterns according to similarity externalDocs: description: User documentation - url: http://wiremock.org/docs/verifying/#near-misses + url: https://wiremock.org/docs/verifying/#near-misses - name: Recordings description: Stub mapping record and snapshot functions externalDocs: description: User documentation - url: http://wiremock.org/docs/record-playback/ + url: https://wiremock.org/docs/record-playback/ - name: Scenarios description: Scenarios support modelling of stateful behaviour externalDocs: description: User documentation - url: http://wiremock.org/docs/stateful-behaviour/ + url: https://wiremock.org/docs/stateful-behaviour/ + - name: Files + description: Manage the files used to support WireMock stubs - name: System description: Global operations paths: /__admin/mappings: get: + operationId: getAllStubMappings summary: Get all stub mappings tags: - Stub Mappings @@ -71,6 +75,7 @@ paths: $ref: 'examples/stub-mappings.yaml' description: All stub mappings post: + operationId: createNewStubMapping summary: Create a new stub mapping tags: - Stub Mappings @@ -80,6 +85,7 @@ paths: '201': $ref: "#/components/responses/stubMapping" delete: + operationId: deleteAllStubMappings summary: Delete all stub mappings tags: - Stub Mappings @@ -89,6 +95,7 @@ paths: /__admin/mappings/reset: post: + operationId: resetStubMappings summary: Reset stub mappings description: Restores stub mappings to the defaults defined back in the backing store tags: @@ -99,6 +106,7 @@ paths: /__admin/mappings/save: post: + operationId: persistStubMappings summary: Persist stub mappings description: Save all persistent stub mappings to the backing store tags: @@ -109,6 +117,7 @@ paths: /__admin/mappings/import: post: + operationId: importStubMappings summary: Import stub mappings description: Import given stub mappings to the backing store tags: @@ -127,6 +136,7 @@ paths: schema: type: string get: + operationId: getStubMappingById summary: Get stub mapping by ID tags: - Stub Mappings @@ -136,6 +146,7 @@ paths: '200': $ref: "#/components/responses/stubMapping" put: + operationId: updateStubMapping summary: Update a stub mapping tags: - Stub Mappings @@ -147,6 +158,7 @@ paths: '200': $ref: "#/components/responses/stubMapping" delete: + operationId: deleteStubMapping summary: Delete a stub mapping tags: - Stub Mappings @@ -158,6 +170,7 @@ paths: /__admin/mappings/find-by-metadata: post: + operationId: findStubMappingsByMetadata description: Find stubs by matching on their metadata tags: - Stub Mappings @@ -181,6 +194,7 @@ paths: /__admin/mappings/remove-by-metadata: post: + operationId: removeStubMappingsByMetadata summary: Delete stub mappings matching metadata tags: - Stub Mappings @@ -197,6 +211,7 @@ paths: /__admin/requests: get: + operationId: getAllRequestsInJournal summary: Get all requests in journal tags: - Requests @@ -221,6 +236,7 @@ paths: $ref: 'examples/serve-events.yaml' description: List of received requests delete: + operationId: deleteAllRequestsInJournal summary: Delete all requests in journal tags: - Requests @@ -230,6 +246,7 @@ paths: /__admin/requests/{requestId}: get: + operationId: getRequestById summary: Get request by ID tags: - Requests @@ -251,6 +268,7 @@ paths: example: $ref: "examples/request.yaml" delete: + operationId: deleteRequestById summary: Delete request by ID tags: - Requests @@ -268,6 +286,7 @@ paths: /__admin/requests/reset: post: + operationId: emptyRequestJournal deprecated: true summary: Empty the request journal tags: @@ -278,6 +297,7 @@ paths: /__admin/requests/count: post: + operationId: countRequestsByCriteria summary: Count requests by criteria description: Count requests logged in the journal matching the specified criteria tags: @@ -298,6 +318,7 @@ paths: /__admin/requests/remove: post: + operationId: removeRequestsByCriteria summary: Remove requests by criteria description: Removed requests logged in the journal matching the specified criteria tags: @@ -312,8 +333,11 @@ paths: example: $ref: "examples/requests.yaml" + + /__admin/requests/remove-by-metadata: post: + operationId: removeRequestsByMetadata summary: Delete requests mappings matching metadata tags: - Requests @@ -334,6 +358,7 @@ paths: /__admin/requests/find: post: + operationId: findRequestsByCriteria summary: Find requests by criteria description: Retrieve details of requests logged in the journal matching the specified criteria tags: @@ -350,6 +375,7 @@ paths: /__admin/requests/unmatched: get: + operationId: findUnmatchedRequests summary: Find unmatched requests description: Get details of logged requests that weren't matched by any stub mapping tags: @@ -364,6 +390,7 @@ paths: /__admin/requests/unmatched/near-misses: get: + operationId: retrieveNearMissesForUnmatchedRequests description: Retrieve near-misses for all unmatched requests tags: - Near Misses @@ -373,6 +400,7 @@ paths: /__admin/near-misses/request: post: + operationId: findNearMissesForRequest summary: Find near misses matching specific request description: Find at most 3 near misses for closest stub mappings to the specified request tags: @@ -391,6 +419,7 @@ paths: /__admin/near-misses/request-pattern: post: + operationId: findNearMissesForRequestPattern summary: Find near misses matching request pattern description: Find at most 3 near misses for closest logged requests to the specified request pattern tags: @@ -403,6 +432,7 @@ paths: /__admin/recordings/start: post: + operationId: startRecording summary: Start recording description: Begin recording stub mappings tags: @@ -415,6 +445,7 @@ paths: /__admin/recordings/stop: post: + operationId: stopRecording summary: Stop recording description: End recording of stub mappings tags: @@ -431,6 +462,7 @@ paths: /__admin/recordings/status: get: + operationId: getRecordingStatus summary: Get recording status tags: - Recordings @@ -452,6 +484,7 @@ paths: /__admin/recordings/snapshot: post: + operationId: takeRecordingSnapshot summary: Take a snapshot recording tags: - Recordings @@ -469,6 +502,7 @@ paths: /__admin/scenarios: get: + operationId: getAllScenarios summary: Get all scenarios tags: - Scenarios @@ -487,6 +521,7 @@ paths: /__admin/scenarios/reset: post: + operationId: resetAllScenarios summary: Reset the state of all scenarios tags: - Scenarios @@ -494,8 +529,69 @@ paths: '200': description: Successfully reset + + /__admin/files: + get: + operationId: getAllFileNames + summary: Get all file names + tags: + - Files + responses: + '200': + content: + application/json: + schema: + type: array + items: + type: string + example: ["file1.json", "file2.json", "file3.txt"] + description: All scenarios + + /__admin/files/{fileId}: + parameters: + - description: The name of the file + in: path + name: fileId + required: true + example: file1.json + schema: + type: string + get: + operationId: getFileById + summary: Get file by ID + tags: + - Files + responses: + '404': + description: File not found + '200': + description: The contents of the file + put: + operationId: updateFileById + summary: Update or create a file + tags: + - Files + requestBody: + content: + application/octet-stream: + schema: + type: string + format: byte + responses: + '200': + description: OK - contents of the request body as a string + delete: + operationId: deleteFileById + summary: Delete a file if it exists + tags: + - Files + responses: + '200': + description: OK + /__admin/settings: post: + operationId: updateGlobalSettings summary: Update global settings tags: - System @@ -518,6 +614,7 @@ paths: /__admin/reset: post: + operationId: resetMappingsAndJournal summary: Reset mappings and request journal description: Reset mappings to the default state and reset the request journal tags: @@ -528,12 +625,51 @@ paths: /__admin/shutdown: post: + operationId: shutdownServer + summary: Shutdown the WireMock server description: Shutdown the WireMock server tags: - System responses: '200': description: Server will be shut down + + + /__admin/version: + get: + operationId: getVersion + summary: Return the version of the WireMock server + description: Returns the version of the WireMock server + tags: + - System + responses: + '200': + description: Successfully returned the version of the WireMock server + content: + application/json: + schema: + type: object + properties: + version: + type: string + example: "3.8.0" + + /__admin/health: + get: + operationId: getHealth + summary: Return the health of the WireMock server + description: Returns the health of the WireMock server + tags: + - System + responses: + '200': + description: Successful health and uptime data + content: + application/json: + schema: + $ref: 'schemas/health.yaml' + example: + $ref: 'examples/health.yaml' components: requestBodies: @@ -569,7 +705,7 @@ components: targetBaseUrl: type: string description: Target URL when using the record and playback API - example: http://examples.wiremockapi.cloud/ + example: https://example.wiremock.org example: $ref: "examples/record-spec.yaml" From 22e6e2224d3615333e06edd5d668b4080e64203a Mon Sep 17 00:00:00 2001 From: leeturner Date: Thu, 4 Jul 2024 09:54:09 +0100 Subject: [PATCH 097/152] Fix old url --- swagger/examples/record-spec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swagger/examples/record-spec.yaml b/swagger/examples/record-spec.yaml index 660b9125..f8164291 100644 --- a/swagger/examples/record-spec.yaml +++ b/swagger/examples/record-spec.yaml @@ -1,4 +1,4 @@ -targetBaseUrl: http://example.mocklab.io +targetBaseUrl: https://examples.wiremockapi.cloud/ filters: urlPathPattern: "/api/.*" method: GET From 45ec231f4965fd775c8cda1549b5c150147399c5 Mon Sep 17 00:00:00 2001 From: leeturner Date: Fri, 5 Jul 2024 11:15:40 +0100 Subject: [PATCH 098/152] Update the external resources page with new items --- external-resources/index.html | 416 ++++++++++++++-------------------- 1 file changed, 173 insertions(+), 243 deletions(-) diff --git a/external-resources/index.html b/external-resources/index.html index 8ae46985..fb918bcf 100644 --- a/external-resources/index.html +++ b/external-resources/index.html @@ -15,263 +15,193 @@

Community Resources

-

- Code, articles and videos related to WireMock from around the web. -

-

- Integrations -

-

- WireMocha is a WireMock plugin for IntelliJ: -

- https://plugins.jetbrains.com/plugin/18860-wiremocha + +

Code, articles and videos related to WireMock from around the web.

+ + +

Configuration / Clients

+ +

Automate configuration of stubs from JAX-RS annotated resources.

+ https://github.com/tomasbjerre/wiremock-jaxrs + +

Monitor JVM metrics and WireMock response times.

+ https://github.com/rasklaad/wiremock-metrics + +

PHP client for WireMock

+ https://github.com/rowanhill/wiremock-php + +

NodeJS client for WireMock

+ https://www.npmjs.com/package/wiremock -

- Mark Winteringham wrote a very handy Chrome extension to provide a UI over WireMock: -

- http://www.mwtestconsultancy.co.uk/wiremock-chrome-extension/ +

NodeJS + TypeScript client WireMock

+ https://www.npmjs.com/package/wiremock-captain + +

Epresso test using WireMock as the backend for Android apps

+ https://handstandsam.com/2016/01/30/running-wiremock-on-android/ + +

Make the creation of WireMock stubs for Spring REST controllers safe and effortless.

+ https://dzone.com/articles/wiremock-the-ridiculously-easy-way + + +

Integrations

+ +

WireMocha is a WireMock plugin for IntelliJ.

+ https://plugins.jetbrains.com/plugin/18860-wiremocha

Spring Contract Verifier (previously called Accurest) is a consumer driven contracts tool that generates WireMock stub mappings as examples for client testing.

- http://cloud.spring.io/spring-cloud-contract/ + https://spring.io/projects/spring-cloud-contract -

A Spring REST Docs integration for WireMock that generates WireMock stub mappings from - your test cases:

+

A Spring REST Docs integration for WireMock that generates WireMock stub mappings from your test cases.

https://github.com/epages-de/restdocs-wiremock -

WireMock Maven Plugin:

+

A WireMock plugin for Maven.

https://github.com/automatictester/wiremock-maven-plugin - -

Maciej Walkowiak has built a library providing zero-config, fully declarative Spring Boot integration with WireMock in JUnit 5 tests:

+ +

Zero-config, fully declarative Spring Boot integration with WireMock.

https://github.com/maciejwalkowiak/wiremock-spring-boot -

@GenerateWireMockStub for Spring REST controllers, built by Lukasz Gryzbon, makes the creation of WireMock stubs for tests safe and effortless:

- https://github.com/lsd-consulting/spring-wiremock-stub-generator - -

- Extensions -

-

- Simulate webhooks with this extension: -

- https://github.com/wiremock/wiremock-webhooks-extension - -

- Some folks at Open Table have written a response transformer for injecting data from the request body into the response: -

- - https://github.com/opentable/wiremock-body-transformer - - -

- In a similar vein, Adam York has written a response transformer utilising Velocity templates: -

- - https://github.com/adamyork/wiremock-velocity-transformer - - - -

- Mason Malone has built an extension for matching requests based on the contents of JSON web tokens: -

- - https://github.com/MasonM/wiremock-jwt-extension - - - -

- Also from Mason, an extension for finding and removing unused stub mappings: -

- - https://github.com/MasonM/wiremock-unused-stubs-extension - - -

- Felipe Fernández has built a Spock extension to enhance automation around record and replay functionality: -

- - https://github.com/felipefzdz/spock-wiremock-extension - -

- Automate configuration of stubs, given JAX-RS annotated resources, with this extension: -

- - https://github.com/tomasbjerre/wiremock-jaxrs - -

- Monitor JVM metrics and wiremock response time: -

- - https://github.com/rasklaad/wiremock-metrics - - -

- Other languages -

-

- PHP client by Rowan Hill: -

- - https://github.com/rowanhill/wiremock-php - - -

- Ruby wrapper by Jeffres S. Morgan: -

- - https://rubygems.org/gems/service_mock - - -

- Groovy binding by Tom Jankes: -

- - https://github.com/tomjankes/wiremock-groovy - - -

- Python client by Cody Lee: -

- - - https://pypi.python.org/pypi/wiremock/1.1.1 - - -

- NodeJS wrapper: -

- - https://www.npmjs.com/package/wiremock - - -

- NodeJS + TypeScript client: -

- - https://www.npmjs.com/package/wiremock-captain - - - -

- Articles -

- -

- Sam Edwards has been hugely helpful in getting WireMock onto the Android platform and helping others do so. Here is his blog post explaining how to write an Espresso test using WireMock as your app's back-end: -

- - http://handstandsam.com/2016/01/30/running-wiremock-on-android/ - - -

- Dusan Dević at Yenlo wrote a useful guide to testing error conditions in the WSO2 ESB using Wiremock: -

- - https://www.yenlo.com/blog/wso2torial-error-handling-in-wso2-esb-with-wiremock - - -

- Phill Barber has written a couple of interesting posts about practical testing scenarios with WireMock: -

- - - http://phillbarber.blogspot.co.uk/2015/05/how-to-write-end-to-end-tests-for-nginx.html - - - http://phillbarber.blogspot.co.uk/2015/02/how-to-test-for-connection-leaks.html - - -

- Bas Dijkstra kindly open sourced the content for the workshop he ran on WireMock and REST Assured: -

- - - http://www.ontestautomation.com/open-sourcing-my-workshop-on-wiremock/ - - -

- @GenerateWireMockStub for Spring REST controllers, built by Lukasz Gryzbon, makes the creation of WireMock stubs for tests safe and effortless: -

- - - https://dzone.com/articles/wiremock-the-ridiculously-easy-way - - -

- WireMock workshop: -

- - - https://github.com/basdijkstra/wiremock-workshop - - -

Videos

-

- Fluent and thorough live-coding demonstration of WireMock delivered by Sam Edwards at DevFest DC: -

- - https://youtu.be/x3MvZ8DFrpE - - -

- Sebastian Daschner presents a step-by-step guide to running your acceptance tests in Kubernetes using WireMock: -

- - - https://blog.sebastian-daschner.com/entries/acceptance_tests_wiremock_kubernetes - - -

- Interesting and detailed presentation by Lotte Johansen on testing microservices with WireMock at Norway's top online marketplace: -

- - - https://www.youtube.com/watch?v=cmJfMnGK-r0 - - -

- Chris Batey did an excellent talk at Skillsmatter in London about building fault tolerant microservices. He showed some practical failure testing strategies using WireMock and Saboteur he'd used for real while working at Sky: -

- - https://skillsmatter.com/skillscasts/5810-building-fault-tolerant-microservices - - -

- Daniel Bryant's excellent QCon presentation “The Seven Deadly Sins of Microservices” covers the full gamut of microservice anti-patterns seen in the wild, with some sound advice on how to fix them. WireMock and Saboteur get an honourable mention in the testing discussion: -

- - - https://www.infoq.com/presentations/7-sins-microservices - - -

- - The folks at Intuit have built a very impressive and ambitious testing setup, using WireMock to isolate individual services. Here's a talk they did at AWS:Reinvent: -

+

A response transformer for injecting data from the request body into the response from Open Table.

+ https://github.com/opentable/wiremock-body-transformer + +

An extension for matching requests based on the contents of JSON web tokens.

+ https://github.com/MasonM/wiremock-jwt-extension + +

Create a mock server with WireMock and Postman - Practical implementation

+ https://www.youtube.com/watch?v=Zd4_tUSOHfw&pp=ygUId2lyZW1vY2s%3D + +

Create a mock server with WireMock and Postman - Configuration theory

+ https://www.youtube.com/watch?v=gVVTO4U8M_k&pp=ygUId2lyZW1vY2s%3D + +

Transparent http client testing with http4K and WireMock

+ https://www.youtube.com/watch?v=fpXf1K_E_bY&pp=ygUId2lyZW1vY2s%3D + + +

Tutorial

+ +

A workshop introduction to service virtualization with WireMock

+ https://github.com/basdijkstra/wiremock-workshop + +

A step-by-step guide to running your acceptance tests in Kubernetes using WireMock.

+ https://blog.sebastian-daschner.com/entries/acceptance_tests_wiremock_kubernetes + +

Testing microservices with WireMock at Norway's top online marketplace.

+ https://www.youtube.com/watch?v=cmJfMnGK-r0 + +

AWS:Reinvent talk from Intuit on isolating services for testing with WireMock.

+ https://www.youtube.com/watch?list=PLhr1KZpdzuke5pqzTvI2ZxwP8-NwLACuU&v=sUsh3EnzKKk + +

Using WireMock for HTTP stubbing and mocking.

+ https://medium.com/@2023sl93093/using-wiremock-for-http-stubbing-and-mocking-a-guide-0446dcf37b07 + +

Request filtering (interception) and modification with WireMock.

+ https://medium.com/gitconnected/wiremock-server-request-filtering-interception-and-modification-b13c48c87e32 + +

Mastering API Performance Testing with k6, Grafana and WireMock.

+ https://medium.com/gitconnected/mastering-api-performance-testing-with-k6-grafana-and-wiremock-e09825fb2241 - - https://www.youtube.com/watch?list=PLhr1KZpdzuke5pqzTvI2ZxwP8-NwLACuU&v=sUsh3EnzKKk - - -

- Michael Bailey was the first person to publicly demonstrate the possibility of running WireMock on Android. Here's his presentation at Google's GTAC conference on the testing setup used by his team at Amex: -

- - - https://www.youtube.com/watch?v=-xQCNf_5NNM - +

Standalone stub server using Spring Cloud Contract and WireMock.

+ https://medium.com/@boottechnologies-ci/standalone-stub-server-using-spring-cloud-contract-wiremock-c91e72d8cdde -

- Tom and Rob Elliot gave a join talk at Skillsmatter about patterns for readable and scalable tests with WireMock, and an approach for unit testing a CDN: -

+

Mock servers in the era of microservices.

+ https://medium.com/gitconnected/mock-server-using-wiremock-a61cbd55a690 - +

Understanding proxying with WireMock and .NET

+
https://www.youtube.com/watch?v=kRHiNlkF2po&pp=ygUId2lyZW1vY2s%3D - https://skillsmatter.com/skillscasts/6853-scalable-management-of-test-data-making-tests-readable - +

Running WireMock as a .NET Tool in CommandLine

+ https://www.youtube.com/watch?v=YdyR1ZWrnC4&pp=ygUId2lyZW1vY2s%3D -

MockLab

-

Build a Paypal sandbox for load testing in 10 minutes

+

Generating Static Mappings for Stubs in WireMock and .NET

+ https://www.youtube.com/watch?v=xilAgj4NqhQ&pp=ygUId2lyZW1vY2s%3D -

Mock REST API tutorial

+

Using admin interfaces to debug tests efficiently with WireMock and .NET

+ https://www.youtube.com/watch?v=Q5sxMG84H0w&pp=ygUId2lyZW1vY2s%3D +

Getting JSON body responses from WireMock and .NET

+ https://www.youtube.com/watch?v=fPAUqXo68e8&pp=ygUId2lyZW1vY2s%3D + +

Mocking Bearer Token Authentication using WireMock and .NET

+ https://www.youtube.com/watch?v=IC1lMYuPd4Y&pp=ygUId2lyZW1vY2s%3D + +

Custom database Logging with WireMock

+ https://www.youtube.com/watch?v=HuGAXwrg0nE&pp=ygUId2lyZW1vY2s%3D + +

Understanding request matchers in WireMock and .NET

+ https://www.youtube.com/watch?v=XrgS1ZsUKCY&pp=ygUId2lyZW1vY2s%3D + +

Advanced API mocking Strategies with WireMock Cloud

+ https://www.youtube.com/watch?v=Pdg5wIEyS08&pp=ygUId2lyZW1vY2s%3D + +

Introduction to WireMock and .NET

+ https://www.youtube.com/watch?v=SQRPqBWHeJs&pp=ygUId2lyZW1vY2s%3D + +

Dev Services for Gradle Projects with Quarkus, Gradle and WireMock

+ https://www.youtube.com/watch?v=Lf15C0Jl3Yk&pp=ygUId2lyZW1vY2s%3D + +

Spring Cloud OpenFeign & Testing with WireMock

+ https://www.youtube.com/watch?v=GpqnYd8VR3k&pp=ygUId2lyZW1vY2s%3D + +

Easy Integration Tests for Spring webclients with WireMock.

+ https://www.youtube.com/watch?v=hbr4snySA6I&pp=ygUId2lyZW1vY2s%3D + +

Wiremock - How to use dynamic responses (Espanol)

+ https://www.youtube.com/watch?v=eazDmNtl5aM&pp=ygUId2lyZW1vY2s%3D + +

WireMock platform Enhanced API Security Astra Review

+ https://www.youtube.com/watch?v=2zC7L1uMeis&pp=ygUId2lyZW1vY2s%3D + +

The power of visualization with WireMock (Espanol)

+ https://www.youtube.com/watch?v=aiH83J8ZgsU&pp=ygUId2lyZW1vY2s%3D + +

Exploring WireMock's built-in request matchers

+ https://www.youtube.com/watch?v=73quuWlJAkM&pp=ygUId2lyZW1vY2s%3D + +

Request Matching With URLs with WireMock

+ https://www.youtube.com/watch?v=1VIr__OWYRI&pp=ygUId2lyZW1vY2s%3D + +

External APIs Testing with WireMock

+ https://www.youtube.com/watch?v=KaW8yl52z5w&pp=ygUId2lyZW1vY2s%3D + +

Setup a WireMock Standalone Server Locally and create a basic JSON stub

+ https://www.youtube.com/watch?v=kIgl7Yxmd4M&pp=ygUId2lyZW1vY2s%3D + +

Top use cases for API mocking with WireMock

+ https://www.youtube.com/watch?v=L3Pb0ciIhgI&pp=ygUId2lyZW1vY2s%3D + +

Wiremock for monoliths vs microservices

+ https://www.youtube.com/watch?v=wTD9vBRxoP0&pp=ygUId2lyZW1vY2s%3D + +

Web services integration testing with WireMock

+ https://www.youtube.com/watch?v=koxLAS6PM-g&pp=ygUId2lyZW1vY2s%3D + +

Exploring API Testing: Challenges and Tools

+ https://www.youtube.com/watch?v=BhsSd2wLfM0&pp=ygUId2lyZW1vY2s%3D + +

How to generate WireMock stubs with the OpenAPI generator (French)

+ https://www.youtube.com/watch?v=0jhONfBrcKw&pp=ygUId2lyZW1vY2s%3D + +

Fake It until You Make It! API Integration Testing with Containers & WireMock

+ https://www.youtube.com/watch?v=YEc6EwiHrjM&pp=ygUId2lyZW1vY2s%3D + +

Apidays Paris 2023 - Boost Productivity with Mock APIs: A Game Changer

+ https://www.youtube.com/watch?v=paqtGXPKVwE&pp=ygUId2lyZW1vY2s%3D + +

Testcontainers and API mocking with WireMock for C/C++

+ https://www.youtube.com/watch?v=dBjjFDZS5FM&pp=ygUId2lyZW1vY2s%3D + +

Spring Integration Testing Demystified: Testcontainers, WebTestClient, and WireMock

+ https://www.youtube.com/watch?v=kPqbfzZSUE4&pp=ygUId2lyZW1vY2s%3D + +

Integration Tests with WireMock and Spring Boot

+ https://www.youtube.com/watch?v=QnfwblMrBd4&pp=ygUId2lyZW1vY2s%3D + +

Response templating - how to create mock APIs that return dynamic responses in WireMock Cloud

+ https://www.youtube.com/watch?v=A-LWoewCJN4&pp=ygUId2lyZW1vY2s%3D + +

Stub External APIs with WireMock and Spring Boot

+ https://www.youtube.com/watch?v=dx-69FrfZrw&pp=ygUId2lyZW1vY2s%3D + +

REST APIs for your tests with WIreMock (Russian)

+ https://www.youtube.com/watch?v=bDKMvb3RUTg&pp=ygUId2lyZW1vY2s%3D +
From 5a82c11227a927c56be969bbe908c3259b7688d3 Mon Sep 17 00:00:00 2001 From: Tom Akehurst Date: Sat, 6 Jul 2024 10:35:30 +0100 Subject: [PATCH 099/152] Switched to redocly CLI for bundling OpenAPI, updated redoc, imported newest WireMock OpenAPI --- assets/js/redoc.standalone.js | 1946 ++++- assets/js/wiremock-admin-api.json | 6617 ++++------------ package.json | 10 +- swagger/examples/record-spec.yaml | 2 +- swagger/schemas/absent-pattern.yaml | 8 + swagger/schemas/after-pattern.yaml | 14 + swagger/schemas/and-pattern.yaml | 10 + swagger/schemas/bad-request-entity.yaml | 16 + swagger/schemas/base64-string.yaml | 4 + swagger/schemas/before-pattern.yaml | 14 + swagger/schemas/binary-equal-to-pattern.yaml | 7 + swagger/schemas/contains-pattern.yaml | 7 + swagger/schemas/content-pattern.yaml | 89 +- swagger/schemas/date-time-elements.yaml | 21 + swagger/schemas/delay-distribution.yaml | 28 +- swagger/schemas/does-not-contain-pattern.yaml | 7 + swagger/schemas/does-not-match-pattern.yaml | 7 + .../schemas/equal-to-date-time-pattern.yaml | 14 + swagger/schemas/equal-to-json-pattern.yaml | 14 + swagger/schemas/equal-to-pattern.yaml | 9 + swagger/schemas/equal-to-xml-pattern.yaml | 17 + .../has-exactly-multivalue-pattern.yaml | 10 + .../schemas/includes-multivalue-pattern.yaml | 10 + .../schemas/matches-json-path-pattern.yaml | 20 + .../schemas/matches-json-schema-pattern.yaml | 25 + swagger/schemas/matches-pattern.yaml | 7 + swagger/schemas/matches-xpath-pattern.yaml | 25 + swagger/schemas/not-pattern.yaml | 7 + swagger/schemas/or-pattern.yaml | 10 + swagger/schemas/request-pattern.yaml | 69 +- swagger/schemas/response-definition.yaml | 34 +- swagger/wiremock-admin-api.json | 6669 +++++++++++++++++ swagger/wiremock-admin-api.yaml | 11 +- yarn.lock | 2299 +++--- 34 files changed, 11551 insertions(+), 6506 deletions(-) create mode 100644 swagger/schemas/absent-pattern.yaml create mode 100644 swagger/schemas/after-pattern.yaml create mode 100644 swagger/schemas/and-pattern.yaml create mode 100644 swagger/schemas/bad-request-entity.yaml create mode 100644 swagger/schemas/base64-string.yaml create mode 100644 swagger/schemas/before-pattern.yaml create mode 100644 swagger/schemas/binary-equal-to-pattern.yaml create mode 100644 swagger/schemas/contains-pattern.yaml create mode 100644 swagger/schemas/date-time-elements.yaml create mode 100644 swagger/schemas/does-not-contain-pattern.yaml create mode 100644 swagger/schemas/does-not-match-pattern.yaml create mode 100644 swagger/schemas/equal-to-date-time-pattern.yaml create mode 100644 swagger/schemas/equal-to-json-pattern.yaml create mode 100644 swagger/schemas/equal-to-pattern.yaml create mode 100644 swagger/schemas/equal-to-xml-pattern.yaml create mode 100644 swagger/schemas/has-exactly-multivalue-pattern.yaml create mode 100644 swagger/schemas/includes-multivalue-pattern.yaml create mode 100644 swagger/schemas/matches-json-path-pattern.yaml create mode 100644 swagger/schemas/matches-json-schema-pattern.yaml create mode 100644 swagger/schemas/matches-pattern.yaml create mode 100644 swagger/schemas/matches-xpath-pattern.yaml create mode 100644 swagger/schemas/not-pattern.yaml create mode 100644 swagger/schemas/or-pattern.yaml create mode 100644 swagger/wiremock-admin-api.json diff --git a/assets/js/redoc.standalone.js b/assets/js/redoc.standalone.js index 7fa12786..a66ab517 100644 --- a/assets/js/redoc.standalone.js +++ b/assets/js/redoc.standalone.js @@ -1,122 +1,1826 @@ -/*! - * ReDoc - OpenAPI/Swagger-generated API Reference Documentation - * ------------------------------------------------------------- - * Version: "2.0.0-rc.18" - * Repo: https://github.com/Redocly/redoc - */ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null"),function(){try{return require("esprima")}catch(e){}}()):"function"==typeof define&&define.amd?define(["null","esprima"],t):"object"==typeof exports?exports.Redoc=t(require("null"),function(){try{return require("esprima")}catch(e){}}()):e.Redoc=t(e.null,e.esprima)}(this,(function(e,t){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=153)}([function(e,t,n){"use strict";e.exports=n(216)},function(e,t,n){"use strict";n.r(t),n.d(t,"__extends",(function(){return o})),n.d(t,"__assign",(function(){return i})),n.d(t,"__rest",(function(){return a})),n.d(t,"__decorate",(function(){return s})),n.d(t,"__param",(function(){return l})),n.d(t,"__metadata",(function(){return c})),n.d(t,"__awaiter",(function(){return u})),n.d(t,"__generator",(function(){return p})),n.d(t,"__exportStar",(function(){return f})),n.d(t,"__values",(function(){return d})),n.d(t,"__read",(function(){return h})),n.d(t,"__spread",(function(){return m})),n.d(t,"__spreadArrays",(function(){return g})),n.d(t,"__await",(function(){return y})),n.d(t,"__asyncGenerator",(function(){return v})),n.d(t,"__asyncDelegator",(function(){return b})),n.d(t,"__asyncValues",(function(){return w})),n.d(t,"__makeTemplateObject",(function(){return x})),n.d(t,"__importStar",(function(){return k})),n.d(t,"__importDefault",(function(){return _})); -/*! ***************************************************************************** -Copyright (c) Microsoft Corporation. All rights reserved. -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at http://www.apache.org/licenses/LICENSE-2.0 - -THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -MERCHANTABLITY OR NON-INFRINGEMENT. - -See the Apache Version 2.0 License for specific language governing permissions -and limitations under the License. -***************************************************************************** */ -var r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)};function o(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var i=function(){return(i=Object.assign||function(e){for(var t,n=1,r=arguments.length;n=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}function l(e,t){return function(n,r){t(n,r,e)}}function c(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function u(e,t,n,r){return new(n||(n=Promise))((function(o,i){function a(e){try{l(r.next(e))}catch(e){i(e)}}function s(e){try{l(r.throw(e))}catch(e){i(e)}}function l(e){e.done?o(e.value):new n((function(t){t(e.value)})).then(a,s)}l((r=r.apply(e,t||[])).next())}))}function p(e,t){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===i[0]||2===i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}}}function h(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,o,i=n.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a}function m(){for(var e=[],t=0;t1||s(e,t)}))})}function s(e,t){try{(n=o[e](t)).value instanceof y?Promise.resolve(n.value.v).then(l,c):u(i[0][2],n)}catch(e){u(i[0][3],e)}var n}function l(e){s("next",e)}function c(e){s("throw",e)}function u(e,t){e(t),i.shift(),i.length&&s(i[0][0],i[0][1])}}function b(e){var t,n;return t={},r("next"),r("throw",(function(e){throw e})),r("return"),t[Symbol.iterator]=function(){return this},t;function r(r,o){t[r]=e[r]?function(t){return(n=!n)?{value:y(e[r](t)),done:"return"===r}:o?o(t):t}:o}}function w(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,n=e[Symbol.asyncIterator];return n?n.call(e):(e=d(e),t={},r("next"),r("throw"),r("return"),t[Symbol.asyncIterator]=function(){return this},t);function r(n){t[n]=e[n]&&function(t){return new Promise((function(r,o){(function(e,t,n,r){Promise.resolve(r).then((function(t){e({value:t,done:n})}),t)})(r,o,(t=e[n](t)).done,t.value)}))}}}function x(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e}function k(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function _(e){return e&&e.__esModule?e:{default:e}}},function(e,t,n){"use strict";(function(e,r){n.d(t,"a",(function(){return an})),n.d(t,"b",(function(){return Ue})),n.d(t,"c",(function(){return ue})),n.d(t,"d",(function(){return tt})),n.d(t,"e",(function(){return se})),n.d(t,"f",(function(){return lt})),n.d(t,"g",(function(){return M})),n.d(t,"h",(function(){return ut})),n.d(t,"i",(function(){return Mt})),n.d(t,"j",(function(){return zt})),n.d(t,"k",(function(){return Kt})),n.d(t,"l",(function(){return re})),n.d(t,"m",(function(){return ht})),n.d(t,"n",(function(){return Ke})),n.d(t,"o",(function(){return mt})),n.d(t,"p",(function(){return Ee})); -/*! ***************************************************************************** -Copyright (c) Microsoft Corporation. All rights reserved. -Licensed under the Apache License, Version 2.0 (the "License"); you may not use -this file except in compliance with the License. You may obtain a copy of the -License at http://www.apache.org/licenses/LICENSE-2.0 - -THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -MERCHANTABLITY OR NON-INFRINGEMENT. - -See the Apache Version 2.0 License for specific language governing permissions -and limitations under the License. -***************************************************************************** */ -var o=function(e,t){return(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)};function i(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0)&&!(r=i.next()).done;)a.push(r.value)}catch(e){o={error:e}}finally{try{r&&!r.done&&(n=i.return)&&n.call(i)}finally{if(o)throw o.error}}return a}function l(){for(var e=[],t=0;t2&&oe("box");var n=X(t);return new de(e,K(n),n.name,!0,n.equals)},shallowBox:function(e,t){return arguments.length>2&&oe("shallowBox"),re.box(e,{name:t,deep:!1})},array:function(e,t){arguments.length>2&&oe("array");var n=X(t);return new At(e,K(n),n.name)},shallowArray:function(e,t){return arguments.length>2&&oe("shallowArray"),re.array(e,{name:t,deep:!1})},map:function(e,t){arguments.length>2&&oe("map");var n=X(t);return new Ft(e,K(n),n.name)},shallowMap:function(e,t){return arguments.length>2&&oe("shallowMap"),re.map(e,{name:t,deep:!1})},set:function(e,t){arguments.length>2&&oe("set");var n=X(t);return new $t(e,K(n),n.name)},object:function(e,t,n){"string"==typeof arguments[1]&&oe("object");var r=X(n);return ct({},e,t,r)},shallowObject:function(e,t){return"string"==typeof arguments[1]&&oe("shallowObject"),re.object(e,{},{name:t,deep:!1})},ref:ee,shallow:Z,deep:J,struct:te},re=function(e,t,n){if("string"==typeof arguments[1])return J.apply(null,arguments);if(dt(e))return e;var r=w(e)?re.object(e,t,n):Array.isArray(e)?re.array(e,t):E(e)?re.map(e,t):O(e)?re.set(e,t):e;if(r!==e)return r;m(!1)};function oe(e){m("Expected one or two arguments to observable."+e+". Did you accidentally try to use observable."+e+" as decorator?")}Object.keys(ne).forEach((function(e){return re[e]=ne[e]}));var ie=q(!1,(function(e,t,n,r,o){var i=n.get,s=n.set,l=o[0]||{};!function(e,t,n){var r=Ht(e);n.name=r.name+"."+t,n.context=e,r.values[t]=new he(n),Object.defineProperty(e,t,function(e){return Qt[e]||(Qt[e]={configurable:Ie.computedConfigurable,enumerable:!1,get:function(){return Gt(this).read(this,e)},set:function(t){Gt(this).write(this,e,t)}})}(t))}(e,t,a({get:i,set:s},l))})),ae=ie({equals:F.structural}),se=function(e,t,n){if("string"==typeof t)return ie.apply(null,arguments);if(null!==e&&"object"==typeof e&&1===arguments.length)return ie.apply(null,arguments);var r="object"==typeof t?t:{};return r.get=e,r.set="function"==typeof t?t:r.set,r.name=r.name||e.name||"",new he(r)};function le(e,t){var n=function(){return ce(e,t,this,arguments)};return n.isMobxAction=!0,n}function ce(e,t,n,r){var o=function(e,t,n){var r=Ve()&&!!e,o=0;if(r){o=Date.now();var i=n&&n.length||0,a=new Array(i);if(i>0)for(var s=0;s0;Ie.computationDepth>0&&t&&m(!1),Ie.allowStateChanges||!t&&"strict"!==Ie.enforceActions||m(!1)}function ke(e,t,n){Te(e),e.newObserving=new Array(e.observing.length+100),e.unboundDepsCount=0,e.runId=++Ie.runId;var r,o=Ie.trackingDerivation;if(Ie.trackingDerivation=e,!0===Ie.disableErrorBoundaries)r=t.call(n);else try{r=t.call(n)}catch(e){r=new ve(e)}return Ie.trackingDerivation=o,function(e){for(var t=e.observing,n=e.observing=e.newObserving,r=me.UP_TO_DATE,o=0,i=e.unboundDepsCount,a=0;ar&&(r=s.dependenciesState)}n.length=o,e.newObserving=null,i=t.length;for(;i--;){0===(s=t[i]).diffValue&&Re(s,e),s.diffValue=0}for(;o--;){var s;1===(s=n[o]).diffValue&&(s.diffValue=0,Pe(s,e))}r!==me.UP_TO_DATE&&(e.dependenciesState=r,e.onBecomeStale())}(e),r}function _e(e){var t=e.observing;e.observing=[];for(var n=t.length;n--;)Re(t[n],e);e.dependenciesState=me.NOT_TRACKING}function Ee(e){var t=Oe(),n=e();return Se(t),n}function Oe(){var e=Ie.trackingDerivation;return Ie.trackingDerivation=null,e}function Se(e){Ie.trackingDerivation=e}function Te(e){if(e.dependenciesState!==me.UP_TO_DATE){e.dependenciesState=me.UP_TO_DATE;for(var t=e.observing,n=t.length;n--;)t[n].lowestObserverState=me.UP_TO_DATE}}var je=function(){this.version=5,this.UNCHANGED={},this.trackingDerivation=null,this.computationDepth=0,this.runId=0,this.mobxGuid=0,this.inBatch=0,this.pendingUnobservations=[],this.pendingReactions=[],this.isRunningReactions=!1,this.allowStateChanges=!0,this.enforceActions=!1,this.spyListeners=[],this.globalReactionErrorHandlers=[],this.computedRequiresReaction=!1,this.computedConfigurable=!1,this.disableErrorBoundaries=!1,this.suppressReactionErrors=!1,this.currentActionId=0,this.nextActionId=1},Ce=!0,Ae=!1,Ie=function(){var e=d();return e.__mobxInstanceCount>0&&!e.__mobxGlobals&&(Ce=!1),e.__mobxGlobals&&e.__mobxGlobals.version!==(new je).version&&(Ce=!1),Ce?e.__mobxGlobals?(e.__mobxInstanceCount+=1,e.__mobxGlobals.UNCHANGED||(e.__mobxGlobals.UNCHANGED={}),e.__mobxGlobals):(e.__mobxInstanceCount=1,e.__mobxGlobals=new je):(setTimeout((function(){Ae||m("There are multiple, different versions of MobX active. Make sure MobX is loaded only once or use `configure({ isolateGlobalState: true })`")}),1),new je)}();function Pe(e,t){var n=e.observers.length;n&&(e.observersIndexes[t.__mapid]=n),e.observers[n]=t,e.lowestObserverState>t.dependenciesState&&(e.lowestObserverState=t.dependenciesState)}function Re(e,t){if(1===e.observers.length)e.observers.length=0,Ne(e);else{var n=e.observers,r=e.observersIndexes,o=n.pop();if(o!==t){var i=r[t.__mapid]||0;i?r[o.__mapid]=i:delete r[o.__mapid],n[i]=o}delete r[t.__mapid]}}function Ne(e){!1===e.isPendingUnobservation&&(e.isPendingUnobservation=!0,Ie.pendingUnobservations.push(e))}function Le(){Ie.inBatch++}function Me(){if(0==--Ie.inBatch){$e();for(var e=Ie.pendingUnobservations,t=0;t0&&Ne(e),!1)}function Fe(e,t){if(console.log("[mobx.trace] '"+e.name+"' is invalidated due to a change in: '"+t.name+"'"),e.isTracing===ge.BREAK){var n=[];!function e(t,n,r){if(n.length>=1e3)return void n.push("(and many more)");n.push(""+new Array(r).join("\t")+t.name);t.dependencies&&t.dependencies.forEach((function(t){return e(t,n,r+1)}))}(ut(e),n,1),new Function("debugger;\n/*\nTracing '"+e.name+"'\n\nYou are entering this break point because derivation '"+e.name+"' is being traced and '"+t.name+"' is now forcing it to update.\nJust follow the stacktrace you should now see in the devtools to see precisely what piece of your code is causing this update\nThe stackframe you are looking for is at least ~6-8 stack-frames up.\n\n"+(e instanceof he?e.derivation.toString().replace(/[*]\//g,"/"):"")+"\n\nThe dependencies for this derivation are:\n\n"+n.join("\n")+"\n*/\n ")()}}var Ue=function(){function e(e,t,n){void 0===e&&(e="Reaction@"+h()),this.name=e,this.onInvalidate=t,this.errorHandler=n,this.observing=[],this.newObserving=[],this.dependenciesState=me.NOT_TRACKING,this.diffValue=0,this.runId=0,this.unboundDepsCount=0,this.__mapid="#"+h(),this.isDisposed=!1,this._isScheduled=!1,this._isTrackPending=!1,this._isRunning=!1,this.isTracing=ge.NONE}return e.prototype.onBecomeStale=function(){this.schedule()},e.prototype.schedule=function(){this._isScheduled||(this._isScheduled=!0,Ie.pendingReactions.push(this),$e())},e.prototype.isScheduled=function(){return this._isScheduled},e.prototype.runReaction=function(){if(!this.isDisposed){if(Le(),this._isScheduled=!1,we(this)){this._isTrackPending=!0;try{this.onInvalidate(),this._isTrackPending&&Ve()&&Ye({name:this.name,type:"scheduled-reaction"})}catch(e){this.reportExceptionInDerivation(e)}}Me()}},e.prototype.track=function(e){Le();var t,n=Ve();n&&(t=Date.now(),Qe({name:this.name,type:"reaction"})),this._isRunning=!0;var r=ke(this,e,void 0);this._isRunning=!1,this._isTrackPending=!1,this.isDisposed&&_e(this),be(r)&&this.reportExceptionInDerivation(r.cause),n&&Xe({time:Date.now()-t}),Me()},e.prototype.reportExceptionInDerivation=function(e){var t=this;if(this.errorHandler)this.errorHandler(e,this);else{if(Ie.disableErrorBoundaries)throw e;var n="[mobx] Encountered an uncaught exception that was thrown by a reaction or observer component, in: '"+this+"'";Ie.suppressReactionErrors?console.warn("[mobx] (error in reaction '"+this.name+"' suppressed, fix error of causing action below)"):console.error(n,e),Ve()&&Ye({type:"error",name:this.name,message:n,error:""+e}),Ie.globalReactionErrorHandlers.forEach((function(n){return n(e,t)}))}},e.prototype.dispose=function(){this.isDisposed||(this.isDisposed=!0,this._isRunning||(Le(),_e(this),Me()))},e.prototype.getDisposer=function(){var e=this.dispose.bind(this);return e.$mobx=this,e},e.prototype.toString=function(){return"Reaction["+this.name+"]"},e.prototype.trace=function(e){void 0===e&&(e=!1),function(){for(var e=[],t=0;t0||Ie.isRunningReactions||Be(qe)}function qe(){Ie.isRunningReactions=!0;for(var e=Ie.pendingReactions,t=0;e.length>0;){++t===ze&&(console.error("Reaction doesn't converge to a stable state after "+ze+" iterations. Probably there is a cycle in the reactive function: "+e[0]),e.splice(0));for(var n=e.splice(0),r=0,o=n.length;r",e):2===arguments.length&&"function"==typeof t?le(e,t):1===arguments.length&&"string"==typeof e?Ze(e):!0!==r?Ze(t).apply(null,arguments):void(e[t]=le(e.name||t,n.value))};function nt(e,t,n){x(e,t,le(t,n.bind(e)))}function rt(e,t){void 0===t&&(t=p);var n,r=t&&t.name||e.name||"Autorun@"+h();if(!t.scheduler&&!t.delay)n=new Ue(r,(function(){this.track(a)}),t.onError);else{var o=it(t),i=!1;n=new Ue(r,(function(){i||(i=!0,o((function(){i=!1,n.isDisposed||n.track(a)})))}),t.onError)}function a(){e(n)}return n.schedule(),n.getDisposer()}tt.bound=function(e,t,n,r){return!0===r?(nt(e,t,n.value),null):n?{configurable:!0,enumerable:!1,get:function(){return nt(this,t,n.value||n.initializer.call(this)),this[t]},set:Je}:{enumerable:!1,configurable:!0,set:function(e){nt(this,t,e)},get:function(){}}};var ot=function(e){return e()};function it(e){return e.scheduler?e.scheduler:e.delay?function(t){return setTimeout(t,e.delay)}:ot}function at(e,t,n){return st("onBecomeUnobserved",e,t,n)}function st(e,t,n,r){var o="function"==typeof r?Jt(t,n):Jt(t),i="function"==typeof r?r:n,a=o[e];return"function"!=typeof a?m(!1):(o[e]=function(){a.call(this),i.call(this)},function(){o[e]=a})}function lt(e){var t=e.enforceActions,n=e.computedRequiresReaction,r=e.computedConfigurable,o=e.disableErrorBoundaries,i=e.arrayBuffer,a=e.reactionScheduler;if(!0===e.isolateGlobalState&&((Ie.pendingReactions.length||Ie.inBatch||Ie.isRunningReactions)&&m("isolateGlobalState should be called before MobX is running any reactions"),Ae=!0,Ce&&(0==--d().__mobxInstanceCount&&(d().__mobxGlobals=void 0),Ie=new je)),void 0!==t){var s=void 0;switch(t){case!0:case"observed":s=!0;break;case!1:case"never":s=!1;break;case"strict":case"always":s="strict";break;default:m("Invalid value for 'enforceActions': '"+t+"', expected 'never', 'always' or 'observed'")}Ie.enforceActions=s,Ie.allowStateChanges=!0!==s&&"strict"!==s}void 0!==n&&(Ie.computedRequiresReaction=!!n),void 0!==r&&(Ie.computedConfigurable=!!r),void 0!==o&&(!0===o&&console.warn("WARNING: Debug feature only. MobX will NOT recover from errors if this is on."),Ie.disableErrorBoundaries=!!o),"number"==typeof i&&Nt(i),a&&He(a)}function ct(e,t,n,r){var o=(r=X(r)).defaultDecorator||(!1===r.deep?ee:J);$(e),Ht(e,r.name,o.enhancer),Le();try{for(var i in t){var a=Object.getOwnPropertyDescriptor(t,i);0;var s=(n&&i in n?n[i]:a.get?ie:o)(e,i,a,!0);s&&Object.defineProperty(e,i,s)}}finally{Me()}return e}function ut(e,t){return pt(Jt(e,t))}function pt(e){var t,n,r={name:e.name};return e.observing&&e.observing.length>0&&(r.dependencies=(t=e.observing,n=[],t.forEach((function(e){-1===n.indexOf(e)&&n.push(e)})),n).map(pt)),r}function ft(e,t){if(null==e)return!1;if(void 0!==t){if(Kt(e)){var n=e.$mobx;return n.values&&!!n.values[t]}return!1}return Kt(e)||!!e.$mobx||L(e)||We(e)||ye(e)}function dt(e){return 1!==arguments.length&&m(!1),ft(e)}function ht(e,t,n,r){return"function"==typeof n?function(e,t,n,r){return Zt(e,t).observe(n,r)}(e,t,n,r):function(e,t,n){return Zt(e).observe(t,n)}(e,t,n)}function mt(e,t){void 0===t&&(t=void 0),Le();try{return e.apply(t)}finally{Me()}}function gt(e){return void 0!==e.interceptors&&e.interceptors.length>0}function yt(e,t){var n=e.interceptors||(e.interceptors=[]);return n.push(t),y((function(){var e=n.indexOf(t);-1!==e&&n.splice(e,1)}))}function vt(e,t){var n=Oe();try{var r=e.interceptors;if(r)for(var o=0,i=r.length;o0}function wt(e,t){var n=e.changeListeners||(e.changeListeners=[]);return n.push(t),y((function(){var e=n.indexOf(t);-1!==e&&n.splice(e,1)}))}function xt(e,t){var n=Oe(),r=e.changeListeners;if(r){for(var o=0,i=(r=r.slice()).length;o0?e.map(this.dehancer):e},e.prototype.intercept=function(e){return yt(this,e)},e.prototype.observe=function(e,t){return void 0===t&&(t=!1),t&&e({object:this.array,type:"splice",index:0,added:this.values.slice(),addedCount:this.values.length,removed:[],removedCount:0}),wt(this,e)},e.prototype.getArrayLength=function(){return this.atom.reportObserved(),this.values.length},e.prototype.setArrayLength=function(e){if("number"!=typeof e||e<0)throw new Error("[mobx.array] Out of range: "+e);var t=this.values.length;if(e!==t)if(e>t){for(var n=new Array(e-t),r=0;r0&&e+t+1>Tt&&Nt(e+t+1)},e.prototype.spliceWithArray=function(e,t,n){var r=this;xe(this.atom);var o=this.values.length;if(void 0===e?e=0:e>o?e=o:e<0&&(e=Math.max(0,o+e)),t=1===arguments.length?o-e:null==t?0:Math.max(0,Math.min(t,o-e)),void 0===n&&(n=u),gt(this)){var i=vt(this,{object:this.array,type:"splice",index:e,removedCount:t,added:n});if(!i)return u;t=i.removedCount,n=i.added}var a=(n=0===n.length?n:n.map((function(e){return r.enhancer(e,void 0)}))).length-t;this.updateArrayLength(o,a);var s=this.spliceItemsIntoValues(e,t,n);return 0===t&&0===n.length||this.notifyArraySplice(e,n,s),this.dehanceValues(s)},e.prototype.spliceItemsIntoValues=function(e,t,n){var r;if(n.length<1e4)return(r=this.values).splice.apply(r,l([e,t],n));var o=this.values.slice(e,e+t);return this.values=this.values.slice(0,e).concat(n,this.values.slice(e+t)),o},e.prototype.notifyArrayChildUpdate=function(e,t,n){var r=!this.owned&&Ve(),o=bt(this),i=o||r?{object:this.array,type:"update",index:e,newValue:t,oldValue:n}:null;r&&Qe(a({},i,{name:this.atom.name})),this.atom.reportChanged(),o&&xt(this,i),r&&Xe()},e.prototype.notifyArraySplice=function(e,t,n){var r=!this.owned&&Ve(),o=bt(this),i=o||r?{object:this.array,type:"splice",index:e,removed:n,added:t,removedCount:n.length,addedCount:t.length}:null;r&&Qe(a({},i,{name:this.atom.name})),this.atom.reportChanged(),o&&xt(this,i),r&&Xe()},e}(),At=function(e){function t(t,n,r,o){void 0===r&&(r="ObservableArray@"+h()),void 0===o&&(o=!1);var i=e.call(this)||this,a=new Ct(r,n,i,o);if(k(i,"$mobx",a),t&&t.length){var s=pe(!0);i.spliceWithArray(0,0,t),fe(s)}return St&&Object.defineProperty(a.array,"0",It),i}return i(t,e),t.prototype.intercept=function(e){return this.$mobx.intercept(e)},t.prototype.observe=function(e,t){return void 0===t&&(t=!1),this.$mobx.observe(e,t)},t.prototype.clear=function(){return this.splice(0)},t.prototype.concat=function(){for(var e=[],t=0;t-1&&(this.splice(t,1),!0)},t.prototype.move=function(e,t){function n(e){if(e<0)throw new Error("[mobx.array] Index out of bounds: "+e+" is negative");var t=this.$mobx.values.length;if(e>=t)throw new Error("[mobx.array] Index out of bounds: "+e+" is not smaller than "+t)}if(n.call(this,e),n.call(this,t),e!==t){var r,o=this.$mobx.values;r=e",'"',"`"," ","\r","\n","\t"]),u=["'"].concat(c),p=["%","/","?",";","#"].concat(u),f=["/","?","#"],d=/^[+a-z0-9A-Z_-]{0,63}$/,h=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,m={javascript:!0,"javascript:":!0},g={javascript:!0,"javascript:":!0},y={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},v=n(225);function b(e,t,n){if(e&&o.isObject(e)&&e instanceof i)return e;var r=new i;return r.parse(e,t,n),r}i.prototype.parse=function(e,t,n){if(!o.isString(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var i=e.indexOf("?"),s=-1!==i&&i127?R+="x":R+=P[N];if(!R.match(d)){var M=A.slice(0,T),D=A.slice(T+1),F=P.match(h);F&&(M.push(F[1]),D.unshift(F[2])),D.length&&(b="/"+D.join(".")+b),this.hostname=M.join(".");break}}}this.hostname.length>255?this.hostname="":this.hostname=this.hostname.toLowerCase(),C||(this.hostname=r.toASCII(this.hostname));var U=this.port?":"+this.port:"",z=this.hostname||"";this.host=z+U,this.href+=this.host,C&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==b[0]&&(b="/"+b))}if(!m[k])for(T=0,I=u.length;T0)&&n.host.split("@"))&&(n.auth=C.shift(),n.host=n.hostname=C.shift());return n.search=e.search,n.query=e.query,o.isNull(n.pathname)&&o.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.href=n.format(),n}if(!_.length)return n.pathname=null,n.search?n.path="/"+n.search:n.path=null,n.href=n.format(),n;for(var O=_.slice(-1)[0],S=(n.host||e.host||_.length>1)&&("."===O||".."===O)||""===O,T=0,j=_.length;j>=0;j--)"."===(O=_[j])?_.splice(j,1):".."===O?(_.splice(j,1),T++):T&&(_.splice(j,1),T--);if(!x&&!k)for(;T--;T)_.unshift("..");!x||""===_[0]||_[0]&&"/"===_[0].charAt(0)||_.unshift(""),S&&"/"!==_.join("/").substr(-1)&&_.push("");var C,A=""===_[0]||_[0]&&"/"===_[0].charAt(0);E&&(n.hostname=n.host=A?"":_.length?_.shift():"",(C=!!(n.host&&n.host.indexOf("@")>0)&&n.host.split("@"))&&(n.auth=C.shift(),n.host=n.hostname=C.shift()));return(x=x||n.host&&_.length)&&!A&&_.unshift(""),_.length?n.pathname=_.join("/"):(n.pathname=null,n.path=null),o.isNull(n.pathname)&&o.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.auth=e.auth||n.auth,n.slashes=n.slashes||e.slashes,n.href=n.format(),n},i.prototype.parseHost=function(){var e=this.host,t=s.exec(e);t&&(":"!==(t=t[0])&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)}},function(e,t,n){var r=n(25),o=n(13),i=n(121),a=n(15).f;e.exports=function(e){var t=r.Symbol||(r.Symbol={});o(t,e)||a(t,e,{value:i.f(e)})}},function(e,t,n){"use strict";(function(e){ -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh - * @license MIT - */ -var r=n(229),o=n(230),i=n(123);function a(){return l.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function s(e,t){if(a()=a())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a().toString(16)+" bytes");return 0|e}function h(e,t){if(l.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return B(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return $(e).length;default:if(r)return B(e).length;t=(""+t).toLowerCase(),r=!0}}function m(e,t,n){var r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return A(this,t,n);case"utf8":case"utf-8":return S(this,t,n);case"ascii":return j(this,t,n);case"latin1":case"binary":return C(this,t,n);case"base64":return O(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return I(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}function g(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function y(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=l.from(t,r)),l.isBuffer(t))return 0===t.length?-1:v(e,t,n,r,o);if("number"==typeof t)return t&=255,l.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):v(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function v(e,t,n,r,o){var i,a=1,s=e.length,l=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;a=2,s/=2,l/=2,n/=2}function c(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}if(o){var u=-1;for(i=n;is&&(n=s-l),i=n;i>=0;i--){for(var p=!0,f=0;fo&&(r=o):r=o;var i=t.length;if(i%2!=0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var a=0;a>8,o=n%256,i.push(o),i.push(r);return i}(t,e.length-n),e,n,r)}function O(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function S(e,t,n){n=Math.min(e.length,n);for(var r=[],o=t;o239?4:c>223?3:c>191?2:1;if(o+p<=n)switch(p){case 1:c<128&&(u=c);break;case 2:128==(192&(i=e[o+1]))&&(l=(31&c)<<6|63&i)>127&&(u=l);break;case 3:i=e[o+1],a=e[o+2],128==(192&i)&&128==(192&a)&&(l=(15&c)<<12|(63&i)<<6|63&a)>2047&&(l<55296||l>57343)&&(u=l);break;case 4:i=e[o+1],a=e[o+2],s=e[o+3],128==(192&i)&&128==(192&a)&&128==(192&s)&&(l=(15&c)<<18|(63&i)<<12|(63&a)<<6|63&s)>65535&&l<1114112&&(u=l)}null===u?(u=65533,p=1):u>65535&&(u-=65536,r.push(u>>>10&1023|55296),u=56320|1023&u),r.push(u),o+=p}return function(e){var t=e.length;if(t<=T)return String.fromCharCode.apply(String,e);var n="",r=0;for(;r0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),""},l.prototype.compare=function(e,t,n,r,o){if(!l.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),t<0||n>e.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&t>=n)return 0;if(r>=o)return-1;if(t>=n)return 1;if(this===e)return 0;for(var i=(o>>>=0)-(r>>>=0),a=(n>>>=0)-(t>>>=0),s=Math.min(i,a),c=this.slice(r,o),u=e.slice(t,n),p=0;po)&&(n=o),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return b(this,e,t,n);case"utf8":case"utf-8":return w(this,e,t,n);case"ascii":return x(this,e,t,n);case"latin1":case"binary":return k(this,e,t,n);case"base64":return _(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return E(this,e,t,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},l.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var T=4096;function j(e,t,n){var r="";n=Math.min(e.length,n);for(var o=t;or)&&(n=r);for(var o="",i=t;in)throw new RangeError("Trying to access beyond buffer length")}function R(e,t,n,r,o,i){if(!l.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||te.length)throw new RangeError("Index out of range")}function N(e,t,n,r){t<0&&(t=65535+t+1);for(var o=0,i=Math.min(e.length-n,2);o>>8*(r?o:1-o)}function L(e,t,n,r){t<0&&(t=4294967295+t+1);for(var o=0,i=Math.min(e.length-n,4);o>>8*(r?o:3-o)&255}function M(e,t,n,r,o,i){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function D(e,t,n,r,i){return i||M(e,0,n,4),o.write(e,t,n,r,23,4),n+4}function F(e,t,n,r,i){return i||M(e,0,n,8),o.write(e,t,n,r,52,8),n+8}l.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t0&&(o*=256);)r+=this[e+--t]*o;return r},l.prototype.readUInt8=function(e,t){return t||P(e,1,this.length),this[e]},l.prototype.readUInt16LE=function(e,t){return t||P(e,2,this.length),this[e]|this[e+1]<<8},l.prototype.readUInt16BE=function(e,t){return t||P(e,2,this.length),this[e]<<8|this[e+1]},l.prototype.readUInt32LE=function(e,t){return t||P(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},l.prototype.readUInt32BE=function(e,t){return t||P(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},l.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||P(e,t,this.length);for(var r=this[e],o=1,i=0;++i=(o*=128)&&(r-=Math.pow(2,8*t)),r},l.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||P(e,t,this.length);for(var r=t,o=1,i=this[e+--r];r>0&&(o*=256);)i+=this[e+--r]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*t)),i},l.prototype.readInt8=function(e,t){return t||P(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},l.prototype.readInt16LE=function(e,t){t||P(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},l.prototype.readInt16BE=function(e,t){t||P(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},l.prototype.readInt32LE=function(e,t){return t||P(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},l.prototype.readInt32BE=function(e,t){return t||P(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},l.prototype.readFloatLE=function(e,t){return t||P(e,4,this.length),o.read(this,e,!0,23,4)},l.prototype.readFloatBE=function(e,t){return t||P(e,4,this.length),o.read(this,e,!1,23,4)},l.prototype.readDoubleLE=function(e,t){return t||P(e,8,this.length),o.read(this,e,!0,52,8)},l.prototype.readDoubleBE=function(e,t){return t||P(e,8,this.length),o.read(this,e,!1,52,8)},l.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||R(this,e,t,n,Math.pow(2,8*n)-1,0);var o=1,i=0;for(this[t]=255&e;++i=0&&(i*=256);)this[t+o]=e/i&255;return t+n},l.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,1,255,0),l.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},l.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,2,65535,0),l.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):N(this,e,t,!0),t+2},l.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,2,65535,0),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):N(this,e,t,!1),t+2},l.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,4,4294967295,0),l.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):L(this,e,t,!0),t+4},l.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,4,4294967295,0),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):L(this,e,t,!1),t+4},l.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);R(this,e,t,n,o-1,-o)}var i=0,a=1,s=0;for(this[t]=255&e;++i>0)-s&255;return t+n},l.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var o=Math.pow(2,8*n-1);R(this,e,t,n,o-1,-o)}var i=n-1,a=1,s=0;for(this[t+i]=255&e;--i>=0&&(a*=256);)e<0&&0===s&&0!==this[t+i+1]&&(s=1),this[t+i]=(e/a>>0)-s&255;return t+n},l.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,1,127,-128),l.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},l.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,2,32767,-32768),l.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):N(this,e,t,!0),t+2},l.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,2,32767,-32768),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):N(this,e,t,!1),t+2},l.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,4,2147483647,-2147483648),l.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):L(this,e,t,!0),t+4},l.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||R(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):L(this,e,t,!1),t+4},l.prototype.writeFloatLE=function(e,t,n){return D(this,e,t,!0,n)},l.prototype.writeFloatBE=function(e,t,n){return D(this,e,t,!1,n)},l.prototype.writeDoubleLE=function(e,t,n){return F(this,e,t,!0,n)},l.prototype.writeDoubleBE=function(e,t,n){return F(this,e,t,!1,n)},l.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t=0;--o)e[o+t]=this[o+n];else if(i<1e3||!l.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(i=t;i55295&&n<57344){if(!o){if(n>56319){(t-=3)>-1&&i.push(239,191,189);continue}if(a+1===r){(t-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(t-=3)>-1&&i.push(239,191,189),o=n;continue}n=65536+(o-55296<<10|n-56320)}else o&&(t-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((t-=1)<0)break;i.push(n)}else if(n<2048){if((t-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function $(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(U,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function q(e,t,n,r){for(var o=0;o=t.length||o>=e.length);++o)t[o+n]=e[o];return o}}).call(this,n(6))},function(e,t){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t){var n,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function s(e){if(n===setTimeout)return setTimeout(e,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:i}catch(e){n=i}try{r="function"==typeof clearTimeout?clearTimeout:a}catch(e){r=a}}();var l,c=[],u=!1,p=-1;function f(){u&&l&&(u=!1,l.length?c=l.concat(c):p=-1,c.length&&d())}function d(){if(!u){var e=s(f);u=!0;for(var t=c.length;t;){for(l=c,c=[];++p1)for(var n=1;n=0?e.substr(t).toLowerCase():""},t.getHash=function(e){var t=e.indexOf("#");return t>=0?e.substr(t):"#"},t.stripHash=function(e){var t=e.indexOf("#");return t>=0&&(e=e.substr(0,t)),e},t.isHttp=function(e){var t=s.getProtocol(e);return"http"===t||"https"===t||void 0===t&&r.browser},t.isFileSystemPath=function(e){if(r.browser)return!1;var t=s.getProtocol(e);return void 0===t||"file"===t},t.fromFileSystemPath=function(e){o&&(e=e.replace(/\\/g,"/")),e=encodeURI(e);for(var t=0;t0&&(p=e.exports.formatter.apply(null,s)),n&&n.message&&(p+=(p?" \n":"")+n.message);var f=new t(p);return l(f,n),c(f),u(f,r),f}}function l(e,t){!function(e,t){!function(e){if(!m)return!1;var t=Object.getOwnPropertyDescriptor(e,"stack");if(!t)return!1;return"function"==typeof t.get}(e)?e.stack=t?d(e.stack,t.stack):h(e.stack):t?function(e,t){var n=Object.getOwnPropertyDescriptor(e,"stack");Object.defineProperty(e,"stack",{get:function(){return d(n.get.apply(e),t.stack)},enumerable:!1,configurable:!0})}(e,t):(n=e,r=Object.getOwnPropertyDescriptor(n,"stack"),Object.defineProperty(n,"stack",{get:function(){return h(r.get.apply(n))},enumerable:!1,configurable:!0}));var n,r}(e,t),u(e,t)}function c(e){e.toJSON=p,e.inspect=f}function u(e,t){if(t&&"object"==typeof t)for(var n=Object.keys(t),r=0;r=0))try{e[o]=t[o]}catch(e){}}}function p(){var e={},t=Object.keys(this);t=t.concat(a);for(var n=0;n=0)return t.splice(n,1),t.join("\n")}return e}}e.exports=s(Error),e.exports.error=s(Error),e.exports.eval=s(EvalError),e.exports.range=s(RangeError),e.exports.reference=s(ReferenceError),e.exports.syntax=s(SyntaxError),e.exports.type=s(TypeError),e.exports.uri=s(URIError),e.exports.formatter=r;var m=!(!Object.getOwnPropertyDescriptor||!Object.defineProperty||"undefined"!=typeof navigator&&/Android/.test(navigator.userAgent))},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){t&&(e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}))}:e.exports=function(e,t){if(t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}}},function(e,t,n){"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE){0;try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(e){console.error(e)}}}(),e.exports=n(217)},function(e,t){e.exports=!1},function(e,t,n){var r,o,i,a=n(156),s=n(3),l=n(7),c=n(20),u=n(13),p=n(53),f=n(39),d=s.WeakMap;if(a){var h=new d,m=h.get,g=h.has,y=h.set;r=function(e,t){return y.call(h,e,t),t},o=function(e){return m.call(h,e)||{}},i=function(e){return g.call(h,e)}}else{var v=p("state");f[v]=!0,r=function(e,t){return c(e,v,t),t},o=function(e){return u(e,v)?e[v]:{}},i=function(e){return u(e,v)}}e.exports={set:r,get:o,has:i,enforce:function(e){return i(e)?o(e):r(e,{})},getterFor:function(e){return function(t){var n;if(!l(t)||(n=o(t)).type!==e)throw TypeError("Incompatible receiver, "+e+" required");return n}}}},function(e,t,n){var r=n(71),o=n(40);e.exports=function(e){return r(o(e))}},function(e,t,n){var r=n(68),o=Math.min;e.exports=function(e){return e>0?o(r(e),9007199254740991):0}},function(e,t,n){"use strict";var r=n(46),o=n(58),i=n(5);function a(e,t,n){var r=[];return e.include.forEach((function(e){n=a(e,t,n)})),e[t].forEach((function(e){n.forEach((function(t,n){t.tag===e.tag&&t.kind===e.kind&&r.push(n)})),n.push(e)})),n.filter((function(e,t){return-1===r.indexOf(t)}))}function s(e){this.include=e.include||[],this.implicit=e.implicit||[],this.explicit=e.explicit||[],this.implicit.forEach((function(e){if(e.loadKind&&"scalar"!==e.loadKind)throw new o("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.")})),this.compiledImplicit=a(this,"implicit",[]),this.compiledExplicit=a(this,"explicit",[]),this.compiledTypeMap=function(){var e,t,n={scalar:{},sequence:{},mapping:{},fallback:{}};function r(e){n[e.kind][e.tag]=n.fallback[e.tag]=e}for(e=0,t=arguments.length;ee.length)return;if(!(x instanceof o)){if(m&&b!=t.length-1){if(f.lastIndex=w,!(T=f.exec(e)))break;for(var k=T.index+(h?T[1].length:0),_=T.index+T[0].length,E=b,O=w,S=t.length;E=(O+=t[E].length)&&(++b,w=O);if(t[b]instanceof o)continue;j=E-b,x=e.slice(w,O),T.index-=w}else{f.lastIndex=0;var T=f.exec(x),j=1}if(T){h&&(g=T[1]?T[1].length:0);_=(k=T.index+g)+(T=T[0].slice(g)).length;var C=x.slice(0,k),A=x.slice(_),I=[b,j];C&&(++b,w+=C.length,I.push(C));var P=new o(c,d?r.tokenize(T,d):T,y,T,m);if(I.push(P),A&&I.push(A),Array.prototype.splice.apply(t,I),1!=j&&r.matchGrammar(e,t,n,b,w,!0,c),s)break}else if(s)break}}}}},tokenize:function(e,t){var n=[e],o=t.rest;if(o){for(var i in o)t[i]=o[i];delete t.rest}return r.matchGrammar(e,n,t,0,0,!1),n},hooks:{all:{},add:function(e,t){var n=r.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=r.hooks.all[e];if(n&&n.length)for(var o,i=0;o=n[i++];)o(t)}},Token:o};function o(e,t,n,r,o){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length,this.greedy=!!o}if(e.Prism=r,o.stringify=function(e,t){if("string"==typeof e)return e;if(Array.isArray(e))return e.map((function(e){return o.stringify(e,t)})).join("");var n={type:e.type,content:o.stringify(e.content,t),tag:"span",classes:["token",e.type],attributes:{},language:t};if(e.alias){var i=Array.isArray(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(n.classes,i)}r.hooks.run("wrap",n);var a=Object.keys(n.attributes).map((function(e){return e+'="'+(n.attributes[e]||"").replace(/"/g,""")+'"'})).join(" ");return"<"+n.tag+' class="'+n.classes.join(" ")+'"'+(a?" "+a:"")+">"+n.content+""},!e.document)return e.addEventListener?(r.disableWorkerMessageHandler||e.addEventListener("message",(function(t){var n=JSON.parse(t.data),o=n.language,i=n.code,a=n.immediateClose;e.postMessage(r.highlight(i,r.languages[o],o)),a&&e.close()}),!1),r):r;var i=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return i&&(r.filename=i.src,r.manual||i.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(r.highlightAll):window.setTimeout(r.highlightAll,16):document.addEventListener("DOMContentLoaded",r.highlightAll))),r}("undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{});e.exports&&(e.exports=n),void 0!==t&&(t.Prism=n),n.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},n.languages.markup.tag.inside["attr-value"].inside.entity=n.languages.markup.entity,n.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(n.languages.markup.tag,"addInlined",{value:function(e,t){var r={};r["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:n.languages[t]},r.cdata=/^$/i;var o={"included-cdata":{pattern://i,inside:r}};o["language-"+t]={pattern:/[\s\S]+/,inside:n.languages[t]};var i={};i[e]={pattern:RegExp(/(<__[\s\S]*?>)(?:\s*|[\s\S])*?(?=<\/__>)/.source.replace(/__/g,e),"i"),lookbehind:!0,greedy:!0,inside:o},n.languages.insertBefore("markup","cdata",i)}}),n.languages.xml=n.languages.extend("markup",{}),n.languages.html=n.languages.markup,n.languages.mathml=n.languages.markup,n.languages.svg=n.languages.markup,function(e){var t=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,inside:{rule:/@[\w-]+/}},url:{pattern:RegExp("url\\((?:"+t.source+"|[^\n\r()]*)\\)","i"),inside:{function:/^url/i,punctuation:/^\(|\)$/}},selector:RegExp("[^{}\\s](?:[^{};\"']|"+t.source+")*?(?=\\s*\\{)"),string:{pattern:t,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),e.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:n.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:e.languages.css}},alias:"language-css"}},n.tag))}(n),n.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/},n.languages.javascript=n.languages.extend("clike",{"class-name":[n.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},{pattern:/(^|[^.])\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,function:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),n.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,n.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=\s*($|[\r\n,.;})\]]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,lookbehind:!0,inside:n.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,inside:n.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,lookbehind:!0,inside:n.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,lookbehind:!0,inside:n.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),n.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:n.languages.javascript}},string:/[\s\S]+/}}}),n.languages.markup&&n.languages.markup.tag.addInlined("script","javascript"),n.languages.js=n.languages.javascript,"undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector&&(self.Prism.fileHighlight=function(e){e=e||document;var t={js:"javascript",py:"python",rb:"ruby",ps1:"powershell",psm1:"powershell",sh:"bash",bat:"batch",h:"c",tex:"latex"};Array.prototype.slice.call(e.querySelectorAll("pre[data-src]")).forEach((function(e){if(!e.hasAttribute("data-src-loaded")){for(var r,o=e.getAttribute("data-src"),i=e,a=/\blang(?:uage)?-([\w-]+)\b/i;i&&!a.test(i.className);)i=i.parentNode;if(i&&(r=(e.className.match(a)||[,""])[1]),!r){var s=(o.match(/\.(\w+)$/)||[,""])[1];r=t[s]||s}var l=document.createElement("code");l.className="language-"+r,e.textContent="",l.textContent="Loading…",e.appendChild(l);var c=new XMLHttpRequest;c.open("GET",o,!0),c.onreadystatechange=function(){4==c.readyState&&(c.status<400&&c.responseText?(l.textContent=c.responseText,n.highlightElement(l),e.setAttribute("data-src-loaded","")):c.status>=400?l.textContent="✖ Error "+c.status+" while fetching file: "+c.statusText:l.textContent="✖ Error: File does not exist or is empty")},c.send(null)}})),n.plugins.toolbar&&n.plugins.toolbar.registerButton("download-file",(function(e){var t=e.element.parentNode;if(t&&/pre/i.test(t.nodeName)&&t.hasAttribute("data-src")&&t.hasAttribute("data-download-link")){var n=t.getAttribute("data-src"),r=document.createElement("a");return r.textContent=t.getAttribute("data-download-link-label")||"Download",r.setAttribute("download",""),r.href=n,r}}))},document.addEventListener("DOMContentLoaded",(function(){self.Prism.fileHighlight()})))}).call(this,n(6))},function(e,t,n){var r=n(3),o=n(66),i=n(30),a=r["__core-js_shared__"]||o("__core-js_shared__",{});(e.exports=function(e,t){return a[e]||(a[e]=void 0!==t?t:{})})("versions",[]).push({version:"3.2.1",mode:i?"pure":"global",copyright:"© 2019 Denis Pushkarev (zloirock.ru)"})},function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t){e.exports={}},function(e,t){e.exports=function(e){if(null==e)throw TypeError("Can't call method on "+e);return e}},function(e,t,n){var r=n(25),o=n(3),i=function(e){return"function"==typeof e?e:void 0};e.exports=function(e,t){return arguments.length<2?i(r[e])||i(o[e]):r[e]&&r[e][t]||o[e]&&o[e][t]}},function(e,t,n){var r=n(40);e.exports=function(e){return Object(r(e))}},function(e,t){e.exports={}},function(e,t){e.exports=function(e){if("function"!=typeof e)throw TypeError(String(e)+" is not a function");return e}},function(e,t,n){var r=n(44);e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 0:return function(){return e.call(t)};case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,o){return e.call(t,n,r,o)}}return function(){return e.apply(t,arguments)}}},function(e,t,n){"use strict";function r(e){return null==e}e.exports.isNothing=r,e.exports.isObject=function(e){return"object"==typeof e&&null!==e},e.exports.toArray=function(e){return Array.isArray(e)?e:r(e)?[]:[e]},e.exports.repeat=function(e,t){var n,r="";for(n=0;n=0;r--){var o=e[r];"."===o?e.splice(r,1):".."===o?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift("..");return e}function r(e,t){if(e.filter)return e.filter(t);for(var n=[],r=0;r=-1&&!o;i--){var a=i>=0?arguments[i]:e.cwd();if("string"!=typeof a)throw new TypeError("Arguments to path.resolve must be strings");a&&(t=a+"/"+t,o="/"===a.charAt(0))}return(o?"/":"")+(t=n(r(t.split("/"),(function(e){return!!e})),!o).join("/"))||"."},t.normalize=function(e){var i=t.isAbsolute(e),a="/"===o(e,-1);return(e=n(r(e.split("/"),(function(e){return!!e})),!i).join("/"))||i||(e="."),e&&a&&(e+="/"),(i?"/":"")+e},t.isAbsolute=function(e){return"/"===e.charAt(0)},t.join=function(){var e=Array.prototype.slice.call(arguments,0);return t.normalize(r(e,(function(e,t){if("string"!=typeof e)throw new TypeError("Arguments to path.join must be strings");return e})).join("/"))},t.relative=function(e,n){function r(e){for(var t=0;t=0&&""===e[n];n--);return t>n?[]:e.slice(t,n-t+1)}e=t.resolve(e).substr(1),n=t.resolve(n).substr(1);for(var o=r(e.split("/")),i=r(n.split("/")),a=Math.min(o.length,i.length),s=a,l=0;l=1;--i)if(47===(t=e.charCodeAt(i))){if(!o){r=i;break}}else o=!1;return-1===r?n?"/":".":n&&1===r?"/":e.slice(0,r)},t.basename=function(e,t){var n=function(e){"string"!=typeof e&&(e+="");var t,n=0,r=-1,o=!0;for(t=e.length-1;t>=0;--t)if(47===e.charCodeAt(t)){if(!o){n=t+1;break}}else-1===r&&(o=!1,r=t+1);return-1===r?"":e.slice(n,r)}(e);return t&&n.substr(-1*t.length)===t&&(n=n.substr(0,n.length-t.length)),n},t.extname=function(e){"string"!=typeof e&&(e+="");for(var t=-1,n=0,r=-1,o=!0,i=0,a=e.length-1;a>=0;--a){var s=e.charCodeAt(a);if(47!==s)-1===r&&(o=!1,r=a+1),46===s?-1===t?t=a:1!==i&&(i=1):-1!==t&&(i=-1);else if(!o){n=a+1;break}}return-1===t||-1===r||0===i||1===i&&t===r-1&&t===n+1?"":e.slice(t,r)};var o="b"==="ab".substr(-1)?function(e,t,n){return e.substr(t,n)}:function(e,t,n){return t<0&&(t=e.length+t),e.substr(t,n)}}).call(this,n(12))},function(e,t,n){var r,o,i;o=[t],void 0===(i="function"==typeof(r=function(e){"use strict";e.__esModule=!0;var t={},n=Object.prototype.hasOwnProperty,r=function(e){var r=arguments.length<=1||void 0===arguments[1]?t:arguments[1],o=r.cache||{};return function(){for(var t=arguments.length,i=Array(t),a=0;a2?r:e).apply(void 0,o)}}e.memoize=a,e.debounce=s,e.bind=l,e.default={memoize:a,debounce:s,bind:l}})?r.apply(t,o):r)||(e.exports=i)},function(e,t,n){(function(t){!function(t){"use strict";var n={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:/^ {0,3}(`{3,}|~{3,})([^`~\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading:/^ {0,3}(#{1,6}) +([^\n]*?)(?: +#+)? *(?:\n+|$)/,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:"^ {0,3}(?:<(script|pre|style)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?\\?>\\n*|\\n*|\\n*|)[\\s\\S]*?(?:\\n{2,}|$)|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$))",def:/^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,nptable:g,table:g,lheading:/^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,_paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html)[^\n]+)*)/,text:/^[^\n]+/};function r(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||k.defaults,this.rules=n.normal,this.options.pedantic?this.rules=n.pedantic:this.options.gfm&&(this.rules=n.gfm)}n._label=/(?!\s*\])(?:\\[\[\]]|[^\[\]])+/,n._title=/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/,n.def=f(n.def).replace("label",n._label).replace("title",n._title).getRegex(),n.bullet=/(?:[*+-]|\d{1,9}\.)/,n.item=/^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/,n.item=f(n.item,"gm").replace(/bull/g,n.bullet).getRegex(),n.list=f(n.list).replace(/bull/g,n.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+n.def.source+")").getRegex(),n._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",n._comment=//,n.html=f(n.html,"i").replace("comment",n._comment).replace("tag",n._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),n.paragraph=f(n._paragraph).replace("hr",n.hr).replace("heading"," {0,3}#{1,6} +").replace("|lheading","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}|~{3,})[^`\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|!--)").replace("tag",n._tag).getRegex(),n.blockquote=f(n.blockquote).replace("paragraph",n.paragraph).getRegex(),n.normal=y({},n),n.gfm=y({},n.normal,{nptable:/^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/,table:/^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/}),n.pedantic=y({},n.normal,{html:f("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",n._comment).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/,fences:g,paragraph:f(n.normal._paragraph).replace("hr",n.hr).replace("heading"," *#{1,6} *[^\n]").replace("lheading",n.lheading).replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").getRegex()}),r.rules=n,r.lex=function(e,t){return new r(t).lex(e)},r.prototype.lex=function(e){return e=e.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n"),this.token(e,!0)},r.prototype.token=function(e,t){var r,o,i,a,s,l,c,p,f,d,h,m,g,y,w,x;for(e=e.replace(/^ +$/gm,"");e;)if((i=this.rules.newline.exec(e))&&(e=e.substring(i[0].length),i[0].length>1&&this.tokens.push({type:"space"})),i=this.rules.code.exec(e)){var k=this.tokens[this.tokens.length-1];e=e.substring(i[0].length),k&&"paragraph"===k.type?k.text+="\n"+i[0].trimRight():(i=i[0].replace(/^ {4}/gm,""),this.tokens.push({type:"code",codeBlockStyle:"indented",text:this.options.pedantic?i:b(i,"\n")}))}else if(i=this.rules.fences.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"code",lang:i[2]?i[2].trim():i[2],text:i[3]||""});else if(i=this.rules.heading.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"heading",depth:i[1].length,text:i[2]});else if((i=this.rules.nptable.exec(e))&&(l={type:"table",header:v(i[1].replace(/^ *| *\| *$/g,"")),align:i[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:i[3]?i[3].replace(/\n$/,"").split("\n"):[]}).header.length===l.align.length){for(e=e.substring(i[0].length),h=0;h ?/gm,""),this.token(i,t),this.tokens.push({type:"blockquote_end"});else if(i=this.rules.list.exec(e)){for(e=e.substring(i[0].length),c={type:"list_start",ordered:y=(a=i[2]).length>1,start:y?+a:"",loose:!1},this.tokens.push(c),p=[],r=!1,g=(i=i[0].match(this.rules.item)).length,h=0;h1?1===s.length:s.length>1||this.options.smartLists&&s!==a)&&(e=i.slice(h+1).join("\n")+e,h=g-1)),o=r||/\n\n(?!\s*$)/.test(l),h!==g-1&&(r="\n"===l.charAt(l.length-1),o||(o=r)),o&&(c.loose=!0),x=void 0,(w=/^\[[ xX]\] /.test(l))&&(x=" "!==l[1],l=l.replace(/^\[[ xX]\] +/,"")),f={type:"list_item_start",task:w,checked:x,loose:o},p.push(f),this.tokens.push(f),this.token(l,!1),this.tokens.push({type:"list_item_end"});if(c.loose)for(g=p.length,h=0;h?@\[\]\\^_`{|}~])/,autolink:/^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url:g,tag:"^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^",link:/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,reflink:/^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,nolink:/^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,strong:/^__([^\s_])__(?!_)|^\*\*([^\s*])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/,em:/^_([^\s_])_(?!_)|^\*([^\s*<\[])\*(?!\*)|^_([^\s<][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_<][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s<"][\s\S]*?[^\s\*])\*(?!\*|[^\spunctuation])|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/,code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,br:/^( {2,}|\\)\n(?!\s*$)/,del:g,text:/^(`+|[^`])(?:[\s\S]*?(?:(?=[\\?@\\[^_{|}~",o.em=f(o.em).replace(/punctuation/g,o._punctuation).getRegex(),o._escapes=/\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g,o._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/,o._email=/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/,o.autolink=f(o.autolink).replace("scheme",o._scheme).replace("email",o._email).getRegex(),o._attribute=/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/,o.tag=f(o.tag).replace("comment",n._comment).replace("attribute",o._attribute).getRegex(),o._label=/(?:\[[^\[\]]*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,o._href=/<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*/,o._title=/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/,o.link=f(o.link).replace("label",o._label).replace("href",o._href).replace("title",o._title).getRegex(),o.reflink=f(o.reflink).replace("label",o._label).getRegex(),o.normal=y({},o),o.pedantic=y({},o.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,link:f(/^!?\[(label)\]\((.*?)\)/).replace("label",o._label).getRegex(),reflink:f(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",o._label).getRegex()}),o.gfm=y({},o.normal,{escape:f(o.escape).replace("])","~|])").getRegex(),_extended_email:/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,url:/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,_backpedal:/(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del:/^~+(?=\S)([\s\S]*?\S)~+/,text:/^(`+|[^`])(?:[\s\S]*?(?:(?=[\\/i.test(a[0])&&(this.inLink=!1),!this.inRawBlock&&/^<(pre|code|kbd|script)(\s|>)/i.test(a[0])?this.inRawBlock=!0:this.inRawBlock&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(a[0])&&(this.inRawBlock=!1),e=e.substring(a[0].length),l+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(a[0]):u(a[0]):a[0];else if(a=this.rules.link.exec(e)){var c=w(a[2],"()");if(c>-1){var p=4+a[1].length+c;a[2]=a[2].substring(0,c),a[0]=a[0].substring(0,p).trim(),a[3]=""}e=e.substring(a[0].length),this.inLink=!0,r=a[2],this.options.pedantic?(t=/^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(r))?(r=t[1],o=t[3]):o="":o=a[3]?a[3].slice(1,-1):"",r=r.trim().replace(/^<([\s\S]*)>$/,"$1"),l+=this.outputLink(a,{href:i.escapes(r),title:i.escapes(o)}),this.inLink=!1}else if((a=this.rules.reflink.exec(e))||(a=this.rules.nolink.exec(e))){if(e=e.substring(a[0].length),t=(a[2]||a[1]).replace(/\s+/g," "),!(t=this.links[t.toLowerCase()])||!t.href){l+=a[0].charAt(0),e=a[0].substring(1)+e;continue}this.inLink=!0,l+=this.outputLink(a,t),this.inLink=!1}else if(a=this.rules.strong.exec(e))e=e.substring(a[0].length),l+=this.renderer.strong(this.output(a[4]||a[3]||a[2]||a[1]));else if(a=this.rules.em.exec(e))e=e.substring(a[0].length),l+=this.renderer.em(this.output(a[6]||a[5]||a[4]||a[3]||a[2]||a[1]));else if(a=this.rules.code.exec(e))e=e.substring(a[0].length),l+=this.renderer.codespan(u(a[2].trim(),!0));else if(a=this.rules.br.exec(e))e=e.substring(a[0].length),l+=this.renderer.br();else if(a=this.rules.del.exec(e))e=e.substring(a[0].length),l+=this.renderer.del(this.output(a[1]));else if(a=this.rules.autolink.exec(e))e=e.substring(a[0].length),r="@"===a[2]?"mailto:"+(n=u(this.mangle(a[1]))):n=u(a[1]),l+=this.renderer.link(r,null,n);else if(this.inLink||!(a=this.rules.url.exec(e))){if(a=this.rules.text.exec(e))e=e.substring(a[0].length),this.inRawBlock?l+=this.renderer.text(this.options.sanitize?this.options.sanitizer?this.options.sanitizer(a[0]):u(a[0]):a[0]):l+=this.renderer.text(u(this.smartypants(a[0])));else if(e)throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}else{if("@"===a[2])r="mailto:"+(n=u(a[0]));else{do{s=a[0],a[0]=this.rules._backpedal.exec(a[0])[0]}while(s!==a[0]);n=u(a[0]),r="www."===a[1]?"http://"+n:n}e=e.substring(a[0].length),l+=this.renderer.link(r,null,n)}return l},i.escapes=function(e){return e?e.replace(i.rules._escapes,"$1"):e},i.prototype.outputLink=function(e,t){var n=t.href,r=t.title?u(t.title):null;return"!"!==e[0].charAt(0)?this.renderer.link(n,r,this.output(e[1])):this.renderer.image(n,r,u(e[1]))},i.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…"):e},i.prototype.mangle=function(e){if(!this.options.mangle)return e;for(var t,n="",r=e.length,o=0;o.5&&(t="x"+t.toString(16)),n+="&#"+t+";";return n},a.prototype.code=function(e,t,n){var r=(t||"").match(/\S*/)[0];if(this.options.highlight){var o=this.options.highlight(e,r);null!=o&&o!==e&&(n=!0,e=o)}return r?'
'+(n?e:u(e,!0))+"
\n":"
"+(n?e:u(e,!0))+"
"},a.prototype.blockquote=function(e){return"
\n"+e+"
\n"},a.prototype.html=function(e){return e},a.prototype.heading=function(e,t,n,r){return this.options.headerIds?"'+e+"\n":""+e+"\n"},a.prototype.hr=function(){return this.options.xhtml?"
\n":"
\n"},a.prototype.list=function(e,t,n){var r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+"\n"},a.prototype.listitem=function(e){return"
  • "+e+"
  • \n"},a.prototype.checkbox=function(e){return" "},a.prototype.paragraph=function(e){return"

    "+e+"

    \n"},a.prototype.table=function(e,t){return t&&(t=""+t+""),"\n\n"+e+"\n"+t+"
    \n"},a.prototype.tablerow=function(e){return"\n"+e+"\n"},a.prototype.tablecell=function(e,t){var n=t.header?"th":"td";return(t.align?"<"+n+' align="'+t.align+'">':"<"+n+">")+e+"\n"},a.prototype.strong=function(e){return""+e+""},a.prototype.em=function(e){return""+e+""},a.prototype.codespan=function(e){return""+e+""},a.prototype.br=function(){return this.options.xhtml?"
    ":"
    "},a.prototype.del=function(e){return""+e+""},a.prototype.link=function(e,t,n){if(null===(e=d(this.options.sanitize,this.options.baseUrl,e)))return n;var r='"},a.prototype.image=function(e,t,n){if(null===(e=d(this.options.sanitize,this.options.baseUrl,e)))return n;var r=''+n+'":">"},a.prototype.text=function(e){return e},s.prototype.strong=s.prototype.em=s.prototype.codespan=s.prototype.del=s.prototype.text=function(e){return e},s.prototype.link=s.prototype.image=function(e,t,n){return""+n},s.prototype.br=function(){return""},l.parse=function(e,t){return new l(t).parse(e)},l.prototype.parse=function(e){this.inline=new i(e.links,this.options),this.inlineText=new i(e.links,y({},this.options,{renderer:new s})),this.tokens=e.reverse();for(var t="";this.next();)t+=this.tok();return t},l.prototype.next=function(){return this.token=this.tokens.pop(),this.token},l.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},l.prototype.parseText=function(){for(var e=this.token.text;"text"===this.peek().type;)e+="\n"+this.next().text;return this.inline.output(e)},l.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,p(this.inlineText.output(this.token.text)),this.slugger);case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var e,t,n,r,o="",i="";for(n="",e=0;e?@[\]^`{|}~]/g,"").replace(/\s/g,"-");if(this.seen.hasOwnProperty(t)){var n=t;do{this.seen[n]++,t=n+"-"+this.seen[n]}while(this.seen.hasOwnProperty(t))}return this.seen[t]=0,t},u.escapeTest=/[&<>"']/,u.escapeReplace=/[&<>"']/g,u.replacements={"&":"&","<":"<",">":">",'"':""","'":"'"},u.escapeTestNoEncode=/[<>"']|&(?!#?\w+;)/,u.escapeReplaceNoEncode=/[<>"']|&(?!#?\w+;)/g;var h={},m=/^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;function g(){}function y(e){for(var t,n,r=1;r=0&&"\\"===n[o];)r=!r;return r?"|":" |"})).split(/ \|/),r=0;if(n.length>t)n.splice(t);else for(;n.lengthAn error occurred:

    "+u(e.message+"",!0)+"
    ";throw e}}g.exec=g,k.options=k.setOptions=function(e){return y(k.defaults,e),k},k.getDefaults=function(){return{baseUrl:null,breaks:!1,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:new a,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,xhtml:!1}},k.defaults=k.getDefaults(),k.Parser=l,k.parser=l.parse,k.Renderer=a,k.TextRenderer=s,k.Lexer=r,k.lexer=r.lex,k.InlineLexer=i,k.inlineLexer=i.output,k.Slugger=c,k.parse=k,e.exports=k}(this||"undefined"!=typeof window&&window)}).call(this,n(6))},function(e,t,n){var r=n(7);e.exports=function(e,t){if(!r(e))return e;var n,o;if(t&&"function"==typeof(n=e.toString)&&!r(o=n.call(e)))return o;if("function"==typeof(n=e.valueOf)&&!r(o=n.call(e)))return o;if(!t&&"function"==typeof(n=e.toString)&&!r(o=n.call(e)))return o;throw TypeError("Can't convert object to primitive value")}},function(e,t,n){var r=n(37),o=n(54),i=r("keys");e.exports=function(e){return i[e]||(i[e]=o(e))}},function(e,t){var n=0,r=Math.random();e.exports=function(e){return"Symbol("+String(void 0===e?"":e)+")_"+(++n+r).toString(36)}},function(e,t,n){var r=n(18),o=n(70),i=n(38),a=n(32),s=n(52),l=n(13),c=n(94),u=Object.getOwnPropertyDescriptor;t.f=r?u:function(e,t){if(e=a(e),t=s(t,!0),c)try{return u(e,t)}catch(e){}if(l(e,t))return i(!o.f.call(e,t),e[t])}},function(e,t,n){var r=n(19),o=n(164),i=n(73),a=n(39),s=n(103),l=n(67),c=n(53)("IE_PROTO"),u=function(){},p=function(){var e,t=l("iframe"),n=i.length;for(t.style.display="none",s.appendChild(t),t.src=String("javascript:"),(e=t.contentWindow.document).open(),e.write("