diff --git a/packages/plugin-openapi/CHANGELOG.md b/packages/plugin-openapi/CHANGELOG.md index 67fe90075..6b679f7d1 100644 --- a/packages/plugin-openapi/CHANGELOG.md +++ b/packages/plugin-openapi/CHANGELOG.md @@ -11,6 +11,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Removed ### BREAKING CHANGE +## [2.0.1] - 2023-04-09 + +### Fixed +- fix(#464): Fix conversion of paths with multiple parameters + ## [2.0.0] - 2022-09-14 ### Changed diff --git a/packages/plugin-openapi/jest.config.js b/packages/plugin-openapi/jest.config.js index 338ca8694..422ef76e7 100644 --- a/packages/plugin-openapi/jest.config.js +++ b/packages/plugin-openapi/jest.config.js @@ -26,7 +26,7 @@ module.exports = { // The glob patterns Jest uses to detect test files testMatch: ["<rootDir>/test/**/*.spec.js"], - // testMatch: ["<rootDir>/test/**/collections.spec.js"], + // testMatch: ["<rootDir>/test/**/*.spec.js"], // The test environment that will be used for testing testEnvironment: "node", diff --git a/packages/plugin-openapi/package.json b/packages/plugin-openapi/package.json index e967359f6..8b87c3ee1 100644 --- a/packages/plugin-openapi/package.json +++ b/packages/plugin-openapi/package.json @@ -1,6 +1,6 @@ { "name": "@mocks-server/plugin-openapi", - "version": "2.0.0", + "version": "2.0.1", "description": "Mocks server plugin allowing to create routes and collections from OpenApi definitions", "keywords": [ "mocks-server-plugin", diff --git a/packages/plugin-openapi/sonar-project.properties b/packages/plugin-openapi/sonar-project.properties index b0b1b9b2d..130575f36 100644 --- a/packages/plugin-openapi/sonar-project.properties +++ b/packages/plugin-openapi/sonar-project.properties @@ -1,7 +1,7 @@ sonar.organization=mocks-server sonar.projectKey=mocks-server_main_plugin-openapi sonar.projectName=plugin-openapi -sonar.projectVersion=2.0.0 +sonar.projectVersion=2.0.1 sonar.javascript.file.suffixes=.js sonar.sourceEncoding=UTF-8 diff --git a/packages/plugin-openapi/src/openapi.ts b/packages/plugin-openapi/src/openapi.ts index 8636ba121..7f56551f9 100644 --- a/packages/plugin-openapi/src/openapi.ts +++ b/packages/plugin-openapi/src/openapi.ts @@ -15,7 +15,7 @@ function notEmpty<TValue>(value: TValue | null | undefined): value is TValue { function replaceTemplateInPath(path: string): string { // /api/users/{userId} -> api/users/:userId - return path.replace(/{(\S*)}/gim, ":$1") + return path.replace(/{(\S*?)}/gim, ":$1") } function pathToId(path: string): string { diff --git a/packages/plugin-openapi/test/fixtures/api-multiple-params/collections.js b/packages/plugin-openapi/test/fixtures/api-multiple-params/collections.js new file mode 100644 index 000000000..26702f6ec --- /dev/null +++ b/packages/plugin-openapi/test/fixtures/api-multiple-params/collections.js @@ -0,0 +1,12 @@ +module.exports = [ + { + id: "base", + routes: [ + "get-users:200-json-one-user", + "post-users:201-status", + "get-users-id:200-json-success", + "get-users-id-books-bookId:200-json-success", + "get-users-id-books-bookId-pages-pageNumber:200-text-success", + ], + }, +]; diff --git a/packages/plugin-openapi/test/fixtures/api-multiple-params/openapi/api.js b/packages/plugin-openapi/test/fixtures/api-multiple-params/openapi/api.js new file mode 100644 index 000000000..03cca811a --- /dev/null +++ b/packages/plugin-openapi/test/fixtures/api-multiple-params/openapi/api.js @@ -0,0 +1,105 @@ +const openApiDocument = require("../../../openapi/users"); + +module.exports = [ + { + basePath: "/api", + document: { + ...openApiDocument, + paths: { + ...openApiDocument.paths, + "/users/{id}/books/{bookId}": { + get: { + parameters: [ + { + name: "id", + in: "path", + description: "ID of the user", + required: true, + schema: { + type: "string", + }, + }, + { + name: "bookId", + in: "path", + description: "ID the user book", + required: true, + schema: { + type: "string", + }, + }, + ], + summary: "Return books of one user", + responses: { + "200": { + description: "successful operation", + content: { + "application/json": { + examples: { + success: { + summary: "One book", + value: { + id: 1, + title: "1984", + }, + }, + }, + }, + }, + }, + }, + }, + }, + "/users/{id}/books/{bookId}/pages/{pageNumber}": { + get: { + parameters: [ + { + name: "id", + in: "path", + description: "ID of the user", + required: true, + schema: { + type: "string", + }, + }, + { + name: "bookId", + in: "path", + description: "ID the user book", + required: true, + schema: { + type: "string", + }, + }, + { + name: "pageNumber", + in: "path", + description: "Book page number", + required: true, + schema: { + type: "number", + }, + }, + ], + summary: "Return a page of a book of one user", + responses: { + "200": { + description: "successful operation", + content: { + "text/plain": { + examples: { + success: { + summary: "Example page", + value: "Page of the book 1984 by George Orwell.", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, +]; diff --git a/packages/plugin-openapi/test/multiple-params.spec.js b/packages/plugin-openapi/test/multiple-params.spec.js new file mode 100644 index 000000000..29a011d1f --- /dev/null +++ b/packages/plugin-openapi/test/multiple-params.spec.js @@ -0,0 +1,109 @@ +import { startServer, fetchJson, fetchText, waitForServer } from "./support/helpers"; + +describe("generated routes", () => { + let server; + + beforeAll(async () => { + server = await startServer("api-multiple-params"); + await waitForServer(); + }); + + afterAll(async () => { + await server.stop(); + }); + + describe("routes", () => { + it("should have created routes from openapi document defined in files", async () => { + expect(server.mock.routes.plain).toEqual([ + { + id: "get-users", + url: "/api/users", + method: "get", + delay: null, + variants: ["get-users:200-json-one-user", "get-users:200-json-two-users"], + }, + { + id: "post-users", + url: "/api/users", + method: "post", + delay: null, + variants: ["post-users:201-status", "post-users:400-text-error-message"], + }, + { + id: "get-users-id", + url: "/api/users/:id", + method: "get", + delay: null, + variants: ["get-users-id:200-json-success", "get-users-id:404-json-not-found"], + }, + { + id: "get-users-id-books-bookId", + url: "/api/users/:id/books/:bookId", + method: "get", + delay: null, + variants: ["get-users-id-books-bookId:200-json-success"], + }, + { + id: "get-users-id-books-bookId-pages-pageNumber", + url: "/api/users/:id/books/:bookId/pages/:pageNumber", + method: "get", + delay: null, + variants: ["get-users-id-books-bookId-pages-pageNumber:200-text-success"], + }, + ]); + }); + }); + + describe("get-users route", () => { + it("should have 200-json-one-user variant available in base collection", async () => { + const response = await fetchJson("/api/users"); + expect(response.body).toEqual([ + { + id: 1, + name: "John Doe", + }, + ]); + expect(response.status).toEqual(200); + }); + }); + + describe("post-users route", () => { + it("should have 201-status variant available in base collection", async () => { + const response = await fetchJson("/api/users", { + method: "POST", + }); + expect(response.body).toBe(undefined); + expect(response.status).toEqual(201); + }); + }); + + describe("get-users-id route", () => { + it("should have 200-json-success variant available in base collection", async () => { + const response = await fetchJson("/api/users/2"); + expect(response.body).toEqual({ + id: 1, + name: "John Doe", + }); + expect(response.status).toEqual(200); + }); + }); + + describe("get-users-id-books-bookId route", () => { + it("should have 200-json-success variant available in base collection", async () => { + const response = await fetchJson("/api/users/2/books/3"); + expect(response.body).toEqual({ + id: 1, + title: "1984", + }); + expect(response.status).toEqual(200); + }); + }); + + describe("get-users-id-books-bookId-pages-pageNumber route", () => { + it("should have 200-text-success variant available in base collection", async () => { + const response = await fetchText("/api/users/2/books/3/pages/4"); + expect(response.body).toEqual("Page of the book 1984 by George Orwell."); + expect(response.status).toEqual(200); + }); + }); +});