├── .github ├── actions │ └── common_setup │ │ └── action.yaml └── workflows │ └── github-actions-image.yaml ├── .gitignore ├── .hlint.yaml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── action.yaml ├── app ├── Data │ └── OpenApi │ │ └── Compare │ │ └── Options.hs ├── FormatHeuristic.hs └── Main.hs ├── benchmarks ├── README.md ├── atlassian │ ├── addDist.patch │ └── yarn.lock ├── default.nix ├── nix │ ├── sources.json │ └── sources.nix ├── oasdiff │ └── gomod2nix.toml ├── openapitools │ └── mavenix.lock └── report.md ├── ci └── policeman.nix ├── compaREST.cabal ├── css └── awsm.min.css ├── default.nix ├── docs ├── Development_guide.md ├── Integration_guide.md ├── Releasing.md ├── User_guide.md └── img │ ├── github-action-report.png │ ├── pre-release-artifacts.png │ ├── pre-release-ci.png │ └── pre-release.png ├── fourmolu.yaml ├── github-action ├── CompaREST │ └── GitHub │ │ ├── API.hs │ │ └── Action │ │ └── Config.hs ├── Control │ └── Monad │ │ └── Freer │ │ └── GitHub.hs ├── GitHub │ ├── Data │ │ └── Checks.hs │ └── Endpoints │ │ └── Checks.hs └── Main.hs ├── nix ├── ci.nix ├── diff-yaml.nix ├── shell.nix ├── sources.json ├── sources.nix └── yq.nix ├── scripts └── diff-yaml ├── src └── Data │ ├── HList.hs │ ├── OpenApi │ └── Compare │ │ ├── Behavior.hs │ │ ├── Common.hs │ │ ├── Formula.hs │ │ ├── Memo.hs │ │ ├── Orphans.hs │ │ ├── Paths.hs │ │ ├── PathsPrefixTree.hs │ │ ├── References.hs │ │ ├── Report.hs │ │ ├── Report │ │ ├── Html │ │ │ └── Template.hs │ │ └── Jet.hs │ │ ├── Run.hs │ │ ├── Subtree.hs │ │ └── Validate │ │ ├── Header.hs │ │ ├── Link.hs │ │ ├── MediaTypeObject.hs │ │ ├── OAuth2Flows.hs │ │ ├── OpenApi.hs │ │ ├── Operation.hs │ │ ├── Param.hs │ │ ├── PathFragment.hs │ │ ├── Products.hs │ │ ├── RequestBody.hs │ │ ├── Responses.hs │ │ ├── Schema.hs │ │ ├── Schema │ │ ├── DNF.hs │ │ ├── Issues.hs │ │ ├── JsonFormula.hs │ │ ├── Partition.hs │ │ ├── Process.hs │ │ ├── Traced.hs │ │ └── TypedJson.hs │ │ ├── SecurityRequirement.hs │ │ ├── SecurityScheme.hs │ │ ├── Server.hs │ │ └── Sums.hs │ └── OpenUnion │ └── Extra.hs ├── stack.yaml ├── stack.yaml.lock └── test ├── README.md ├── Spec.hs ├── Spec └── Golden │ ├── Extra.hs │ └── TraceTree.hs └── golden └── common ├── bad-oneof-unchanged ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml ├── enum-added ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml ├── enum-anyof ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml ├── id ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml ├── json └── recursive │ ├── a.yaml │ ├── b.yaml │ ├── report.md │ └── trace-tree.yaml ├── maximum-lowered ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml ├── pathItem └── operation │ ├── parameters │ ├── allowEmptyValue │ │ ├── reset │ │ │ ├── a.yaml │ │ │ ├── b.yaml │ │ │ ├── report.md │ │ │ └── trace-tree.yaml │ │ └── set │ │ │ ├── a.yaml │ │ │ ├── b.yaml │ │ │ ├── report.md │ │ │ └── trace-tree.yaml │ ├── change │ │ ├── a.yaml │ │ ├── b.yaml │ │ ├── report.md │ │ └── trace-tree.yaml │ └── required │ │ ├── false │ │ ├── add │ │ │ ├── a.yaml │ │ │ ├── b.yaml │ │ │ ├── report.md │ │ │ └── trace-tree.yaml │ │ └── del │ │ │ ├── a.yaml │ │ │ ├── b.yaml │ │ │ ├── report.md │ │ │ └── trace-tree.yaml │ │ ├── reset │ │ ├── a.yaml │ │ ├── b.yaml │ │ ├── report.md │ │ └── trace-tree.yaml │ │ ├── set │ │ ├── a.yaml │ │ ├── b.yaml │ │ ├── report.md │ │ └── trace-tree.yaml │ │ └── true │ │ ├── add │ │ ├── a.yaml │ │ ├── b.yaml │ │ ├── report.md │ │ └── trace-tree.yaml │ │ └── del │ │ ├── a.yaml │ │ ├── b.yaml │ │ ├── report.md │ │ └── trace-tree.yaml │ ├── requestBody │ ├── mediaTypeObject │ │ ├── add │ │ │ ├── a.yaml │ │ │ ├── b.yaml │ │ │ ├── report.md │ │ │ └── trace-tree.yaml │ │ ├── change │ │ │ ├── a.yaml │ │ │ ├── b.yaml │ │ │ ├── report.md │ │ │ └── trace-tree.yaml │ │ └── del │ │ │ ├── a.yaml │ │ │ ├── b.yaml │ │ │ ├── report.md │ │ │ └── trace-tree.yaml │ └── required │ │ ├── reset │ │ ├── a.yaml │ │ ├── b.yaml │ │ ├── report.md │ │ └── trace-tree.yaml │ │ └── set │ │ ├── a.yaml │ │ ├── b.yaml │ │ ├── report.md │ │ └── trace-tree.yaml │ └── responses │ ├── add │ ├── a.yaml │ ├── b.yaml │ ├── report.md │ └── trace-tree.yaml │ ├── change │ ├── headers │ │ ├── mandatory │ │ │ ├── add │ │ │ │ ├── a.yaml │ │ │ │ ├── b.yaml │ │ │ │ ├── report.md │ │ │ │ └── trace-tree.yaml │ │ │ └── del │ │ │ │ ├── a.yaml │ │ │ │ ├── b.yaml │ │ │ │ ├── report.md │ │ │ │ └── trace-tree.yaml │ │ └── optional │ │ │ ├── add │ │ │ ├── a.yaml │ │ │ ├── b.yaml │ │ │ ├── report.md │ │ │ └── trace-tree.yaml │ │ │ └── del │ │ │ ├── a.yaml │ │ │ ├── b.yaml │ │ │ ├── report.md │ │ │ └── trace-tree.yaml │ └── mediaTypeObject │ │ ├── add │ │ ├── a.yaml │ │ ├── b.yaml │ │ ├── report.md │ │ └── trace-tree.yaml │ │ ├── change │ │ ├── a.yaml │ │ ├── b.yaml │ │ ├── report.md │ │ └── trace-tree.yaml │ │ └── del │ │ ├── a.yaml │ │ ├── b.yaml │ │ ├── report.md │ │ └── trace-tree.yaml │ └── del │ ├── a.yaml │ ├── b.yaml │ ├── report.md │ └── trace-tree.yaml ├── property-removed-additional ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml ├── property-removed ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml ├── property-required ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml ├── random-example ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml ├── recursive ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml ├── security-scheme ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml ├── servers ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml ├── tuple-items ├── heterogeneous-component-mismatch │ ├── a.yaml │ ├── b.yaml │ ├── report.md │ └── trace-tree.yaml ├── heterogeneous-length-mismatch │ ├── a.yaml │ ├── b.yaml │ ├── report.md │ └── trace-tree.yaml ├── homogeneous-component-mismatch │ ├── a.yaml │ ├── b.yaml │ ├── report.md │ └── trace-tree.yaml ├── homogeneous-length-mismatch │ ├── a.yaml │ ├── b.yaml │ ├── report.md │ └── trace-tree.yaml └── homogeneous-vector │ ├── a.yaml │ ├── b.yaml │ ├── report.md │ └── trace-tree.yaml ├── type-changing ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml ├── unguarded-recursive ├── basic │ ├── a.yaml │ ├── b.yaml │ ├── report.md │ └── trace-tree.yaml └── silent │ ├── a.yaml │ ├── b.yaml │ ├── report.md │ └── trace-tree.yaml ├── variant-added ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml ├── variant-changed ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml └── variant-deep-changed ├── a.yaml ├── b.yaml ├── report.md └── trace-tree.yaml /.github/actions/common_setup/action.yaml: -------------------------------------------------------------------------------- 1 | name: "Common setup" 2 | description: "Common setup steps" 3 | inputs: 4 | authToken: 5 | description: "Cachix auth token" 6 | required: true 7 | runs: 8 | using: "composite" 9 | steps: 10 | - name: Increase swap if linux 11 | shell: bash 12 | run: | 13 | if [ "$RUNNER_OS" == "Linux" ]; then 14 | 15 | echo "Is Linux" 16 | 17 | free -h 18 | 19 | sudo swapoff /mnt/swapfile 20 | sudo fallocate -l 12G /mnt/swapfile 21 | sudo mkswap /mnt/swapfile 22 | sudo swapon /mnt/swapfile 23 | 24 | free -h 25 | 26 | else 27 | 28 | echo "Not Linux" 29 | 30 | fi 31 | 32 | - name: Install Nix 33 | uses: cachix/install-nix-action@v27 34 | with: 35 | extra_nix_config: | 36 | system-features = kvm 37 | trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= 38 | substituters = https://hydra.iohk.io https://cache.nixos.org/ 39 | - uses: cachix/cachix-action@v15 40 | with: 41 | name: typeable 42 | authToken: "${{ inputs.authToken }}" 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .stack-work 2 | TAGS 3 | .vscode 4 | .dir-locals.el 5 | test/golden/common/prod 6 | -------------------------------------------------------------------------------- /.hlint.yaml: -------------------------------------------------------------------------------- 1 | - ignore: { name: Redundant pure } 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | `compaREST` uses [PVP Versioning][1]. 4 | 5 | ## 0.1.0.1 6 | 7 | * Fixed an issue related to empty commit SHAs in GitHub Actions. 8 | 9 | ## 0.1.0.0 10 | 11 | * Initial release. 12 | 13 | [1]: https://pvp.haskell.org 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Typeable 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /action.yaml: -------------------------------------------------------------------------------- 1 | name: compaREST 2 | author: Typeable 3 | description: API reliability checker 4 | inputs: 5 | GITHUB_TOKEN: 6 | description: "The GitHub access token (e.g. secrets.GITHUB_TOKEN) used to create or update the comment. This defaults to {{ github.token }}." 7 | default: "${{ github.token }}" 8 | required: false 9 | repo: 10 | description: The owner of the repo in which to post the results. 11 | default: "${{ github.repository }}" 12 | required: false 13 | project_name: 14 | description: The name of the project to which the API pertains. Used to name the check. Useful when you have multiple APIs in the same repo. 15 | required: false 16 | default: "" 17 | footer: 18 | description: A footer that can be appended to the check body. 19 | required: false 20 | default: "" 21 | old: 22 | description: The path to the old (client) specification of the API. 23 | required: true 24 | new: 25 | description: The path to new (server) specification of the API. 26 | required: true 27 | sha: 28 | description: The sha of the commit to post the check for. 29 | required: false 30 | default: "${{ github.event.pull_request.head.sha }}" 31 | runs: 32 | using: "docker" 33 | image: "docker://typeable/comparest-github-action:0.1.0.1" 34 | env: 35 | GITHUB_TOKEN: "${{ inputs.GITHUB_TOKEN }}" 36 | REPO: "${{ inputs.repo }}" 37 | PROJECT_NAME: "${{ inputs.project_name }}" 38 | FOOTER: "${{ inputs.footer }}" 39 | ROOT: "/github/workspace" 40 | OLD: "${{ inputs.old }}" 41 | NEW: "${{ inputs.new }}" 42 | SHA: "${{ inputs.sha }}" 43 | pre-entrypoint: "/bin/pre" 44 | entrypoint: "/bin/run" 45 | 46 | branding: 47 | icon: crosshair 48 | color: blue 49 | -------------------------------------------------------------------------------- /app/Main.hs: -------------------------------------------------------------------------------- 1 | module Main (main) where 2 | 3 | import Control.Monad 4 | import Control.Monad.Except 5 | import Control.Monad.Trans (lift) 6 | import Data.Aeson 7 | import qualified Data.ByteString.Lazy as BSL 8 | import Data.Default 9 | import Data.Maybe 10 | import Data.OpenApi.Compare.Options 11 | import Data.OpenApi.Compare.Run 12 | import qualified Data.Text.IO as T 13 | import qualified Data.Yaml as Yaml 14 | import FormatHeuristic 15 | import System.Exit 16 | import System.IO 17 | import Text.Pandoc hiding (report) 18 | import Text.Pandoc.Builder 19 | 20 | main :: IO () 21 | main = do 22 | opts <- parseOptions 23 | let parseSchema path = 24 | eitherDecodeFileStrict path >>= \case 25 | Left jsonErr -> do 26 | Yaml.decodeFileEither path >>= \case 27 | Left yamlErr -> do 28 | putStrLn "Could not parse as json or yaml" 29 | print jsonErr 30 | print yamlErr 31 | fail "Exiting" 32 | Right s -> pure s 33 | Right s -> pure s 34 | a <- parseSchema (clientFile opts) 35 | b <- parseSchema (serverFile opts) 36 | let runPandocIO :: PandocIO a -> ExceptT Errors IO a 37 | runPandocIO x = lift (runIO x) >>= either (throwError . DocumentError) pure 38 | options = def {writerExtensions = githubMarkdownExtensions} 39 | write :: Pandoc -> ExceptT Errors IO () 40 | write = case outputMode opts of 41 | StdoutMode -> lift . T.putStrLn <=< runPandocIO . writeMarkdown options 42 | FileMode f -> case formatFromFilePath f of 43 | Nothing -> \_ -> throwError UnknownOutputFormat 44 | Just (writer, f') -> lift . BSL.writeFile f' <=< runPandocIO . writer 45 | reportConfig = 46 | ReportConfig 47 | { treeStyle = reportTreeStyle opts 48 | , reportMode = fromMaybe All $ mode opts 49 | } 50 | (report, status) = runReport reportConfig (a, b) 51 | case mode opts of 52 | Just _ -> either handler pure <=< runExceptT $ write $ doc report 53 | Nothing -> pure () 54 | when (signalExitCode opts) $ 55 | case status of 56 | NoBreakingChanges -> exitSuccess 57 | BreakingChanges -> exitWith $ ExitFailure 1 58 | OnlyUnsupportedChanges -> exitWith $ ExitFailure 2 59 | 60 | data Errors 61 | = DocumentError PandocError 62 | | UnknownOutputFormat 63 | 64 | handler :: Errors -> IO a 65 | handler (DocumentError err) = do 66 | T.hPutStrLn stderr (renderError err) 67 | exitWith $ ExitFailure 100 68 | handler UnknownOutputFormat = do 69 | T.hPutStrLn stderr "Could not determine output format from file extension." 70 | exitWith $ ExitFailure 101 71 | -------------------------------------------------------------------------------- /benchmarks/README.md: -------------------------------------------------------------------------------- 1 | # OpenApi comparison benchmarks 2 | 3 | This is a nix expression that automatically downloads, builds and runs multiple OpenAPI comparison tools on the same set of inputs to compare how well they behave. 4 | 5 | To run the benchmarks run the following command in this directory: 6 | 7 | ```bash 8 | nix-build 9 | ``` 10 | 11 | ## The tools 12 | 13 | | Tool | Output file name | 14 | | -------------------------------------------------------------------------- | ------------------------------------------- | 15 | | [Typeable CompaREST](https://github.com/typeable/compaREST) | `typeable.md` | 16 | | [Atlassian OpenApi Diff](https://bitbucket.org/atlassian/openapi-diff) | `atlassian.json`, `atlassian.error.txt` | 17 | | [OpenApi Tools OpenApi Diff](https://github.com/OpenAPITools/openapi-diff) | `openapitools.md`, `openapitools.error.txt` | 18 | | [Tufin OpenApi Diff](https://github.com/tufin/oasdiff) | `oasdiff.txt`, `oasdiff.error.txt` | 19 | | [Bump](https://bump.sh) | `bump.txt` | 20 | 21 | ## Running with Bump.sh 22 | 23 | Bump.sh is a closed-source tool that is only available via REST API. To include bump.sh in the benchmark results you have to supply your credentials as arguments: 24 | 25 | ```bash 26 | nix-build --argstr bumpToken --argstr bumpDocumentation 27 | ``` 28 | -------------------------------------------------------------------------------- /benchmarks/atlassian/addDist.patch: -------------------------------------------------------------------------------- 1 | diff --git a/gulpfile.js b/gulpfile.js 2 | index c3161cf..c123cc0 100644 3 | --- a/gulpfile.js 4 | +++ b/gulpfile.js 5 | @@ -153,3 +153,5 @@ exports.watch = gulp.series( 6 | exports.watchE2e = function () { 7 | gulp.watch(['build-output/lib/**/*', 'build-output/test/e2e/**/*', 'test/e2e/**/*.json'], gulp.series(e2eTest)); 8 | }; 9 | + 10 | +exports.compileDist = compileDist 11 | -------------------------------------------------------------------------------- /ci/policeman.nix: -------------------------------------------------------------------------------- 1 | { sources ? import ../nix/sources.nix 2 | , pkgs ? import sources.nixpkgs { } 3 | }: 4 | pkgs.haskellPackages.policeman 5 | -------------------------------------------------------------------------------- /docs/Integration_guide.md: -------------------------------------------------------------------------------- 1 | # Integration guide 2 | 3 | ## Github Actions 4 | 5 | In cases where your OpenAPI spec can be generated from your code, it can be useful to see how a pull request changes your API. For this very purpose we have a Github Action. 6 | 7 | ### Generating the inputs 8 | 9 | To use it you need to first get the old (before the pull request) and new (after the pull request) specs. 10 | 11 | For example: 12 | 13 | - To get the old spec you can: 14 | - Download from a public "production" server (if your api is public and you provide an OpenAPI spec) 15 | - Checkout the base commit of the pull request and generate is programmatically. 16 | 17 | You can checkout the base commit like so in Github Actions: 18 | 19 | ```bash 20 | git checkout $(git merge-base ${{ github.event.pull_request.head.sha }} ${{ github.event.pull_request.base.sha }}) 21 | ``` 22 | - To get the new spec you can: 23 | - Build and run the spec generation for the head commit of the pull request 24 | 25 | ### Run the action 26 | 27 | In our example we have already generated the two OpenAPI specs and placed them in the `old-openapi.yaml` and `new-openapi.yaml` files. 28 | 29 | We can now run our action: 30 | 31 | ```yaml 32 | - uses: typeable/comparest 33 | with: 34 | old: old-openapi.yaml 35 | new: new-openapi.yaml 36 | project_name: TEST 37 | ``` 38 | 39 | This will create a check on the pull request displaying the changes (if there are any) similar to this: 40 | 41 | ![](img/github-action-report.png) 42 | 43 | The check will show success when there are no breaking changes, and be neutral otherwise. 44 | 45 | ## Integrating into something other than Github Actions 46 | 47 | We have a dedicated implementation only for Github Actions. However, we provide a generic CLI which can be used to integrate compaREST into arbitrary workflows and CI systems. 48 | 49 | You see an example of CLI usage in our [readme](../README.md#assessing-compatibility-automatically). 50 | -------------------------------------------------------------------------------- /docs/Releasing.md: -------------------------------------------------------------------------------- 1 | # The release procedure 2 | 3 | 1. Update the version number everywhere: 4 | 1. Version in [compaREST.cabal](../compaREST.cabal) 5 | 2. Docker tag in [action.yaml](../action.yaml) 6 | 3. Set the version of unreleased changes in [CHANGELOG.md](../CHANGELOG.md) 7 | 2. Publish! 8 | 1. Create a pre-release on GitHub: 9 | ![](img/pre-release.png) 10 | 2. This will automatically start the release procedure. You can check the state of it in the "Actions" tab on GitHub: 11 | ![](img/pre-release-ci.png) 12 | 3. If everything goes as planned, the release action should pass and all assets should be added to the release: 13 | ![](img/pre-release-artifacts.png) 14 | 4. The new version should be automatically uploaded a release candidate to [Hackage](https://hackage.haskell.org/package/compaREST/candidates/). Make sure everything looks okay and publish it. 15 | 5. Go to the Releases tab on GitHub and edit the release to make it not a "pre-release". 16 | -------------------------------------------------------------------------------- /docs/User_guide.md: -------------------------------------------------------------------------------- 1 | CompaREST User Guide 2 | ==================== 3 | 4 | Running the Tool 5 | ---------------- 6 | The tool accepts two OpenAPI 3.0.0 schema files in either JSON or YAML format. 7 | One is assumed to be the client version of the schema, and the other is the 8 | server version. 9 | 10 | The tool will look for changes between the schemas and detect whether they are 11 | breaking or not -- that is, if they prevent interoperability between the client 12 | and the server. 13 | 14 | Running: 15 | ``` 16 | comparest -c client.json -s server.json 17 | ``` 18 | will output a markdown report of the changes to the standard output. 19 | 20 | Compatibility status can be signaled via the exit code using 21 | `--signal-exit-code`. In case no report is needed, output can be suppressed with 22 | `--silent`. For example: 23 | ``` 24 | comparest -c client.json -s server.json --signal-exit-code --silent 25 | echo $? 26 | ``` 27 | If there were changes that the tool determined to be breaking, the exit code 28 | will be 1. If there were some changes the tool couldn't understand, the exit 29 | code will be 2. Otherwise if there were no breaking changes, the exit code will 30 | be 0. 31 | 32 | Controlling the Report 33 | ---------------------- 34 | By default the report includes breaking changes, as well as non-breaking: 35 | changes that would be considered breaking in the opposite direction. To only 36 | include breaking changes in the report use `--only-breaking`. The `--all` option 37 | restores the default behavior. 38 | 39 | The report can be formatted in a variety of ways supported by Pandoc. The `-o` 40 | option causes the report to be written to a file. The format of the file is 41 | determined from the extension. The supported extensions include: 42 | - `.md` for markdown 43 | - `.html` for an HTML snippet 44 | - `.rst` for restructured text 45 | - no extension for a self-contained HTML document with styles 46 | 47 | By default the report is split up into parts relating to different paths, 48 | requests, responses, etc, using headers of various levels. Alternatively, the 49 | report can use indended block-quotes to visualize the tree structure of the 50 | report. The header style is enabled with `--header-style`, and the block-quote 51 | style is enabled with `--folding-block-quotes-style`. 52 | -------------------------------------------------------------------------------- /docs/img/github-action-report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typeable/compaREST/218679898bdc293c6613e5d0692927e24c1dd136/docs/img/github-action-report.png -------------------------------------------------------------------------------- /docs/img/pre-release-artifacts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typeable/compaREST/218679898bdc293c6613e5d0692927e24c1dd136/docs/img/pre-release-artifacts.png -------------------------------------------------------------------------------- /docs/img/pre-release-ci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typeable/compaREST/218679898bdc293c6613e5d0692927e24c1dd136/docs/img/pre-release-ci.png -------------------------------------------------------------------------------- /docs/img/pre-release.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typeable/compaREST/218679898bdc293c6613e5d0692927e24c1dd136/docs/img/pre-release.png -------------------------------------------------------------------------------- /fourmolu.yaml: -------------------------------------------------------------------------------- 1 | indentation: 2 2 | comma-style: leading # for lists, tuples etc. - can also be 'trailing' 3 | record-brace-space: true # rec {x = 1} vs. rec{x = 1} 4 | indent-wheres: true # 'false' means save space by only half-indenting the 'where' keyword 5 | diff-friendly-import-export: false # 'false' uses Ormolu-style lists 6 | respectful: true # don't be too opinionated about newlines etc. 7 | haddock-style: single-line # '--' vs. '{-' 8 | newlines-between-decls: 1 # number of newlines between top-level declarations 9 | -------------------------------------------------------------------------------- /github-action/CompaREST/GitHub/API.hs: -------------------------------------------------------------------------------- 1 | module CompaREST.GitHub.API 2 | ( postStatus, 3 | postStatusProcessing, 4 | ) 5 | where 6 | 7 | import CompaREST.GitHub.Action.Config 8 | import Control.Monad.Freer 9 | import Control.Monad.Freer.GitHub 10 | import Control.Monad.Freer.Reader 11 | import Control.Monad.IO.Class 12 | import Data.Aeson 13 | import qualified Data.ByteString.Lazy.Char8 as BSLC 14 | import Data.OpenApi.Compare.Report 15 | import Data.Proxy 16 | import Data.Text (Text) 17 | import GitHub 18 | import GitHub.Data.Checks 19 | import GitHub.Endpoints.Checks 20 | 21 | postStatusProcessing :: 22 | (Members '[GitHub, Reader Config] effs, MonadIO (Eff effs)) => 23 | Eff effs () 24 | postStatusProcessing = do 25 | Config {..} <- ask 26 | printJSON $ 27 | sendGitHub $ 28 | checkR 29 | repoOwner 30 | repoName 31 | Check 32 | { checkName = mkName Proxy checkName 33 | , checkSha = sha 34 | , checkDetailsURL = Nothing 35 | , checkExternalId = Nothing 36 | , checkStatus = Just CheckInProgress 37 | , checkStartedAt = Nothing 38 | , checkConclusion = Nothing 39 | , checkCompletedAt = Nothing 40 | , checkOutput = Nothing 41 | , checkActions = Nothing 42 | } 43 | 44 | postStatus :: 45 | (Members '[GitHub, Reader Config] effs, MonadIO (Eff effs)) => 46 | -- | 'Nothing' means that there were no changes at all 47 | Maybe (Text, ReportStatus) -> 48 | Eff effs () 49 | postStatus x = do 50 | let (body, (title, conclusion)) = case x of 51 | Just (b, s) -> (b,) $ case s of 52 | BreakingChanges -> ("⚠️ Breaking changes found!", CheckNeutral) 53 | NoBreakingChanges -> ("No breaking changes found ✨", CheckSuccess) 54 | OnlyUnsupportedChanges -> ("🤷 Couldn't determine compatibility", CheckNeutral) 55 | Nothing -> ("", ("✅ The API did not change", CheckSuccess)) 56 | Config {..} <- ask 57 | printJSON $ 58 | sendGitHub $ 59 | checkR 60 | repoOwner 61 | repoName 62 | Check 63 | { checkName = mkName Proxy checkName 64 | , checkSha = sha 65 | , checkDetailsURL = Nothing 66 | , checkExternalId = Nothing 67 | , checkStatus = Just CheckCompleted 68 | , checkStartedAt = Nothing 69 | , checkConclusion = Just conclusion 70 | , checkCompletedAt = Nothing 71 | , checkOutput = 72 | Just $ 73 | CheckOutput 74 | { checkTitle = title 75 | , checkSummary = body 76 | , checkText = Nothing 77 | , checkAnnotations = Nothing 78 | , checkImages = Nothing 79 | } 80 | , checkActions = Nothing 81 | } 82 | 83 | printJSON :: MonadIO (Eff effs) => Eff effs Value -> Eff effs () 84 | printJSON m = do 85 | x <- m 86 | liftIO . BSLC.putStrLn $ encode x 87 | -------------------------------------------------------------------------------- /github-action/CompaREST/GitHub/Action/Config.hs: -------------------------------------------------------------------------------- 1 | module CompaREST.GitHub.Action.Config 2 | ( Config (..), 3 | ) 4 | where 5 | 6 | import Data.Proxy 7 | import Data.Text (Text) 8 | import qualified Data.Text as T 9 | import qualified GitHub as GH 10 | 11 | import Data.Functor 12 | import System.Envy 13 | 14 | data Config = Config 15 | { githubToken :: GH.Auth 16 | , repoOwner :: GH.Name GH.Owner 17 | , repoName :: GH.Name GH.Repo 18 | , checkName :: Text 19 | , footerText :: Text 20 | , root :: FilePath 21 | , sha :: GH.Name GH.Commit 22 | } 23 | 24 | instance FromEnv Config where 25 | fromEnv _ = do 26 | token <- GH.OAuth <$> env "GITHUB_TOKEN" 27 | (owner, repo) <- 28 | T.split (== '/') <$> env "REPO" >>= \case 29 | [owner, name] -> pure (owner, name) 30 | _ -> fail "malformed repo" 31 | checkName <- 32 | envMaybe "PROJECT_NAME" <&> \case 33 | Just pName | not . T.null . T.strip $ pName -> "compaREST – " <> pName 34 | _ -> "compaREST" 35 | footerText <- env "FOOTER" 36 | root <- envMaybe "ROOT" .!= "." 37 | sha <- env "SHA" 38 | pure $ 39 | Config 40 | { githubToken = token 41 | , repoOwner = GH.mkName Proxy owner 42 | , repoName = GH.mkName Proxy repo 43 | , checkName = checkName 44 | , footerText = footerText 45 | , root = root 46 | , sha = GH.mkName Proxy sha 47 | } 48 | -------------------------------------------------------------------------------- /github-action/Control/Monad/Freer/GitHub.hs: -------------------------------------------------------------------------------- 1 | module Control.Monad.Freer.GitHub 2 | ( GitHub (..), 3 | runGitHub, 4 | sendGitHub, 5 | ) 6 | where 7 | 8 | import Control.Monad.Freer 9 | import Control.Monad.Freer.Error 10 | import Control.Monad.IO.Class 11 | import Data.Aeson 12 | import GitHub hiding (Error) 13 | import qualified GitHub as GH 14 | 15 | data GitHub r where 16 | SendGHRequest :: FromJSON x => Request 'RW x -> GitHub x 17 | 18 | runGitHub :: (Member (Error GH.Error) effs, MonadIO (Eff effs)) => Auth -> Eff (GitHub ': effs) ~> Eff effs 19 | runGitHub auth = 20 | interpret 21 | ( \(SendGHRequest req) -> 22 | liftIO (executeRequest auth req) 23 | >>= either throwError pure 24 | ) 25 | 26 | sendGitHub :: (FromJSON x, Member GitHub effs) => Request 'RW x -> Eff effs x 27 | sendGitHub req = send $ SendGHRequest req 28 | -------------------------------------------------------------------------------- /github-action/GitHub/Endpoints/Checks.hs: -------------------------------------------------------------------------------- 1 | module GitHub.Endpoints.Checks 2 | ( checkR, 3 | ) 4 | where 5 | 6 | import Data.Aeson 7 | import GitHub 8 | import GitHub.Data.Checks 9 | 10 | checkR :: Name Owner -> Name Repo -> Check -> Request 'RW Value 11 | checkR user repo = 12 | command Post ["repos", toPathPart user, toPathPart repo, "check-runs"] . encode 13 | -------------------------------------------------------------------------------- /github-action/Main.hs: -------------------------------------------------------------------------------- 1 | module Main (main) where 2 | 3 | import CompaREST.GitHub.API 4 | import CompaREST.GitHub.Action.Config 5 | import Control.Exception 6 | import Control.Monad.Freer 7 | import Control.Monad.Freer.Error 8 | import Control.Monad.Freer.GitHub 9 | import Control.Monad.Freer.Reader 10 | import Data.OpenApi.Compare.Run 11 | import Data.Text (Text) 12 | import qualified Data.Text as T 13 | import qualified Data.Yaml.Aeson as Yaml 14 | import qualified GitHub as GH 15 | import System.Environment 16 | import System.Envy (decodeEnv) 17 | import System.FilePath (()) 18 | import Text.Pandoc (runPure) 19 | import Text.Pandoc.Builder 20 | import Text.Pandoc.Options 21 | import Text.Pandoc.Writers 22 | 23 | main :: IO () 24 | main = do 25 | cfg <- decodeEnv >>= either error pure 26 | case sha cfg of 27 | x | T.null . T.strip . GH.untagName $ x -> do 28 | putStrLn "SHA not specified. Exiting without doing anything." 29 | pure () 30 | _ -> 31 | getArgs >>= \case 32 | ["pre"] -> runPre cfg 33 | ["run"] -> do 34 | oldFile <- getEnv "OLD" 35 | newFile <- getEnv "NEW" 36 | runRun cfg (root cfg oldFile) (root cfg newFile) 37 | _ -> error "Invalid arguments." 38 | 39 | runner :: Config -> Eff '[GitHub, Error GH.Error, Reader Config, IO] a -> IO a 40 | runner cfg = 41 | runM @IO . runReader cfg 42 | . flip (handleError @GH.Error) (error . displayException) 43 | . runGitHub (githubToken cfg) 44 | 45 | runPre :: Config -> IO () 46 | runPre cfg = runner cfg postStatusProcessing 47 | 48 | runRun :: Config -> FilePath -> FilePath -> IO () 49 | runRun cfg old' new' = runner cfg $ do 50 | old <- Yaml.decodeFileThrow old' 51 | new <- Yaml.decodeFileThrow new' 52 | let reportConfig = 53 | ReportConfig 54 | { treeStyle = FoldingBlockquotesTreeStyle 55 | , reportMode = All 56 | } 57 | (report, status) = runReport reportConfig (old, new) 58 | 59 | body = markdown report <> "\n\n" <> footerText cfg 60 | 61 | result = 62 | if old == new 63 | then Nothing 64 | else Just (body, status) 65 | postStatus result 66 | 67 | markdown :: Blocks -> Text 68 | markdown = 69 | either (error . displayException) id 70 | . runPure 71 | . writeHtml5String def 72 | . doc 73 | -------------------------------------------------------------------------------- /nix/ci.nix: -------------------------------------------------------------------------------- 1 | { sources ? import ./sources.nix 2 | , pkgs ? import sources.nixpkgs { } 3 | }: 4 | 5 | let 6 | yq = import ./yq.nix { inherit pkgs; }; 7 | diff-yaml = import ./diff-yaml.nix { inherit pkgs; }; 8 | in 9 | pkgs.mkShell { 10 | packages = [ pkgs.haskellPackages.fourmolu diff-yaml yq ]; 11 | } 12 | -------------------------------------------------------------------------------- /nix/diff-yaml.nix: -------------------------------------------------------------------------------- 1 | { pkgs ? import {} }: 2 | 3 | let 4 | inherit (pkgs) stdenv; 5 | yq = import ./yq.nix { inherit pkgs; }; 6 | in 7 | stdenv.mkDerivation { 8 | name = "diff-yaml"; 9 | 10 | src = ../scripts/diff-yaml; 11 | 12 | buildInputs = [ pkgs.bash yq ]; 13 | 14 | phases = [ "installPhase" ]; 15 | 16 | installPhase = '' 17 | mkdir -p $out/bin 18 | cp $src $out/bin/diff-yaml 19 | ''; 20 | } 21 | -------------------------------------------------------------------------------- /nix/shell.nix: -------------------------------------------------------------------------------- 1 | { sources ? import ./sources.nix 2 | , pkgs ? import sources.nixpkgs { } 3 | }: 4 | 5 | let 6 | patched-yq = import ./yq.nix { inherit pkgs; }; 7 | diffYaml = import ./diff-yaml.nix { inherit pkgs; }; 8 | in 9 | pkgs.mkShell { 10 | buildInputs = with pkgs; [ pkg-config diffYaml patched-yq zlib ]; 11 | } 12 | -------------------------------------------------------------------------------- /nix/sources.json: -------------------------------------------------------------------------------- 1 | { 2 | "haskellNix": { 3 | "branch": "master", 4 | "description": "Alternative Haskell Infrastructure for Nixpkgs", 5 | "homepage": "https://input-output-hk.github.io/haskell.nix", 6 | "owner": "input-output-hk", 7 | "repo": "haskell.nix", 8 | "rev": "d7f95903c84a5a50d6fe0844280da82c3c81680a", 9 | "sha256": "02870rk4sx44lwwa0k20iwdhqcx0ayz34yb3b0qy045p22q45815", 10 | "type": "tarball", 11 | "url": "https://github.com/input-output-hk/haskell.nix/archive/d7f95903c84a5a50d6fe0844280da82c3c81680a.tar.gz", 12 | "url_template": "https://github.com///archive/.tar.gz" 13 | }, 14 | "niv": { 15 | "branch": "master", 16 | "description": "Easy dependency management for Nix projects", 17 | "homepage": "https://github.com/nmattia/niv", 18 | "owner": "nmattia", 19 | "repo": "niv", 20 | "rev": "f7c538837892dd2eb83567c9f380a11efb59b53f", 21 | "sha256": "0xl33k24vfc29cg9lnp95kvcq69qbq5fzb7jk9ig4lgrhaarh651", 22 | "type": "tarball", 23 | "url": "https://github.com/nmattia/niv/archive/f7c538837892dd2eb83567c9f380a11efb59b53f.tar.gz", 24 | "url_template": "https://github.com///archive/.tar.gz" 25 | }, 26 | "nix-filter": { 27 | "branch": "main", 28 | "description": "a small self-container source filtering lib", 29 | "homepage": "", 30 | "owner": "numtide", 31 | "repo": "nix-filter", 32 | "rev": "3342559a24e85fc164b295c3444e8a139924675b", 33 | "sha256": "08xia32g5jzaiyhfl3kzxslzbr4w1i56i0mhy5gpfggv8gqy8sym", 34 | "type": "tarball", 35 | "url": "https://github.com/numtide/nix-filter/archive/3342559a24e85fc164b295c3444e8a139924675b.tar.gz", 36 | "url_template": "https://github.com///archive/.tar.gz" 37 | }, 38 | "nixpkgs": { 39 | "branch": "master", 40 | "description": "Nix Packages collection", 41 | "homepage": "", 42 | "owner": "NixOS", 43 | "repo": "nixpkgs", 44 | "rev": "bf038bd724982de67a2ee9a6b2f1fcb7d6a87bd7", 45 | "sha256": "0ivvwdmg9fipj6ylq5ipxqpb0xnz6hsx3lyn377jacfpiqi9w0cv", 46 | "type": "tarball", 47 | "url": "https://github.com/NixOS/nixpkgs/archive/bf038bd724982de67a2ee9a6b2f1fcb7d6a87bd7.tar.gz", 48 | "url_template": "https://github.com///archive/.tar.gz" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /nix/yq.nix: -------------------------------------------------------------------------------- 1 | { pkgs ? import {} }: 2 | 3 | # Make yq work inside whatever `stack test` launches. 4 | # Nuke this when https://github.com/kislyuk/yq/pull/193 is merged 5 | # and nixpkgs includes that fix. 6 | 7 | let 8 | yq-patch = pkgs.writeText "yq-tty-fix.patch" '' 9 | diff --git a/yq/__init__.py b/yq/__init__.py 10 | index d95ac4b..ae7d59e 100644 11 | --- a/yq/__init__.py 12 | +++ b/yq/__init__.py 13 | @@ -110,7 +110,7 @@ def cli(args=None, input_format="yaml", program_name="yq"): 14 | in_place = args.in_place 15 | delattr(args, "in_place") 16 | 17 | - if sys.stdin.isatty() and not args.input_streams: 18 | + if (sys.stdin is None or sys.stdin.isatty()) and not args.input_streams: 19 | parser.print_help() 20 | sys.exit(2) 21 | elif not args.input_streams: 22 | ''; 23 | in 24 | pkgs.yq.overrideAttrs (final: old: { 25 | patches = old.patches ++ [ yq-patch ]; 26 | }) 27 | -------------------------------------------------------------------------------- /scripts/diff-yaml: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | # Normalise YAML files passed as inputs, then run diff on them. 5 | 6 | check_util() { 7 | local util=$1 8 | 9 | if [ -z $util ]; then 10 | echo "Error: $util not found in PATH" 11 | exit 1 12 | fi 13 | } 14 | 15 | DIFF=`which diff` 16 | check_util $DIFF 17 | 18 | YQ=`which yq` 19 | check_util $YQ 20 | 21 | # Only normalise YAML files. 22 | # Print anything else as is. 23 | normalise() { 24 | local file=$1 25 | local contents=($YQ -y -S '.' $file) 26 | 27 | # if $contents contains actual YAML data, print it 28 | if [[ $? == 0 ]]; then 29 | echo $contents 30 | else 31 | cat $file 32 | fi 33 | } 34 | 35 | $DIFF -u <(normalise $1) <(normalise $2) 36 | -------------------------------------------------------------------------------- /src/Data/HList.hs: -------------------------------------------------------------------------------- 1 | module Data.HList 2 | ( Has, 3 | HasAll, 4 | getH, 5 | HList (..), 6 | singletonH, 7 | ReassembleHList, 8 | reassemble, 9 | ) 10 | where 11 | 12 | import Data.Kind 13 | import GHC.TypeLits 14 | 15 | data HList (xs :: [Type]) where 16 | HNil :: HList '[] 17 | HCons :: x -> HList xs -> HList (x ': xs) 18 | 19 | infixr 5 `HCons` 20 | 21 | type family HasAll xs ys :: Constraint where 22 | HasAll '[] _ = () 23 | HasAll (x ': xs) ys = (Has x ys, HasAll xs ys) 24 | 25 | type Has x xs = Has' x xs (HeadEq x xs) 26 | 27 | type family HeadEq x xs where 28 | HeadEq x (x ': _) = 'True 29 | HeadEq _ _ = 'False 30 | 31 | class t ~ HeadEq x xs => Has' (x :: Type) (xs :: [Type]) (t :: Bool) where 32 | getH :: HList xs -> x 33 | 34 | instance Has' x (x ': xs) 'True where 35 | getH (HCons x _) = x 36 | {-# INLINE getH #-} 37 | 38 | instance (Has' x xs t, HeadEq x (y : xs) ~ 'False) => Has' x (y ': xs) 'False where 39 | getH (HCons _ xs) = getH xs 40 | {-# INLINE getH #-} 41 | 42 | instance 43 | TypeError ( 'ShowType x ':<>: 'Text " is not a part of the list.") => 44 | Has' x '[] 'False 45 | where 46 | getH HNil = undefined 47 | {-# INLINE getH #-} 48 | 49 | singletonH :: a -> HList '[a] 50 | singletonH a = a `HCons` HNil 51 | {-# INLINE singletonH #-} 52 | 53 | instance Eq (HList '[]) where 54 | HNil == HNil = True 55 | 56 | instance (Eq x, Eq (HList xs)) => Eq (HList (x ': xs)) where 57 | (HCons x xs) == (HCons y ys) = x == y && xs == ys 58 | 59 | type family (==) a b :: Bool where 60 | a == a = 'True 61 | _ == _ = 'False 62 | 63 | type ReassembleHList xs ys = ReassembleHList' xs ys (xs == ys) 64 | 65 | class f ~ (xs == ys) => ReassembleHList' xs ys f where 66 | reassemble :: HList xs -> HList ys 67 | 68 | instance ReassembleHList' xs xs 'True where 69 | reassemble = id 70 | {-# INLINE reassemble #-} 71 | 72 | instance ReassembleHList' (x ': xs) '[] 'False where 73 | reassemble _ = HNil 74 | {-# INLINE reassemble #-} 75 | 76 | instance 77 | (Has y xs, ReassembleHList' xs ys f, (xs == (y ': ys)) ~ 'False) => 78 | ReassembleHList' xs (y ': ys) 'False 79 | where 80 | reassemble xs = getH @y xs `HCons` reassemble xs 81 | {-# INLINE reassemble #-} 82 | -------------------------------------------------------------------------------- /src/Data/OpenApi/Compare/Common.hs: -------------------------------------------------------------------------------- 1 | module Data.OpenApi.Compare.Common 2 | ( zipAll, 3 | ) 4 | where 5 | 6 | zipAll :: [a] -> [b] -> Maybe [(a, b)] 7 | zipAll [] [] = Just [] 8 | zipAll (x : xs) (y : ys) = ((x, y) :) <$> zipAll xs ys 9 | zipAll (_ : _) [] = Nothing 10 | zipAll [] (_ : _) = Nothing 11 | -------------------------------------------------------------------------------- /src/Data/OpenApi/Compare/Orphans.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -Wno-orphans #-} 2 | 3 | module Data.OpenApi.Compare.Orphans () where 4 | 5 | import Control.Comonad.Env 6 | import qualified Data.HashMap.Strict.InsOrd as IOHM 7 | import Data.OpenApi 8 | 9 | deriving newtype instance Ord Reference 10 | 11 | deriving stock instance Ord a => Ord (Referenced a) 12 | 13 | deriving stock instance Ord Schema 14 | 15 | deriving stock instance Ord AdditionalProperties 16 | 17 | deriving stock instance Ord Discriminator 18 | 19 | deriving stock instance Ord Xml 20 | 21 | deriving stock instance Ord OpenApiType 22 | 23 | deriving stock instance Ord Style 24 | 25 | deriving stock instance Ord OpenApiItems 26 | 27 | deriving stock instance Ord ParamLocation 28 | 29 | deriving stock instance Ord HttpSchemeType 30 | 31 | deriving stock instance Ord ApiKeyParams 32 | 33 | deriving stock instance Ord ApiKeyLocation 34 | 35 | instance (Ord k, Ord v) => Ord (IOHM.InsOrdHashMap k v) where 36 | compare xs ys = compare (IOHM.toList xs) (IOHM.toList ys) 37 | 38 | deriving stock instance (Eq e, Eq (w a)) => Eq (EnvT e w a) 39 | 40 | deriving stock instance (Ord e, Ord (w a)) => Ord (EnvT e w a) 41 | 42 | deriving stock instance (Show e, Show (w a)) => Show (EnvT e w a) 43 | -------------------------------------------------------------------------------- /src/Data/OpenApi/Compare/References.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -Wno-orphans #-} 2 | 3 | module Data.OpenApi.Compare.References 4 | ( Step (..), 5 | dereference, 6 | Typeable, 7 | ) 8 | where 9 | 10 | import Data.HList 11 | import qualified Data.HashMap.Strict.InsOrd as IOHM 12 | import Data.Maybe 13 | import Data.OpenApi 14 | import Data.OpenApi.Compare.Orphans () 15 | import Data.OpenApi.Compare.Subtree 16 | 17 | instance Typeable a => Steppable (Referenced a) a where 18 | data Step (Referenced a) a = InlineStep 19 | deriving stock (Eq, Ord, Show) 20 | 21 | dereference :: 22 | Typeable a => 23 | Traced (Definitions a) -> 24 | Traced (Referenced a) -> 25 | Traced a 26 | dereference defs x = case extract x of 27 | Inline a -> 28 | traced (ask x >>> step InlineStep) a 29 | Ref (Reference ref) -> 30 | traced (ask defs >>> step (InsOrdHashMapKeyStep ref)) (fromJust $ IOHM.lookup ref $ extract defs) 31 | 32 | instance Subtree a => Subtree (Referenced a) where 33 | type CheckEnv (Referenced a) = ProdCons (Traced (Definitions a)) ': CheckEnv a 34 | type SubtreeLevel (Referenced a) = SubtreeLevel a 35 | 36 | checkStructuralCompatibility (defs `HCons` env) pc' = do 37 | let pc = do 38 | x <- pc' 39 | defs' <- defs 40 | pure (dereference defs' x) 41 | checkSubstructure env pc 42 | 43 | checkSemanticCompatibility (defs `HCons` env) bhv pc' = do 44 | let pc = do 45 | x <- pc' 46 | defs' <- defs 47 | pure (dereference defs' x) 48 | checkCompatibility bhv env pc 49 | -------------------------------------------------------------------------------- /src/Data/OpenApi/Compare/Report/Html/Template.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE TemplateHaskell #-} 2 | 3 | module Data.OpenApi.Compare.Report.Html.Template 4 | ( template, 5 | ) 6 | where 7 | 8 | import Control.Monad.Identity 9 | import Data.ByteString (ByteString) 10 | import Data.FileEmbed 11 | import Data.Text (Text) 12 | import qualified Data.Text.Encoding as T 13 | import Text.DocTemplates 14 | 15 | template :: Template Text 16 | template = 17 | either error id . runIdentity . compileTemplate "" $ 18 | "\ 19 | \\ 20 | \\ 21 | \\ 24 | \\ 25 | \\ 26 | \\ 27 | \\ 28 | \\ 29 | \\ 30 | \\ 31 | \

CompaREST

\ 32 | \
\ 33 | \$body$\ 34 | \
\ 35 | \\ 36 | \" 37 | 38 | awsmCss :: ByteString 39 | awsmCss = $(makeRelativeToProject "css/awsm.min.css" >>= embedFile) 40 | -------------------------------------------------------------------------------- /src/Data/OpenApi/Compare/Report/Jet.hs: -------------------------------------------------------------------------------- 1 | module Data.OpenApi.Compare.Report.Jet 2 | ( ReportJet (..), 3 | ReportJet', 4 | ConstructReportJet (..), 5 | ReportJetResult, 6 | ) 7 | where 8 | 9 | import Control.Applicative 10 | import Control.Monad.Free 11 | import Data.List.NonEmpty 12 | import qualified Data.List.NonEmpty as NE 13 | import Data.OpenUnion 14 | import Data.OpenUnion.Extra 15 | import Data.Typeable 16 | import Text.Pandoc.Builder 17 | 18 | -- | A "jet" is a way of simplifying expressions from "outside". The "jetted" 19 | -- expressions should still be completely valid and correct without the jets. 20 | -- Jets just make the expression more "optimized" by identifying patterns and 21 | -- replacing the expressions with "better" ones that have the same sematics. 22 | -- 23 | -- The term "jet" in this context was introduced in the Urbit project: 24 | -- https://urbit.org/docs/vere/jetting/ 25 | -- 26 | -- The pattern fits well for simplifying 'Behavior' tree paths. 27 | class ConstructReportJet x f where 28 | constructReportJet :: x -> ReportJetResult f (Maybe Inlines) 29 | 30 | instance (ConstructReportJet b f, JetArg a) => ConstructReportJet (a -> b) f where 31 | constructReportJet f = Free (fmap f <$> consumeJetArg @a) >>= constructReportJet 32 | 33 | instance ConstructReportJet (Maybe Inlines) f where 34 | constructReportJet x = Pure x 35 | 36 | instance ConstructReportJet Inlines f where 37 | constructReportJet x = Pure $ Just x 38 | 39 | class JetArg a where 40 | consumeJetArg :: ReportJet' f a 41 | 42 | instance Typeable (f a b) => JetArg (f a b) where 43 | consumeJetArg = 44 | ReportJet $ \(x :: x) -> 45 | case eqT @(f a b) @x of 46 | Nothing -> empty 47 | Just Refl -> pure $ Pure x 48 | 49 | instance TryLiftUnion xs => JetArg (Union xs) where 50 | consumeJetArg = ReportJet $ fmap Pure . tryLiftUnion 51 | 52 | instance JetArg x => JetArg (NonEmpty x) where 53 | consumeJetArg = 54 | let (ReportJet f) = (consumeJetArg @x) 55 | in ReportJet $ \a -> do 56 | u <- f a 57 | pure (u >>= \y -> Free $ fmap (NE.cons y) <$> consumeJetArg) 58 | <|> pure (pure <$> u) 59 | 60 | type ReportJetResult f = Free (ReportJet f) 61 | 62 | -- Not a true 'Applicative' 63 | newtype ReportJet f x 64 | = ReportJet (forall a b m. (Typeable (f a b), Alternative m, Monad m) => f a b -> m x) 65 | deriving stock (Functor) 66 | 67 | type ReportJet' f a = ReportJet f (Free (ReportJet f) a) 68 | -------------------------------------------------------------------------------- /src/Data/OpenApi/Compare/Run.hs: -------------------------------------------------------------------------------- 1 | module Data.OpenApi.Compare.Run 2 | ( runChecker, 3 | runReport, 4 | module Data.OpenApi.Compare.Report, 5 | ) 6 | where 7 | 8 | import Data.HList 9 | import Data.OpenApi (OpenApi) 10 | import Data.OpenApi.Compare.Paths 11 | import Data.OpenApi.Compare.Report 12 | import Data.OpenApi.Compare.Subtree 13 | import Data.OpenApi.Compare.Validate.OpenApi () 14 | import Text.Pandoc.Builder 15 | 16 | runChecker :: (OpenApi, OpenApi) -> CheckerOutput 17 | runChecker (client, server) = 18 | CheckerOutput 19 | { forwardChanges = run client server 20 | , backwardChanges = run server client 21 | } 22 | where 23 | toPC p c = 24 | ProdCons 25 | { producer = traced (step ClientSchema) p 26 | , consumer = traced (step ServerSchema) c 27 | } 28 | run p c = either id mempty . runCompatFormula . checkCompatibility Root HNil $ toPC p c 29 | 30 | runReport :: ReportConfig -> (OpenApi, OpenApi) -> (Blocks, ReportStatus) 31 | runReport cfg = generateReport cfg . segregateIssues . runChecker 32 | -------------------------------------------------------------------------------- /src/Data/OpenApi/Compare/Validate/Header.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -Wno-orphans #-} 2 | 3 | module Data.OpenApi.Compare.Validate.Header 4 | ( 5 | ) 6 | where 7 | 8 | import Data.Foldable 9 | import Data.Functor 10 | import Data.Maybe 11 | import Data.OpenApi 12 | import Data.OpenApi.Compare.Behavior 13 | import Data.OpenApi.Compare.References () 14 | import Data.OpenApi.Compare.Subtree 15 | import Data.OpenApi.Compare.Validate.Schema () 16 | import Text.Pandoc.Builder 17 | 18 | instance Subtree Header where 19 | type SubtreeLevel Header = 'HeaderLevel 20 | type CheckEnv Header = '[ProdCons (Traced (Definitions Schema))] 21 | checkStructuralCompatibility env pc = do 22 | structuralEq $ fmap _headerRequired <$> pc 23 | structuralEq $ fmap _headerAllowEmptyValue <$> pc 24 | structuralEq $ fmap _headerExplode <$> pc 25 | structuralMaybe env $ tracedSchema <$> pc 26 | pure () 27 | checkSemanticCompatibility env beh (ProdCons p c) = do 28 | if (fromMaybe False $ _headerRequired $ extract c) && not (fromMaybe False $ _headerRequired $ extract p) 29 | then issueAt beh RequiredHeaderMissing 30 | else pure () 31 | if not (fromMaybe False $ _headerAllowEmptyValue $ extract c) && (fromMaybe False $ _headerAllowEmptyValue $ extract p) 32 | then issueAt beh NonEmptyHeaderRequired 33 | else pure () 34 | for_ (tracedSchema c) $ \consRef -> 35 | case tracedSchema p of 36 | Nothing -> issueAt beh HeaderSchemaRequired 37 | Just prodRef -> checkCompatibility (beh >>> step InSchema) env (ProdCons prodRef consRef) 38 | pure () 39 | 40 | instance Steppable Header (Referenced Schema) where 41 | data Step Header (Referenced Schema) = HeaderSchema 42 | deriving stock (Eq, Ord, Show) 43 | 44 | tracedSchema :: Traced Header -> Maybe (Traced (Referenced Schema)) 45 | tracedSchema hdr = _headerSchema (extract hdr) <&> traced (ask hdr >>> step HeaderSchema) 46 | 47 | instance Issuable 'HeaderLevel where 48 | data Issue 'HeaderLevel 49 | = RequiredHeaderMissing 50 | | NonEmptyHeaderRequired 51 | | HeaderSchemaRequired 52 | deriving stock (Eq, Ord, Show) 53 | issueKind = \case 54 | HeaderSchemaRequired -> ProbablyIssue -- catch-all schema? 55 | _ -> CertainIssue 56 | describeIssue Forward RequiredHeaderMissing = para "Header has become required." 57 | describeIssue Backward RequiredHeaderMissing = para "Header is no longer required." 58 | describeIssue Forward NonEmptyHeaderRequired = para "The header does not allow empty values anymore." 59 | describeIssue Backward NonEmptyHeaderRequired = para "The header now allows empty values." 60 | describeIssue _ HeaderSchemaRequired = para "Expected header schema, but it is not present." 61 | 62 | instance Behavable 'HeaderLevel 'SchemaLevel where 63 | data Behave 'HeaderLevel 'SchemaLevel 64 | = InSchema 65 | deriving stock (Eq, Ord, Show) 66 | describeBehavior InSchema = "JSON Schema" 67 | -------------------------------------------------------------------------------- /src/Data/OpenApi/Compare/Validate/Link.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -Wno-orphans #-} 2 | 3 | module Data.OpenApi.Compare.Validate.Link () where 4 | 5 | import Data.OpenApi 6 | import Data.OpenApi.Compare.Behavior 7 | import Data.OpenApi.Compare.Subtree 8 | import Text.Pandoc.Builder 9 | 10 | instance Subtree Link where 11 | type SubtreeLevel Link = 'LinkLevel 12 | type CheckEnv Link = '[] 13 | checkStructuralCompatibility _ _ = structuralIssue 14 | checkSemanticCompatibility _ bhv _ = issueAt bhv LinksUnsupported 15 | 16 | instance Issuable 'LinkLevel where 17 | data Issue 'LinkLevel 18 | = LinksUnsupported 19 | deriving stock (Eq, Ord, Show) 20 | issueKind = \case 21 | LinksUnsupported -> Unsupported 22 | describeIssue _ LinksUnsupported = para "CompaREST does not currently support Link Objects." 23 | -------------------------------------------------------------------------------- /src/Data/OpenApi/Compare/Validate/PathFragment.hs: -------------------------------------------------------------------------------- 1 | module Data.OpenApi.Compare.Validate.PathFragment 2 | ( parsePath, 3 | PathFragment (..), 4 | PathFragmentParam, 5 | ) 6 | where 7 | 8 | import qualified Data.Aeson as A 9 | import Data.OpenApi 10 | import Data.OpenApi.Compare.Behavior 11 | import Data.OpenApi.Compare.Subtree 12 | import Data.OpenApi.Compare.Validate.Param 13 | import Data.Text (Text) 14 | import qualified Data.Text as T 15 | 16 | -- TODO: templates can be only part of the PathFragment. Currently only supports templates as full PathFragment. 17 | -- #23 18 | parsePath :: FilePath -> [PathFragment Text] 19 | parsePath = fmap partition . T.splitOn "/" . T.pack 20 | where 21 | partition :: Text -> PathFragment Text 22 | partition t 23 | | Just ('{', rest) <- T.uncons t 24 | , Just (ref, '}') <- T.unsnoc rest = 25 | DynamicPath ref 26 | partition t = StaticPath t 27 | 28 | -- | Fragment parameterized by parameter. The dynamic part may be either 29 | -- reference to some parameter (in context of operation) or dereferenced 30 | -- parameter itself. 31 | data PathFragment param 32 | = StaticPath Text 33 | | DynamicPath param 34 | deriving stock (Eq, Ord, Show, Functor) 35 | 36 | type PathFragmentParam = PathFragment (Traced Param) 37 | 38 | instance (Typeable param) => Steppable (PathFragment param) Param where 39 | data Step (PathFragment param) Param = StaticPathParam Text 40 | deriving stock (Eq, Ord, Show) 41 | 42 | tracedPathFragmentParam :: Traced PathFragmentParam -> Traced Param 43 | tracedPathFragmentParam pfp = case extract pfp of 44 | StaticPath s -> 45 | traced (ask pfp >>> step (StaticPathParam s)) $ 46 | mempty 47 | { _paramRequired = Just True 48 | , _paramIn = ParamPath 49 | , _paramAllowEmptyValue = Just False 50 | , _paramAllowReserved = Just False 51 | , _paramSchema = Just $ Inline $ staticStringSchema s 52 | } 53 | DynamicPath p -> p 54 | 55 | staticStringSchema :: Text -> Schema 56 | staticStringSchema t = 57 | mempty 58 | { _schemaNullable = Just False 59 | , _schemaType = Just OpenApiString 60 | , _schemaEnum = Just [A.String t] 61 | } 62 | 63 | instance Subtree PathFragmentParam where 64 | type SubtreeLevel PathFragmentParam = 'PathFragmentLevel 65 | type 66 | CheckEnv PathFragmentParam = 67 | '[ProdCons (Traced (Definitions Schema))] 68 | 69 | -- Not much to compare at this level 70 | checkStructuralCompatibility _ _ = structuralIssue 71 | 72 | -- This case isn't strictly needed. It is here for optimization. 73 | checkSemanticCompatibility _ beh (ProdCons (extract -> StaticPath x) (extract -> StaticPath y)) = 74 | if x == y 75 | then pure () 76 | else issueAt beh (PathFragmentsDontMatch (ProdCons x y)) 77 | checkSemanticCompatibility env beh prodCons = do 78 | checkCompatibility beh env (tracedPathFragmentParam <$> prodCons) 79 | -------------------------------------------------------------------------------- /src/Data/OpenApi/Compare/Validate/Products.hs: -------------------------------------------------------------------------------- 1 | -- | Checks product-like entities. The key is some identificator for the product 2 | --element. Each element may be required or optional. 3 | -- 4 | --One example of product is request parameters. There are optional and required 5 | --parameters. The client and server have possibly different set of 6 | --parameters. What we must check is if server requires some request parameter, 7 | --then this parameter must be presented by client and their schemas must match. 8 | -- 9 | --So when we checking products we are checking from the server's (consumer) 10 | --perspective, ensuring that all parameters are provided by the client (producer) 11 | --and their schemas match. 12 | -- 13 | --This module abstracts this logic for arbitrary elements 14 | module Data.OpenApi.Compare.Validate.Products 15 | ( checkProducts, 16 | ProductLike (..), 17 | ) 18 | where 19 | 20 | import Data.Foldable 21 | import Data.Map.Strict (Map) 22 | import qualified Data.Map.Strict as M 23 | import Data.OpenApi.Compare.Behavior 24 | import Data.OpenApi.Compare.Paths 25 | import Data.OpenApi.Compare.Subtree 26 | 27 | -- | Some entity which is product-like 28 | data ProductLike a = ProductLike 29 | { productValue :: a 30 | , required :: Bool 31 | } 32 | 33 | checkProducts :: 34 | (Ord k, Issuable l) => 35 | Paths q r l -> 36 | -- | No required element found 37 | (k -> Issue l) -> 38 | (k -> ProdCons t -> CompatFormula' q AnIssue r ()) -> 39 | ProdCons (Map k (ProductLike t)) -> 40 | CompatFormula' q AnIssue r () 41 | checkProducts xs noElt check (ProdCons p c) = for_ (M.toList c) $ \(key, consElt) -> 42 | case M.lookup key p of 43 | Nothing -> case required consElt of 44 | True -> issueAt xs $ noElt key 45 | False -> pure () 46 | Just prodElt -> do 47 | let elts = ProdCons prodElt consElt 48 | check key (productValue <$> elts) 49 | -------------------------------------------------------------------------------- /src/Data/OpenApi/Compare/Validate/SecurityScheme.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -Wno-orphans #-} 2 | 3 | module Data.OpenApi.Compare.Validate.SecurityScheme 4 | ( 5 | ) 6 | where 7 | 8 | import Control.Monad 9 | import Data.OpenApi 10 | import Data.OpenApi.Compare.Behavior 11 | import Data.OpenApi.Compare.Orphans () 12 | import Data.OpenApi.Compare.Subtree 13 | import Data.OpenApi.Compare.Validate.OAuth2Flows 14 | 15 | instance Subtree SecurityScheme where 16 | type CheckEnv SecurityScheme = '[] 17 | type SubtreeLevel SecurityScheme = 'SecuritySchemeLevel 18 | checkStructuralCompatibility _ pc = structuralEq $ tracedSecuritySchemaTypes <$> pc 19 | checkSemanticCompatibility env bhv pcSecScheme = case tracedSecuritySchemaTypes <$> pcSecScheme of 20 | (ProdCons (Traced _ (SecuritySchemeHttp pType)) (Traced _ (SecuritySchemeHttp cType))) -> case (pType, cType) of 21 | (HttpSchemeBearer _, HttpSchemeBearer _) -> pure () 22 | (HttpSchemeBasic, HttpSchemeBasic) -> pure () 23 | (HttpSchemeCustom p, HttpSchemeCustom c) -> 24 | unless (p == c) (issueAt bhv $ CustomHttpSchemesDontMatch p c) 25 | _ -> issueAt bhv $ HttpSchemeTypesDontMatch pType cType 26 | (ProdCons (Traced _ (SecuritySchemeApiKey pParams)) (Traced _ (SecuritySchemeApiKey cParams))) -> do 27 | unless (pParams == cParams) (issueAt bhv $ ApiKeyParamsDontMatch pParams cParams) 28 | (ProdCons (Traced pT (SecuritySchemeOAuth2 pFlows)) (Traced cT (SecuritySchemeOAuth2 cFlows))) -> do 29 | checkCompatibility bhv env . fmap (stepTraced SecurityOAuthFlowsStep) $ ProdCons (Traced pT pFlows) (Traced cT cFlows) 30 | (ProdCons (Traced _ (SecuritySchemeOpenIdConnect pUrl)) (Traced _ (SecuritySchemeOpenIdConnect cUrl))) -> do 31 | unless (pUrl == cUrl) (issueAt bhv $ OpenIdConnectUrlsDontMatch pUrl cUrl) 32 | _ -> issueAt bhv DifferentSecuritySchemes 33 | 34 | tracedSecuritySchemaTypes :: Traced SecurityScheme -> Traced SecuritySchemeType 35 | tracedSecuritySchemaTypes (Traced t x) = Traced (t >>> step SecuritySchemeTypeStep) (_securitySchemeType x) 36 | 37 | instance Steppable SecurityScheme SecuritySchemeType where 38 | data Step SecurityScheme SecuritySchemeType = SecuritySchemeTypeStep 39 | deriving stock (Eq, Ord, Show) 40 | 41 | instance Steppable SecuritySchemeType OAuth2Flows where 42 | data Step SecuritySchemeType OAuth2Flows = SecurityOAuthFlowsStep 43 | deriving stock (Eq, Ord, Show) 44 | -------------------------------------------------------------------------------- /src/Data/OpenApi/Compare/Validate/Sums.hs: -------------------------------------------------------------------------------- 1 | module Data.OpenApi.Compare.Validate.Sums 2 | ( checkSums, 3 | ) 4 | where 5 | 6 | import Data.Foldable 7 | import Data.Map.Strict (Map) 8 | import qualified Data.Map.Strict as M 9 | import Data.OpenApi.Compare.Behavior 10 | import Data.OpenApi.Compare.Paths 11 | import Data.OpenApi.Compare.Subtree 12 | 13 | checkSums :: 14 | (Ord k, Issuable l) => 15 | Paths q r l -> 16 | (k -> Issue l) -> 17 | (k -> ProdCons t -> CompatFormula' q AnIssue r ()) -> 18 | ProdCons (Map k t) -> 19 | CompatFormula' q AnIssue r () 20 | checkSums xs noElt check (ProdCons p c) = for_ (M.toList p) $ \(key, prodElt) -> 21 | case M.lookup key c of 22 | Nothing -> issueAt xs $ noElt key 23 | Just consElt -> 24 | let sumElts = ProdCons prodElt consElt 25 | in check key sumElts 26 | -------------------------------------------------------------------------------- /src/Data/OpenUnion/Extra.hs: -------------------------------------------------------------------------------- 1 | module Data.OpenUnion.Extra 2 | ( (@@>), 3 | TryLiftUnion (..), 4 | pattern SingletonUnion, 5 | ) 6 | where 7 | 8 | import Control.Applicative 9 | import Data.Dynamic 10 | import Data.OpenUnion.Internal 11 | import Data.Typeable 12 | import TypeFun.Data.List hiding (Union) 13 | 14 | class TryLiftUnion xs where 15 | tryLiftUnion :: (Alternative m, Typeable x) => x -> m (Union xs) 16 | 17 | instance TryLiftUnion '[] where 18 | tryLiftUnion _ = empty 19 | 20 | instance 21 | (Typeable y, SubList ys (y : ys), TryLiftUnion ys) => 22 | TryLiftUnion (y ': ys) 23 | where 24 | tryLiftUnion (x :: x) = case eqT @x @y of 25 | Nothing -> reUnion <$> tryLiftUnion @ys x 26 | Just Refl -> pure $ liftUnion x 27 | 28 | -- | Like '@>', but enforces a specific type list order. 29 | -- (Useful for deconstruction-directed type inference.) 30 | (@@>) :: Typeable a => (a -> b) -> (Union xs -> b) -> Union (a ': xs) -> b 31 | r @@> l = either l r . restrict' 32 | where 33 | restrict' :: Typeable a => Union (a ': aa) -> Either (Union aa) a 34 | restrict' (Union d) = maybe (Left $ Union d) Right $ fromDynamic d 35 | {-# INLINE (@@>) #-} 36 | 37 | infixr 2 @@> 38 | 39 | pattern SingletonUnion :: (Typeable a, Elem a s) => a -> Union s 40 | pattern SingletonUnion x <- 41 | ((\(Union y) -> fromDynamic y) -> Just x) 42 | where 43 | SingletonUnion x = liftUnion x 44 | -------------------------------------------------------------------------------- /stack.yaml: -------------------------------------------------------------------------------- 1 | resolver: lts-22.34 2 | 3 | packages: 4 | - . 5 | 6 | extra-deps: 7 | - base16-bytestring-1.0.2.0 8 | - freer-simple-1.2.1.2 9 | - generics-sop-0.5.1.4 10 | - github-0.29 11 | - http-link-header-1.2.1 12 | - open-union-0.4.0.0 13 | - th-abstraction-0.7.0.0 14 | - type-fun-0.1.3 15 | - typerep-map-0.6.0.0 16 | 17 | # Required for freer-simple and typerep-map 18 | allow-newer: true 19 | 20 | nix: 21 | # packages: [pkg-config yq zlib] 22 | shell-file: ./nix/shell.nix 23 | pure: false 24 | -------------------------------------------------------------------------------- /stack.yaml.lock: -------------------------------------------------------------------------------- 1 | # This file was autogenerated by Stack. 2 | # You should not edit this file by hand. 3 | # For more information, please see the documentation at: 4 | # https://docs.haskellstack.org/en/stable/lock_files 5 | 6 | packages: 7 | - completed: 8 | hackage: open-union-0.4.0.0@sha256:1c8f8090054b0974e95e44bed88e74fff956ba2120aade6e8deea92d65ef5e49,3503 9 | pantry-tree: 10 | size: 329 11 | sha256: e01838ec41f7aa2a97aa2c3586c8188c4ad093ba0b2be41229ab7b8dbd33869e 12 | original: 13 | hackage: open-union-0.4.0.0 14 | - completed: 15 | hackage: type-fun-0.1.3@sha256:336b851757792f201078043210aec180021ac052f0955c71fa330a5fe11b0604,1765 16 | pantry-tree: 17 | size: 583 18 | sha256: b977d42525f0b4223959918d18e7905085283e937493c395077b608cd19b42c1 19 | original: 20 | hackage: type-fun-0.1.3 21 | - completed: 22 | hackage: github-0.26@sha256:a9d4046325c3eb28cdc7bef2c3f5bb213328caeae0b7dce6f51de655f0bffaa1,7162 23 | pantry-tree: 24 | size: 7511 25 | sha256: b71aab2984b268030c9e2617043575681134c1fe60dffbd5596e659c0a3e9aec 26 | original: 27 | hackage: github-0.26 28 | - completed: 29 | hackage: base16-bytestring-0.1.1.7@sha256:0021256a9628971c08da95cb8f4d0d72192f3bb8a7b30b55c080562d17c43dd3,2231 30 | pantry-tree: 31 | size: 454 32 | sha256: 2dc99cd67293b09204098202d0bdcdcf89d2b8c69ce6c8f4e31deadbdab2a7f9 33 | original: 34 | hackage: base16-bytestring-0.1.1.7 35 | - completed: 36 | hackage: http-link-header-1.0.3.1@sha256:9917c26635a46eff5d36c5344a4ae42fad2b5de79c0e300363bddd5eec66facd,1937 37 | pantry-tree: 38 | size: 990 39 | sha256: 155feaf856daf5b55491048c8c4726ba765a8fe79263ebdbfc82f6c385a15715 40 | original: 41 | hackage: http-link-header-1.0.3.1 42 | snapshots: 43 | - completed: 44 | size: 587393 45 | url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/25.yaml 46 | sha256: 1b74fb5e970497b5aefae56703f1bd44aa648bd1a5ef95c1eb8c29775087e2bf 47 | original: lts-18.25 48 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | # Golden tests 2 | 3 | ## The basics 4 | 5 | The `test/golden` directory contains a tree with golden tests. A test is a any nested directory with no folders nested inside it (i. e. tests can only be leaves in the file system): 6 | 7 | ``` 8 | id 9 | ├── a.yaml 10 | ├── b.yaml 11 | └── report.yaml 12 | ``` 13 | 14 | All of the files and their meaning are specified in code: 15 | 16 | 17 | ```haskell 18 | tests :: IO TestTree 19 | tests = 20 | goldenInputsTreeUniform 21 | "Golden Reports" 22 | "test/golden/common" 23 | "report.yaml" 24 | ("a.yaml", "b.yaml") 25 | Yaml.decodeFileThrow 26 | (uncurry reportCompat) 27 | ``` 28 | 29 | This test would read the files `a.yaml` and `b.yaml` using the `Yaml.decodeFileThrow` function, and pass the resulting tuple to `uncurry reportCompat`. The resul will be compared to `report.yaml`. 30 | 31 | ## Supported feature tests 32 | 33 | If a test starts with either `x ` or `v `, the test is assumed to test the support of some OpenAPI functionality. If the test begins `x ` it means that the feature is expected to be not supported, and the result will only be checked to have an "unsupported" flag set. If it starts with `v ` the test is expected to be supported and the result is compared to some file on disk. 34 | 35 | The result will be reflected in the generated compatibility matrix. 36 | 37 | If a test does not begin with either `x ` or `v `, then it is presumed to be a normal test and will not be reflected in the resulting compatibility matrix. 38 | -------------------------------------------------------------------------------- /test/Spec.hs: -------------------------------------------------------------------------------- 1 | module Main (main) where 2 | 3 | import qualified Spec.Golden.TraceTree 4 | import Test.Tasty 5 | 6 | main :: IO () 7 | main = defaultMain =<< tests 8 | 9 | tests :: IO TestTree 10 | tests = do 11 | goldenReportTree <- Spec.Golden.TraceTree.tests 12 | return . localOption (mkTimeout 5000000) $ goldenReportTree 13 | -------------------------------------------------------------------------------- /test/Spec/Golden/Extra.hs: -------------------------------------------------------------------------------- 1 | module Spec.Golden.Extra 2 | ( getGoldenInputs, 3 | getGoldenInputsUniform, 4 | goldenInputsTree, 5 | goldenInputsTreeUniform, 6 | ) 7 | where 8 | 9 | import Control.Lens 10 | import Control.Monad 11 | import qualified Data.ByteString.Lazy as BSL 12 | import System.Directory 13 | import System.FilePath 14 | import Test.Tasty 15 | import Test.Tasty.Golden 16 | 17 | data TestInput t 18 | = TestInputNode TestName [TestInput t] 19 | | TestInputLeaf TestName t FilePath 20 | deriving stock (Functor) 21 | 22 | getGoldenInputs :: 23 | (Each s t (FilePath, FilePath -> IO a) a) => 24 | TestName -> 25 | FilePath -> 26 | s -> 27 | IO (TestInput t) 28 | getGoldenInputs name filepath inp = do 29 | dirs' <- listDirectory filepath >>= filterM (doesDirectoryExist . (filepath )) 30 | case dirs' of 31 | -- A test 32 | [] -> do 33 | x <- 34 | inp & each %%~ \(file, f) -> 35 | f $ filepath file 36 | return $ TestInputLeaf name x filepath 37 | -- A test group 38 | dirs -> 39 | TestInputNode name 40 | <$> forM dirs (\dir -> getGoldenInputs dir (filepath dir) inp) 41 | 42 | getGoldenInputsUniform :: 43 | (Each t h (FilePath, FilePath -> IO a) a) => 44 | (Each s t FilePath (FilePath, FilePath -> IO a)) => 45 | TestName -> 46 | (FilePath -> IO a) -> 47 | FilePath -> 48 | s -> 49 | IO (TestInput h) 50 | getGoldenInputsUniform name f filepath inp = getGoldenInputs name filepath $ inp & each %~ (,f) 51 | 52 | goldenInputsTree :: 53 | (Each s t (FilePath, FilePath -> IO a) a) => 54 | TestName -> 55 | -- | Root path 56 | FilePath -> 57 | -- | Name of golden file 58 | FilePath -> 59 | s -> 60 | (t -> IO BSL.ByteString) -> 61 | IO TestTree 62 | goldenInputsTree name filepath golden inp f = 63 | runTestInputTree golden f <$> getGoldenInputs name filepath inp 64 | 65 | runTestInputTree :: 66 | FilePath -> 67 | (t -> IO BSL.ByteString) -> 68 | TestInput t -> 69 | TestTree 70 | runTestInputTree golden f (TestInputNode name rest) = 71 | testGroup name (runTestInputTree golden f <$> rest) 72 | runTestInputTree golden f (TestInputLeaf name t path) = 73 | goldenVsStringDiff 74 | name 75 | (\ref new -> ["diff-yaml", ref, new]) 76 | (path golden) 77 | (f t) 78 | 79 | goldenInputsTreeUniform :: 80 | ( Each t h (FilePath, FilePath -> IO a) a 81 | , Each s t FilePath (FilePath, FilePath -> IO a) 82 | ) => 83 | String -> 84 | -- | Root path 85 | FilePath -> 86 | -- | Name of golden file 87 | FilePath -> 88 | s -> 89 | (FilePath -> IO a) -> 90 | (h -> IO BSL.ByteString) -> 91 | IO TestTree 92 | goldenInputsTreeUniform name filepath golden inp h = 93 | goldenInputsTree name filepath golden (inp & each %~ (,h)) 94 | -------------------------------------------------------------------------------- /test/Spec/Golden/TraceTree.hs: -------------------------------------------------------------------------------- 1 | module Spec.Golden.TraceTree 2 | ( tests, 3 | ) 4 | where 5 | 6 | import Control.Category 7 | import Control.Exception 8 | import qualified Data.ByteString.Lazy as BSL 9 | import Data.Default 10 | import Data.OpenApi.Compare.Run 11 | import Data.OpenApi.Compare.Validate.OpenApi () 12 | import Data.Text (Text) 13 | import qualified Data.Text.Encoding as T 14 | import qualified Data.Yaml as Yaml 15 | import Spec.Golden.Extra 16 | import Test.Tasty (TestTree, testGroup) 17 | import Text.Pandoc.Builder 18 | import Text.Pandoc.Class 19 | import Text.Pandoc.Options 20 | import Text.Pandoc.Writers 21 | import Prelude hiding (id, (.)) 22 | 23 | tests :: IO TestTree 24 | tests = do 25 | traceTreeTests <- 26 | goldenInputsTreeUniform 27 | "TraceTree" 28 | "test/golden" 29 | "trace-tree.yaml" 30 | ("a.yaml", "b.yaml") 31 | Yaml.decodeFileThrow 32 | (pure . BSL.fromStrict . Yaml.encode . runChecker) 33 | 34 | reportTests <- 35 | goldenInputsTreeUniform 36 | "Report" 37 | "test/golden" 38 | "report.md" 39 | ("a.yaml", "b.yaml") 40 | Yaml.decodeFileThrow 41 | (runPandoc . writeMarkdown def {writerExtensions = githubMarkdownExtensions} . doc . fst . runReport def) 42 | 43 | return $ testGroup "Golden tests" [traceTreeTests, reportTests] 44 | 45 | runPandoc :: PandocPure Text -> IO BSL.ByteString 46 | runPandoc = either throwIO (pure . BSL.fromStrict . T.encodeUtf8) . runPure 47 | -------------------------------------------------------------------------------- /test/golden/common/bad-oneof-unchanged/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | oneOf: 26 | - type: object 27 | required: ["tag", "prop_A"] 28 | properties: 29 | tag: 30 | enum: ["A"] 31 | prop_A: 32 | type: string 33 | - type: object 34 | required: ["tag", "prop_B"] 35 | properties: 36 | tag: 37 | enum: ["A"] 38 | prop_B: 39 | type: number 40 | -------------------------------------------------------------------------------- /test/golden/common/bad-oneof-unchanged/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | oneOf: 26 | - type: object 27 | required: ["tag", "prop_B"] 28 | properties: 29 | tag: 30 | enum: ["A"] 31 | prop_B: 32 | type: number 33 | - type: object 34 | required: ["tag", "prop_A"] 35 | properties: 36 | tag: 37 | enum: ["A"] 38 | prop_A: 39 | type: string 40 | -------------------------------------------------------------------------------- /test/golden/common/bad-oneof-unchanged/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | ⚠️ Non-breaking changes | [❓ Unsupported feature changes](#unsupported-changes) | 4 | |---------------------|-------------------------|--------------------------------------------------------| 5 | | 0 | 0 | 2 | 6 | 7 | # ❓ Unsupported feature changes 8 | 9 | ## **POST** /test 10 | 11 | ### ➡️☁️ JSON Request 12 | 13 | Could not deduce that `oneOf` cases don't overlap. Treating the `oneOf` 14 | as an `anyOf`. Reported errors might not be accurate. 15 | 16 | ### ⬅️☁️ JSON Response – 200 17 | 18 | Could not deduce that `oneOf` cases don't overlap. Treating the `oneOf` 19 | as an `anyOf`. Reported errors might not be accurate. 20 | -------------------------------------------------------------------------------- /test/golden/common/bad-oneof-unchanged/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | InRequest: 5 | InPayload: 6 | PayloadSchema: OneOfNotDisjoint 7 | WithStatusCode 200: 8 | ResponsePayload: 9 | PayloadSchema: OneOfNotDisjoint 10 | backwardChanges: 11 | AtPath "/test": 12 | InOperation PostMethod: 13 | InRequest: 14 | InPayload: 15 | PayloadSchema: OneOfNotDisjoint 16 | WithStatusCode 200: 17 | ResponsePayload: 18 | PayloadSchema: OneOfNotDisjoint 19 | -------------------------------------------------------------------------------- /test/golden/common/enum-added/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | enum: ["A", "B"] 26 | -------------------------------------------------------------------------------- /test/golden/common/enum-added/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | enum: ["A", "B", "C"] 26 | -------------------------------------------------------------------------------- /test/golden/common/enum-added/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 1 | 1 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### ⬅️☁️ JSON Response – 200 12 | 13 | #### `$(String)` 14 | 15 | The following enum value was added: 16 | 17 | ``` json 18 | "C" 19 | ``` 20 | 21 | # ⚠️ Non-breaking changes 22 | 23 | ## **POST** /test 24 | 25 | ### ➡️☁️ JSON Request 26 | 27 | #### `$(String)` 28 | 29 | The following enum value was added: 30 | 31 | ``` json 32 | "C" 33 | ``` 34 | -------------------------------------------------------------------------------- /test/golden/common/enum-added/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | WithStatusCode 200: 5 | ResponsePayload: 6 | PayloadSchema: 7 | OfType String: EnumDoesntSatisfy (String "C") 8 | backwardChanges: 9 | AtPath "/test": 10 | InOperation PostMethod: 11 | InRequest: 12 | InPayload: 13 | PayloadSchema: 14 | OfType String: EnumDoesntSatisfy (String "C") 15 | -------------------------------------------------------------------------------- /test/golden/common/enum-anyof/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | anyOf: 26 | - enum: 27 | - "foo" 28 | - enum: 29 | - "bar" 30 | -------------------------------------------------------------------------------- /test/golden/common/enum-anyof/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | enum: 26 | - "foo" 27 | - "bar" 28 | -------------------------------------------------------------------------------- /test/golden/common/enum-anyof/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | ⚠️ Non-breaking changes | 4 | |---------------------|-------------------------| 5 | | 0 | 0 | 6 | -------------------------------------------------------------------------------- /test/golden/common/enum-anyof/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: {} 3 | -------------------------------------------------------------------------------- /test/golden/common/id/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /pets: 11 | get: 12 | summary: List all pets 13 | operationId: listPets 14 | tags: 15 | - pets 16 | parameters: 17 | - name: limit 18 | in: query 19 | description: How many items to return at one time (max 100) 20 | required: false 21 | schema: 22 | type: integer 23 | format: int32 24 | responses: 25 | '200': 26 | description: A paged array of pets 27 | headers: 28 | x-next: 29 | description: A link to the next page of responses 30 | schema: 31 | type: string 32 | content: 33 | application/json: 34 | schema: 35 | $ref: "#/components/schemas/Pets" 36 | default: 37 | description: unexpected error 38 | content: 39 | application/json: 40 | schema: 41 | $ref: "#/components/schemas/Error" 42 | post: 43 | summary: Create a pet 44 | operationId: createPets 45 | tags: 46 | - pets 47 | responses: 48 | '201': 49 | description: Null response 50 | default: 51 | description: unexpected error 52 | content: 53 | application/json: 54 | schema: 55 | $ref: "#/components/schemas/Error" 56 | /pets/{petId}: 57 | get: 58 | summary: Info for a specific pet 59 | operationId: showPetById 60 | tags: 61 | - pets 62 | parameters: 63 | - name: petId 64 | in: path 65 | required: true 66 | description: The id of the pet to retrieve 67 | schema: 68 | type: string 69 | responses: 70 | '200': 71 | description: Expected response to a valid request 72 | content: 73 | application/json: 74 | schema: 75 | $ref: "#/components/schemas/Pet" 76 | default: 77 | description: unexpected error 78 | content: 79 | application/json: 80 | schema: 81 | $ref: "#/components/schemas/Error" 82 | components: 83 | schemas: 84 | Pet: 85 | type: object 86 | required: 87 | - id 88 | - name 89 | properties: 90 | id: 91 | type: integer 92 | format: int64 93 | name: 94 | type: string 95 | tag: 96 | type: string 97 | Pets: 98 | type: array 99 | items: 100 | $ref: "#/components/schemas/Pet" 101 | Error: 102 | type: object 103 | required: 104 | - code 105 | - message 106 | properties: 107 | code: 108 | type: integer 109 | format: int32 110 | message: 111 | type: string 112 | -------------------------------------------------------------------------------- /test/golden/common/id/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /pets: 11 | get: 12 | summary: List all pets 13 | operationId: listPets 14 | tags: 15 | - pets 16 | parameters: 17 | - name: limit 18 | in: query 19 | description: How many items to return at one time (max 100) 20 | required: false 21 | schema: 22 | type: integer 23 | format: int32 24 | responses: 25 | '200': 26 | description: A paged array of pets 27 | headers: 28 | x-next: 29 | description: A link to the next page of responses 30 | schema: 31 | type: string 32 | content: 33 | application/json: 34 | schema: 35 | $ref: "#/components/schemas/Pets" 36 | default: 37 | description: unexpected error 38 | content: 39 | application/json: 40 | schema: 41 | $ref: "#/components/schemas/Error" 42 | post: 43 | summary: Create a pet 44 | operationId: createPets 45 | tags: 46 | - pets 47 | responses: 48 | '201': 49 | description: Null response 50 | default: 51 | description: unexpected error 52 | content: 53 | application/json: 54 | schema: 55 | $ref: "#/components/schemas/Error" 56 | /pets/{petId}: 57 | get: 58 | summary: Info for a specific pet 59 | operationId: showPetById 60 | tags: 61 | - pets 62 | parameters: 63 | - name: petId 64 | in: path 65 | required: true 66 | description: The id of the pet to retrieve 67 | schema: 68 | type: string 69 | responses: 70 | '200': 71 | description: Expected response to a valid request 72 | content: 73 | application/json: 74 | schema: 75 | $ref: "#/components/schemas/Pet" 76 | default: 77 | description: unexpected error 78 | content: 79 | application/json: 80 | schema: 81 | $ref: "#/components/schemas/Error" 82 | components: 83 | schemas: 84 | Pet: 85 | type: object 86 | required: 87 | - id 88 | - name 89 | properties: 90 | id: 91 | type: integer 92 | format: int64 93 | name: 94 | type: string 95 | tag: 96 | type: string 97 | Pets: 98 | type: array 99 | items: 100 | $ref: "#/components/schemas/Pet" 101 | Error: 102 | type: object 103 | required: 104 | - code 105 | - message 106 | properties: 107 | code: 108 | type: integer 109 | format: int32 110 | message: 111 | type: string 112 | -------------------------------------------------------------------------------- /test/golden/common/id/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | ⚠️ Non-breaking changes | 4 | |---------------------|-------------------------| 5 | | 0 | 0 | 6 | -------------------------------------------------------------------------------- /test/golden/common/id/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: {} 3 | -------------------------------------------------------------------------------- /test/golden/common/json/recursive/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | title: "" 4 | version: "" 5 | servers: 6 | - url: / 7 | paths: 8 | /api/foo: 9 | get: 10 | responses: 11 | 200: 12 | description: "" 13 | content: 14 | application/json;charset=utf-8: 15 | schema: 16 | $ref: '#/components/schemas/Tree' 17 | components: 18 | schemas: 19 | Tree: 20 | type: object 21 | properties: 22 | node: 23 | required: 24 | - children 25 | type: object 26 | properties: 27 | children: 28 | type: array 29 | items: 30 | $ref: '#/components/schemas/Tree' 31 | leaf: 32 | required: 33 | - value 34 | type: object 35 | properties: 36 | value: 37 | $ref: '#/components/schemas/Item' 38 | Item: 39 | required: 40 | - foo 41 | type: object 42 | properties: 43 | foo: 44 | type: string 45 | -------------------------------------------------------------------------------- /test/golden/common/json/recursive/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | title: "" 4 | version: "" 5 | servers: 6 | - url: / 7 | paths: 8 | /api/foo: 9 | get: 10 | responses: 11 | 200: 12 | description: "" 13 | content: 14 | application/json;charset=utf-8: 15 | schema: 16 | $ref: '#/components/schemas/Tree' 17 | components: 18 | schemas: 19 | Tree: 20 | type: object 21 | properties: 22 | node: 23 | required: 24 | - children 25 | type: object 26 | properties: 27 | children: 28 | type: array 29 | items: 30 | $ref: '#/components/schemas/Tree' 31 | leaf: 32 | required: 33 | - value 34 | type: object 35 | properties: 36 | value: 37 | $ref: '#/components/schemas/Item' 38 | Item: 39 | required: 40 | - foo 41 | type: object 42 | properties: 43 | foo: 44 | type: string 45 | -------------------------------------------------------------------------------- /test/golden/common/json/recursive/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | ⚠️ Non-breaking changes | 4 | |---------------------|-------------------------| 5 | | 0 | 0 | 6 | -------------------------------------------------------------------------------- /test/golden/common/json/recursive/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: {} 3 | -------------------------------------------------------------------------------- /test/golden/common/maximum-lowered/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | maximum: 3 26 | -------------------------------------------------------------------------------- /test/golden/common/maximum-lowered/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | maximum: 2 26 | -------------------------------------------------------------------------------- /test/golden/common/maximum-lowered/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 1 | 1 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### ➡️☁️ JSON Request 12 | 13 | #### `$(Number)` 14 | 15 | Upper bound changed from 3.0 inclusive to 2.0 inclusive. 16 | 17 | # ⚠️ Non-breaking changes 18 | 19 | ## **POST** /test 20 | 21 | ### ⬅️☁️ JSON Response – 200 22 | 23 | #### `$(Number)` 24 | 25 | Upper bound changed from 3.0 inclusive to 2.0 inclusive. 26 | -------------------------------------------------------------------------------- /test/golden/common/maximum-lowered/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | InRequest: 5 | InPayload: 6 | PayloadSchema: 7 | OfType Number: MatchingMaximumWeak (ProdCons {producer = Inclusive 3.0, 8 | consumer = Inclusive 2.0}) 9 | backwardChanges: 10 | AtPath "/test": 11 | InOperation PostMethod: 12 | WithStatusCode 200: 13 | ResponsePayload: 14 | PayloadSchema: 15 | OfType Number: MatchingMaximumWeak (ProdCons {producer = Inclusive 3.0, 16 | consumer = Inclusive 2.0}) 17 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/allowEmptyValue/reset/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | allowEmptyValue: true 16 | responses: 17 | "200": 18 | description: "Test" 19 | components: {} 20 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/allowEmptyValue/reset/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | allowEmptyValue: false 16 | responses: 17 | "200": 18 | description: "Test" 19 | components: {} 20 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/allowEmptyValue/reset/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | ⚠️ Non-breaking changes | 4 | |------------------------------------------|-------------------------| 5 | | 1 | 0 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### Parameter test1 12 | 13 | The parameter can no longer be empty. 14 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/allowEmptyValue/reset/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | InParam "test1": ParamEmptinessIncompatible 5 | backwardChanges: {} 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/allowEmptyValue/set/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | allowEmptyValue: false 16 | responses: 17 | "200": 18 | description: "Test" 19 | components: {} 20 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/allowEmptyValue/set/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | allowEmptyValue: true 16 | responses: 17 | "200": 18 | description: "Test" 19 | components: {} 20 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/allowEmptyValue/set/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |---------------------|--------------------------------------------------| 5 | | 0 | 1 | 6 | 7 | # ⚠️ Non-breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### Parameter test1 12 | 13 | The parameter can now be empty. 14 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/allowEmptyValue/set/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: 3 | AtPath "/test": 4 | InOperation PostMethod: 5 | InParam "test1": ParamEmptinessIncompatible 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/change/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test 14 | in: query 15 | schema: 16 | type: "string" 17 | responses: 18 | "200": 19 | description: "Test" 20 | components: {} 21 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/change/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test 14 | in: query 15 | schema: 16 | type: "number" 17 | responses: 18 | "200": 19 | description: "Test" 20 | components: {} 21 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/change/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 1 | 1 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### Parameter test 12 | 13 | #### JSON Schema 14 | 15 | ##### `$(String)` 16 | 17 | The type has been removed. 18 | 19 | # ⚠️ Non-breaking changes 20 | 21 | ## **POST** /test 22 | 23 | ### Parameter test 24 | 25 | #### JSON Schema 26 | 27 | ##### `$(Number)` 28 | 29 | The type has been added. 30 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/change/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | InParam "test": 5 | InParamSchema: 6 | OfType String: TypeBecomesEmpty 7 | backwardChanges: 8 | AtPath "/test": 9 | InOperation PostMethod: 10 | InParam "test": 11 | InParamSchema: 12 | OfType Number: TypeBecomesEmpty 13 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/false/add/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | responses: 16 | "200": 17 | description: "Test" 18 | components: {} 19 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/false/add/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | - name: test2 16 | in: query 17 | responses: 18 | "200": 19 | description: "Test" 20 | components: {} 21 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/false/add/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | ⚠️ Non-breaking changes | 4 | |---------------------|-------------------------| 5 | | 0 | 0 | 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/false/add/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: {} 3 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/false/del/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | - name: test2 16 | in: query 17 | responses: 18 | "200": 19 | description: "Test" 20 | components: {} 21 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/false/del/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | responses: 16 | "200": 17 | description: "Test" 18 | components: {} 19 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/false/del/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | ⚠️ Non-breaking changes | 4 | |---------------------|-------------------------| 5 | | 0 | 0 | 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/false/del/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: {} 3 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/reset/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | required: true 16 | responses: 17 | "200": 18 | description: "Test" 19 | components: {} 20 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/reset/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | required: false 16 | responses: 17 | "200": 18 | description: "Test" 19 | components: {} 20 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/reset/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |---------------------|--------------------------------------------------| 5 | | 0 | 1 | 6 | 7 | # ⚠️ Non-breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### Parameter test1 12 | 13 | Parameter is no longer required. 14 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/reset/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: 3 | AtPath "/test": 4 | InOperation PostMethod: 5 | InParam "test1": ParamRequired 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/set/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | required: false 16 | responses: 17 | "200": 18 | description: "Test" 19 | components: {} 20 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/set/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | required: true 16 | responses: 17 | "200": 18 | description: "Test" 19 | components: {} 20 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/set/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | ⚠️ Non-breaking changes | 4 | |------------------------------------------|-------------------------| 5 | | 1 | 0 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### Parameter test1 12 | 13 | Parameter has become required. 14 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/set/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | InParam "test1": ParamRequired 5 | backwardChanges: {} 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/true/add/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | responses: 16 | "200": 17 | description: "Test" 18 | components: {} 19 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/true/add/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | - name: test2 16 | in: query 17 | required: true 18 | responses: 19 | "200": 20 | description: "Test" 21 | components: {} 22 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/true/add/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | ⚠️ Non-breaking changes | 4 | |------------------------------------------|-------------------------| 5 | | 1 | 0 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | Parameter `test2` has become required. 12 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/true/add/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: ParamNotMatched "test2" 4 | backwardChanges: {} 5 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/true/del/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | - name: test2 16 | in: query 17 | required: true 18 | responses: 19 | "200": 20 | description: "Test" 21 | components: {} 22 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/true/del/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | parameters: 13 | - name: test1 14 | in: query 15 | responses: 16 | "200": 17 | description: "Test" 18 | components: {} 19 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/true/del/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |---------------------|--------------------------------------------------| 5 | | 0 | 1 | 6 | 7 | # ⚠️ Non-breaking changes 8 | 9 | ## **POST** /test 10 | 11 | Parameter `test2` is no longer required. 12 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/parameters/required/true/del/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: 3 | AtPath "/test": 4 | InOperation PostMethod: ParamNotMatched "test2" 5 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/mediaTypeObject/add/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | responses: 18 | "200": 19 | description: "Test" 20 | components: {} 21 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/mediaTypeObject/add/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | "application/x-www-form-urlencoded": 18 | schema: 19 | type: "string" 20 | responses: 21 | "200": 22 | description: "Test" 23 | components: {} 24 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/mediaTypeObject/add/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |---------------------|--------------------------------------------------| 5 | | 0 | 1 | 6 | 7 | # ⚠️ Non-breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### Request 12 | 13 | Media type `application/x-www-form-urlencoded` has been added. 14 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/mediaTypeObject/add/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: 3 | AtPath "/test": 4 | InOperation PostMethod: 5 | InRequest: RequestMediaTypeNotFound application/x-www-form-urlencoded 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/mediaTypeObject/change/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | responses: 18 | "200": 19 | description: "Test" 20 | components: {} 21 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/mediaTypeObject/change/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "number" 17 | responses: 18 | "200": 19 | description: "Test" 20 | components: {} 21 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/mediaTypeObject/change/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 1 | 1 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### ➡️☁️ JSON Request 12 | 13 | #### `$(String)` 14 | 15 | The type has been removed. 16 | 17 | # ⚠️ Non-breaking changes 18 | 19 | ## **POST** /test 20 | 21 | ### ➡️☁️ JSON Request 22 | 23 | #### `$(Number)` 24 | 25 | The type has been added. 26 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/mediaTypeObject/change/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | InRequest: 5 | InPayload: 6 | PayloadSchema: 7 | OfType String: TypeBecomesEmpty 8 | backwardChanges: 9 | AtPath "/test": 10 | InOperation PostMethod: 11 | InRequest: 12 | InPayload: 13 | PayloadSchema: 14 | OfType Number: TypeBecomesEmpty 15 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/mediaTypeObject/del/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | "application/x-www-form-urlencoded": 18 | schema: 19 | type: "string" 20 | responses: 21 | "200": 22 | description: "Test" 23 | components: {} 24 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/mediaTypeObject/del/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | responses: 18 | "200": 19 | description: "Test" 20 | components: {} 21 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/mediaTypeObject/del/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | ⚠️ Non-breaking changes | 4 | |------------------------------------------|-------------------------| 5 | | 1 | 0 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### Request 12 | 13 | Media type `application/x-www-form-urlencoded` has been removed. 14 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/mediaTypeObject/del/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | InRequest: RequestMediaTypeNotFound application/x-www-form-urlencoded 5 | backwardChanges: {} 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/required/reset/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: true 18 | responses: 19 | "200": 20 | description: "Test" 21 | components: {} 22 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/required/reset/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | components: {} 22 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/required/reset/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |---------------------|--------------------------------------------------| 5 | | 0 | 1 | 6 | 7 | # ⚠️ Non-breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### Request 12 | 13 | Request body is no longer required. 14 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/required/reset/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: 3 | AtPath "/test": 4 | InOperation PostMethod: 5 | InRequest: RequestBodyRequired 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/required/set/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | components: {} 22 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/required/set/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: true 18 | responses: 19 | "200": 20 | description: "Test" 21 | components: {} 22 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/required/set/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | ⚠️ Non-breaking changes | 4 | |------------------------------------------|-------------------------| 5 | | 1 | 0 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### Request 12 | 13 | Request body has become required. 14 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/requestBody/required/set/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | InRequest: RequestBodyRequired 5 | backwardChanges: {} 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/add/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | components: {} 22 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/add/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | "500": 22 | description: "Added" 23 | components: {} 24 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/add/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | ⚠️ Non-breaking changes | 4 | |------------------------------------------|-------------------------| 5 | | 1 | 0 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | Response code 500 has been added. 12 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/add/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: ConsumerDoesntHaveResponseCode 500 4 | backwardChanges: {} 5 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/mandatory/add/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | headers: 22 | "Test": 23 | description: "Test header" 24 | required: true 25 | components: {} 26 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/mandatory/add/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | headers: 22 | "Test": 23 | description: "Test header" 24 | required: true 25 | "Test2": 26 | description: "Test2 header" 27 | required: true 28 | components: {} 29 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/mandatory/add/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |---------------------|--------------------------------------------------| 5 | | 0 | 1 | 6 | 7 | # ⚠️ Non-breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### Response code 200 12 | 13 | New header was added `Test2`. 14 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/mandatory/add/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: 3 | AtPath "/test": 4 | InOperation PostMethod: 5 | WithStatusCode 200: ProducerDoesntHaveResponseHeader "Test2" 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/mandatory/del/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | headers: 22 | "Test": 23 | description: "Test header" 24 | required: true 25 | "Test2": 26 | description: "Test2 header" 27 | required: true 28 | components: {} 29 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/mandatory/del/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | headers: 22 | "Test": 23 | description: "Test header" 24 | required: true 25 | components: {} 26 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/mandatory/del/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | ⚠️ Non-breaking changes | 4 | |------------------------------------------|-------------------------| 5 | | 1 | 0 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### Response code 200 12 | 13 | Header was removed `Test2`. 14 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/mandatory/del/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | WithStatusCode 200: ProducerDoesntHaveResponseHeader "Test2" 5 | backwardChanges: {} 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/optional/add/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | headers: 22 | "Test": 23 | description: "Test header" 24 | components: {} 25 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/optional/add/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | headers: 22 | "Test": 23 | description: "Test header" 24 | "Test2": 25 | description: "Test2 header" 26 | components: {} 27 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/optional/add/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | ⚠️ Non-breaking changes | 4 | |---------------------|-------------------------| 5 | | 0 | 0 | 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/optional/add/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: {} 3 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/optional/del/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | headers: 22 | "Test": 23 | description: "Test header" 24 | "Test2": 25 | description: "Test2 header" 26 | components: {} 27 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/optional/del/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | headers: 22 | "Test": 23 | description: "Test header" 24 | components: {} 25 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/optional/del/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | ⚠️ Non-breaking changes | 4 | |---------------------|-------------------------| 5 | | 0 | 0 | 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/headers/optional/del/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: {} 3 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/mediaTypeObject/add/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | content: 22 | "application/json": 23 | schema: 24 | type: "string" 25 | components: {} 26 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/mediaTypeObject/add/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | content: 22 | "application/json": 23 | schema: 24 | type: "string" 25 | "application/x-www-form-urlencoded": 26 | schema: 27 | type: "string" 28 | components: {} 29 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/mediaTypeObject/add/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | ⚠️ Non-breaking changes | 4 | |------------------------------------------|-------------------------| 5 | | 1 | 0 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### Response code 200 12 | 13 | Media type was added: `application/x-www-form-urlencoded`. 14 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/mediaTypeObject/add/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | WithStatusCode 200: ConsumerDoesntHaveMediaType application/x-www-form-urlencoded 5 | backwardChanges: {} 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/mediaTypeObject/change/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | content: 22 | "application/json": 23 | schema: 24 | type: "string" 25 | components: {} 26 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/mediaTypeObject/change/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | content: 22 | "application/json": 23 | schema: 24 | type: "number" 25 | components: {} 26 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/mediaTypeObject/change/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 1 | 1 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### ⬅️☁️ JSON Response – 200 12 | 13 | #### `$(Number)` 14 | 15 | The type has been added. 16 | 17 | # ⚠️ Non-breaking changes 18 | 19 | ## **POST** /test 20 | 21 | ### ⬅️☁️ JSON Response – 200 22 | 23 | #### `$(String)` 24 | 25 | The type has been removed. 26 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/mediaTypeObject/change/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | WithStatusCode 200: 5 | ResponsePayload: 6 | PayloadSchema: 7 | OfType Number: TypeBecomesEmpty 8 | backwardChanges: 9 | AtPath "/test": 10 | InOperation PostMethod: 11 | WithStatusCode 200: 12 | ResponsePayload: 13 | PayloadSchema: 14 | OfType String: TypeBecomesEmpty 15 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/mediaTypeObject/del/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | content: 22 | "application/json": 23 | schema: 24 | type: "string" 25 | "application/x-www-form-urlencoded": 26 | schema: 27 | type: "string" 28 | components: {} 29 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/mediaTypeObject/del/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | content: 22 | "application/json": 23 | schema: 24 | type: "string" 25 | components: {} 26 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/mediaTypeObject/del/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |---------------------|--------------------------------------------------| 5 | | 0 | 1 | 6 | 7 | # ⚠️ Non-breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### Response code 200 12 | 13 | Media type was removed: `application/x-www-form-urlencoded`. 14 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/change/mediaTypeObject/del/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: 3 | AtPath "/test": 4 | InOperation PostMethod: 5 | WithStatusCode 200: ConsumerDoesntHaveMediaType application/x-www-form-urlencoded 6 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/del/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | "500": 22 | description: "Added" 23 | components: {} 24 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/del/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /test: 11 | post: 12 | requestBody: 13 | content: 14 | "application/json" : 15 | schema: 16 | type: "string" 17 | required: false 18 | responses: 19 | "200": 20 | description: "Test" 21 | components: {} 22 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/del/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |---------------------|--------------------------------------------------| 5 | | 0 | 1 | 6 | 7 | # ⚠️ Non-breaking changes 8 | 9 | ## **POST** /test 10 | 11 | Response code 500 has been removed. 12 | -------------------------------------------------------------------------------- /test/golden/common/pathItem/operation/responses/del/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: 3 | AtPath "/test": 4 | InOperation PostMethod: ConsumerDoesntHaveResponseCode 500 5 | -------------------------------------------------------------------------------- /test/golden/common/property-removed-additional/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | "200": 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | required: 26 | - property1 27 | - property2 28 | properties: 29 | property1: 30 | type: string 31 | property2: 32 | type: number 33 | -------------------------------------------------------------------------------- /test/golden/common/property-removed-additional/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | "200": 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | required: 26 | - property1 27 | properties: 28 | property1: 29 | type: string 30 | -------------------------------------------------------------------------------- /test/golden/common/property-removed-additional/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 3 | 3 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### ⬅️☁️ JSON Response – 200 12 | 13 | #### `$.property2` 14 | 15 | 1. Values are no longer limited to the following types: 16 | 17 | - Number 18 | 19 | 2. The property was previously explicitly defined. It is now implicitly 20 | described by the catch-all "additional properties" case. 21 | 22 | 3. The property may not be present. 23 | 24 | # ⚠️ Non-breaking changes 25 | 26 | ## **POST** /test 27 | 28 | ### ➡️☁️ JSON Request 29 | 30 | #### `$.property2` 31 | 32 | 1. Values are no longer limited to the following types: 33 | 34 | - Number 35 | 36 | 2. The property was previously explicitly defined. It is now implicitly 37 | described by the catch-all "additional properties" case. 38 | 39 | 3. The property may not be present. 40 | -------------------------------------------------------------------------------- /test/golden/common/property-removed-additional/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | WithStatusCode 200: 5 | ResponsePayload: 6 | PayloadSchema: 7 | OfType Object: 8 | InProperty "property2": 9 | - TypesRestricted [Number] 10 | - AdditionalToProperty 11 | - PropertyNowRequired 12 | backwardChanges: 13 | AtPath "/test": 14 | InOperation PostMethod: 15 | InRequest: 16 | InPayload: 17 | PayloadSchema: 18 | OfType Object: 19 | InProperty "property2": 20 | - TypesRestricted [Number] 21 | - AdditionalToProperty 22 | - PropertyNowRequired 23 | -------------------------------------------------------------------------------- /test/golden/common/property-removed/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | required: 26 | - property1 27 | - property2 28 | properties: 29 | property1: 30 | type: string 31 | property2: 32 | type: number 33 | additionalProperties: false 34 | -------------------------------------------------------------------------------- /test/golden/common/property-removed/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | required: 26 | - property1 27 | properties: 28 | property1: 29 | type: string 30 | additionalProperties: false 31 | -------------------------------------------------------------------------------- /test/golden/common/property-removed/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | ⚠️ Non-breaking changes | 4 | |------------------------------------------|-------------------------| 5 | | 2 | 0 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### ➡️☁️ JSON Request 12 | 13 | #### `$.property2` 14 | 15 | The property has been removed. 16 | 17 | ### ⬅️☁️ JSON Response – 200 18 | 19 | #### `$.property2` 20 | 21 | The property may not be present. 22 | -------------------------------------------------------------------------------- /test/golden/common/property-removed/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | InRequest: 5 | InPayload: 6 | PayloadSchema: 7 | OfType Object: 8 | InProperty "property2": UnexpectedProperty 9 | WithStatusCode 200: 10 | ResponsePayload: 11 | PayloadSchema: 12 | OfType Object: 13 | InProperty "property2": PropertyNowRequired 14 | backwardChanges: 15 | AtPath "/test": 16 | InOperation PostMethod: 17 | InRequest: 18 | InPayload: 19 | PayloadSchema: 20 | OfType Object: 21 | InProperty "property2": PropertyNowRequired 22 | WithStatusCode 200: 23 | ResponsePayload: 24 | PayloadSchema: 25 | OfType Object: 26 | InProperty "property2": UnexpectedProperty 27 | -------------------------------------------------------------------------------- /test/golden/common/property-required/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | required: 26 | - property1 27 | properties: 28 | property1: 29 | type: string 30 | property2: 31 | type: number 32 | additionalProperties: false 33 | -------------------------------------------------------------------------------- /test/golden/common/property-required/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | required: 26 | - property1 27 | - property2 28 | properties: 29 | property1: 30 | type: string 31 | property2: 32 | type: number 33 | additionalProperties: false 34 | -------------------------------------------------------------------------------- /test/golden/common/property-required/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 1 | 1 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### ➡️☁️ JSON Request 12 | 13 | #### `$.property2` 14 | 15 | The property has become required. 16 | 17 | # ⚠️ Non-breaking changes 18 | 19 | ## **POST** /test 20 | 21 | ### ⬅️☁️ JSON Response – 200 22 | 23 | #### `$.property2` 24 | 25 | The property has become required. 26 | -------------------------------------------------------------------------------- /test/golden/common/property-required/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | InRequest: 5 | InPayload: 6 | PayloadSchema: 7 | OfType Object: 8 | InProperty "property2": PropertyNowRequired 9 | backwardChanges: 10 | AtPath "/test": 11 | InOperation PostMethod: 12 | WithStatusCode 200: 13 | ResponsePayload: 14 | PayloadSchema: 15 | OfType Object: 16 | InProperty "property2": PropertyNowRequired 17 | -------------------------------------------------------------------------------- /test/golden/common/random-example/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: https://example.com 9 | paths: 10 | /pets: 11 | get: 12 | parameters: 13 | - name: limit 14 | in: query 15 | required: false 16 | schema: 17 | type: integer 18 | maximum: 20 19 | responses: 20 | "200": 21 | description: "" 22 | headers: 23 | x-next: 24 | schema: 25 | type: string 26 | content: 27 | application/json: 28 | schema: 29 | $ref: "#/components/schemas/Pets" 30 | post: 31 | requestBody: 32 | content: 33 | application/json: 34 | schema: 35 | $ref: "#/components/schemas/Pet" 36 | responses: 37 | "201": 38 | description: "" 39 | components: 40 | schemas: 41 | Pet: 42 | type: object 43 | required: 44 | - id 45 | - name 46 | properties: 47 | id: 48 | type: integer 49 | name: 50 | type: string 51 | minLength: 3 52 | maxLength: 10 53 | Pets: 54 | type: array 55 | items: 56 | $ref: "#/components/schemas/Pet" 57 | -------------------------------------------------------------------------------- /test/golden/common/random-example/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.1.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: https://example.com 9 | paths: 10 | /pets: 11 | get: 12 | parameters: 13 | - name: limit 14 | in: query 15 | required: false 16 | schema: 17 | type: integer 18 | maximum: 30 19 | responses: 20 | "200": 21 | description: "" 22 | headers: 23 | x-next: 24 | schema: 25 | type: string 26 | content: 27 | application/json: 28 | schema: 29 | $ref: "#/components/schemas/Pets" 30 | post: 31 | requestBody: 32 | content: 33 | application/json: 34 | schema: 35 | $ref: "#/components/schemas/Pet" 36 | responses: 37 | "201": 38 | description: "" 39 | components: 40 | schemas: 41 | Pet: 42 | type: object 43 | required: 44 | - id 45 | - name 46 | properties: 47 | id: 48 | type: integer 49 | name: 50 | type: string 51 | minLength: 1 52 | maxLength: 15 53 | weight: 54 | type: integer 55 | Pets: 56 | type: array 57 | items: 58 | $ref: "#/components/schemas/Pet" 59 | -------------------------------------------------------------------------------- /test/golden/common/random-example/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 5 | 6 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **GET** /pets 10 | 11 | ### ⬅️☁️ JSON Response – 200 12 | 13 | #### `$[*].name(String)` 14 | 15 | 1. Maximum length of the string changed from 10 to 15. 16 | 17 | 2. Minimum length of the string changed from 3 to 1. 18 | 19 | ## **POST** /pets 20 | 21 | ### ➡️☁️ JSON Request 22 | 23 | #### `$.weight` 24 | 25 | 1. Values are now limited to the following types: 26 | 27 | - Number 28 | 29 | 2. The property was previously implicitly described by the catch-all 30 | "additional properties" case. It is now explicitly defined. 31 | 32 | #### `$.weight(Number)` 33 | 34 | Value is now a multiple of 1.0. 35 | 36 | # ⚠️ Non-breaking changes 37 | 38 | ## **GET** /pets 39 | 40 | ### Parameter limit 41 | 42 | #### JSON Schema 43 | 44 | ##### `$(Number)` 45 | 46 | Upper bound changed from 20.0 inclusive to 30.0 inclusive. 47 | 48 | ### ⬅️☁️ JSON Response – 200 49 | 50 | #### `$[*].weight` 51 | 52 | 1. Values are now limited to the following types: 53 | 54 | - Number 55 | 56 | 2. The property was previously implicitly described by the catch-all 57 | "additional properties" case. It is now explicitly defined. 58 | 59 | #### `$[*].weight(Number)` 60 | 61 | Value is now a multiple of 1.0. 62 | 63 | ## **POST** /pets 64 | 65 | ### ➡️☁️ JSON Request 66 | 67 | #### `$.name(String)` 68 | 69 | 1. Maximum length of the string changed from 10 to 15. 70 | 71 | 2. Minimum length of the string changed from 3 to 1. 72 | -------------------------------------------------------------------------------- /test/golden/common/random-example/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/pets": 3 | InOperation GetMethod: 4 | WithStatusCode 200: 5 | ResponsePayload: 6 | PayloadSchema: 7 | OfType Array: 8 | InItems: 9 | OfType Object: 10 | InProperty "name": 11 | OfType String: 12 | - MatchingMaxLengthWeak (ProdCons {producer = 15, consumer = 10}) 13 | - MatchingMinLengthWeak (ProdCons {producer = 1, consumer = 3}) 14 | InOperation PostMethod: 15 | InRequest: 16 | InPayload: 17 | PayloadSchema: 18 | OfType Object: 19 | InProperty "weight": 20 | - TypesRestricted [Number] 21 | - AdditionalToProperty 22 | - OfType Number: NoMatchingMultipleOf 1.0 23 | backwardChanges: 24 | AtPath "/pets": 25 | InOperation GetMethod: 26 | InParam "limit": 27 | InParamSchema: 28 | OfType Number: MatchingMaximumWeak (ProdCons {producer = Inclusive 30.0, 29 | consumer = Inclusive 20.0}) 30 | WithStatusCode 200: 31 | ResponsePayload: 32 | PayloadSchema: 33 | OfType Array: 34 | InItems: 35 | OfType Object: 36 | InProperty "weight": 37 | - TypesRestricted [Number] 38 | - AdditionalToProperty 39 | - OfType Number: NoMatchingMultipleOf 1.0 40 | InOperation PostMethod: 41 | InRequest: 42 | InPayload: 43 | PayloadSchema: 44 | OfType Object: 45 | InProperty "name": 46 | OfType String: 47 | - MatchingMaxLengthWeak (ProdCons {producer = 15, consumer = 10}) 48 | - MatchingMinLengthWeak (ProdCons {producer = 1, consumer = 3}) 49 | -------------------------------------------------------------------------------- /test/golden/common/recursive/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | title: "" 4 | version: "" 5 | servers: 6 | - url: / 7 | paths: 8 | /api/foo: 9 | get: 10 | requestBody: 11 | content: 12 | application/json;charset=utf-8: 13 | schema: 14 | $ref: "#/components/schemas/Tree" 15 | 16 | responses: 17 | 200: 18 | description: "" 19 | content: 20 | application/json;charset=utf-8: 21 | schema: 22 | $ref: "#/components/schemas/Tree" 23 | components: 24 | schemas: 25 | Tree: 26 | type: object 27 | properties: 28 | node: 29 | required: 30 | - children 31 | type: object 32 | properties: 33 | children: 34 | type: array 35 | items: 36 | $ref: "#/components/schemas/Tree" 37 | leaf: 38 | required: 39 | - value 40 | type: object 41 | properties: 42 | value: 43 | $ref: "#/components/schemas/Item" 44 | Item: 45 | required: 46 | - foo 47 | type: object 48 | properties: 49 | foo: 50 | type: string 51 | -------------------------------------------------------------------------------- /test/golden/common/recursive/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | title: "" 4 | version: "" 5 | servers: 6 | - url: / 7 | paths: 8 | /api/foo: 9 | get: 10 | requestBody: 11 | content: 12 | application/json;charset=utf-8: 13 | schema: 14 | $ref: "#/components/schemas/Tree" 15 | 16 | responses: 17 | 200: 18 | description: "" 19 | content: 20 | application/json;charset=utf-8: 21 | schema: 22 | $ref: "#/components/schemas/Tree" 23 | components: 24 | schemas: 25 | Tree: 26 | type: object 27 | properties: 28 | node: 29 | required: 30 | - children 31 | type: object 32 | properties: 33 | children: 34 | type: array 35 | items: 36 | $ref: "#/components/schemas/Tree" 37 | leaf: 38 | required: 39 | - value 40 | type: object 41 | properties: 42 | value: 43 | required: 44 | - foo 45 | type: object 46 | properties: 47 | foo: 48 | enum: 49 | - "a" 50 | -------------------------------------------------------------------------------- /test/golden/common/recursive/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 1 | 1 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **GET** /api/foo 10 | 11 | ### ➡️☁️ JSON Request 12 | 13 | #### `$.leaf.value.foo(String)` 14 | 15 | The following enum value has been added: 16 | 17 | ``` json 18 | "a" 19 | ``` 20 | 21 | # ⚠️ Non-breaking changes 22 | 23 | ## **GET** /api/foo 24 | 25 | ### ⬅️☁️ JSON Response – 200 26 | 27 | #### `$.leaf.value.foo(String)` 28 | 29 | The following enum value has been added: 30 | 31 | ``` json 32 | "a" 33 | ``` 34 | -------------------------------------------------------------------------------- /test/golden/common/recursive/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/api/foo": 3 | InOperation GetMethod: 4 | InRequest: 5 | InPayload: 6 | PayloadSchema: 7 | OfType Object: 8 | InProperty "leaf": 9 | OfType Object: 10 | InProperty "value": 11 | OfType Object: 12 | InProperty "foo": 13 | OfType String: NoMatchingEnum (String "a") 14 | backwardChanges: 15 | AtPath "/api/foo": 16 | InOperation GetMethod: 17 | WithStatusCode 200: 18 | ResponsePayload: 19 | PayloadSchema: 20 | OfType Object: 21 | InProperty "leaf": 22 | OfType Object: 23 | InProperty "value": 24 | OfType Object: 25 | InProperty "foo": 26 | OfType String: NoMatchingEnum (String "a") 27 | -------------------------------------------------------------------------------- /test/golden/common/security-scheme/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | version: "" 4 | title: "" 5 | paths: 6 | /oauth/sign_out: 7 | get: 8 | parameters: 9 | - required: false 10 | schema: 11 | type: string 12 | in: query 13 | name: redirect 14 | responses: 15 | "302": 16 | content: 17 | application/x-www-form-urlencoded: {} 18 | headers: 19 | Location: 20 | schema: 21 | type: string 22 | set-cookie: 23 | schema: 24 | type: string 25 | description: "" 26 | "400": 27 | description: Invalid `redirect` 28 | security: 29 | - sign-out-oauth: [] 30 | - oauth: [] 31 | /oauth/authorize: 32 | get: 33 | responses: 34 | "302": 35 | content: 36 | application/x-www-form-urlencoded: {} 37 | headers: 38 | Location: 39 | schema: 40 | type: string 41 | description: "" 42 | security: 43 | - get-oauth: [] 44 | /oauth/token: 45 | post: 46 | requestBody: 47 | content: 48 | application/x-www-form-urlencoded: 49 | schema: 50 | type: string 51 | responses: 52 | "200": 53 | content: 54 | application/json;charset=utf-8: 55 | schema: 56 | type: string 57 | description: "" 58 | "400": 59 | description: Invalid `body` 60 | security: 61 | - oauth: [] 62 | /oauth/check: 63 | post: 64 | requestBody: 65 | content: 66 | application/json;charset=utf-8: 67 | schema: 68 | type: string 69 | responses: 70 | "200": 71 | content: 72 | application/json;charset=utf-8: 73 | schema: 74 | example: [] 75 | items: {} 76 | maxItems: 0 77 | type: array 78 | description: "" 79 | "400": 80 | description: Invalid `body` 81 | security: 82 | - oauth: [] 83 | components: 84 | securitySchemes: 85 | sign-out-oauth: 86 | in: cookie 87 | name: _SESSION 88 | type: apiKey 89 | description: Session cookie 90 | get-oauth: 91 | in: cookie 92 | name: _SESSION 93 | type: apiKey 94 | description: Session cookie 95 | oauth: 96 | scheme: Basic 97 | type: http 98 | oauth-token: 99 | scheme: Bearer 100 | type: http 101 | description: Bearer token 102 | oauth-token-client-only: 103 | scheme: Bearer 104 | type: http 105 | description: Bearer token 106 | spa-oauth: 107 | in: cookie 108 | name: _SESSION 109 | type: apiKey 110 | description: Session cookie 111 | -------------------------------------------------------------------------------- /test/golden/common/security-scheme/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | version: "" 4 | title: "" 5 | paths: 6 | /oauth/sign_out: 7 | get: 8 | parameters: 9 | - required: false 10 | schema: 11 | type: string 12 | in: query 13 | name: redirect 14 | responses: 15 | "302": 16 | content: 17 | application/x-www-form-urlencoded: {} 18 | headers: 19 | Location: 20 | schema: 21 | type: string 22 | set-cookie: 23 | schema: 24 | type: string 25 | description: "" 26 | "400": 27 | description: Invalid `redirect` 28 | security: 29 | - sign-out-oauth: [] 30 | /oauth/authorize: 31 | get: 32 | responses: 33 | "302": 34 | content: 35 | application/x-www-form-urlencoded: {} 36 | headers: 37 | Location: 38 | schema: 39 | type: string 40 | description: "" 41 | security: 42 | - get-oauth: [] 43 | - spa-oauth: [] 44 | /oauth/token: 45 | post: 46 | requestBody: 47 | content: 48 | application/x-www-form-urlencoded: 49 | schema: 50 | type: string 51 | responses: 52 | "200": 53 | content: 54 | application/json;charset=utf-8: 55 | schema: 56 | type: string 57 | description: "" 58 | "400": 59 | description: Invalid `body` 60 | security: 61 | - oauth: [] 62 | /oauth/check: 63 | post: 64 | requestBody: 65 | content: 66 | application/json;charset=utf-8: 67 | schema: 68 | type: string 69 | responses: 70 | "200": 71 | content: 72 | application/json;charset=utf-8: 73 | schema: 74 | example: [] 75 | items: {} 76 | maxItems: 0 77 | type: array 78 | description: "" 79 | "400": 80 | description: Invalid `body` 81 | security: 82 | - spa-oauth: [] 83 | components: 84 | securitySchemes: 85 | sign-out-oauth: 86 | in: cookie 87 | name: _SESSION 88 | type: apiKey 89 | description: Session cookie 90 | get-oauth: 91 | in: cookie 92 | name: _SESSION 93 | type: apiKey 94 | description: Session cookie 95 | oauth: 96 | scheme: Basic 97 | type: http 98 | oauth-token: 99 | scheme: Bearer 100 | type: http 101 | description: Bearer token 102 | oauth-token-client-only: 103 | scheme: Bearer 104 | type: http 105 | description: Bearer token 106 | spa-oauth: 107 | in: cookie 108 | name: _SESSION 109 | type: apiKey 110 | description: Session cookie 111 | -------------------------------------------------------------------------------- /test/golden/common/security-scheme/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 2 | 1 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /oauth/check 10 | 11 | ### Security requirement 0 12 | 13 | #### oauth 14 | 15 | Security scheme has been removed. 16 | 17 | ## **GET** /oauth/sign\_out 18 | 19 | ### Security requirement 1 20 | 21 | #### oauth 22 | 23 | Security scheme has been removed. 24 | 25 | # ⚠️ Non-breaking changes 26 | 27 | ## **POST** /oauth/check 28 | 29 | ### Security requirement 0 30 | 31 | #### spa-oauth 32 | 33 | Security scheme has been added. 34 | -------------------------------------------------------------------------------- /test/golden/common/security-scheme/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/oauth/sign_out": 3 | InOperation GetMethod: 4 | SecurityRequirementStep 1: 5 | SecuritySchemeStep "oauth": SecuritySchemeNotMatched 6 | AtPath "/oauth/check": 7 | InOperation PostMethod: 8 | SecurityRequirementStep 0: 9 | SecuritySchemeStep "oauth": SecuritySchemeNotMatched 10 | backwardChanges: 11 | AtPath "/oauth/check": 12 | InOperation PostMethod: 13 | SecurityRequirementStep 0: 14 | SecuritySchemeStep "spa-oauth": SecuritySchemeNotMatched 15 | -------------------------------------------------------------------------------- /test/golden/common/servers/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | servers: 6 | - url: http://petstore.swagger.io/v1 7 | variables: 8 | variableThatDoesntDoAnything: 9 | default: a 10 | enum: 11 | - a 12 | - bbb 13 | - url: http://missing.url 14 | - url: http://{x}variable.path/{y}/{openVariable1}/{openVariable2} 15 | variables: 16 | x: 17 | default: a 18 | enum: 19 | - a 20 | - b 21 | - c 22 | y: 23 | default: aa 24 | enum: 25 | - a 26 | - aa 27 | - aaa 28 | openVariable1: 29 | default: henlo 30 | openVariable2: 31 | default: henlo 32 | paths: 33 | /pets: 34 | get: 35 | responses: 36 | "200": 37 | description: A paged array of pets 38 | components: {} 39 | -------------------------------------------------------------------------------- /test/golden/common/servers/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | servers: 6 | - url: http://petstore.swagger.io/v1 7 | - url: http://{x}variable.path/{y}/{openVariable1}/{openVariable2} 8 | variables: 9 | x: 10 | default: a 11 | enum: 12 | - b 13 | - c 14 | y: 15 | default: aa 16 | enum: 17 | - a 18 | - aa 19 | - aaa 20 | - bbb 21 | openVariable1: 22 | default: henlo 23 | openVariable2: 24 | default: henlo 25 | enum: 26 | - a 27 | - aaa 28 | paths: 29 | /pets: 30 | get: 31 | responses: 32 | "200": 33 | description: A paged array of pets 34 | components: {} 35 | -------------------------------------------------------------------------------- /test/golden/common/servers/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 3 | 1 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **GET** /pets 10 | 11 | ### Server `http://missing.url` 12 | 13 | The server was removed. 14 | 15 | ### Server `http://{x}variable.path/{y}/{openVariable1}/{openVariable2}` 16 | 17 | 1. Enum value `a` has been removed. 18 | 19 | 2. A variable has been changed from being open to being closed. 20 | 21 | # ⚠️ Non-breaking changes 22 | 23 | ## **GET** /pets 24 | 25 | ### Server `http://{x}variable.path/{y}/{openVariable1}/{openVariable2}` 26 | 27 | Enum value `bbb` has been added. 28 | -------------------------------------------------------------------------------- /test/golden/common/servers/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/pets": 3 | InOperation GetMethod: 4 | InServer "http://{x}variable.path/{y}/{openVariable1}/{openVariable2}": 5 | - EnumValueNotConsumed 1 "a" 6 | - ConsumerNotOpen 7 7 | InServer "http://missing.url": ServerNotMatched 8 | backwardChanges: 9 | AtPath "/pets": 10 | InOperation GetMethod: 11 | InServer "http://{x}variable.path/{y}/{openVariable1}/{openVariable2}": EnumValueNotConsumed 12 | 3 "bbb" 13 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/heterogeneous-component-mismatch/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | type: array 26 | items: 27 | - type: number 28 | - type: string 29 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/heterogeneous-component-mismatch/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | type: array 26 | items: 27 | - type: number 28 | - type: object 29 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/heterogeneous-component-mismatch/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 2 | 2 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### ➡️☁️ JSON Request 12 | 13 | #### `$[1](String)` 14 | 15 | The type has been removed. 16 | 17 | ### ⬅️☁️ JSON Response – 200 18 | 19 | #### `$[1](Object)` 20 | 21 | The type has been added. 22 | 23 | # ⚠️ Non-breaking changes 24 | 25 | ## **POST** /test 26 | 27 | ### ➡️☁️ JSON Request 28 | 29 | #### `$[1](Object)` 30 | 31 | The type has been added. 32 | 33 | ### ⬅️☁️ JSON Response – 200 34 | 35 | #### `$[1](String)` 36 | 37 | The type has been removed. 38 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/heterogeneous-component-mismatch/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | InRequest: 5 | InPayload: 6 | PayloadSchema: 7 | OfType Array: 8 | InItem 1: 9 | OfType String: TypeBecomesEmpty 10 | WithStatusCode 200: 11 | ResponsePayload: 12 | PayloadSchema: 13 | OfType Array: 14 | InItem 1: 15 | OfType Object: TypeBecomesEmpty 16 | backwardChanges: 17 | AtPath "/test": 18 | InOperation PostMethod: 19 | InRequest: 20 | InPayload: 21 | PayloadSchema: 22 | OfType Array: 23 | InItem 1: 24 | OfType Object: TypeBecomesEmpty 25 | WithStatusCode 200: 26 | ResponsePayload: 27 | PayloadSchema: 28 | OfType Array: 29 | InItem 1: 30 | OfType String: TypeBecomesEmpty 31 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/heterogeneous-length-mismatch/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | type: array 26 | items: 27 | - type: number 28 | - type: string 29 | - type: object 30 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/heterogeneous-length-mismatch/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | type: array 26 | items: 27 | - type: number 28 | - type: object 29 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/heterogeneous-length-mismatch/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | ⚠️ Non-breaking changes | 4 | |------------------------------------------|-------------------------| 5 | | 2 | 0 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### ➡️☁️ JSON Request 12 | 13 | #### `$(Array)` 14 | 15 | Tuple length changed from 3 to 2. 16 | 17 | ### ⬅️☁️ JSON Response – 200 18 | 19 | #### `$(Array)` 20 | 21 | Tuple length changed from 3 to 2. 22 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/heterogeneous-length-mismatch/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | InRequest: 5 | InPayload: 6 | PayloadSchema: 7 | OfType Array: TupleItemsLengthChanged (ProdCons {producer = 3, consumer 8 | = 2}) 9 | WithStatusCode 200: 10 | ResponsePayload: 11 | PayloadSchema: 12 | OfType Array: TupleItemsLengthChanged (ProdCons {producer = 2, consumer 13 | = 3}) 14 | backwardChanges: 15 | AtPath "/test": 16 | InOperation PostMethod: 17 | InRequest: 18 | InPayload: 19 | PayloadSchema: 20 | OfType Array: TupleItemsLengthChanged (ProdCons {producer = 2, consumer 21 | = 3}) 22 | WithStatusCode 200: 23 | ResponsePayload: 24 | PayloadSchema: 25 | OfType Array: TupleItemsLengthChanged (ProdCons {producer = 3, consumer 26 | = 2}) 27 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/homogeneous-component-mismatch/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | type: array 26 | items: 27 | - type: string 28 | - type: number 29 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/homogeneous-component-mismatch/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | type: array 26 | minItems: 2 27 | maxItems: 2 28 | items: 29 | type: number 30 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/homogeneous-component-mismatch/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 4 | 2 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### ➡️☁️ JSON Request 12 | 13 | #### `$(Array)` 14 | 15 | The array is no longer explicitly defined as a tuple. 16 | 17 | #### `$[0](String)` 18 | 19 | The type has been removed. 20 | 21 | ### ⬅️☁️ JSON Response – 200 22 | 23 | #### `$(Array)` 24 | 25 | The array is no longer explicitly defined as a tuple. 26 | 27 | #### `$[0](Number)` 28 | 29 | The type has been added. 30 | 31 | # ⚠️ Non-breaking changes 32 | 33 | ## **POST** /test 34 | 35 | ### ➡️☁️ JSON Request 36 | 37 | #### `$[0](Number)` 38 | 39 | The type has been added. 40 | 41 | ### ⬅️☁️ JSON Response – 200 42 | 43 | #### `$[0](String)` 44 | 45 | The type has been removed. 46 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/homogeneous-component-mismatch/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | InRequest: 5 | InPayload: 6 | PayloadSchema: 7 | OfType Array: 8 | - TupleToArray 9 | - InItem 0: 10 | OfType String: TypeBecomesEmpty 11 | WithStatusCode 200: 12 | ResponsePayload: 13 | PayloadSchema: 14 | OfType Array: 15 | - ArrayToTuple 16 | - InItem 0: 17 | OfType Number: TypeBecomesEmpty 18 | backwardChanges: 19 | AtPath "/test": 20 | InOperation PostMethod: 21 | InRequest: 22 | InPayload: 23 | PayloadSchema: 24 | OfType Array: 25 | - ArrayToTuple 26 | - InItem 0: 27 | OfType Number: TypeBecomesEmpty 28 | WithStatusCode 200: 29 | ResponsePayload: 30 | PayloadSchema: 31 | OfType Array: 32 | - TupleToArray 33 | - InItem 0: 34 | OfType String: TypeBecomesEmpty 35 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/homogeneous-length-mismatch/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test1: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | /test2: 23 | post: 24 | requestBody: 25 | content: 26 | application/json: 27 | schema: 28 | $ref: "#/components/schemas/Test" 29 | responses: 30 | '200': 31 | description: test 32 | content: 33 | application/json: 34 | schema: 35 | $ref: "#/components/schemas/Test" 36 | /test3: 37 | post: 38 | requestBody: 39 | content: 40 | application/json: 41 | schema: 42 | $ref: "#/components/schemas/Test" 43 | responses: 44 | '200': 45 | description: test 46 | content: 47 | application/json: 48 | schema: 49 | $ref: "#/components/schemas/Test" 50 | components: 51 | schemas: 52 | Test: 53 | type: array 54 | items: 55 | - type: number 56 | - type: number 57 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/homogeneous-length-mismatch/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test1: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test1" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test1" 22 | /test2: 23 | post: 24 | requestBody: 25 | content: 26 | application/json: 27 | schema: 28 | $ref: "#/components/schemas/Test2" 29 | responses: 30 | '200': 31 | description: test 32 | content: 33 | application/json: 34 | schema: 35 | $ref: "#/components/schemas/Test2" 36 | /test3: 37 | post: 38 | requestBody: 39 | content: 40 | application/json: 41 | schema: 42 | $ref: "#/components/schemas/Test3" 43 | responses: 44 | '200': 45 | description: test 46 | content: 47 | application/json: 48 | schema: 49 | $ref: "#/components/schemas/Test3" 50 | components: 51 | schemas: 52 | Test1: 53 | type: array 54 | maxItems: 2 55 | items: 56 | type: number 57 | Test2: 58 | type: array 59 | minItems: 2 60 | items: 61 | type: number 62 | Test3: 63 | type: array 64 | minItems: 3 65 | maxItems: 3 66 | items: 67 | type: number 68 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/homogeneous-length-mismatch/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 5 | 5 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test1 10 | 11 | ### ⬅️☁️ JSON Response – 200 12 | 13 | #### `$(Array)` 14 | 15 | The array is no longer explicitly defined as a tuple. 16 | 17 | ## **POST** /test2 18 | 19 | ### ⬅️☁️ JSON Response – 200 20 | 21 | #### `$(Array)` 22 | 23 | The array is no longer explicitly defined as a tuple. 24 | 25 | ## **POST** /test3 26 | 27 | ### ➡️☁️ JSON Request 28 | 29 | #### `$(Array)` 30 | 31 | Minimum length of the array changed from 2 to 3. 32 | 33 | ### ⬅️☁️ JSON Response – 200 34 | 35 | #### `$(Array)` 36 | 37 | 1. Tuple length changed from 2 to 3. 38 | 39 | 2. The array is no longer explicitly defined as a tuple. 40 | 41 | # ⚠️ Non-breaking changes 42 | 43 | ## **POST** /test1 44 | 45 | ### ➡️☁️ JSON Request 46 | 47 | #### `$(Array)` 48 | 49 | The array is no longer explicitly defined as a tuple. 50 | 51 | ## **POST** /test2 52 | 53 | ### ➡️☁️ JSON Request 54 | 55 | #### `$(Array)` 56 | 57 | The array is no longer explicitly defined as a tuple. 58 | 59 | ## **POST** /test3 60 | 61 | ### ➡️☁️ JSON Request 62 | 63 | #### `$(Array)` 64 | 65 | 1. Tuple length changed from 2 to 3. 66 | 67 | 2. The array is no longer explicitly defined as a tuple. 68 | 69 | ### ⬅️☁️ JSON Response – 200 70 | 71 | #### `$(Array)` 72 | 73 | Minimum length of the array changed from 2 to 3. 74 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/homogeneous-length-mismatch/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test3": 3 | InOperation PostMethod: 4 | InRequest: 5 | InPayload: 6 | PayloadSchema: 7 | OfType Array: MatchingMinItemsWeak (ProdCons {producer = 2, consumer = 8 | 3}) 9 | WithStatusCode 200: 10 | ResponsePayload: 11 | PayloadSchema: 12 | OfType Array: 13 | - TupleItemsLengthChanged (ProdCons {producer = 3, consumer = 2}) 14 | - ArrayToTuple 15 | AtPath "/test1": 16 | InOperation PostMethod: 17 | WithStatusCode 200: 18 | ResponsePayload: 19 | PayloadSchema: 20 | OfType Array: NoMatchingTupleItems 21 | AtPath "/test2": 22 | InOperation PostMethod: 23 | WithStatusCode 200: 24 | ResponsePayload: 25 | PayloadSchema: 26 | OfType Array: NoMatchingTupleItems 27 | backwardChanges: 28 | AtPath "/test3": 29 | InOperation PostMethod: 30 | InRequest: 31 | InPayload: 32 | PayloadSchema: 33 | OfType Array: 34 | - TupleItemsLengthChanged (ProdCons {producer = 3, consumer = 2}) 35 | - ArrayToTuple 36 | WithStatusCode 200: 37 | ResponsePayload: 38 | PayloadSchema: 39 | OfType Array: MatchingMinItemsWeak (ProdCons {producer = 2, consumer = 40 | 3}) 41 | AtPath "/test1": 42 | InOperation PostMethod: 43 | InRequest: 44 | InPayload: 45 | PayloadSchema: 46 | OfType Array: NoMatchingTupleItems 47 | AtPath "/test2": 48 | InOperation PostMethod: 49 | InRequest: 50 | InPayload: 51 | PayloadSchema: 52 | OfType Array: NoMatchingTupleItems 53 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/homogeneous-vector/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | type: array 26 | items: 27 | - type: number 28 | - type: number 29 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/homogeneous-vector/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | type: array 26 | minItems: 2 27 | maxItems: 2 28 | items: 29 | type: number 30 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/homogeneous-vector/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | ⚠️ Non-breaking changes | 4 | |---------------------|-------------------------| 5 | | 0 | 0 | 6 | -------------------------------------------------------------------------------- /test/golden/common/tuple-items/homogeneous-vector/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: {} 2 | backwardChanges: {} 3 | -------------------------------------------------------------------------------- /test/golden/common/type-changing/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test1: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test1" 15 | responses: 16 | "200": 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test1" 22 | /test2: 23 | post: 24 | requestBody: 25 | content: 26 | application/json: 27 | schema: 28 | $ref: "#/components/schemas/Test2" 29 | responses: 30 | "200": 31 | description: test 32 | content: 33 | application/json: 34 | schema: 35 | $ref: "#/components/schemas/Test2" 36 | /test3: 37 | post: 38 | requestBody: 39 | content: 40 | application/json: 41 | schema: 42 | $ref: "#/components/schemas/Test3" 43 | responses: 44 | "200": 45 | description: test 46 | content: 47 | application/json: 48 | schema: 49 | $ref: "#/components/schemas/Test3" 50 | /test4: 51 | post: 52 | requestBody: 53 | content: 54 | application/json: 55 | schema: 56 | $ref: "#/components/schemas/Test4" 57 | responses: 58 | "200": 59 | description: test 60 | content: 61 | application/json: 62 | schema: 63 | $ref: "#/components/schemas/Test4" 64 | /test5: 65 | post: 66 | requestBody: 67 | content: 68 | application/json: 69 | schema: 70 | $ref: "#/components/schemas/Test5" 71 | responses: 72 | "200": 73 | description: test 74 | content: 75 | application/json: 76 | schema: 77 | $ref: "#/components/schemas/Test5" 78 | components: 79 | schemas: 80 | Test1: 81 | multipleOf: 1 82 | minLength: 1 83 | minItems: 1 84 | Test2: 85 | multipleOf: 1 86 | minLength: 1 87 | minItems: 1 88 | Test3: 89 | anyOf: 90 | - type: number 91 | multipleOf: 1 92 | - type: array 93 | minItems: 1 94 | - type: string 95 | minLength: 1 96 | - type: object 97 | Test4: 98 | anyOf: 99 | - type: number 100 | multipleOf: 1 101 | - type: array 102 | minItems: 1 103 | - type: string 104 | minLength: 1 105 | - type: object 106 | Test5: 107 | anyOf: 108 | - type: number 109 | multipleOf: 1 110 | - type: array 111 | minItems: 1 112 | - type: object 113 | - minLength: 1 114 | -------------------------------------------------------------------------------- /test/golden/common/type-changing/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test1: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test1" 15 | responses: 16 | "200": 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test1" 22 | /test2: 23 | post: 24 | requestBody: 25 | content: 26 | application/json: 27 | schema: 28 | $ref: "#/components/schemas/Test2" 29 | responses: 30 | "200": 31 | description: test 32 | content: 33 | application/json: 34 | schema: 35 | $ref: "#/components/schemas/Test2" 36 | /test3: 37 | post: 38 | requestBody: 39 | content: 40 | application/json: 41 | schema: 42 | $ref: "#/components/schemas/Test3" 43 | responses: 44 | "200": 45 | description: test 46 | content: 47 | application/json: 48 | schema: 49 | $ref: "#/components/schemas/Test3" 50 | /test4: 51 | post: 52 | requestBody: 53 | content: 54 | application/json: 55 | schema: 56 | $ref: "#/components/schemas/Test4" 57 | responses: 58 | "200": 59 | description: test 60 | content: 61 | application/json: 62 | schema: 63 | $ref: "#/components/schemas/Test4" 64 | /test5: 65 | post: 66 | requestBody: 67 | content: 68 | application/json: 69 | schema: 70 | $ref: "#/components/schemas/Test5" 71 | responses: 72 | "200": 73 | description: test 74 | content: 75 | application/json: 76 | schema: 77 | $ref: "#/components/schemas/Test5" 78 | components: 79 | schemas: 80 | Test1: 81 | type: array 82 | minItems: 1 83 | Test2: 84 | anyOf: 85 | - type: number 86 | multipleOf: 1 87 | - type: array 88 | minItems: 1 89 | - type: object 90 | Test3: 91 | anyOf: 92 | - type: number 93 | multipleOf: 1 94 | - type: string 95 | minLength: 1 96 | - type: object 97 | Test4: 98 | anyOf: 99 | - type: number 100 | multipleOf: 1 101 | - type: array 102 | minItems: 1 103 | - type: string 104 | minLength: 1 105 | Test5: 106 | anyOf: 107 | - type: number 108 | multipleOf: 1 109 | -------------------------------------------------------------------------------- /test/golden/common/type-changing/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 6 | 6 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test1 10 | 11 | ### ➡️☁️ JSON Request 12 | 13 | Values are now limited to the following types: 14 | 15 | - Array 16 | 17 | ## **POST** /test2 18 | 19 | ### ➡️☁️ JSON Request 20 | 21 | Values are now limited to the following types: 22 | 23 | - Number 24 | 25 | - Array 26 | 27 | - Object 28 | 29 | ## **POST** /test3 30 | 31 | ### ➡️☁️ JSON Request 32 | 33 | #### `$(Array)` 34 | 35 | The type has been removed. 36 | 37 | ## **POST** /test4 38 | 39 | ### ➡️☁️ JSON Request 40 | 41 | #### `$(Object)` 42 | 43 | The type has been removed. 44 | 45 | ## **POST** /test5 46 | 47 | ### ➡️☁️ JSON Request 48 | 49 | Values are now limited to the following types: 50 | 51 | - Number 52 | 53 | #### `$(Number)` 54 | 55 | Value is now a multiple of 1.0. 56 | 57 | # ⚠️ Non-breaking changes 58 | 59 | ## **POST** /test1 60 | 61 | ### ⬅️☁️ JSON Response – 200 62 | 63 | Values are now limited to the following types: 64 | 65 | - Array 66 | 67 | ## **POST** /test2 68 | 69 | ### ⬅️☁️ JSON Response – 200 70 | 71 | Values are now limited to the following types: 72 | 73 | - Number 74 | 75 | - Array 76 | 77 | - Object 78 | 79 | ## **POST** /test3 80 | 81 | ### ⬅️☁️ JSON Response – 200 82 | 83 | #### `$(Array)` 84 | 85 | The type has been removed. 86 | 87 | ## **POST** /test4 88 | 89 | ### ⬅️☁️ JSON Response – 200 90 | 91 | #### `$(Object)` 92 | 93 | The type has been removed. 94 | 95 | ## **POST** /test5 96 | 97 | ### ⬅️☁️ JSON Response – 200 98 | 99 | Values are now limited to the following types: 100 | 101 | - Number 102 | 103 | #### `$(Number)` 104 | 105 | Value is now a multiple of 1.0. 106 | -------------------------------------------------------------------------------- /test/golden/common/type-changing/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test5": 3 | InOperation PostMethod: 4 | InRequest: 5 | InPayload: 6 | PayloadSchema: 7 | - TypesRestricted [Number] 8 | - OfType Number: NoMatchingMultipleOf 1.0 9 | AtPath "/test3": 10 | InOperation PostMethod: 11 | InRequest: 12 | InPayload: 13 | PayloadSchema: 14 | OfType Array: TypeBecomesEmpty 15 | AtPath "/test4": 16 | InOperation PostMethod: 17 | InRequest: 18 | InPayload: 19 | PayloadSchema: 20 | OfType Object: TypeBecomesEmpty 21 | AtPath "/test1": 22 | InOperation PostMethod: 23 | InRequest: 24 | InPayload: 25 | PayloadSchema: TypesRestricted [Array] 26 | AtPath "/test2": 27 | InOperation PostMethod: 28 | InRequest: 29 | InPayload: 30 | PayloadSchema: TypesRestricted [Number,Array,Object] 31 | backwardChanges: 32 | AtPath "/test5": 33 | InOperation PostMethod: 34 | WithStatusCode 200: 35 | ResponsePayload: 36 | PayloadSchema: 37 | - TypesRestricted [Number] 38 | - OfType Number: NoMatchingMultipleOf 1.0 39 | AtPath "/test3": 40 | InOperation PostMethod: 41 | WithStatusCode 200: 42 | ResponsePayload: 43 | PayloadSchema: 44 | OfType Array: TypeBecomesEmpty 45 | AtPath "/test4": 46 | InOperation PostMethod: 47 | WithStatusCode 200: 48 | ResponsePayload: 49 | PayloadSchema: 50 | OfType Object: TypeBecomesEmpty 51 | AtPath "/test1": 52 | InOperation PostMethod: 53 | WithStatusCode 200: 54 | ResponsePayload: 55 | PayloadSchema: TypesRestricted [Array] 56 | AtPath "/test2": 57 | InOperation PostMethod: 58 | WithStatusCode 200: 59 | ResponsePayload: 60 | PayloadSchema: TypesRestricted [Number,Array,Object] 61 | -------------------------------------------------------------------------------- /test/golden/common/unguarded-recursive/basic/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | title: "" 4 | version: "" 5 | servers: 6 | - url: / 7 | paths: 8 | /api/foo: 9 | get: 10 | responses: 11 | 200: 12 | description: "" 13 | content: 14 | application/json;charset=utf-8: 15 | schema: 16 | $ref: "#/components/schemas/Bad" 17 | components: 18 | schemas: 19 | Bad: 20 | anyOf: 21 | - $ref: "#/components/schemas/Bad" 22 | -------------------------------------------------------------------------------- /test/golden/common/unguarded-recursive/basic/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | title: "" 4 | version: "" 5 | servers: 6 | - url: / 7 | paths: 8 | /api/foo: 9 | get: 10 | responses: 11 | 200: 12 | description: "" 13 | content: 14 | application/json;charset=utf-8: 15 | schema: 16 | $ref: "#/components/schemas/Bad" 17 | components: 18 | schemas: 19 | Bad: 20 | allOf: 21 | - $ref: "#/components/schemas/Bad" 22 | -------------------------------------------------------------------------------- /test/golden/common/unguarded-recursive/basic/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | ⚠️ Non-breaking changes | [❓ Unsupported feature changes](#unsupported-changes) | 4 | |---------------------|-------------------------|--------------------------------------------------------| 5 | | 0 | 0 | 1 | 6 | 7 | # ❓ Unsupported feature changes 8 | 9 | ## **GET** /api/foo 10 | 11 | ### ⬅️☁️ JSON Response – 200 12 | 13 | Encountered recursion that is too complex for CompaREST to untangle. 14 | -------------------------------------------------------------------------------- /test/golden/common/unguarded-recursive/basic/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/api/foo": 3 | InOperation GetMethod: 4 | WithStatusCode 200: 5 | ResponsePayload: 6 | PayloadSchema: UnguardedRecursion 7 | backwardChanges: 8 | AtPath "/api/foo": 9 | InOperation GetMethod: 10 | WithStatusCode 200: 11 | ResponsePayload: 12 | PayloadSchema: UnguardedRecursion 13 | -------------------------------------------------------------------------------- /test/golden/common/unguarded-recursive/silent/a.yaml: -------------------------------------------------------------------------------- 1 | components: 2 | schemas: 3 | A: 4 | type: object 5 | properties: 6 | bar: 7 | $ref: "#/components/schemas/B" 8 | B: 9 | anyOf: 10 | - $ref: "#/components/schemas/B" 11 | type: object 12 | openapi: 3.0.0 13 | info: 14 | version: "" 15 | title: "" 16 | paths: 17 | /foo: 18 | get: 19 | responses: 20 | "200": 21 | content: 22 | application/json;charset=utf-8: 23 | schema: 24 | $ref: "#/components/schemas/A" 25 | description: "" 26 | -------------------------------------------------------------------------------- /test/golden/common/unguarded-recursive/silent/b.yaml: -------------------------------------------------------------------------------- 1 | components: 2 | schemas: {} 3 | openapi: 3.0.0 4 | info: 5 | version: "" 6 | title: "" 7 | paths: 8 | /foo: 9 | get: 10 | responses: 11 | "200": 12 | content: 13 | application/json;charset=utf-8: 14 | schema: 15 | type: object 16 | properties: 17 | bar: 18 | type: object 19 | description: "" 20 | -------------------------------------------------------------------------------- /test/golden/common/unguarded-recursive/silent/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | ❌ Breaking changes | ⚠️ Non-breaking changes | [❓ Unsupported feature changes](#unsupported-changes) | 4 | |---------------------|-------------------------|--------------------------------------------------------| 5 | | 0 | 0 | 1 | 6 | 7 | # ❓ Unsupported feature changes 8 | 9 | ## **GET** /foo 10 | 11 | ### ⬅️☁️ JSON Response – 200 12 | 13 | #### `$.bar` 14 | 15 | Encountered recursion that is too complex for CompaREST to untangle. 16 | -------------------------------------------------------------------------------- /test/golden/common/unguarded-recursive/silent/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/foo": 3 | InOperation GetMethod: 4 | WithStatusCode 200: 5 | ResponsePayload: 6 | PayloadSchema: 7 | OfType Object: 8 | InProperty "bar": UnguardedRecursion 9 | backwardChanges: 10 | AtPath "/foo": 11 | InOperation GetMethod: 12 | WithStatusCode 200: 13 | ResponsePayload: 14 | PayloadSchema: 15 | OfType Object: 16 | InProperty "bar": UnguardedRecursion 17 | -------------------------------------------------------------------------------- /test/golden/common/variant-added/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | oneOf: 26 | - type: object 27 | required: ["tag", "prop_A"] 28 | properties: 29 | tag: 30 | enum: ["A"] 31 | prop_A: 32 | type: string 33 | - type: object 34 | required: ["tag", "prop_B"] 35 | properties: 36 | tag: 37 | enum: ["B"] 38 | prop_B: 39 | type: number 40 | -------------------------------------------------------------------------------- /test/golden/common/variant-added/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | oneOf: 26 | - type: object 27 | required: ["tag", "prop_A"] 28 | properties: 29 | tag: 30 | enum: ["A"] 31 | prop_A: 32 | type: string 33 | - type: object 34 | required: ["tag", "prop_B"] 35 | properties: 36 | tag: 37 | enum: ["B"] 38 | prop_B: 39 | type: number 40 | - type: object 41 | required: ["tag", "prop_C"] 42 | properties: 43 | tag: 44 | enum: ["C"] 45 | prop_C: 46 | type: number 47 | -------------------------------------------------------------------------------- /test/golden/common/variant-added/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 1 | 1 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### ⬅️☁️ JSON Response – 200 12 | 13 | #### `$(Object)` 14 | 15 | The case where `$.tag` is `"C"` – has been added. 16 | 17 | # ⚠️ Non-breaking changes 18 | 19 | ## **POST** /test 20 | 21 | ### ➡️☁️ JSON Request 22 | 23 | #### `$(Object)` 24 | 25 | The case where `$.tag` is `"C"` – has been added. 26 | -------------------------------------------------------------------------------- /test/golden/common/variant-added/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | WithStatusCode 200: 5 | ResponsePayload: 6 | PayloadSchema: 7 | OfType Object: PartitionBecomesEmpty (PInProperty "tag" PHere,CByEnumValue 8 | (fromList [String "C"])) 9 | backwardChanges: 10 | AtPath "/test": 11 | InOperation PostMethod: 12 | InRequest: 13 | InPayload: 14 | PayloadSchema: 15 | OfType Object: PartitionBecomesEmpty (PInProperty "tag" PHere,CByEnumValue 16 | (fromList [String "C"])) 17 | -------------------------------------------------------------------------------- /test/golden/common/variant-changed/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | oneOf: 26 | - type: object 27 | required: ["tag", "prop_A"] 28 | properties: 29 | tag: 30 | enum: ["A"] 31 | prop_A: 32 | type: string 33 | - type: object 34 | required: ["tag", "prop_B"] 35 | properties: 36 | tag: 37 | enum: ["B"] 38 | prop_B: 39 | type: number 40 | -------------------------------------------------------------------------------- /test/golden/common/variant-changed/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | oneOf: 26 | - type: object 27 | required: ["tag", "prop_A"] 28 | properties: 29 | tag: 30 | enum: ["A"] 31 | prop_A: 32 | type: string 33 | - type: object 34 | required: ["tag", "prop_B"] 35 | properties: 36 | tag: 37 | enum: ["B"] 38 | prop_B: 39 | type: string 40 | -------------------------------------------------------------------------------- /test/golden/common/variant-changed/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 2 | 2 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### ➡️☁️ JSON Request 12 | 13 | #### In cases where `$.tag` is `"B"` 14 | 15 | ##### `$.prop_B(Number)` 16 | 17 | The type has been removed. 18 | 19 | ### ⬅️☁️ JSON Response – 200 20 | 21 | #### In cases where `$.tag` is `"B"` 22 | 23 | ##### `$.prop_B(String)` 24 | 25 | The type has been added. 26 | 27 | # ⚠️ Non-breaking changes 28 | 29 | ## **POST** /test 30 | 31 | ### ➡️☁️ JSON Request 32 | 33 | #### In cases where `$.tag` is `"B"` 34 | 35 | ##### `$.prop_B(String)` 36 | 37 | The type has been added. 38 | 39 | ### ⬅️☁️ JSON Response – 200 40 | 41 | #### In cases where `$.tag` is `"B"` 42 | 43 | ##### `$.prop_B(Number)` 44 | 45 | The type has been removed. 46 | -------------------------------------------------------------------------------- /test/golden/common/variant-changed/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | InRequest: 5 | InPayload: 6 | PayloadSchema: 7 | OfType Object: 8 | InPartition (PInProperty "tag" PHere,CByEnumValue (fromList [String "B"])): 9 | InProperty "prop_B": 10 | OfType Number: TypeBecomesEmpty 11 | WithStatusCode 200: 12 | ResponsePayload: 13 | PayloadSchema: 14 | OfType Object: 15 | InPartition (PInProperty "tag" PHere,CByEnumValue (fromList [String "B"])): 16 | InProperty "prop_B": 17 | OfType String: TypeBecomesEmpty 18 | backwardChanges: 19 | AtPath "/test": 20 | InOperation PostMethod: 21 | InRequest: 22 | InPayload: 23 | PayloadSchema: 24 | OfType Object: 25 | InPartition (PInProperty "tag" PHere,CByEnumValue (fromList [String "B"])): 26 | InProperty "prop_B": 27 | OfType String: TypeBecomesEmpty 28 | WithStatusCode 200: 29 | ResponsePayload: 30 | PayloadSchema: 31 | OfType Object: 32 | InPartition (PInProperty "tag" PHere,CByEnumValue (fromList [String "B"])): 33 | InProperty "prop_B": 34 | OfType Number: TypeBecomesEmpty 35 | -------------------------------------------------------------------------------- /test/golden/common/variant-deep-changed/a.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | oneOf: 26 | - type: object 27 | required: ["desc", "prop_A"] 28 | properties: 29 | desc: 30 | type: object 31 | required: ["name"] 32 | properties: 33 | name: 34 | enum: ["A"] 35 | prop_A: 36 | type: string 37 | - type: object 38 | required: ["desc", "prop_B"] 39 | properties: 40 | desc: 41 | type: object 42 | required: ["name"] 43 | properties: 44 | name: 45 | enum: ["B"] 46 | prop_B: 47 | type: number 48 | -------------------------------------------------------------------------------- /test/golden/common/variant-deep-changed/b.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | servers: 6 | - url: http://localhost/ 7 | paths: 8 | /test: 9 | post: 10 | requestBody: 11 | content: 12 | application/json: 13 | schema: 14 | $ref: "#/components/schemas/Test" 15 | responses: 16 | '200': 17 | description: test 18 | content: 19 | application/json: 20 | schema: 21 | $ref: "#/components/schemas/Test" 22 | components: 23 | schemas: 24 | Test: 25 | oneOf: 26 | - type: object 27 | required: ["desc", "prop_A"] 28 | properties: 29 | desc: 30 | type: object 31 | required: ["name"] 32 | properties: 33 | name: 34 | enum: ["A"] 35 | prop_A: 36 | type: string 37 | - type: object 38 | required: ["desc", "prop_B"] 39 | properties: 40 | desc: 41 | type: object 42 | required: ["name"] 43 | properties: 44 | name: 45 | enum: ["B"] 46 | prop_B: 47 | type: string 48 | -------------------------------------------------------------------------------- /test/golden/common/variant-deep-changed/report.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) | 4 | |------------------------------------------|--------------------------------------------------| 5 | | 2 | 2 | 6 | 7 | # ❌ Breaking changes 8 | 9 | ## **POST** /test 10 | 11 | ### ➡️☁️ JSON Request 12 | 13 | #### In cases where `$.desc.name` is `"B"` 14 | 15 | ##### `$.prop_B(Number)` 16 | 17 | The type has been removed. 18 | 19 | ### ⬅️☁️ JSON Response – 200 20 | 21 | #### In cases where `$.desc.name` is `"B"` 22 | 23 | ##### `$.prop_B(String)` 24 | 25 | The type has been added. 26 | 27 | # ⚠️ Non-breaking changes 28 | 29 | ## **POST** /test 30 | 31 | ### ➡️☁️ JSON Request 32 | 33 | #### In cases where `$.desc.name` is `"B"` 34 | 35 | ##### `$.prop_B(String)` 36 | 37 | The type has been added. 38 | 39 | ### ⬅️☁️ JSON Response – 200 40 | 41 | #### In cases where `$.desc.name` is `"B"` 42 | 43 | ##### `$.prop_B(Number)` 44 | 45 | The type has been removed. 46 | -------------------------------------------------------------------------------- /test/golden/common/variant-deep-changed/trace-tree.yaml: -------------------------------------------------------------------------------- 1 | forwardChanges: 2 | AtPath "/test": 3 | InOperation PostMethod: 4 | InRequest: 5 | InPayload: 6 | PayloadSchema: 7 | OfType Object: 8 | InPartition (PInProperty "desc" (PInProperty "name" PHere),CByEnumValue (fromList [String "B"])): 9 | InProperty "prop_B": 10 | OfType Number: TypeBecomesEmpty 11 | WithStatusCode 200: 12 | ResponsePayload: 13 | PayloadSchema: 14 | OfType Object: 15 | InPartition (PInProperty "desc" (PInProperty "name" PHere),CByEnumValue (fromList [String "B"])): 16 | InProperty "prop_B": 17 | OfType String: TypeBecomesEmpty 18 | backwardChanges: 19 | AtPath "/test": 20 | InOperation PostMethod: 21 | InRequest: 22 | InPayload: 23 | PayloadSchema: 24 | OfType Object: 25 | InPartition (PInProperty "desc" (PInProperty "name" PHere),CByEnumValue (fromList [String "B"])): 26 | InProperty "prop_B": 27 | OfType String: TypeBecomesEmpty 28 | WithStatusCode 200: 29 | ResponsePayload: 30 | PayloadSchema: 31 | OfType Object: 32 | InPartition (PInProperty "desc" (PInProperty "name" PHere),CByEnumValue (fromList [String "B"])): 33 | InProperty "prop_B": 34 | OfType Number: TypeBecomesEmpty 35 | --------------------------------------------------------------------------------