1"use strict";(self.webpackChunkpartners=self.webpackChunkpartners||[]).push([[23138],{15680:(e,n,t)=>{t.d(n,{xA:()=>p,yg:()=>g});var a=t(96540);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function r(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?o(Object(t),!0).forEach((function(n){i(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):o(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function s(e,n){if(null==e)return{};var t,a,i=function(e,n){if(null==e)return{};var t,a,i={},o=Object.keys(e);for(a=0;a<o.length;a++)t=o[a],n.indexOf(t)>=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)t=o[a],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=a.createContext({}),c=function(e){var n=a.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):r(r({},n),e)),t},p=function(e){var n=c(e.components);return a.createElement(l.Provider,{value:n},e.children)},d="mdxType",m={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},u=a.forwardRef((function(e,n){var t=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=c(t),u=i,g=d["".concat(l,".").concat(u)]||d[u]||m[u]||o;return t?a.createElement(g,r(r({ref:n},p),{},{components:t})):a.createElement(g,r({ref:n},p))}));function g(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var o=t.length,r=new Array(o);r[0]=u;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s[d]="string"==typeof e?e:i,r[1]=s;for(var c=2;c<o;c++)r[c]=t[c];return a.createElement.apply(null,r)}return a.createElement.apply(null,t)}u.displayName="MDXCreateElement"},19365:(e,n,t)=>{t.d(n,{A:()=>r});var a=t(96540),i=t(40870);const o={tabItem:"tabItem_Ymn6"};function r(e){let{children:n,hidden:t,className:r}=e;return a.createElement("div",{role:"tabpanel",className:(0,i.A)(o.tabItem,r),hidden:t},n)}},11470:(e,n,t)=>{t.d(n,{A:()=>f});var a=t(58168),i=t(96540),o=t(40870),r=t(23104),s=t(56347),l=t(57485),c=t(31682),p=t(89466);function d(e){return function(e){var n,t;return null!=(n=null==(t=i.Children.map(e,(e=>{if(!e||(0,i.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error("Docusaurus error: Bad <Tabs> child <"+("string"==typeof e.type?e.type:e.type.name)+'>: all children of the <Tabs> component should be <TabItem>, and every <TabItem> should have a unique "value" prop.')})))?void 0:t.filter(Boolean))?n:[]}(e).map((e=>{let{props:{value:n,label:t,attributes:a,default:i}}=e;return{value:n,label:t,attributes:a,default:i}}))}function m(e){const{values:n,children:t}=e;return(0,i.useMemo)((()=>{const e=null!=n?n:d(t);return function(e){const n=(0,c.X)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error('Docusaurus error: Duplicate values "'+n.map((e=>e.value)).join(", ")+'" found in <Tabs>. Every value needs to be unique.')}(e),e}),[n,t])}function u(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function g(e){let{queryString:n=!1,groupId:t}=e;const a=(0,s.W6)(),o=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The <Tabs> component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return null!=t?t:null}({queryString:n,groupId:t});return[(0,l.aZ)(o),(0,i.useCallback)((e=>{if(!o)return;const n=new URLSearchParams(a.location.search);n.set(o,e),a.replace({...a.location,search:n.toString()})}),[o,a])]}function v(e){const{defaultValue:n,queryString:t=!1,groupId:a}=e,o=m(e),[r,s]=(0,i.useState)((()=>function(e){var n;let{defaultValue:t,tabValues:a}=e;if(0===a.length)throw new Error("Docusaurus error: the <Tabs> component requires at least one <TabItem> children component");if(t){if(!u({value:t,tabValues:a}))throw new Error('Docusaurus error: The <Tabs> has a defaultValue "'+t+'" but none of its children has the corresponding value. Available values are: '+a.map((e=>e.value)).join(", ")+". If you intend to show no default tab, use defaultValue={null} instead.");return t}const i=null!=(n=a.find((e=>e.default)))?n:a[0];if(!i)throw new Error("Unexpected error: 0 tabValues");return i.value}({defaultValue:n,tabValues:o}))),[l,c]=g({queryString:t,groupId:a}),[d,v]=function(e){let{groupId:n}=e;const t=function(e){return e?"docusaurus.tab."+e:null}(n),[a,o]=(0,p.Dv)(t);return[a,(0,i.useCallback)((e=>{t&&o.set(e)}
1),[t,o])]}({groupId:a}),b=(()=>{const e=null!=l?l:d;return u({value:e,tabValues:o})?e:null})();(0,i.useLayoutEffect)((()=>{b&&s(b)}),[b]);return{selectedValue:r,selectValue:(0,i.useCallback)((e=>{if(!u({value:e,tabValues:o}))throw new Error("Can't select invalid tab value="+e);s(e),c(e),v(e)}),[c,v,o]),tabValues:o}}var b=t(92303);const k={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};function h(e){let{className:n,block:t,selectedValue:s,selectValue:l,tabValues:c}=e;const p=[],{blockElementScrollPositionUntilNextRender:d}=(0,r.a_)(),m=e=>{const n=e.currentTarget,t=p.indexOf(n),a=c[t].value;a!==s&&(d(n),l(a))},u=e=>{var n;let t=null;switch(e.key){case"Enter":m(e);break;case"ArrowRight":{var a;const n=p.indexOf(e.currentTarget)+1;t=null!=(a=p[n])?a:p[0];break}case"ArrowLeft":{var i;const n=p.indexOf(e.currentTarget)-1;t=null!=(i=p[n])?i:p[p.length-1];break}}null==(n=t)||n.focus()};return i.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.A)("tabs",{"tabs--block":t},n)},c.map((e=>{let{value:n,label:t,attributes:r}=e;return i.createElement("li",(0,a.A)({role:"tab",tabIndex:s===n?0:-1,"aria-selected":s===n,key:n,ref:e=>p.push(e),onKeyDown:u,onClick:m},r,{className:(0,o.A)("tabs__item",k.tabItem,null==r?void 0:r.className,{"tabs__item--active":s===n})}),null!=t?t:n)})))}function y(e){let{lazy:n,children:t,selectedValue:a}=e;const o=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=o.find((e=>e.props.value===a));return e?(0,i.cloneElement)(e,{className:"margin-top--md"}):null}return i.createElement("div",{className:"margin-top--md"},o.map(((e,n)=>(0,i.cloneElement)(e,{key:n,hidden:e.props.value!==a}))))}function x(e){const n=v(e);return i.createElement("div",{className:(0,o.A)("tabs-container",k.tabList)},i.createElement(h,(0,a.A)({},e,n)),i.createElement(y,(0,a.A)({},e,n)))}function f(e){const n=(0,b.A)();return i.createElement(x,(0,a.A)({key:String(n)},e))}},47522:(e,n,t)=>{t.d(n,{R:()=>i,z:()=>o});var a=t(96540);function i(e){let{iconTitle:n,iconLocation:t,iconLink:i}=e;return a.createElement("div",{style:{textAlign:"center"}},a.createElement("a",{href:i||void 0},a.createElement("img",{src:t,height:"48",width:"48"}),a.createElement("br",null),n))}function o(e){let{iconLocation:n,iconLink:t}=e;return a.createElement("div",{style:{textAlign:"center"}},a.createElement("a",{href:t||void 0},a.createElement("img",{src:n,height:"48",width:"48"})))}},64974:(e,n,t)=>{t.d(n,{E3:()=>p,L0:()=>c});var a=t(96540),i=t(11470),o=t(19365),r=t(47522),s=t(82667);function l(e){let{data:n,key:t,content:i,withLabel:s=!1,withLink:l=!1}=e;const c=l?n[t]:{...n[t],iconLink:void 0},p=s?(0,r.R)(c):(0,r.z)(c);return a.createElement(o.A,{value:t,label:p,key:t},p.content?p.content:i)}function c(e){let{data:n,withLabel:t,withLink:o,useCaseFilter:r}=e;return a.createElement(i.A,{groupId:"languages"},Object.keys(n).map((e=>l({data:n,key:e,content:a.createElement("div",null,a.createElement("a",{href:n[e].iconLink},"Pact Language implementation guide for ",n[e].iconTitle),a.createElement("p",null),"Demo applications:",a.createElement("p",null),s.x.filter((t=>t.language===n[e].iconTitle&&t.useCase!==r)).map((e=>a.createElement("li",{key:e.linkTitle+"language_link"+Math.random()},a.createElement("a",{href:e.linkUrl},e.linkTitle))))),withLabel:t,withLink:o}))))}function p(e){let{data:n,withLabel:t,withLink:o,side:r}=e;return a.createElement(i.A,{groupId:"testing_tools"},Object.keys(n).filter((e=>{var t;return null==(t=r&&n[e].side===r)||t})).map((e=>l({data:n,key:e,content:a.createElement("a",{href:n[e].iconLink,key:e},"PactFlow ",n[e].side," side demo with ",n[e].iconTitle),withLabel:t,withLink:o}))))}},82667:(e,n,t)=>{t.d(n,{Y:()=>o,x:()=>i});var a=t(96540);const i=[{linkTitle:"React JavaScript Website tested using Pact to generate consumer pacts",linkUrl:"/docs/examples/js/consumer",badges:["https://testdemo.pactflow.io/pacts/provider/pactflow-example-provider/consumer/pactflow-example-consumer/latest/badge.svg"],language:"JavaScript",useCase:"Web",side:"Consumer",compatible_clients:[{name:"Example Provider",link:"/docs/examples/js/provider"}]},{linkTitle:"React JavaScript Website tested using Cypress to generate consumer pacts",linkUrl:"/docs/examples/cypress",badges:["https://testdemo.pactflow.io/pacts/provider/pactflow-example-provider/consumer/example-consumer-cypress/latest/badge.svg"],language:"JavaScript",useCase:"Web",side:"C
1onsumer",compatible_clients:[{name:"Example Provider",link:"/docs/examples/js/provider"}]},{linkTitle:"ExpressJS API provider tested with Pact Verifier",linkUrl:"/docs/examples/js/provider",badges:["https://testdemo.pactflow.io/pacts/provider/pactflow-example-provider/consumer/pactflow-example-consumer/latest/badge.svg","https://testdemo.pactflow.io/pacts/provider/pactflow-example-provider/consumer/example-consumer-cypress/latest/badge.svg"],language:"JavaScript",useCase:"API",side:"Provider",compatible_clients:[{name:"Example Consumer Cypress",link:"/docs/examples/cypress/"},{name:"Example Consumer",link:"/docs/examples/js/consumer"}]},{linkTitle:".NET API Provider tested wtih Swashbuckle and Schemathesis against OAS",linkUrl:"/docs/examples/bi-directional/provider/dotnet",badges:[],language:".NET",useCase:"OpenAPI",side:"Provider",compatible_clients:[{name:"Example Bi-Directional Consumer .NET",link:"/docs/examples/bi-directional/provider/dotnet/"}]},{linkTitle:"SpringBoot API Provider tested with RestAssured against OAS",linkUrl:"/docs/examples/bi-directional/provider/restassured",badges:[],language:"Java",useCase:"OpenAPI",side:"Provider",compatible_clients:[{name:"Example Bi-Directional Consumer Cypress",link:"/docs/examples/bi-directional/consumer/cypress/"},{name:"Example Bi-Directional Consumer Mountebank",link:"/docs/examples/bi-directional/consumer/mountebank/"},{name:"Example Bi-Directional Consumer Wiremock",link:"/docs/examples/bi-directional/consumer/wiremock/"},{name:"Example Bi-Directional Consumer Nock",link:"/docs/examples/bi-directional/consumer/nock/"},{name:"Example Bi-Directional Consumer MSW",link:"/docs/examples/bi-directional/consumer/msw/"}]},{linkTitle:"ExpressJS API Provider tested with Postman against OAS",linkUrl:"/docs/examples/bi-directional/provider/postman",badges:[],language:"JavaScript",useCase:"OpenAPI",side:"Provider",compatible_clients:[{name:"Example Bi-Directional Consumer Cypress",link:"/docs/examples/bi-directional/consumer/cypress/"},{name:"Example Bi-Directional Consumer Mountebank",link:"/docs/examples/bi-directional/consumer/mountebank/"},{name:"Example Bi-Directional Consumer Wiremock",link:"/docs/examples/bi-directional/consumer/wiremock/"},{name:"Example Bi-Directional Consumer Nock",link:"/docs/examples/bi-directional/consumer/nock/"},{name:"Example Bi-Directional Consumer MSW",link:"/docs/examples/bi-directional/consumer/msw/"}]},{linkTitle:"ExpressJS API Provider tested with ReadyAPI against OAS",linkUrl:"/docs/examples/bi-directional/provider/readyapi",badges:[],language:"JavaScript",useCase:"OpenAPI",side:"Provider",compatible_clients:[{name:"Example Bi-Directional Consumer Cypress",link:"/docs/examples/bi-directional/consumer/cypress/"},{name:"Example Bi-Directional Consumer Mountebank",link:"/docs/examples/bi-directional/consumer/mountebank/"},{name:"Example Bi-Directional Consumer Wiremock",link:"/docs/examples/bi-directional/consumer/wiremock/"},{name:"Example Bi-Directional Consumer Nock",link:"/docs/examples/bi-directional/consumer/nock/"},{name:"Example Bi-Directional Consumer MSW",link:"/docs/examples/bi-directional/consumer/msw/"}]},{linkTitle:"ExpressJS API Provider tested with SoapUI against OAS",linkUrl:"/docs/examples/bi-directional/provider/soapui",badges:[],language:"JavaScript",useCase:"OpenAPI",side:"Provider",compatible_clients:[{name:"Example Bi-Directional Consumer Cypress",link:"/docs/examples/bi-directional/consumer/cypress/"},{name:"Example Bi-Directional Consumer Mountebank",link:"/docs/examples/bi-directional/consumer/mountebank/"},{name:"Example Bi-Directional Consumer Wiremock",link:"/docs/examples/bi-directional/consumer/wiremock/"},{name:"Example Bi-Directional Consumer Nock",link:"/docs/examples/bi-directional/consumer/nock/"},{name:"Example Bi-Directional Consumer MSW",link:"/docs/examples/bi-directional/consumer/msw/"}]},{linkTitle:"ExpressJS API Provider tested with Dredd against OAS",linkUrl:"/docs/examples/bi-directional/provider/dredd",badges:[],language:"JavaScript",useCase:"OpenAPI",side:"Provider",compatible_clients:[{name:"Example Bi-Directional Consumer Cypress",link:"/docs/examples/bi-directional/consumer/cypress/"},{name:"Example Bi-Directional Consumer Mountebank",link:"/docs/examples/bi-directional/consumer/mountebank/"},{name:"Example Bi-Directional Consumer Wiremock",link:"/docs/examples/bi-directional/consumer/wiremock/"},{name:"Example Bi-Directional Consumer Nock",link:"/docs/examples/bi-directional/consumer/nock/"},{name:"Example Bi-Directional Consumer MSW",link:"/docs/examples/bi-directional/consumer/msw/"}]},{linkTitle:"Python API Provider tested with Pact Verifier",linkUrl:"/docs/examples/python/provider",badges:[],language:"Python",useCase:"API",side:"Provider",compatible_clients:[{name:"Example Python Consumer",link:"/docs/examples/python/consumer/"}
1]},{linkTitle:"Golang Gin API Provider tested with Pact Verifier",linkUrl:"/docs/examples/golang/provider",badges:[],language:"Golang",useCase:"API",side:"Provider",compatible_clients:[{name:"Example Golang Consumer",link:"/docs/examples/golang/consumer/"}]},{linkTitle:".NET API Provider tested with Pact Verifier",linkUrl:"/docs/examples/dotnet/provider",badges:[],language:".NET",useCase:"API",side:"Provider",compatible_clients:[{name:"Example .NET Consumer",link:"/docs/examples/dotnet/consumer/"}]},{linkTitle:"Java SOAP API provider tested with Pact Verifier",linkUrl:"/docs/examples/soap/java/provider",badges:[],language:"Java",useCase:"SOAP",side:"Provider",compatible_clients:[{name:"Example Java XML Consumer",link:"/docs/examples/soap/java/consumer/"}]},{linkTitle:"Java Kafka message provider tested with Pact Verifier",linkUrl:"/docs/examples/kafka/java/provider",badges:[],language:"Java",useCase:"Messages",side:"Provider",compatible_clients:[{name:"Example Java Kafka Consumer",link:"/docs/examples/kafka/java/consumer/"},{name:"Example NodeJS Kafka Consumer",link:"/docs/examples/kafka/js/consumer/"}]},{linkTitle:"Java Spring Boot API provider tested with Pact Verifier",linkUrl:"/docs/examples/java/provider-springboot",badges:[],language:"Java",useCase:"API",side:"Provider",compatible_clients:[{name:"Example Java Junit Consumer",link:"/docs/examples/java/consumer/junit/"}]},{linkTitle:"ExpressJS AWS Lambda SNS Provider tested with Pact Verifier",linkUrl:"/docs/examples/aws/sns/provider",badges:[],language:"JavaScript",useCase:"Messages",side:"Provider",compatible_clients:[{name:"Example Node AWS SNS Consumer",link:"/docs/examples/aws/sns/consumer"}]},{linkTitle:"Node API consumer using Mountebank stubs and Pact Bi-Directional BYO adapters to generate Pact contracts",linkUrl:"/docs/examples/bi-directional/consumer/mountebank",badges:[],language:"JavaScript",useCase:"OpenAPI",side:"Consumer",compatible_clients:[{name:"Example Bi-Directional Provider Dredd",link:"/docs/examples/bi-directional/provider/dredd/"},{name:"Example Bi-Directional Provider Postman",link:"/docs/examples/bi-directional/provider/postman/"},{name:"Example Bi-Directional Provider RestAssured",link:"/docs/examples/bi-directional/provider/restassured/"},{name:"Example Provider",link:"/docs/examples/js/provider"}]},{linkTitle:"Java API consumer using Wiremock stubs and Pact Bi-Directional BYO adapters to generate Pact contracts",linkUrl:"/docs/examples/bi-directional/consumer/wiremock",badges:[],language:"Java",useCase:"OpenAPI",side:"Consumer",compatible_clients:[{name:"Example Bi-Directional Provider Dredd",link:"/docs/examples/bi-directional/provider/dredd/"},{name:"Example Bi-Directional Provider Postman",link:"/docs/examples/bi-directional/provider/postman/"},{name:"Example Bi-Directional Provider RestAssured",link:"/docs/examples/bi-directional/provider/restassured/"},{name:"Example Provider",link:"/docs/examples/js/provider"}]},{linkTitle:"React JavaScript Website using MSW mocks and pact-msw-adapter to generate Pact contracts",linkUrl:"/docs/examples/bi-directional/consumer/msw",badges:[],language:"JavaScript",useCase:"OpenAPI",side:"Consumer",compatible_clients:[{name:"Example Bi-Directional Provider Dredd",link:"/docs/examples/bi-directional/provider/dredd/"},{name:"Example Bi-Directional Provider Postman",link:"/docs/examples/bi-directional/provider/postman/"},{name:"Example Bi-Directional Provider RestAssured",link:"/docs/examples/bi-directional/provider/restassured/"},{name:"Example Provider",link:"/docs/examples/js/provider"}]},{linkTitle:"React JavaScript Website using Playwright routes and custom pact adapter to generate Pact contracts",linkUrl:"/docs/examples/bi-directional/consumer/playwright_js",badges:[],language:"JavaScript",useCase:"OpenAPI",side:"Consumer",compatible_clients:[{name:"Example Bi-Directional Provider Dredd",link:"/docs/examples/bi-directional/provider/dredd/"},{name:"Example Bi-Directional Provider Postman",link:"/docs/examples/bi-directional/provider/postman/"},{name:"Example Bi-Directional Provider RestAssured",link:"/docs/examples/bi-directional/provider/restassured/"},{name:"Example Provider",link:"/docs/examples/js/provider"}]},{linkTitle:"React JavaScript Website using Cypress fixtures and pact-cypress-adapter to generate Pact contracts",linkUrl:"/docs/examples/bi-directional/consumer/cypress",badges:[],language:"JavaScript",useCase:"OpenAPI",side:"C
1onsumer",compatible_clients:[{name:"Example Bi-Directional Provider Dredd",link:"/docs/examples/bi-directional/provider/dredd/"},{name:"Example Bi-Directional Provider Postman",link:"/docs/examples/bi-directional/provider/postman/"},{name:"Example Bi-Directional Provider RestAssured",link:"/docs/examples/bi-directional/provider/restassured/"},{name:"Example Provider",link:"/docs/examples/js/provider"}]},{linkTitle:"React JavaScript Website using Nock Record & Replay feature and pact-nock-adapter to generate Pact contracts",linkUrl:"/docs/examples/bi-directional/consumer/recordreplay",badges:[],language:"JavaScript",useCase:"OpenAPI",side:"Consumer",compatible_clients:[{name:"Example Bi-Directional Provider Dredd",link:"/docs/examples/bi-directional/provider/dredd/"},{name:"Example Bi-Directional Provider Postman",link:"/docs/examples/bi-directional/provider/postman/"},{name:"Example Bi-Directional Provider RestAssured",link:"/docs/examples/bi-directional/provider/restassured/"},{name:"Example Provider",link:"/docs/examples/js/provider"}]},{linkTitle:"Python API Consumer tested using Pact to generate consumer pacts",linkUrl:"/docs/examples/python/consumer",badges:[],language:"Python",useCase:"API",side:"Consumer",compatible_clients:[{name:"Example Python Provider",link:"/docs/examples/python/provider/"}]},{linkTitle:"Golang API Consumer tested using Pact to generate consumer pacts",linkUrl:"/docs/examples/golang/consumer",badges:[],language:"Golang",useCase:"API",side:"Consumer",compatible_clients:[{name:"Example Golang Provider",link:"/docs/examples/golang/provider/"}]},{linkTitle:".NET (v3.x.x) API Consumer tested using Pact to generate consumer pacts",linkUrl:"/docs/examples/dotnet/consumer",badges:[],language:".NET",useCase:"API",side:"Consumer",compatible_clients:[{name:"Example Provider .NET",link:"/docs/examples/dotnet/provider/"}]},{linkTitle:".NET (v4.x.x) API Consumer tested using Pact to generate consumer pacts",linkUrl:"/docs/examples/bi-directional/consumer/dotnet",badges:[],language:".NET",useCase:"API",side:"Consumer",compatible_clients:[{name:"Example Bi-Directional Provider .NET",link:"/docs/examples/bi-directional/consumer/dotnet/"}]},{linkTitle:"Java Junit API Consumer tested using Pact to generate consumer pacts",linkUrl:"/docs/examples/java/consumer/junit",badges:[],language:"Java",useCase:"API",side:"Consumer",compatible_clients:[{name:"Example Java Spring Boot Provider",link:"/docs/examples/java/provider-springboot/"}]},{linkTitle:"Java SOAP API Consumer tested using Pact to generate consumer pacts",linkUrl:"/docs/examples/soap/java/consumer",badges:[],language:"Java",useCase:"SOAP",side:"Consumer",compatible_clients:[{name:"Example Java XML Provider",link:"/docs/examples/soap/java/provider"}]},{linkTitle:"Java Kafka Consumer tested using Pact to generate consumer pacts",linkUrl:"/docs/examples/kafka/java/consumer",badges:[],language:"Java",useCase:"Messages",side:"Consumer",compatible_clients:[{name:"Example Java Kafka Producer",link:"/docs/examples/kafka/java/provider"}]},{linkTitle:"NodeJS Kafka Consumer tested using Pact to generate consumer pacts",linkUrl:"/docs/examples/kafka/js/consumer",badges:[],language:"NodeJS",useCase:"Messages",side:"Consumer",compatible_clients:[{name:"Example Java Kafka Producer",link:"/docs/examples/kafka/java/provider"}]},{linkTitle:"NodeJS AWS Lambda SNS Consumer tested using Pact to generate consumer pacts",linkUrl:"/docs/examples/aws/sns/consumer",badges:[],language:"NodeJS",useCase:"Messages",side:"Consumer",compatible_clients:[{name:"Example NodeJS SNS Provider",link:"/docs/examples/aws/sns/provider/"}]}],o=[{Header:"Language",accessor:"language",className:"data-table"},{Header:"Type",accessor:"side",className:"data-table"},{Header:"Use Case",accessor:"useCase",className:"data-table"},{Header:"Demo",accessor:"linkTitle",className:"data-table left",Cell:e=>{let{cell:{value:n},row:{original:t}}=e;return a.createElement("a",{href:""+t.linkUrl,rel:"noreferrer noopener"},n)}},{Header:"Compatible With",accessor:"compatible_clients",className:"data-table",Cell:e=>{let{row:{original:n}}=e;const t=n.compatible_clients;return t?t.map((e=>a.createElement("li",{key:e.link+n.linkTitle+Math.random()},a.createElement("a",{href:e.link},e.name)))):""}}]},93255:(e,n,t)=>{t.d(n,{m:()=>l});const a={readyapi:{iconTitle:"ReadyAPI",iconLocation:"/img/testing_tools/readyapi.svg",iconLink:"/docs/examples/bi-directional/provider/readyapi/",contentUrl:"",content:"",iconType:"svg",side:"provider"},soapui:{iconTitle:"SoapUI",iconLocation:"/img/testing_tools/soapui-icon.svg",iconLink:"/docs/examples/bi-directional/provider/soapui/",contentUrl:"",content:"",iconType:"svg",side:"provider"},postman:{iconTitle:"Postman",iconLocation:"/img/testing_tools/postman.svg",iconLink:"/docs/examples/bi-directional/provider/postman/",contentUrl:"",content:"",iconType:"svg",side:"provider"},restassured:{iconTitle:"REST-assured",iconLocation:"/img/testing_tools/rest_assured.png",iconLink:"/docs/examples/bi-directional/provider/restassured/",contentUrl:"",content:"",iconType:"png",side:"provider"},dredd:{iconTitle:"Dredd",iconLocation:"/img/testing_tools/dredd-logo.png",iconLink:"/docs/examples/bi-directional/provider/dredd/",contentUrl:"",content:"",iconType:"png",side:"provider"},schemathesis:{iconTitle:"Schemathesis",iconLocation:"/img/testing_tools/schemathesis.png",iconLink:"/docs/examples/bi-directional/provider/dotnet/",contentUrl:"",content:"",iconType:"png",side:"provider"},cypress:{iconTitle:"Cypress",iconLocation:"/img/testing_tools/cypress.svg",iconLink:"/docs/examples/bi-directional/consumer/cypress/",contentUrl:"",content:"",iconType:"svg",side:"consumer"},wiremock:{iconTitle:"Wiremock",iconLocation:"/img/testing_tools/wireMockLogo.png",iconLink:"/docs/examples/bi-directional/consumer/wiremock/",contentUrl:"",content:"",iconType:"png",side:"consumer"},nock:{iconTitle:"Nock",iconLocation:"/img/testing_tools/nock.svg",iconLink:"/docs/examples/bi-directional/consumer/recordreplay/",contentUrl:"",content:"",iconType:"svg",side:"consumer"},mountebank:{iconTitle:"Mountebank",iconLocation:"/img/testing_tools/mountebank.png",iconLink:"/docs/examples/bi-directional/consumer/mountebank/",contentUrl:"",content:"",iconType:"png",side:"consumer"}
1,pact:{iconTitle:"Pact",iconLocation:"/img/testing_tools/pact.svg",iconLink:"/docs/examples/bi-directional/consumer/dotnet/",contentUrl:"",content:"",iconType:"svg",side:"consumer"},msw:{iconTitle:"Mock Service Worker",iconLocation:"/img/testing_tools/msw.svg",iconLink:"/docs/examples/bi-directional/consumer/msw/",contentUrl:"",content:"",iconType:"svg",side:"consumer"},playwright_js:{iconTitle:"Playwright - JS",iconLocation:"/img/testing_tools/playwright.png",iconLink:"/docs/examples/bi-directional/consumer/playwright_js/",contentUrl:"",content:"",iconType:"png",side:"consumer"}},i=["readyapi","soapui","dredd","restassured","postman","schemathesis"],o=["cypress","wiremock","nock","mountebank","pact","msw","playwright_js"],r=Object.keys(a).filter((e=>i.includes(e))).reduce(((e,n)=>(e[n]=a[n],e)),{}),s=Object.keys(a).filter((e=>o.includes(e))).reduce(((e,n)=>(e[n]=a[n],e)),{}),l={languages:{js:{iconTitle:"JavaScript",iconLocation:"https://raw.githubusercontent.com/pact-foundation/pact.io/master/pages/assets/img/languages/javascript-original.svg",iconLink:"https://docs.pact.io/implementation_guides/javascript",contentUrl:"",content:""},java:{iconTitle:"Java",iconLocation:"https://raw.githubusercontent.com/pact-foundation/pact.io/master/pages/assets/img/languages/java-original.svg",iconLink:"https://docs.pact.io/implementation_guides/jvm",contentUrl:"",content:""},golang:{iconTitle:"Golang",iconLocation:"https://raw.githubusercontent.com/pact-foundation/pact.io/master/pages/assets/img/languages/go-original.svg",iconLink:"https://docs.pact.io/implementation_guides/go",contentUrl:"",content:""},ruby:{iconTitle:"Ruby",iconLocation:"https://raw.githubusercontent.com/pact-foundation/pact.io/master/pages/assets/img/languages/ruby-original.svg",iconLink:"https://docs.pact.io/implementation_guides/ruby/readme",contentUrl:"",content:""},dotnet:{iconTitle:".NET",iconLocation:"https://raw.githubusercontent.com/pact-foundation/pact.io/master/pages/assets/img/languages/csharp-original.svg",iconLink:"https://docs.pact.io/implementation_guides/net",contentUrl:"",content:""},docker:{iconTitle:"Docker",iconLocation:"https://www.svgrepo.com/show/331370/docker.svg",iconLink:"https://docs.pact.io/docker",contentUrl:"",content:""},kotlin:{iconTitle:"Kotlin",iconLocation:"https://raw.githubusercontent.com/pact-foundation/pact.io/master/pages/assets/img/languages/kotlin-original.svg",iconLink:"https://docs.pact.io/implementation_guides/jvm",contentUrl:"",content:""},scala:{iconTitle:"Scala",iconLocation:"https://raw.githubusercontent.com/pact-foundation/pact.io/master/pages/assets/img/languages/scala-original.svg",iconLink:"https://docs.pact.io/implementation_guides/jvm",contentUrl:"",content:""},clojure:{iconTitle:"Clojure",iconLocation:"https://raw.githubusercontent.com/pact-foundation/pact.io/master/pages/assets/img/languages/clojure-original.svg",iconLink:"https://docs.pact.io/implementation_guides/jvm",contentUrl:"",content:""},python:{iconTitle:"Python",iconLocation:"https://raw.githubusercontent.com/pact-foundation/pact.io/master/pages/assets/img/languages/python-original.svg",iconLink:"https://docs.pact.io/implementation_guides/python",contentUrl:"",content:""},swift:{iconTitle:"Swift and Objective-C",iconLocation:"https://raw.githubusercontent.com/pact-foundation/pact.io/master/pages/assets/img/languages/swift-original.svg",iconLink:"https://docs.pact.io/implementation_guides/swift",contentUrl:"",content:""},php:{iconTitle:"PHP",iconLocation:"https://raw.githubusercontent.com/pact-foundation/pact.io/master/pages/assets/img/languages/php-original.svg",iconLink:"https://docs.pact.io/implementation_guides/php",contentUrl:"",content:""},cplusplus:{iconTitle:"C++",iconLocation:"https://raw.githubusercontent.com/pact-foundation/pact.io/master/pages/assets/img/languages/csharp-original.svg",iconLink:"https://docs.pact.io/implementation_guides/cpp",contentUrl:"",content:""}},testing_tools:a,testing_tools_provider_side:r,testing_tools_consumer_side:s}},58030:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>p,contentTitle:()=>l,default:()=>g,frontMatter:()=>s,metadata:()=>c,toc:()=>d});var a=t(58168),i=(t(96540),t(15680)),o=(t(11470),t(19365),t(64974)),r=t(93255);const s={},l="2. Create and document an API using OpenAPI",c={unversionedId:"docs/workshops/bi-directional/step2",id:"docs/workshops/bi-directional/step2",title:"2. Create and document an API using OpenAPI",description:"The Provider",source:"@site/docs/docs/workshops/bi-directional/step2.mdx",sourceDirName:"docs/workshops/bi-directional",slug:"/docs/workshops/bi-directional/step2",permalink:"/docs/workshops/bi-directional/step2",draft:!1,editUrl:"https://github.com/pactflow/docs.pactflow.io/edit/master/website/docs/docs/workshops/bi-directional/step2.mdx",tags:[],version:"current",lastUpdatedBy:"Yousaf Nabi",lastUpdatedAt:1674493712,formattedLastUpdatedAt:"Jan 23, 2023",frontMatter:{},sidebar:"university",previous:{title:"1. Setting the scene",permalink:"/docs/workshops/bi-directional/step1"},next:{title:"3. Write tests for your Provider",permalink:"/docs/workshops/bi-directional/step3"}},p={},d=[{value:"The Provider",id:"the-provider",level:2},{value:"Design the API",id:"design-the-api",level:3},{value:"Implement the Product API",id:"implement-the-product-api",level:3},{value:"Fork and clone the provider",id:"fork-and-clone-the-provider",level:3},{value:"Check",id:"check",level:3}],m={toc:d},u="wrapper";
1function g(e){let{components:n,...t}=e;return(0,i.yg)(u,(0,a.A)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,i.yg)("h1",{id:"2-create-and-document-an-api-using-openapi"},"2. Create and document an API using OpenAPI"),(0,i.yg)("h2",{id:"the-provider"},"The Provider"),(0,i.yg)("h3",{id:"design-the-api"},"Design the API"),(0,i.yg)("p",null,"As we are following a specification or ",(0,i.yg)("a",{parentName:"p",href:"https://swagger.io/blog/api-design/design-first-or-code-first-api-development/"},"design first approach")," to API development, we start by creating an ",(0,i.yg)("a",{parentName:"p",href:"https://oai.github.io/Documentation/start-here.html"},"OpenAPI")," description document, that describes how our API should work."),(0,i.yg)("p",null,"Authoring an OAS document is beyond the scope of this tutorial, but you can find plenty of resources on the internet (such as at ",(0,i.yg)("a",{parentName:"p",href:"https://swagger.io"},"swagger.io"),")."),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre"},'openapi: 3.0.1\ninfo:\n title: Product API\n description: PactFlow Product API demo\n version: 1.0.0\npaths:\n /products:\n post:\n summary: Create a product\n description: Creates a new product\n operationId: createProduct\n requestBody:\n description: Create a new Product\n required: true\n content:\n application/json:\n schema:\n $ref: \'#/components/schemas/Product\'\n examples:\n application/json:\n value:\n id: "1234"\n type: "food"\n price: 42\n responses:\n "200":\n description: successful operation\n content:\n "application/json; charset=utf-8":\n schema:\n oneOf:\n - $ref: \'#/components/schemas/Product\'\n examples:\n application/json:\n value:\n id: "1234"\n type: "food"\n price: 42\n get:\n summary: List all products\n description: Returns all products\n operationId: getAllProducts\n responses:\n "200":\n description: successful operation\n content:\n "application/json; charset=utf-8":\n schema:\n type: "array"\n items:\n $ref: \'#/components/schemas/Product\'\n examples:\n application/json:\n value:\n - id: "1234"\n type: "food"\n price: 42\n # name: "pizza"\n # version: "1.0.0"\n # see https://github.com/apiaryio/dredd/issues/1430 for why\n "400":\n description: Invalid ID supplied\n content: {}\n /product/{id}:\n get:\n summary: Find product by ID\n description: Returns a single product\n operationId: getProductByID\n parameters:\n - name: id\n in: path\n description: ID of product to get\n schema:\n type: string\n required: true\n example: 10\n responses:\n "200":\n description: successful operation\n content:\n "application/json; charset=utf-8":\n schema:\n $ref: \'#/components/schemas/Product\'\n examples:\n application/json:\n value:\n id: "1234"\n type: "food"\n price: 42\n # name: "pizza"\n # version: "1.0.0"\n # see https://github.com/apiaryio/dredd/issues/1430 for why\n "400":\n description: Invalid ID supplied\n content: {}\n "404":\n description: Product not found\n content: {}\ncomponents:\n schemas:\n Product:\n type: object\n required:\n - id\n - name\n - price\n additionalProperties: false\n properties:\n id:\n type: string\n type:\n type: string\n name:\n type: string\n version:\n type: string\n price:\n type: number\n')),(0,i.yg)("p",null,"As you can see, we have 3 main endpoints:"),(0,i.yg)("ol",null,(0,i.yg)("li",{parentName:"ol"},(0,i.yg)("inlineCode",{parentName:"li"},"POST /products")," - create a new product"),(0,i.yg)("li",{parentName:"ol"},(0,i.yg)("inlineCode",{parentName:"li"},"GET /products")," - gets all products"),(0,i.yg)("li",{parentName:"ol"},(0,i.yg)("inlineCode",{parentName:"li"},"GET /products/:id")," - gets a single product")),(0,i.yg)("p",null,"Having designed our API, we can now set about building it."),(0,i.yg)("h3",{id:"implement-the-product-api"},"Implement the Product API"),(0,i.yg)("p",null,"Here is the Product API using the ",(0,i.yg)("a",{parentName:"p",href:"https://expressjs.com"},"Express JS")," framework. Once again, writing an API is beyond the scope of this tutorial."),(0,i.yg)("p",null,"We define our product, the available routes, the datastore (an simple in-memory database) and the server."),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-js",metastring:"reference",reference:!0}
1,"https://github.com/pactflow/example-bi-directional-provider-dredd/blob/master/src/product/product.js#L1-L8\n")),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-js",metastring:"reference",reference:!0},"https://github.com/pactflow/example-bi-directional-provider-dredd/blob/master/src/product/product.routes.js#L1-L8\n")),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-js",metastring:"reference",reference:!0},"https://github.com/pactflow/example-bi-directional-provider-dredd/blob/master/src/product/product.repository.js#L1-L26\n")),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-js",metastring:"reference",reference:!0},"https://github.com/pactflow/example-bi-directional-provider-dredd/blob/master/src/product/product.controller.js#L1-L19\n")),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-js",metastring:"reference",reference:!0},"https://github.com/pactflow/example-bi-directional-provider-dredd/blob/master/server.js#L1-L16\n")),(0,i.yg)("admonition",{type:"info"},(0,i.yg)("p",{parentName:"admonition"},"You can pick your provider now")),(0,i.yg)("div",null,(0,o.E3)({data:r.m.testing_tools_provider_side,withLabel:!0,withLink:!1})),(0,i.yg)("h3",{id:"fork-and-clone-the-provider"},"Fork and clone the provider"),(0,i.yg)("ol",null,(0,i.yg)("li",{parentName:"ol"},(0,i.yg)("p",{parentName:"li"},"Fork the ",(0,i.yg)("a",{parentName:"p",href:"https://github.com/pactflow/example-bi-directional-provider-dredd"},"example-bi-directional-provider-dredd")," project in to your own Github account (click the 'Fork' button in the top right).")),(0,i.yg)("li",{parentName:"ol"},(0,i.yg)("p",{parentName:"li"},"Clone the repository on to your local machine."),(0,i.yg)("pre",{parentName:"li"},(0,i.yg)("code",{parentName:"pre",className:"language-bash"},"git clone [email protected]:<YOUR_GITHUB_USERNAME>/example-bi-directional-provider-dredd.git\n"))),(0,i.yg)("li",{parentName:"ol"},(0,i.yg)("p",{parentName:"li"},"Install the dependencies."),(0,i.yg)("pre",{parentName:"li"},(0,i.yg)("code",{parentName:"pre",className:"language-bash"},"npm install\n")))),(0,i.yg)("h3",{id:"check"},"Check"),(0,i.yg)("p",null,"Before moving to the next step, cd into the ",(0,i.yg)("inlineCode",{parentName:"p"},"example-bi-directional-provider-dredd")," directory and run the provider to see if it starts."),(0,i.yg)("p",null,"The tutorial environment should have installed 2 projects and their dependencies. Once the terminal process completes you can run:"),(0,i.yg)("ol",null,(0,i.yg)("li",{parentName:"ol"},(0,i.yg)("inlineCode",{parentName:"li"},"cd /root/example-bi-directional-provider-dredd")),(0,i.yg)("li",{parentName:"ol"},(0,i.yg)("inlineCode",{parentName:"li"},"npm i")),(0,i.yg)("li",{parentName:"ol"},(0,i.yg)("inlineCode",{parentName:"li"},"npm start"))),(0,i.yg)("p",null,"Open up a separate terminal and run the following command:"),(0,i.yg)("ol",null,(0,i.yg)("li",{parentName:"ol"},(0,i.yg)("inlineCode",{parentName:"li"},"cd /root/example-bi-directional-provider-dredd")),(0,i.yg)("li",{parentName:"ol"},(0,i.yg)("inlineCode",{parentName:"li"},"curl localhost:3001/products | jq ."))),(0,i.yg)("p",null,"You should see the following output:"),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-json"},'[\n {\n "id": "09",\n "type": "CREDIT_CARD",\n "name": "Gem Visa",\n "version": "v1",\n "price": 99.99\n },\n {\n "id": "10",\n "type": "CREDIT_CARD",\n "name": "28 Degrees",\n "version": "v1",\n "price": 49.49\n },\n {\n "id": "11",\n "type": "PERSONAL_LOAN",\n "name": "MyFlexiPay",\n "version": "v2",\n "price": 16.5\n }\n]\n')),(0,i.yg)("p",null,"Switch back to your first terminal and terminate (",(0,i.yg)("inlineCode",{parentName:"p"},"ctrl-c"),") the process to make sure your provider is no longer running."))}g.isMDXComponent=!0}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.