From 9b9e06c6733c8b6e320b03c17282672e279330c9 Mon Sep 17 00:00:00 2001 From: Oscar Reyes Date: Fri, 24 Nov 2023 09:28:48 -0600 Subject: [PATCH] feat: Import Definition (#3399) --- web/package-lock.json | 216 ++++++++---------- web/package.json | 1 + .../components/ImportModal/ImportModal.tsx | 5 +- web/src/components/ImportModal/Tip.tsx | 2 +- .../Inputs/Editor/CurlCommand/CurlCommand.tsx | 1 + .../Inputs/Editor/Definition/Definition.tsx | 32 +++ .../Inputs/Editor/Definition/index.ts | 2 + web/src/components/Inputs/Editor/Editor.tsx | 1 + .../Inputs/ImportSelector/ImportSelector.tsx | 2 +- .../components/TestPlugins/ImportFactory.tsx | 2 + .../Imports/Definition/Definition.styled.ts | 31 +++ .../Imports/Definition/Definition.tsx | 28 +++ .../TestPlugins/Imports/Definition/index.ts | 2 + web/src/constants/Editor.constants.ts | 1 + web/src/constants/Plugins.constants.ts | 7 +- web/src/constants/Test.constants.ts | 1 + web/src/models/Test.model.ts | 6 + web/src/services/Import.service.ts | 7 + web/src/services/Importers/Curl.service.ts | 5 + .../services/Importers/Definition.service.ts | 65 ++++++ .../services/Importers/Postman.service.tsx | 6 + web/src/types/Test.types.ts | 9 +- 22 files changed, 295 insertions(+), 137 deletions(-) create mode 100644 web/src/components/Inputs/Editor/Definition/Definition.tsx create mode 100644 web/src/components/Inputs/Editor/Definition/index.ts create mode 100644 web/src/components/TestPlugins/Imports/Definition/Definition.styled.ts create mode 100644 web/src/components/TestPlugins/Imports/Definition/Definition.tsx create mode 100644 web/src/components/TestPlugins/Imports/Definition/index.ts create mode 100644 web/src/services/Importers/Definition.service.ts diff --git a/web/package-lock.json b/web/package-lock.json index da78b8399d..51664288cb 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -41,6 +41,7 @@ "fast-xml-parser": "4.2.4", "history": "5.2.0", "html-react-parser": "3.0.4", + "js-yaml": "4.1.0", "less": "4.1.3", "lodash": "4.17.21", "markdown-it": "13.0.1", @@ -2693,11 +2694,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "13.12.1", "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", @@ -2720,17 +2716,6 @@ "node": ">= 4" } }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/@eslint/eslintrc/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -2799,6 +2784,14 @@ "node": ">=8" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -2819,6 +2812,18 @@ "node": ">=8" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -9710,12 +9715,9 @@ "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==" }, "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/aria-query": { "version": "4.2.2", @@ -13953,11 +13955,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, "node_modules/eslint/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -14022,17 +14019,6 @@ "node": ">=8" } }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -18733,12 +18719,11 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" @@ -19465,11 +19450,6 @@ "markdown-it": "bin/markdown-it.js" } }, - "node_modules/markdown-it/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, "node_modules/markdown-it/node_modules/entities": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", @@ -20321,24 +20301,6 @@ "npm": ">= 7.0.0" } }, - "node_modules/openapi-typescript/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/openapi-typescript/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/openapi-typescript/node_modules/mime": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", @@ -24429,7 +24391,7 @@ "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "node_modules/sshpk": { "version": "1.17.0", @@ -24948,6 +24910,14 @@ "node": ">=4.0.0" } }, + "node_modules/svgo/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, "node_modules/svgo/node_modules/css-select": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", @@ -24993,6 +24963,18 @@ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" }, + "node_modules/svgo/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/svgo/node_modules/nth-check": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", @@ -28800,11 +28782,6 @@ "strip-json-comments": "^3.1.1" }, "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, "globals": { "version": "13.12.1", "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", @@ -28818,14 +28795,6 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "requires": { - "argparse": "^2.0.1" - } - }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -28877,6 +28846,14 @@ "resolve-from": "^5.0.0" }, "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -28891,6 +28868,15 @@ "path-exists": "^4.0.0" } }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -32980,12 +32966,9 @@ "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==" }, "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "~1.0.2" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "aria-query": { "version": "4.2.2", @@ -35668,11 +35651,6 @@ "color-convert": "^2.0.1" } }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -35713,14 +35691,6 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "requires": { - "argparse": "^2.0.1" - } - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -39580,12 +39550,11 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" } }, "jsbn": { @@ -40134,11 +40103,6 @@ "uc.micro": "^1.0.5" }, "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, "entities": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", @@ -40769,21 +40733,6 @@ "yargs-parser": "^21.0.1" }, "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, "mime": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", @@ -43696,7 +43645,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "sshpk": { "version": "1.17.0", @@ -44078,6 +44027,14 @@ "util.promisify": "~1.0.0" }, "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, "css-select": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", @@ -44119,6 +44076,15 @@ } } }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "nth-check": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", diff --git a/web/package.json b/web/package.json index a662b7d0f8..b641c4f128 100644 --- a/web/package.json +++ b/web/package.json @@ -37,6 +37,7 @@ "fast-xml-parser": "4.2.4", "history": "5.2.0", "html-react-parser": "3.0.4", + "js-yaml": "4.1.0", "less": "4.1.3", "lodash": "4.17.21", "markdown-it": "13.0.1", diff --git a/web/src/components/ImportModal/ImportModal.tsx b/web/src/components/ImportModal/ImportModal.tsx index 634ed4e090..ee1a002676 100644 --- a/web/src/components/ImportModal/ImportModal.tsx +++ b/web/src/components/ImportModal/ImportModal.tsx @@ -4,7 +4,6 @@ import {TDraftTest} from 'types/Test.types'; import {ImportTypes} from 'constants/Test.constants'; import ImportService from 'services/Import.service'; import {useDashboard} from 'providers/Dashboard/Dashboard.provider'; -import {ImportTypeToPlugin} from 'constants/Plugins.constants'; import {useCreateTest} from 'providers/CreateTest/CreateTest.provider'; import {ImportSelector} from 'components/Inputs'; import ImportFactory from 'components/TestPlugins/ImportFactory'; @@ -36,7 +35,7 @@ const ImportModal = ({isOpen, onClose}: IProps) => { const handleImport = useCallback( async (values: TDraftTest) => { const draft = await ImportService.getRequest(type, values); - const plugin = ImportTypeToPlugin[type]; + const plugin = await ImportService.getPlugin(type, values); onInitialValues(draft); navigate(`/test/create/${plugin.type}`); @@ -66,7 +65,7 @@ const ImportModal = ({isOpen, onClose}: IProps) => { layout="vertical" name={FORM_ID} onFinish={handleImport} - initialValues={{importType: ImportTypes.curl}} + initialValues={{importType: ImportTypes.definition}} onValuesChange={(_: any, values) => handleChange(values)} > diff --git a/web/src/components/ImportModal/Tip.tsx b/web/src/components/ImportModal/Tip.tsx index 5cdce3b586..09349350a5 100644 --- a/web/src/components/ImportModal/Tip.tsx +++ b/web/src/components/ImportModal/Tip.tsx @@ -6,7 +6,7 @@ const Tip = () => ( What are the supported formats? - We support cURL & Postman. OpenAPI is coming soon! + We support Tracetest Definition, cURL & Postman. OpenAPI is coming soon! ); diff --git a/web/src/components/Inputs/Editor/CurlCommand/CurlCommand.tsx b/web/src/components/Inputs/Editor/CurlCommand/CurlCommand.tsx index a7f37f8f19..41c66eae13 100644 --- a/web/src/components/Inputs/Editor/CurlCommand/CurlCommand.tsx +++ b/web/src/components/Inputs/Editor/CurlCommand/CurlCommand.tsx @@ -13,6 +13,7 @@ const CurlCommand = ({value, onChange}: IEditorProps) => { extensions={[StreamLanguage.define(shell)]} spellCheck={false} placeholder="curl -X POST http://site.com" + autoFocus /> ); }; diff --git a/web/src/components/Inputs/Editor/Definition/Definition.tsx b/web/src/components/Inputs/Editor/Definition/Definition.tsx new file mode 100644 index 0000000000..34e461e504 --- /dev/null +++ b/web/src/components/Inputs/Editor/Definition/Definition.tsx @@ -0,0 +1,32 @@ +import CodeMirror from '@uiw/react-codemirror'; +import {StreamLanguage} from '@codemirror/language'; +import {yaml} from '@codemirror/legacy-modes/mode/yaml'; +import {IEditorProps} from '../Editor'; + +const placeholder = `type: Test +spec: + name: My Test + trigger: + type: http + httpRequest: + method: GET + url: google.com +`; + +const Definition = ({value, onChange}: IEditorProps) => { + return ( + + ); +}; + +export default Definition; diff --git a/web/src/components/Inputs/Editor/Definition/index.ts b/web/src/components/Inputs/Editor/Definition/index.ts new file mode 100644 index 0000000000..7e9c8d6cb8 --- /dev/null +++ b/web/src/components/Inputs/Editor/Definition/index.ts @@ -0,0 +1,2 @@ +// eslint-disable-next-line no-restricted-exports +export {default} from './Definition'; diff --git a/web/src/components/Inputs/Editor/Editor.tsx b/web/src/components/Inputs/Editor/Editor.tsx index 4957ad42eb..bbd306687e 100644 --- a/web/src/components/Inputs/Editor/Editor.tsx +++ b/web/src/components/Inputs/Editor/Editor.tsx @@ -11,6 +11,7 @@ const EditorMap = { [SupportedEditors.Selector]: lazy(() => import('./Selector')), [SupportedEditors.Interpolation]: lazy(() => import('./Interpolation')), [SupportedEditors.CurlCommand]: lazy(() => import('./CurlCommand')), + [SupportedEditors.Definition]: lazy(() => import('./Definition')), } as const; export interface IEditorProps { diff --git a/web/src/components/Inputs/ImportSelector/ImportSelector.tsx b/web/src/components/Inputs/ImportSelector/ImportSelector.tsx index e0b67b826d..7380d922f9 100644 --- a/web/src/components/Inputs/ImportSelector/ImportSelector.tsx +++ b/web/src/components/Inputs/ImportSelector/ImportSelector.tsx @@ -3,7 +3,7 @@ import {ImportTypes} from 'constants/Test.constants'; import ImportCard from './ImportCard'; import * as S from './ImportSelector.styled'; -const importList = [ImportTypes.curl, ImportTypes.postman]; +const importList = [ImportTypes.definition, ImportTypes.curl, ImportTypes.postman]; interface IProps { value?: ImportTypes; diff --git a/web/src/components/TestPlugins/ImportFactory.tsx b/web/src/components/TestPlugins/ImportFactory.tsx index e538ca4dcc..c2a93cd69f 100644 --- a/web/src/components/TestPlugins/ImportFactory.tsx +++ b/web/src/components/TestPlugins/ImportFactory.tsx @@ -3,10 +3,12 @@ import {TDraftTestForm} from 'types/Test.types'; import Postman from './Imports/Postman'; import Curl from './Imports/Curl'; import useShortcut from './hooks/useShortcut'; +import Definition from './Imports/Definition'; const ImportFactoryMap = { [ImportTypes.postman]: Postman, [ImportTypes.curl]: Curl, + [ImportTypes.definition]: Definition, }; export interface IFormProps { diff --git a/web/src/components/TestPlugins/Imports/Definition/Definition.styled.ts b/web/src/components/TestPlugins/Imports/Definition/Definition.styled.ts new file mode 100644 index 0000000000..d055882da9 --- /dev/null +++ b/web/src/components/TestPlugins/Imports/Definition/Definition.styled.ts @@ -0,0 +1,31 @@ +import {DeleteOutlined} from '@ant-design/icons'; +import {Typography} from 'antd'; +import styled from 'styled-components'; + +export const Row = styled.div` + display: flex; +`; + +export const Label = styled(Typography.Text).attrs({as: 'div'})` + margin-bottom: 8px; +`; + +export const URLInputContainer = styled.div` + display: flex; + align-items: flex-start; + + .ant-form-item { + margin: 0; + } +`; + +export const HeaderContainer = styled.div` + align-items: center; + display: flex; + margin-bottom: 8px; +`; + +export const DeleteIcon = styled(DeleteOutlined)` + color: ${({theme}) => theme.color.textSecondary}; + font-size: ${({theme}) => theme.size.md}; +`; diff --git a/web/src/components/TestPlugins/Imports/Definition/Definition.tsx b/web/src/components/TestPlugins/Imports/Definition/Definition.tsx new file mode 100644 index 0000000000..419a77055d --- /dev/null +++ b/web/src/components/TestPlugins/Imports/Definition/Definition.tsx @@ -0,0 +1,28 @@ +import {Form} from 'antd'; +import {Editor} from 'components/Inputs'; +import {SupportedEditors} from 'constants/Editor.constants'; +import DefinitionService from 'services/Importers/Definition.service'; + +const Definition = () => { + return ( + { + const errors = DefinitionService.validate(definition); + if (errors.length) return Promise.reject(new Error(errors.join(', '))); + + return Promise.resolve(); + }, + }, + ]} + > + + + ); +}; + +export default Definition; diff --git a/web/src/components/TestPlugins/Imports/Definition/index.ts b/web/src/components/TestPlugins/Imports/Definition/index.ts new file mode 100644 index 0000000000..7e9c8d6cb8 --- /dev/null +++ b/web/src/components/TestPlugins/Imports/Definition/index.ts @@ -0,0 +1,2 @@ +// eslint-disable-next-line no-restricted-exports +export {default} from './Definition'; diff --git a/web/src/constants/Editor.constants.ts b/web/src/constants/Editor.constants.ts index acaa82c8ca..66800ca2b5 100644 --- a/web/src/constants/Editor.constants.ts +++ b/web/src/constants/Editor.constants.ts @@ -70,6 +70,7 @@ export enum SupportedEditors { Interpolation = 'interpolation-editor', Expression = 'expression-editor', CurlCommand = 'curlCommand-editor', + Definition = 'definition-editor', } export const operatorList = [ diff --git a/web/src/constants/Plugins.constants.ts b/web/src/constants/Plugins.constants.ts index f35dffad4b..99a595852d 100644 --- a/web/src/constants/Plugins.constants.ts +++ b/web/src/constants/Plugins.constants.ts @@ -1,6 +1,6 @@ import {IPlugin} from 'types/Plugins.types'; import {SupportedPlugins} from './Common.constants'; -import {ImportTypes, TriggerTypes} from './Test.constants'; +import {TriggerTypes} from './Test.constants'; export enum ComponentNames { SelectPlugin = 'SelectPlugin', @@ -61,8 +61,3 @@ export const TriggerTypeToPlugin = { [TriggerTypes.kafka]: Plugins.Kafka, [TriggerTypes.traceid]: Plugins.TraceID, } as const; - -export const ImportTypeToPlugin = { - [ImportTypes.curl]: Plugins.REST, - [ImportTypes.postman]: Plugins.REST, -} as const; diff --git a/web/src/constants/Test.constants.ts b/web/src/constants/Test.constants.ts index 174554358b..bc8902577a 100644 --- a/web/src/constants/Test.constants.ts +++ b/web/src/constants/Test.constants.ts @@ -15,6 +15,7 @@ export enum TriggerTypes { export enum ImportTypes { postman = 'postman', curl = 'curl', + definition = 'definition', } export enum SortBy { diff --git a/web/src/models/Test.model.ts b/web/src/models/Test.model.ts index 4035a0147c..f3bfd74d26 100644 --- a/web/src/models/Test.model.ts +++ b/web/src/models/Test.model.ts @@ -1,3 +1,4 @@ +import {load} from 'js-yaml'; import {Model, TTestSchemas} from 'types/Common.types'; import TestOutput from './TestOutput.model'; import TestSpecs from './TestSpecs.model'; @@ -48,4 +49,9 @@ Test.FromRawTest = ({ }; }; +Test.FromDefinition = (definition: string): Test => { + const raw: TRawTestResource = load(definition); + return Test(raw); +}; + export default Test; diff --git a/web/src/services/Import.service.ts b/web/src/services/Import.service.ts index 11dd7db68b..d7d5404eab 100644 --- a/web/src/services/Import.service.ts +++ b/web/src/services/Import.service.ts @@ -1,11 +1,14 @@ import {ImportTypes} from 'constants/Test.constants'; import {TDraftTest} from 'types/Test.types'; +import {IPlugin} from 'types/Plugins.types'; import CurlService from './Importers/Curl.service'; import PostmanService from './Importers/Postman.service'; +import DefinitionService from './Importers/Definition.service'; const ImportServiceMap = { [ImportTypes.curl]: CurlService, [ImportTypes.postman]: PostmanService, + [ImportTypes.definition]: DefinitionService, } as const; const ImportService = () => ({ @@ -16,6 +19,10 @@ const ImportService = () => ({ async validateDraft(type: ImportTypes, draft: TDraftTest): Promise { return ImportServiceMap[type].validateDraft(draft); }, + + async getPlugin(type: ImportTypes, draft: TDraftTest): Promise { + return ImportServiceMap[type].getPlugin(draft); + }, }); export default ImportService(); diff --git a/web/src/services/Importers/Curl.service.ts b/web/src/services/Importers/Curl.service.ts index a8f011b0d8..ea453bdfcb 100644 --- a/web/src/services/Importers/Curl.service.ts +++ b/web/src/services/Importers/Curl.service.ts @@ -1,6 +1,7 @@ import parseCurl from 'parse-curl'; import {ICurlValues, IImportService} from 'types/Test.types'; import Validator from 'utils/Validator'; +import {Plugins} from 'constants/Plugins.constants'; import {HTTP_METHOD} from 'constants/Common.constants'; interface ICurlTriggerService extends IImportService { @@ -27,6 +28,10 @@ const CurlTriggerService = (): ICurlTriggerService => ({ return Validator.required(url) && Validator.required(method); }, + getPlugin() { + return Plugins.REST; + }, + getRequestFromCommand(command) { const {url = '', method, header = {}, body} = parseCurl(command); diff --git a/web/src/services/Importers/Definition.service.ts b/web/src/services/Importers/Definition.service.ts new file mode 100644 index 0000000000..bfda2c3ae8 --- /dev/null +++ b/web/src/services/Importers/Definition.service.ts @@ -0,0 +1,65 @@ +import {load} from 'js-yaml'; +import {IDefinitionValues, IImportService} from 'types/Test.types'; +import {TriggerTypeToPlugin} from 'constants/Plugins.constants'; +import Test, {TRawTestResource} from 'models/Test.model'; +import TestService from '../Test.service'; +import {isJson} from '../../utils/Common'; + +interface IDefinitionImportService extends IImportService { + validate(definition: string): string[]; + load(raw: string): TRawTestResource; +} + +const DefinitionImportService = (): IDefinitionImportService => ({ + async getRequest(values) { + const {definition} = values as IDefinitionValues; + + const test = Test.FromDefinition(definition); + return TestService.getInitialValues(test); + }, + + async validateDraft(draft) { + const {definition} = draft as IDefinitionValues; + + return !this.validate(definition).length; + }, + + getPlugin(draft) { + const {definition} = draft as IDefinitionValues; + const {spec = {}}: TRawTestResource = this.load(definition); + + const triggerType = spec.trigger?.type; + return TriggerTypeToPlugin[triggerType!]; + }, + + load(raw) { + if (isJson(raw)) return JSON.parse(raw) as TRawTestResource; + + return load(raw) as TRawTestResource; + }, + + validate(raw) { + const {type, spec = {}}: TRawTestResource = this.load(raw); + const errors = []; + + if (type !== 'Test') { + errors.push(`Invalid type: ${type}`); + } + + if (!spec.name) { + errors.push(`Missing Name`); + } + + if (!spec.trigger) { + errors.push(`Missing trigger`); + } + + if (!spec.trigger?.type) { + errors.push('Missing trigger type'); + } + + return errors; + }, +}); + +export default DefinitionImportService(); diff --git a/web/src/services/Importers/Postman.service.tsx b/web/src/services/Importers/Postman.service.tsx index ecd94121ae..10b8001556 100644 --- a/web/src/services/Importers/Postman.service.tsx +++ b/web/src/services/Importers/Postman.service.tsx @@ -1,6 +1,7 @@ import {Collection, Item, ItemGroup, Request, RequestAuthDefinition, VariableDefinition} from 'postman-collection'; import {HTTP_METHOD} from 'constants/Common.constants'; import {IImportService, IPostmanValues, TDraftTestForm, TRequestAuth} from 'types/Test.types'; +import {Plugins} from 'constants/Plugins.constants'; import Validator from 'utils/Validator'; import HttpService from '../Triggers/Http.service'; @@ -45,6 +46,11 @@ const Postman = (): IPostmanTriggerService => ({ const draft = await this.valuesFromRequest(requests, variables, collectionTest || ''); return !!draft && HttpService.validateDraft(draft); }, + + getPlugin() { + return Plugins.REST; + }, + valuesFromRequest(requests, variables, identifier) { const request = requests.find(({id}) => identifier === id); if (request) { diff --git a/web/src/types/Test.types.ts b/web/src/types/Test.types.ts index f6c8ccd323..6a02f6179e 100644 --- a/web/src/types/Test.types.ts +++ b/web/src/types/Test.types.ts @@ -7,6 +7,7 @@ import HttpRequest from 'models/HttpRequest.model'; import TraceIDRequest from 'models/TraceIDRequest.model'; import KafkaRequest from 'models/KafkaRequest.model'; import {Model, TGrpcSchemas, THttpSchemas, TKafkaSchemas} from './Common.types'; +import {IPlugin} from './Plugins.types'; export type TRequestAuth = THttpSchemas['HTTPRequest']['auth']; export type TMethod = THttpSchemas['HTTPRequest']['method']; @@ -62,6 +63,10 @@ export interface ICurlValues extends IHttpValues { command: string; } +export interface IDefinitionValues { + definition: string; +} + export interface IBasicValues { name: string; description: string; @@ -74,6 +79,7 @@ export interface ITraceIDValues extends IHttpValues { } export type TTestRequestDetailsValues = IRpcValues | IHttpValues | IPostmanValues | ICurlValues | ITraceIDValues; + export type TDraftTest = Partial; export type TDraftTestForm = FormInstance>; @@ -85,6 +91,7 @@ export interface ITriggerService { } export interface IImportService { - getRequest(values: TDraftTest): Promise; + getRequest(draft: TDraftTest): Promise; validateDraft(draft: TDraftTest): Promise; + getPlugin(draft: TDraftTest): IPlugin; }