diff --git a/.gitignore b/.gitignore index 2e9dcf9c..8c713860 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ npm-debug.log* .eslintcache package-lock.json *.iml +selenium-debug.log +test/e2e/db.json diff --git a/README.md b/README.md index 15e5429a..57b1aaf8 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,15 @@ If you'd like to make modifications to the codebase, run the dev server with: `n If you'd like to rebuild the `/dist` folder with your codebase changes, run `npm run build`. + +##### Integration Tests + +You will need JDK of version 7 or higher as instructed here +http://nightwatchjs.org/gettingstarted#selenium-server-setup + +Integration tests can be run locally with `npm run e2e` - be sure you aren't running a dev server when testing! + + ##### Browser support Swagger UI works in the latest versions of Chrome, Safari, Firefox, Edge and IE11. diff --git a/make-webpack-config.js b/make-webpack-config.js index 2eeb9bf9..c2cc2268 100644 --- a/make-webpack-config.js +++ b/make-webpack-config.js @@ -1,9 +1,10 @@ var path = require("path") -var webpack = require("webpack") -var ExtractTextPlugin = require("extract-text-webpack-plugin") -var deepExtend = require("deep-extend") -const {gitDescribeSync} = require("git-describe") +var webpack = require('webpack') +var ExtractTextPlugin = require('extract-text-webpack-plugin') +const CopyWebpackPlugin = require('copy-webpack-plugin') +var deepExtend = require('deep-extend') +const {gitDescribeSync} = require('git-describe') const os = require("os") var pkg = require("./package.json") @@ -60,7 +61,8 @@ module.exports = function(rules, options) { })) } - if( specialOptions.minimize ) { + if( specialOptions.minimize ) { // production mode + plugins.push( new webpack.optimize.UglifyJsPlugin({ sourceMap: true, @@ -74,6 +76,8 @@ module.exports = function(rules, options) { plugins.push( new webpack.NoEmitOnErrorsPlugin()) + } else { // development mode + plugins.push(new CopyWebpackPlugin([ { from: 'test/e2e/specs', to: 'test-specs' } ])) } plugins.push( diff --git a/package.json b/package.json index 062afa03..1a2ce9d1 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,11 @@ "test": "npm run lint-errors && npm run just-test-in-node", "test-in-node": "npm run lint-errors && npm run just-test-in-node", "just-test": "karma start --config karma.conf.js", - "just-test-in-node": "mocha --recursive --compilers js:babel-core/register test/core test/components test/bugs test/swagger-ui-dist-package" + "just-test-in-node": "mocha --recursive --compilers js:babel-core/register test/core test/components test/bugs test/swagger-ui-dist-package", + "test-e2e": "sleep 3 && nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json", + "e2e-initial-render": "nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json --group initial-render", + "mock-api": "json-server --watch test/e2e/db.json --port 3204", + "e2e": "npm-run-all --parallel -r hot-server mock-api test-e2e" }, "dependencies": { "base64-js": "^1.2.0", @@ -90,6 +94,8 @@ "babel-preset-react": "^6.23.0", "babel-preset-stage-0": "^6.22.0", "babel-runtime": "^6.23.0", + "chromedriver": "^2.30.1", + "copy-webpack-plugin": "^4.0.1", "css-loader": "0.28.4", "deep-extend": "^0.5.0", "deepmerge": "^1.3.2", @@ -100,9 +106,9 @@ "extract-text-webpack-plugin": "^2.1.2", "file-loader": "0.11.2", "git-describe": "^4.0.1", - "html-webpack-plugin": "^2.28.0", "imports-loader": "0.7.1", "json-loader": "0.5.4", + "json-server": "^0.11.0", "karma": "^1.7.0", "karma-chrome-launcher": "^2.2.0", "karma-mocha": "^1.3.0", @@ -111,6 +117,7 @@ "less": "2.7.2", "license-checker": "^11.0.0", "mocha": "^3.4.2", + "nightwatch": "^0.9.16", "node-sass": "^4.5.0", "npm-run-all": "4.0.2", "null-loader": "0.1.1", @@ -121,6 +128,7 @@ "react-test-renderer": "^15.5.4", "rimraf": "^2.6.0", "sass-loader": "^6.0.2", + "selenium-server-standalone-jar": "3.4.0", "standard": "^10.0.2", "standard-loader": "^6.0.1", "style-loader": "0.18.2", diff --git a/test/e2e/db.json b/test/e2e/db.json new file mode 100644 index 00000000..e33ceaad --- /dev/null +++ b/test/e2e/db.json @@ -0,0 +1,130 @@ +{ + "pet": [ + { + "id": 1, + "category": { + "id": 0, + "name": "string" + }, + "name": "doggie", + "photoUrls": [ + "string" + ], + "tags": [ + { + "id": 0, + "name": "string" + } + ], + "status": "available" + }, + { + "id": 2, + "category": { + "id": 0, + "name": "string" + }, + "name": "doggie", + "photoUrls": [ + "string" + ], + "tags": [ + { + "id": 0, + "name": "string" + } + ], + "status": "available" + }, + { + "id": 3, + "category": { + "id": 0, + "name": "string" + }, + "name": "doggie", + "photoUrls": [ + "string" + ], + "tags": [ + { + "id": 0, + "name": "string" + } + ], + "status": "available" + }, + { + "id": 4, + "category": { + "id": 0, + "name": "string" + }, + "name": "doggie", + "photoUrls": [ + "string" + ], + "tags": [ + { + "id": 0, + "name": "string" + } + ], + "status": "available" + }, + { + "id": 5, + "category": { + "id": 0, + "name": "string" + }, + "name": "doggie", + "photoUrls": [ + "string" + ], + "tags": [ + { + "id": 0, + "name": "string" + } + ], + "status": "available" + }, + { + "id": 6, + "category": { + "id": 0, + "name": "string" + }, + "name": "doggie", + "photoUrls": [ + "string" + ], + "tags": [ + { + "id": 0, + "name": "string" + } + ], + "status": "available" + }, + { + "id": 7, + "category": { + "id": 0, + "name": "string" + }, + "name": "doggie", + "photoUrls": [ + "string" + ], + "tags": [ + { + "id": 0, + "name": "string" + } + ], + "status": "available" + } + ] +} \ No newline at end of file diff --git a/test/e2e/nightwatch.json b/test/e2e/nightwatch.json new file mode 100644 index 00000000..16ac8bcc --- /dev/null +++ b/test/e2e/nightwatch.json @@ -0,0 +1,63 @@ +{ + "src_folders" : ["test/e2e/scenarios"], + "output_folder" : "reports", + "live_output": true, + "custom_commands_path" : "", + "custom_assertions_path" : "", + "page_objects_path" : "test/e2e/pages", + "globals_path" : "", + "test_workers" : { + "enabled" : true, + "workers" : "auto" + }, + + "test_runner" : { + "type" : "mocha", + "options" : { + "ui" : "bdd", + "reporter" : "list" + } + }, + + "selenium" : { + "start_process" : true, + "server_path" : "node_modules/selenium-server-standalone-jar/jar/selenium-server-standalone-3.4.0.jar", + "log_path" : "", + "host" : "127.0.0.1", + "port" : 4444, + "cli_args" : { + "webdriver.chrome.driver" : "node_modules/chromedriver/bin/chromedriver", + "webdriver.firefox.profile" : "", + "webdriver.ie.driver" : "" + } + }, + + "test_settings" : { + "default" : { + "launch_url" : "http://localhost", + "selenium_port" : 4444, + "selenium_host" : "localhost", + "silent": true, + "screenshots" : { + "enabled" : false, + "path" : "" + }, + "desiredCapabilities": { + "browserName": "chrome", + "marionette": true + } + }, + + "chrome" : { + "desiredCapabilities": { + "browserName": "chrome" + } + }, + + "edge" : { + "desiredCapabilities": { + "browserName": "MicrosoftEdge" + } + } + } +} \ No newline at end of file diff --git a/test/e2e/pages/main.js b/test/e2e/pages/main.js new file mode 100644 index 00000000..c3bbb558 --- /dev/null +++ b/test/e2e/pages/main.js @@ -0,0 +1,505 @@ +module.exports = { + sections: { + topbar: { + selector: ".topbar", + elements: { + inputBox: { + selector: "input" + }, + btnExplore: { + selector: "button" + } + } + }, + informationContainer: { + selector: ".information-container.wrapper", + elements: { + title: { + selector: ".title" + }, + version: { + selector: ".version" + }, + baseUrl: { + selector: ".base-url" + }, + mainUrl: { + selector: ".main a" + }, + mainUrlContent: { + selector: ".main a span" + }, + description: { + selector: ".description p" + }, + swaggerUrl: { + selector: ".description p a:nth-of-type(1)" + }, + swaggerircUrl: { + selector: ".description p a:nth-of-type(2)" + }, + termsLink: { + selector: ".info > div:nth-child(3) a" + }, + contactDevLink: { + selector: ".info > div:nth-child(4) a" + }, + apacheLink: { + selector: ".info > div:nth-child(5) a" + }, + aboutSwaggerLink: { + selector: ".info > a" + } + } + }, + schemeContainer: { + selector: ".scheme-container", + elements: { + httpOption: { + selector: "select option" + }, + btnAuthorize: { + selector: "button.authorize" + }, + authorizationModal: { + selector: ".dialog-ux" + }, + appName: { + selector: ".auth-container h5" + }, + authorizationUrl: { + selector: ".auth-container code" + }, + flow: { + selector: ".flow code" + }, + inputClientID: { + selector: "#client_id" + }, + checkWritePetStoreAuth: { + selector: "#write:pets-checkbox-petstore_auth" + }, + checkReadPetStoreAuth: { + selector: "#read:pets-checkbox-petstore_auth" + } + } + }, + apiWrapper: { + selector: ".swagger-ui .wrapper:nth-child(3)", + elements: { + petAPIWrapper: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1)" + }, + petAPIWrapperBar: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) .opblock-tag" + }, + /** + * Post pet/ api + */ + petOperationPostContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet" + }, + petOperationPostTitle: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet .opblock-summary-post span.opblock-summary-path span" + }, + petOperationPostCollpase: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet .opblock-summary-post" + }, + petOperationPostCollapseContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet>div:nth-child(2)" + }, + petOperationPostTryBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet button.try-out__btn" + }, + petOperationPostTryText: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet textarea.body-param__text" + }, + petOperationPostExecuteBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet button.execute" + }, + petOperationPostTryTextArea: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet textarea" + }, + petOperationPostResultsBox: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight" + }, + petOperationPostMockCategoryID: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight span:nth-child(17)" + }, + petOperationPostMockCategoryName: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight span:nth-child(23)" + }, + petOperationPostMockName: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight span:nth-child(31)" + }, + petOperationPostTagID: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight span:nth-child(54)" + }, + petOperationPostTagName: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight span:nth-child(60)" + }, + petOperationPostStatus: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight span:nth-child(70)" + }, + /** + * Put pet/ api + */ + petOperationPutContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet" + }, + petOperationPutTitle: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet .opblock-summary-put span.opblock-summary-path span" + }, + petOperationPutCollpase: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet .opblock-summary-put" + }, + petOperationPutCollapseContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet>div:nth-child(2)" + }, + petOperationPutTryBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet button.try-out__btn" + }, + petOperationPutTryText: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet textarea.body-param__text" + }, + petOperationPutExecuteBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet button.execute" + }, + petOperationPutTryTextArea: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet textarea" + }, + petOperationPutResultsBox: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight" + }, + petOperationPutMockCategoryID: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight span:nth-child(17)" + }, + petOperationPutMockCategoryName: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight span:nth-child(23)" + }, + petOperationPutMockName: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight span:nth-child(31)" + }, + petOperationPutTagID: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight span:nth-child(54)" + }, + petOperationPutTagName: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight span:nth-child(60)" + }, + petOperationPutStatus: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight span:nth-child(70)" + }, + /** + * Get pet/ + */ + petOperationGetByTagContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags" + }, + petOperationGetByTagTitle: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags .opblock-summary-get span.opblock-summary-path__deprecated span" + }, + petOperationGetByTagCollpase: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags .opblock-summary-get" + }, + petOperationGetByTagCollapseContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags .ReactCollapse--collapse" + }, + petOperationGetByTagTryBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags button.try-out__btn" + }, + petOperationGetByTagTryAdded: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags button.json-schema-form-item-add" + }, + petOperationGetByTagExecuteBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags button.execute" + }, + petOperationGetByTagTryTextArea: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags textarea" + }, + petOperationGetByTagResultsBox: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight" + }, + petOperationGetByTagMockCategoryID: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight span:nth-child(17)" + }, + petOperationGetByTagMockCategoryName: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight span:nth-child(23)" + }, + petOperationGetByTagMockName: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight span:nth-child(31)" + }, + petOperationGetByTagTagID: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight span:nth-child(54)" + }, + petOperationGetByTagTagName: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight span:nth-child(60)" + }, + petOperationGetByTagStatus: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight span:nth-child(70)" + }, + + /** + * Delete pet/ + */ + petOperationDeleteContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet" + }, + petOperationDeleteTitle: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet .opblock-summary-delete span.opblock-summary-path span" + }, + petOperationDeleteCollpase: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet .opblock-summary-delete" + }, + petOperationDeleteCollapseContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet>div:nth-child(2)" + }, + petOperationDeleteTryBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet button.try-out__btn" + }, + petOperationDeleteExecuteBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet button.execute" + }, + petOperationDeleteTryTextArea: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet textarea" + }, + petOperationDeleteResultsBox: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet pre.microlight" + }, + petOperationDeleteMockCategoryID: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet pre.microlight span:nth-child(17)" + }, + petOperationDeleteMockCategoryName: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet pre.microlight span:nth-child(23)" + }, + petOperationDeleteMockName: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet pre.microlight span:nth-child(31)" + }, + petOperationDeleteTagID: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet pre.microlight span:nth-child(54)" + }, + petOperationDeleteTagName: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet pre.microlight span:nth-child(60)" + }, + petOperationDeleteStatus: { + selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-deletePet pre.microlight span:nth-child(70)" + }, + + /** + * ***********Store************ + */ + storeAPIWrapper: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2)" + }, + storeAPIWrapperBar: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) .opblock-tag" + }, + /** + * Get /store/inventory + */ + storeOperationGetContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory" + }, + storeOperationGetTitle: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory .opblock-summary-get span.opblock-summary-path span" + }, + storeOperationGetCollpase: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory .opblock-summary-get" + }, + storeOperationGetCollapseContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory>div:nth-child(2)" + }, + storeOperationGetTryBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory button.try-out__btn" + }, + storeOperationGetExecuteBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory button.execute" + }, + storeOperationResponseProps1: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory pre.example.microlight span:nth-child(6)" + }, + storeOperationResponseProps2: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory pre.example.microlight span:nth-child(12)" + }, + storeOperationResponseProps3: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-getInventory pre.example.microlight span:nth-child(18)" + }, + /** + * Post /store/order + */ + storeOperationPostContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder" + }, + storeOperationPostTitle: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder .opblock-summary-post span.opblock-summary-path span" + }, + storeOperationPostCollpase: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder .opblock-summary-post" + }, + storeOperationPostCollapseContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder>div:nth-child(2)" + }, + storeOperationPostTryBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder button.try-out__btn" + }, + storeOperationPostExecuteBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder button.execute" + }, + storeOperationPostResponseId: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder pre.example.microlight span:nth-child(22)" + }, + storeOperationPostResponsePetId: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder pre.example.microlight span:nth-child(31)" + }, + storeOperationPostResponseQuantity: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder pre.example.microlight span:nth-child(40)" + }, + storeOperationPostResponseStatus: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder pre.example.microlight span:nth-child(66)" + }, + storeOperationPostResponseComplete: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-placeOrder pre.example.microlight span:nth-child(75)" + }, + /** + * Delete /store/order/{orderId} + */ + storeOperationDeleteContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-deleteOrder" + }, + storeOperationDeleteTitle: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-deleteOrder .opblock-summary-delete span.opblock-summary-path span" + }, + storeOperationDeleteCollpase: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-deleteOrder .opblock-summary-delete" + }, + storeOperationDeleteCollapseContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-deleteOrder>div:nth-child(2)" + }, + storeOperationDeleteTryBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-deleteOrder button.try-out__btn" + }, + storeOperationDeleteExecuteBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-deleteOrder button.execute" + }, + storeOperationGetResponseHeaders: { + selector: ".swagger-ui .opblock-tag-section:nth-child(2) div#operations-store-deleteOrder pre span" + }, + /** + * *********User************** + */ + userAPIWrapper: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3)" + }, + userAPIWrapperBar: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) .opblock-tag" + }, + /** + * Put /user/login + */ + userOperationPutContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser" + }, + userOperationPutTitle: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser .opblock-summary-put span.opblock-summary-path span" + }, + userOperationPutCollpase: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser .opblock-summary-put" + }, + userOperationPutCollapseContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser>div:nth-child(2)" + }, + userOperationPutTryBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser button.try-out__btn" + }, + userOperationPutExecuteBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser button.execute" + }, + userOperationPutParameter: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser div.parameters-col_description input" + }, + userOperationPutResponseHeader: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-updateUser div.parameters-col_description input" + }, + /** + * Delete /user + */ + userOperationDeleteContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-deleteUser" + }, + userOperationDeleteTitle: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-deleteUser .opblock-summary-delete span.opblock-summary-path span" + }, + userOperationDeleteCollpase: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-deleteUser .opblock-summary-delete" + }, + userOperationDeleteCollapseContainer: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-deleteUser>div:nth-child(2)" + }, + userOperationDeleteTryBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-deleteUser button.try-out__btn" + }, + userOperationDeleteExecuteBtn: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-deleteUser button.execute" + }, + userOperationDeleteParameter: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-user-deleteUser div.parameters-col_description input" + }, + userOperationDeleteResponseHeader: { + selector: ".swagger-ui .opblock-tag-section:nth-child(3) .opblock-delete div.parameters-col_description input" + }, + + } + }, + /* Model Container */ + modelWrapper: { + selector: ".swagger-ui .wrapper:nth-child(4)", + elements: { + modelContainer: { + selector: ".swagger-ui .models" + }, + modelCollapse: { + selector: ".swagger-ui .models h4" + }, + orderModel: { + selector: "section.models div.model-container:nth-child(1)" + }, + orderModelCallapse: { + selector: "section.models div.model-container:nth-child(1) span.model-toggle" + }, + categoryModel: { + selector: "section.models div.model-container:nth-child(2)" + }, + categoryModelCallapse: { + selector: "section.models div.model-container:nth-child(2) span.model-toggle" + }, + userModel: { + selector: "section.models div.model-container:nth-child(3)" + }, + userModelCallapse: { + selector: "section.models div.model-container:nth-child(3) span.model-toggle" + }, + tagModel: { + selector: "section.models div.model-container:nth-child(4)" + }, + tagModelCallapse: { + selector: "section.models div.model-container:nth-child(4) span.model-toggle" + }, + petModel: { + selector: "section.models div.model-container:nth-child(5)" + }, + petModelCallapse: { + selector: "section.models div.model-container:nth-child(5) span.model-toggle" + }, + apiResponseModel: { + selector: "section.models div.model-container:nth-child(6)" + }, + apiResponseModelCallapse: { + selector: "section.models div.model-container:nth-child(6) span.model-toggle" + }, + } + } + + + + + } +} diff --git a/test/e2e/scenarios/informationContainer.js b/test/e2e/scenarios/informationContainer.js new file mode 100644 index 00000000..c5af4148 --- /dev/null +++ b/test/e2e/scenarios/informationContainer.js @@ -0,0 +1,48 @@ +describe("render informationContainer", function () { + let mainPage + let informationContainer + beforeEach(function (client, done) { + + mainPage = client + .url("localhost:3200") + .page.main() + client.waitForElementVisible(".download-url-input", 5000) + .pause(5000) + .clearValue(".download-url-input") + .setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json") + .click("button.download-url-button") + .pause(1000) + + informationContainer = mainPage.section.informationContainer + + done() + }) + + it("renders section", function (client) { + mainPage.expect.section("@informationContainer").to.be.visible.before(5000) + + client.end() + }) + + it("renders content", function (client) { + informationContainer.waitForElementVisible("@title", 5000) + .assert.containsText("@title", "Swagger Petstore") + .assert.containsText("@version", "1.0.0") + .assert.containsText("@baseUrl", "[ Base URL: localhost:3204/ ]") + .assert.attributeEquals("@mainUrl", "href", "http://localhost:3200/test-specs/petstore.json") + .assert.containsText("@mainUrlContent", "http://localhost:3200/test-specs/petstore.json") + .assert.containsText("@description", "This is a sample server Petstore server. You can find out more about Swagger at http://swagger.io or on irc.freenode.net, #swagger. For this sample, you can use the api key special-key to test the authorization filters.") + .assert.attributeEquals("@swaggerUrl", "href", "http://swagger.io/") + .assert.attributeEquals("@swaggerircUrl", "href", "http://swagger.io/irc/") + .assert.attributeEquals("@termsLink", "href", "http://swagger.io/terms/") + .assert.containsText("@termsLink", "Terms of service") + .assert.attributeEquals("@contactDevLink", "href", "mailto:apiteam@swagger.io") + .assert.containsText("@contactDevLink", "Contact the developer") + .assert.attributeEquals("@contactDevLink", "href", "mailto:apiteam@swagger.io") + .assert.containsText("@contactDevLink", "Contact the developer") + .assert.attributeEquals("@aboutSwaggerLink", "href", "http://swagger.io/") + .assert.containsText("@aboutSwaggerLink", "Find out more about Swagger") + + client.end() + }) +}) \ No newline at end of file diff --git a/test/e2e/scenarios/models.js b/test/e2e/scenarios/models.js new file mode 100644 index 00000000..9749b811 --- /dev/null +++ b/test/e2e/scenarios/models.js @@ -0,0 +1,79 @@ +describe("Render Model Wrapper", function () { + let modelWrapper, mainPage + + beforeEach(function (client, done) { + mainPage = client + .url("localhost:3200") + .page.main() + client.waitForElementVisible(".download-url-input", 5000) + .pause(5000) + .clearValue(".download-url-input") + .setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json") + .click("button.download-url-button") + .pause(1000) + + modelWrapper = mainPage.section.modelWrapper + + done() + }) + afterEach(function (client, done){ + done() + }) + it("Render model wrapper", function(client){ + mainPage.expect.section("@modelWrapper").to.be.visible.before(5000) + + client.end() + }) + + it("Render model wrapper collapse", function(client){ + modelWrapper.waitForElementVisible("@modelContainer", 5000) + .click("@modelCollapse") + .assert.cssClassNotPresent("@modelContainer", "is-open") + + client.end() + }) + + it("Testing order model", function(client){ + modelWrapper.waitForElementVisible("@orderModel") + .click("@orderModelCallapse") + .assert.cssClassNotPresent("@orderModelCallapse", "callapsed") + + client.end() + }) + + it("Testing category model", function(client){ + modelWrapper.waitForElementVisible("@categoryModel") + .click("@categoryModelCallapse") + .assert.cssClassNotPresent("@categoryModelCallapse", "callapsed") + + client.end() + }) + it("Testing user model", function(client){ + modelWrapper.waitForElementVisible("@userModel") + .click("@userModelCallapse") + .assert.cssClassNotPresent("@userModelCallapse", "callapsed") + + client.end() + }) + it("Testing tag model", function(client){ + modelWrapper.waitForElementVisible("@tagModel") + .click("@tagModelCallapse") + .assert.cssClassNotPresent("@tagModelCallapse", "callapsed") + + client.end() + }) + it("Testing pet model", function(client){ + modelWrapper.waitForElementVisible("@petModel") + .click("@petModelCallapse") + .assert.cssClassNotPresent("@petModelCallapse", "callapsed") + + client.end() + }) + it("Testing apiResponse model", function(client){ + modelWrapper.waitForElementVisible("@apiResponseModel") + .click("@apiResponseModelCallapse") + .assert.cssClassNotPresent("@apiResponseModelCallapse", "callapsed") + + client.end() + }) +}) diff --git a/test/e2e/scenarios/operations/pet.js b/test/e2e/scenarios/operations/pet.js new file mode 100644 index 00000000..441004c5 --- /dev/null +++ b/test/e2e/scenarios/operations/pet.js @@ -0,0 +1,172 @@ +describe("render pet api container", function () { + let mainPage + let apiWrapper + beforeEach(function (client, done) { + mainPage = client + .url("localhost:3200") + .page.main() + + client.waitForElementVisible(".download-url-input", 5000) + .pause(5000) + .clearValue(".download-url-input") + .setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json") + .click("button.download-url-button") + .pause(1000) + + apiWrapper = mainPage.section.apiWrapper + + done() + }) + afterEach(function (client, done) { + done() + }) + it("render section", function (client) { + mainPage.expect.section("@apiWrapper").to.be.visible.before(10000) + client.end() + }) + it("test rendered pet container", function (client) { + apiWrapper.waitForElementVisible("@petAPIWrapper", 5000) + .expect.element("@petAPIWrapper").to.be.visible + + client.end() + }) + it("collapse pet wrapper", function (client) { + apiWrapper.waitForElementVisible("@petAPIWrapper", 5000) + .click("@petAPIWrapperBar") + .assert.cssClassNotPresent("@petAPIWrapper", "is-open") + + client.end() + }) + it("render post /pet api container", function (client) { + apiWrapper.waitForElementVisible("@petOperationPostContainer", 10000) + .assert.containsText("@petOperationPostTitle", "/pet") + .click("@petOperationPostCollpase") + .waitForElementVisible("@petOperationPostCollapseContainer", 5000) + .click("@petOperationPostTryBtn") + .waitForElementVisible("@petOperationPostTryText", 1000) + .waitForElementVisible("@petOperationPostExecuteBtn", 1000) + .click("@petOperationPostTryBtn") + .assert.cssClassNotPresent("@petOperationPostTryBtn", "cancel") + + client.end() + }) + + it("Testing post /pet api Mock data", function (client) { + apiWrapper.waitForElementVisible("@petOperationPostContainer", 5000) + .click("@petOperationPostCollpase") + .waitForElementVisible("@petOperationPostCollapseContainer", 5000) + .click("@petOperationPostTryBtn") + .waitForElementVisible("@petOperationPostExecuteBtn", 1000) + .click("@petOperationPostExecuteBtn") + .waitForElementVisible("@petOperationPostMockCategoryID", 2000) + .assert.containsText("@petOperationPostMockCategoryID", "0") + .assert.containsText("@petOperationPostMockCategoryName", "\"string\"") + .assert.containsText("@petOperationPostMockName", "\"doggie\"") + .assert.containsText("@petOperationPostTagID", "0") + .assert.containsText("@petOperationPostTagName", "\"string\"") + .assert.containsText("@petOperationPostStatus", "\"available\"") + .click("@petOperationPostTryBtn") + .assert.cssClassNotPresent("@petOperationPostTryBtn", "cancel") + + client.end() + }) + + it("render put /pet api container", function (client) { + apiWrapper.waitForElementVisible("@petOperationPutContainer", 5000) + .assert.containsText("@petOperationPutTitle", "/pet") + .click("@petOperationPutCollpase") + .waitForElementVisible("@petOperationPutCollapseContainer", 3000) + .click("@petOperationPutTryBtn") + .waitForElementVisible("@petOperationPutTryText", 1000) + .waitForElementVisible("@petOperationPutExecuteBtn", 1000) + .click("@petOperationPutTryBtn") + .assert.cssClassNotPresent("@petOperationPutTryBtn", "cancel") + + client.end() + }) + it("Testing put /pet api Mock data", function (client) { + apiWrapper.waitForElementVisible("@petOperationPutContainer", 5000) + .click("@petOperationPutCollpase") + .waitForElementVisible("@petOperationPutCollapseContainer", 3000) + .click("@petOperationPutTryBtn") + .waitForElementVisible("@petOperationPutExecuteBtn", 1000) + .click("@petOperationPutExecuteBtn") + .waitForElementVisible("@petOperationPutMockCategoryID") + .assert.containsText("@petOperationPutMockCategoryID", "0") + .assert.containsText("@petOperationPutMockCategoryName", "\"string\"") + .assert.containsText("@petOperationPutMockName", "\"doggie\"") + .assert.containsText("@petOperationPutTagID", "0") + .assert.containsText("@petOperationPutTagName", "\"string\"") + .assert.containsText("@petOperationPutStatus", "\"available\"") + .click("@petOperationPutTryBtn") + .assert.cssClassNotPresent("@petOperationPutTryBtn", "Cancel") + + client.end() + }) + + it("render get by tag /pet api container", function (client) { + apiWrapper.waitForElementVisible("@petOperationGetByTagContainer", 5000) + .assert.containsText("@petOperationGetByTagTitle", "/pet/findByTags") + .click("@petOperationGetByTagCollpase") + .waitForElementVisible("@petOperationGetByTagCollapseContainer", 3000) + .click("@petOperationGetByTagTryBtn") + .waitForElementVisible("@petOperationGetByTagTryAdded", 1000) + .waitForElementVisible("@petOperationGetByTagExecuteBtn", 1000) + .click("@petOperationGetByTagTryBtn") + .assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel") + + client.end() + }) + + it("Testing get by tag /pet api Mock data", function (client) { + apiWrapper.waitForElementVisible("@petOperationGetByTagContainer", 5000) + .click("@petOperationGetByTagCollpase") + .waitForElementVisible("@petOperationGetByTagCollapseContainer", 3000) + .click("@petOperationGetByTagTryBtn") + .waitForElementVisible("@petOperationGetByTagExecuteBtn", 1000) + .click("@petOperationGetByTagExecuteBtn") + .waitForElementVisible("@petOperationGetByTagMockCategoryID") + .assert.containsText("@petOperationGetByTagMockCategoryID", "0") + .assert.containsText("@petOperationGetByTagMockCategoryName", "\"string\"") + .assert.containsText("@petOperationGetByTagMockName", "\"doggie\"") + .assert.containsText("@petOperationGetByTagTagID", "0") + .assert.containsText("@petOperationGetByTagTagName", "\"string\"") + .assert.containsText("@petOperationGetByTagStatus", "\"available\"") + .click("@petOperationGetByTagTryBtn") + .assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel") + + client.end() + }) + + it("render delete /pet api container", function (client) { + apiWrapper.waitForElementVisible("@petOperationDeleteContainer") + .assert.containsText("@petOperationDeleteTitle", "/pet/{petId}") + .click("@petOperationDeleteCollpase") + .waitForElementVisible("@petOperationDeleteCollapseContainer", 3000) + .click("@petOperationDeleteTryBtn") + .waitForElementVisible("@petOperationDeleteExecuteBtn", 1000) + .click("@petOperationDeleteTryBtn") + .assert.cssClassNotPresent("@petOperationDeleteTryBtn", "cancel") + + client.end() + }) + it("Testing delete /pet api Mock data", function (client) { + apiWrapper.waitForElementVisible("@petOperationDeleteContainer", 3000) + .click("@petOperationDeleteCollpase") + .waitForElementVisible("@petOperationDeleteCollapseContainer", 3000) + .click("@petOperationDeleteTryBtn") + .waitForElementVisible("@petOperationDeleteExecuteBtn", 1000) + .click("@petOperationDeleteExecuteBtn") + .waitForElementVisible("@petOperationDeleteMockCategoryID") + .assert.containsText("@petOperationDeleteMockCategoryID", "0") + .assert.containsText("@petOperationDeleteMockCategoryName", "\"string\"") + .assert.containsText("@petOperationDeleteMockName", "\"doggie\"") + .assert.containsText("@petOperationDeleteTagID", "0") + .assert.containsText("@petOperationDeleteTagName", "\"string\"") + .assert.containsText("@petOperationDeleteStatus", "\"available\"") + .click("@petOperationDeleteTryBtn") + .assert.cssClassNotPresent("@petOperationDeleteTryBtn", "cancel") + + client.end() + }) +}) \ No newline at end of file diff --git a/test/e2e/scenarios/operations/store.js b/test/e2e/scenarios/operations/store.js new file mode 100644 index 00000000..7dbcbc24 --- /dev/null +++ b/test/e2e/scenarios/operations/store.js @@ -0,0 +1,113 @@ +describe("render store api container", function(){ + let mainPage + let apiWrapper + beforeEach( function(client, done){ + mainPage = client + .url("localhost:3200") + .page.main() + + client.waitForElementVisible(".download-url-input", 5000) + .pause(3000) + .clearValue(".download-url-input") + .setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json") + .click("button.download-url-button") + .pause(1000) + + apiWrapper = mainPage.section.apiWrapper + + done() + }) + afterEach(function (client, done) { + done() + }) + it("test rendered store container", function(client){ + apiWrapper.waitForElementVisible("@storeAPIWrapper", 5000) + .expect.element("@storeAPIWrapper").to.be.visible + + client.end() + }) + it("callapse store wrapper", function(client){ + apiWrapper.waitForElementVisible("@storeAPIWrapper", 5000) + .click("@storeAPIWrapperBar") + .assert.cssClassNotPresent("@storeAPIWrapper", "is-open") + + client.end() + }) + it("render get /store/inventory api container", function (client) { + apiWrapper.waitForElementVisible("@storeOperationGetContainer", 5000) + .assert.containsText("@storeOperationGetTitle", "/store/inventory") + .click("@storeOperationGetCollpase") + .waitForElementVisible("@storeOperationGetCollapseContainer", 5000) + .click("@storeOperationGetTryBtn") + .waitForElementVisible("@storeOperationGetExecuteBtn", 1000) + .click("@storeOperationGetTryBtn") + .assert.cssClassNotPresent("@storeOperationGetTryBtn", "cancel") + + client.end() + }) + + it("Testing get /store/inventory api Mock data ", function (client) { + apiWrapper.waitForElementVisible("@storeOperationGetContainer", 5000) + .assert.containsText("@storeOperationGetTitle", "/store/inventory") + .click("@storeOperationGetCollpase") + .waitForElementVisible("@storeOperationGetCollapseContainer", 3000) + .click("@storeOperationGetTryBtn") + .waitForElementVisible("@storeOperationGetExecuteBtn", 1000) + .click("@storeOperationGetExecuteBtn") + .waitForElementVisible("@storeOperationResponseProps1") + .assert.containsText("@storeOperationResponseProps1", "0") + .assert.containsText("@storeOperationResponseProps2", "0") + .assert.containsText("@storeOperationResponseProps3", "0") + .click("@storeOperationGetTryBtn") + .assert.cssClassNotPresent("@storeOperationGetTryBtn", "cancel") + + client.end() + }) + + it("render post /store/order api container", function (client) { + apiWrapper.waitForElementVisible("@storeOperationPostContainer") + .assert.containsText("@storeOperationPostTitle", "/store/order") + .click("@storeOperationPostCollpase") + .waitForElementVisible("@storeOperationPostCollapseContainer", 3000) + .click("@storeOperationPostTryBtn") + .waitForElementVisible("@storeOperationPostExecuteBtn", 1000) + .click("@storeOperationPostTryBtn") + .assert.cssClassNotPresent("@storeOperationPostTryBtn", "cancel") + + client.end() + }) + + it("Testing post /store/order api Mock Data", function (client) { + apiWrapper.waitForElementVisible("@storeOperationPostContainer") + .assert.containsText("@storeOperationPostTitle", "/store/order") + .click("@storeOperationPostCollpase") + .waitForElementVisible("@storeOperationPostCollapseContainer", 3000) + .click("@storeOperationPostTryBtn") + .waitForElementVisible("@storeOperationPostExecuteBtn", 1000) + .click("@storeOperationPostExecuteBtn") + .waitForElementVisible("@storeOperationPostResponseId") + .assert.containsText("@storeOperationPostResponseId", "0") + .assert.containsText("@storeOperationPostResponsePetId", "0") + .assert.containsText("@storeOperationPostResponseQuantity", "0") + .assert.containsText("@storeOperationPostResponseStatus", "placed") + .assert.containsText("@storeOperationPostResponseComplete", "false") + .click("@storeOperationPostTryBtn") + .assert.cssClassNotPresent("@storeOperationPostTryBtn", "cancel") + + client.end() + }) + it("render delete /store/order/{orderId} api container", function (client) { + apiWrapper.waitForElementVisible("@storeOperationDeleteContainer") + .assert.containsText("@storeOperationDeleteTitle", "/store/order/{orderId}") + .click("@storeOperationDeleteCollpase") + .waitForElementVisible("@storeOperationDeleteCollapseContainer", 3000) + .click("@storeOperationDeleteTryBtn") + .waitForElementVisible("@storeOperationDeleteExecuteBtn", 1000) + .click("@storeOperationDeleteExecuteBtn") + .waitForElementVisible("@storeOperationGetResponseHeaders", "content-type: application/xml") + .click("@storeOperationDeleteTryBtn") + .assert.cssClassNotPresent("@storeOperationDeleteTryBtn", "cancel") + + client.end() + }) +}) \ No newline at end of file diff --git a/test/e2e/scenarios/operations/user.js b/test/e2e/scenarios/operations/user.js new file mode 100644 index 00000000..e84984b7 --- /dev/null +++ b/test/e2e/scenarios/operations/user.js @@ -0,0 +1,94 @@ +describe("render user api container", function(){ + let mainPage + let apiWrapper + beforeEach( function(client, done){ + mainPage = client + .url("localhost:3200") + .page.main() + + client.waitForElementVisible(".download-url-input", 5000) + .pause(5000) + .clearValue(".download-url-input") + .setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json") + .click("button.download-url-button") + .pause(1000) + + apiWrapper = mainPage.section.apiWrapper + + done() + }) + afterEach(function (client, done) { + done() + }) + it("test rendered user container", function(client){ + apiWrapper.waitForElementVisible("@userAPIWrapper", 5000) + .expect.element("@userAPIWrapper").to.be.visible + + client.end() + }) + it("callapse user wrapper", function(client){ + apiWrapper.waitForElementVisible("@userAPIWrapper", 5000) + .click("@userAPIWrapperBar") + .assert.cssClassNotPresent("@userAPIWrapper", "is-open") + + client.end() + }) + it("render put /user/{username} api container", function (client) { + apiWrapper.waitForElementVisible("@userOperationPutContainer", 5000) + .assert.containsText("@userOperationPutTitle", "/user/{username}") + .click("@userOperationPutCollpase") + .waitForElementVisible("@userOperationPutCollapseContainer", 3000) + .click("@userOperationPutTryBtn") + .waitForElementVisible("@userOperationPutExecuteBtn", 1000) + .click("@userOperationPutTryBtn") + .assert.cssClassNotPresent("@userOperationPutTryBtn", "cancel") + + client.end() + }) + it("Test put /user/{username} api Mock data", function (client) { + apiWrapper.waitForElementVisible("@userOperationPutContainer", 5000) + .assert.containsText("@userOperationPutTitle", "/user/{username}") + .click("@userOperationPutCollpase") + .waitForElementVisible("@userOperationPutCollapseContainer", 3000) + .click("@userOperationPutTryBtn") + .waitForElementVisible("@userOperationPutParameter") + .setValue("@userOperationPutParameter", "123") + .waitForElementVisible("@userOperationPutExecuteBtn", 1000) + .click("userOperationPutExecuteBtn") + .waitForElementVisible("@userOperationPutResponseHeader") + .assert.containsText("@userOperationPutResponseHeader", "content-type: application/xml") + .click("@userOperationPutTryBtn") + .assert.cssClassNotPresent("@userOperationPutTryBtn", "cancel") + + client.end() + }) + it("render delete /user/{username} api container", function (client) { + apiWrapper.waitForElementVisible("@userOperationDeleteContainer", 5000) + .assert.containsText("@userOperationDeleteTitle", "/user/{username}") + .click("@userOperationDeleteCollpase") + .waitForElementVisible("@userOperationDeleteCollapseContainer", 3000) + .click("@userOperationDeleteTryBtn") + .waitForElementVisible("@userOperationDeleteExecuteBtn", 1000) + .click("@userOperationDeleteTryBtn") + .assert.cssClassNotPresent("@userOperationDeleteTryBtn", "cancel") + + client.end() + }) + it("Test delete /user/{username} api Mock data", function (client) { + apiWrapper.waitForElementVisible("@userOperationDeleteContainer", 5000) + .assert.containsText("@userOperationDeleteTitle", "/user/{username}") + .click("@userOperationDeleteCollpase") + .waitForElementVisible("@userOperationDeleteCollapseContainer", 3000) + .click("@userOperationDeleteTryBtn") + .waitForElementVisible("@userOperationDeleteParameter") + .setValue("@userOperationDeleteParameter", "123") + .waitForElementVisible("@userOperationDeleteExecuteBtn", 1000) + .click("userOperationDeleteExecuteBtn") + .waitForElementVisible("@userOperationDeleteResponseHeader") + .assert.containsText("@userOperationDeleteResponseHeader", "content-type: application/xml") + .click("@userOperationDeleteTryBtn") + .assert.cssClassNotPresent("@userOperationDeleteTryBtn", "cancel") + + client.end() + }) +}) \ No newline at end of file diff --git a/test/e2e/scenarios/schemeContainer.js b/test/e2e/scenarios/schemeContainer.js new file mode 100644 index 00000000..51a309b1 --- /dev/null +++ b/test/e2e/scenarios/schemeContainer.js @@ -0,0 +1,52 @@ +describe("Render scheme", function () { + let mainPage + let schemeContainer + beforeEach(function (client, done) { + + mainPage = client + .url("localhost:3200") + .page.main() + + schemeContainer = mainPage.section.schemeContainer + + client.waitForElementVisible(".download-url-input", 5000) + .pause(5000) + .clearValue(".download-url-input") + .setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json") + .click("button.download-url-button") + .pause(1000) + + + done() + }) + + it("render section", function (client) { + mainPage.expect.section("@schemeContainer").to.be.visible.before(5000) + + client.end() + }) + it("render scheme option", function (client) { + schemeContainer.waitForElementVisible("@httpOption", 5000) + .expect.element("@httpOption").to.be.selected + + client.end() + }) + + it("render authorized button", function (client) { + schemeContainer.waitForElementVisible("@btnAuthorize", 5000) + .expect.element("@btnAuthorize").to.be.visible + + client.end() + }) + it("render click event", function(client) { + schemeContainer.waitForElementVisible("@btnAuthorize", 5000) + .click("@btnAuthorize") + .assert.visible("@authorizationModal") + .assert.containsText("@appName", "Application: your-app-name") + .assert.containsText("@authorizationUrl", "http://petstore.swagger.io/oauth/dialog") + .assert.containsText("@flow", "implicit") + .assert.value("@inputClientID", "your-client-id") + + client.end() + }) +}) \ No newline at end of file diff --git a/test/e2e/scenarios/topbar.js b/test/e2e/scenarios/topbar.js new file mode 100644 index 00000000..d7a17efe --- /dev/null +++ b/test/e2e/scenarios/topbar.js @@ -0,0 +1,52 @@ +describe("initial render", function () { + let mainPage + describe("for topbar", function () { + let topbar + before(function (client, done) { + done() + }) + + after(function (client, done) { + client.end(function () { + done() + }) + }) + + afterEach(function (client, done) { + done() + }) + + beforeEach(function (client, done) { + mainPage = client + .url("localhost:3200") + .page.main() + + topbar = mainPage.section.topbar + + client.waitForElementVisible(".download-url-input", 10000) + .pause(5000) + .clearValue(".download-url-input") + .setValue(".download-url-input", "http://localhost:3200/test-specs/petstore.json") + .click("button.download-url-button") + .pause(1000) + + done() + }) + + it("renders section", function (client) { + mainPage.expect.section("@topbar").to.be.visible + client.end() + }) + + it("renders input box", function (client) { + topbar.expect.element("@inputBox").to.be.visible + client.end() + }) + + it("renders explore button", function (client) { + topbar.expect.element("@btnExplore").to.be.visible + + client.end() + }) + }) +}) diff --git a/test/e2e/specs/petstore.json b/test/e2e/specs/petstore.json new file mode 100644 index 00000000..2d161887 --- /dev/null +++ b/test/e2e/specs/petstore.json @@ -0,0 +1,1043 @@ +{ + "swagger":"2.0", + "info":{ + "description":"This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.", + "version":"1.0.0", + "title":"Swagger Petstore", + "termsOfService":"http://swagger.io/terms/", + "contact":{ + "email":"apiteam@swagger.io" + }, + "license":{ + "name":"Apache 2.0", + "url":"http://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "host":"localhost:3204", + "basePath":"/", + "tags":[ + { + "name":"pet", + "description":"Everything about your Pets", + "externalDocs":{ + "description":"Find out more", + "url":"http://swagger.io" + } + }, + { + "name":"store", + "description":"Access to Petstore orders" + }, + { + "name":"user", + "description":"Operations about user", + "externalDocs":{ + "description":"Find out more about our store", + "url":"http://swagger.io" + } + } + ], + "schemes":[ + "http" + ], + "paths":{ + "/pet":{ + "post":{ + "tags":[ + "pet" + ], + "summary":"Add a new pet to the store", + "description":"", + "operationId":"addPet", + "consumes":[ + "application/json", + "application/xml" + ], + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "in":"body", + "name":"body", + "description":"Pet object that needs to be added to the store", + "required":true, + "schema":{ + "$ref":"#/definitions/Pet" + } + } + ], + "responses":{ + "405":{ + "description":"Invalid input" + } + }, + "security":[ + { + "petstore_auth":[ + "write:pets", + "read:pets" + ] + } + ] + }, + "put":{ + "tags":[ + "pet" + ], + "summary":"Update an existing pet", + "description":"", + "operationId":"updatePet", + "consumes":[ + "application/json", + "application/xml" + ], + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "in":"body", + "name":"body", + "description":"Pet object that needs to be added to the store", + "required":true, + "schema":{ + "$ref":"#/definitions/Pet" + } + } + ], + "responses":{ + "400":{ + "description":"Invalid ID supplied" + }, + "404":{ + "description":"Pet not found" + }, + "405":{ + "description":"Validation exception" + } + }, + "security":[ + { + "petstore_auth":[ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByStatus":{ + "get":{ + "tags":[ + "pet" + ], + "summary":"Finds Pets by status", + "description":"Multiple status values can be provided with comma separated strings", + "operationId":"findPetsByStatus", + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "name":"status", + "in":"query", + "description":"Status values that need to be considered for filter", + "required":true, + "type":"array", + "items":{ + "type":"string", + "enum":[ + "available", + "pending", + "sold" + ], + "default":"available" + }, + "collectionFormat":"multi" + } + ], + "responses":{ + "200":{ + "description":"successful operation", + "schema":{ + "type":"array", + "items":{ + "$ref":"#/definitions/Pet" + } + } + }, + "400":{ + "description":"Invalid status value" + } + }, + "security":[ + { + "petstore_auth":[ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByTags":{ + "get":{ + "tags":[ + "pet" + ], + "summary":"Finds Pets by tags", + "description":"Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", + "operationId":"findPetsByTags", + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "name":"tags", + "in":"query", + "description":"Tags to filter by", + "required":true, + "type":"array", + "items":{ + "type":"string" + }, + "collectionFormat":"multi" + } + ], + "responses":{ + "200":{ + "description":"successful operation", + "schema":{ + "type":"array", + "items":{ + "$ref":"#/definitions/Pet" + } + } + }, + "400":{ + "description":"Invalid tag value" + } + }, + "security":[ + { + "petstore_auth":[ + "write:pets", + "read:pets" + ] + } + ], + "deprecated":true + } + }, + "/pet/{petId}":{ + "get":{ + "tags":[ + "pet" + ], + "summary":"Find pet by ID", + "description":"Returns a single pet", + "operationId":"getPetById", + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "name":"petId", + "in":"path", + "description":"ID of pet to return", + "required":true, + "type":"integer", + "format":"int64" + } + ], + "responses":{ + "200":{ + "description":"successful operation", + "schema":{ + "$ref":"#/definitions/Pet" + } + }, + "400":{ + "description":"Invalid ID supplied" + }, + "404":{ + "description":"Pet not found" + } + }, + "security":[ + { + "api_key":[ + + ] + } + ] + }, + "post":{ + "tags":[ + "pet" + ], + "summary":"Updates a pet in the store with form data", + "description":"", + "operationId":"updatePetWithForm", + "consumes":[ + "application/x-www-form-urlencoded" + ], + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "name":"petId", + "in":"path", + "description":"ID of pet that needs to be updated", + "required":true, + "type":"integer", + "format":"int64" + }, + { + "name":"name", + "in":"formData", + "description":"Updated name of the pet", + "required":false, + "type":"string" + }, + { + "name":"status", + "in":"formData", + "description":"Updated status of the pet", + "required":false, + "type":"string" + } + ], + "responses":{ + "405":{ + "description":"Invalid input" + } + }, + "security":[ + { + "petstore_auth":[ + "write:pets", + "read:pets" + ] + } + ] + }, + "delete":{ + "tags":[ + "pet" + ], + "summary":"Deletes a pet", + "description":"", + "operationId":"deletePet", + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "name":"api_key", + "in":"header", + "required":false, + "type":"string" + }, + { + "name":"petId", + "in":"path", + "description":"Pet id to delete", + "required":true, + "type":"integer", + "format":"int64" + } + ], + "responses":{ + "400":{ + "description":"Invalid ID supplied" + }, + "404":{ + "description":"Pet not found" + } + }, + "security":[ + { + "petstore_auth":[ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/{petId}/uploadImage":{ + "post":{ + "tags":[ + "pet" + ], + "summary":"uploads an image", + "description":"", + "operationId":"uploadFile", + "consumes":[ + "multipart/form-data" + ], + "produces":[ + "application/json" + ], + "parameters":[ + { + "name":"petId", + "in":"path", + "description":"ID of pet to update", + "required":true, + "type":"integer", + "format":"int64" + }, + { + "name":"additionalMetadata", + "in":"formData", + "description":"Additional data to pass to server", + "required":false, + "type":"string" + }, + { + "name":"file", + "in":"formData", + "description":"file to upload", + "required":false, + "type":"file" + } + ], + "responses":{ + "200":{ + "description":"successful operation", + "schema":{ + "$ref":"#/definitions/ApiResponse" + } + } + }, + "security":[ + { + "petstore_auth":[ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/store/inventory":{ + "get":{ + "tags":[ + "store" + ], + "summary":"Returns pet inventories by status", + "description":"Returns a map of status codes to quantities", + "operationId":"getInventory", + "produces":[ + "application/json" + ], + "parameters":[ + + ], + "responses":{ + "200":{ + "description":"successful operation", + "schema":{ + "type":"object", + "additionalProperties":{ + "type":"integer", + "format":"int32" + } + } + } + }, + "security":[ + { + "api_key":[ + + ] + } + ] + } + }, + "/store/order":{ + "post":{ + "tags":[ + "store" + ], + "summary":"Place an order for a pet", + "description":"", + "operationId":"placeOrder", + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "in":"body", + "name":"body", + "description":"order placed for purchasing the pet", + "required":true, + "schema":{ + "$ref":"#/definitions/Order" + } + } + ], + "responses":{ + "200":{ + "description":"successful operation", + "schema":{ + "$ref":"#/definitions/Order" + } + }, + "400":{ + "description":"Invalid Order" + } + } + } + }, + "/store/order/{orderId}":{ + "get":{ + "tags":[ + "store" + ], + "summary":"Find purchase order by ID", + "description":"For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions", + "operationId":"getOrderById", + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "name":"orderId", + "in":"path", + "description":"ID of pet that needs to be fetched", + "required":true, + "type":"integer", + "maximum":10.0, + "minimum":1.0, + "format":"int64" + } + ], + "responses":{ + "200":{ + "description":"successful operation", + "schema":{ + "$ref":"#/definitions/Order" + } + }, + "400":{ + "description":"Invalid ID supplied" + }, + "404":{ + "description":"Order not found" + } + } + }, + "delete":{ + "tags":[ + "store" + ], + "summary":"Delete purchase order by ID", + "description":"For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors", + "operationId":"deleteOrder", + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "name":"orderId", + "in":"path", + "description":"ID of the order that needs to be deleted", + "required":true, + "type":"integer", + "minimum":1.0, + "format":"int64" + } + ], + "responses":{ + "400":{ + "description":"Invalid ID supplied" + }, + "404":{ + "description":"Order not found" + } + } + } + }, + "/user":{ + "post":{ + "tags":[ + "user" + ], + "summary":"Create user", + "description":"This can only be done by the logged in user.", + "operationId":"createUser", + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "in":"body", + "name":"body", + "description":"Created user object", + "required":true, + "schema":{ + "$ref":"#/definitions/User" + } + } + ], + "responses":{ + "default":{ + "description":"successful operation" + } + } + } + }, + "/user/createWithArray":{ + "post":{ + "tags":[ + "user" + ], + "summary":"Creates list of users with given input array", + "description":"", + "operationId":"createUsersWithArrayInput", + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "in":"body", + "name":"body", + "description":"List of user object", + "required":true, + "schema":{ + "type":"array", + "items":{ + "$ref":"#/definitions/User" + } + } + } + ], + "responses":{ + "default":{ + "description":"successful operation" + } + } + } + }, + "/user/createWithList":{ + "post":{ + "tags":[ + "user" + ], + "summary":"Creates list of users with given input array", + "description":"", + "operationId":"createUsersWithListInput", + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "in":"body", + "name":"body", + "description":"List of user object", + "required":true, + "schema":{ + "type":"array", + "items":{ + "$ref":"#/definitions/User" + } + } + } + ], + "responses":{ + "default":{ + "description":"successful operation" + } + } + } + }, + "/user/login":{ + "get":{ + "tags":[ + "user" + ], + "summary":"Logs user into the system", + "description":"", + "operationId":"loginUser", + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "name":"username", + "in":"query", + "description":"The user name for login", + "required":true, + "type":"string" + }, + { + "name":"password", + "in":"query", + "description":"The password for login in clear text", + "required":true, + "type":"string" + } + ], + "responses":{ + "200":{ + "description":"successful operation", + "schema":{ + "type":"string" + }, + "headers":{ + "X-Rate-Limit":{ + "type":"integer", + "format":"int32", + "description":"calls per hour allowed by the user" + }, + "X-Expires-After":{ + "type":"string", + "format":"date-time", + "description":"date in UTC when token expires" + } + } + }, + "400":{ + "description":"Invalid username/password supplied" + } + } + } + }, + "/user/logout":{ + "get":{ + "tags":[ + "user" + ], + "summary":"Logs out current logged in user session", + "description":"", + "operationId":"logoutUser", + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + + ], + "responses":{ + "default":{ + "description":"successful operation" + } + } + } + }, + "/user/{username}":{ + "get":{ + "tags":[ + "user" + ], + "summary":"Get user by user name", + "description":"", + "operationId":"getUserByName", + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "name":"username", + "in":"path", + "description":"The name that needs to be fetched. Use user1 for testing. ", + "required":true, + "type":"string" + } + ], + "responses":{ + "200":{ + "description":"successful operation", + "schema":{ + "$ref":"#/definitions/User" + } + }, + "400":{ + "description":"Invalid username supplied" + }, + "404":{ + "description":"User not found" + } + } + }, + "put":{ + "tags":[ + "user" + ], + "summary":"Updated user", + "description":"This can only be done by the logged in user.", + "operationId":"updateUser", + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "name":"username", + "in":"path", + "description":"name that need to be updated", + "required":true, + "type":"string" + }, + { + "in":"body", + "name":"body", + "description":"Updated user object", + "required":true, + "schema":{ + "$ref":"#/definitions/User" + } + } + ], + "responses":{ + "400":{ + "description":"Invalid user supplied" + }, + "404":{ + "description":"User not found" + } + } + }, + "delete":{ + "tags":[ + "user" + ], + "summary":"Delete user", + "description":"This can only be done by the logged in user.", + "operationId":"deleteUser", + "produces":[ + "application/xml", + "application/json" + ], + "parameters":[ + { + "name":"username", + "in":"path", + "description":"The name that needs to be deleted", + "required":true, + "type":"string" + } + ], + "responses":{ + "400":{ + "description":"Invalid username supplied" + }, + "404":{ + "description":"User not found" + } + } + } + } + }, + "securityDefinitions":{ + "petstore_auth":{ + "type":"oauth2", + "authorizationUrl":"http://petstore.swagger.io/oauth/dialog", + "flow":"implicit", + "scopes":{ + "write:pets":"modify pets in your account", + "read:pets":"read your pets" + } + }, + "api_key":{ + "type":"apiKey", + "name":"api_key", + "in":"header" + } + }, + "definitions":{ + "Order":{ + "type":"object", + "properties":{ + "id":{ + "type":"integer", + "format":"int64" + }, + "petId":{ + "type":"integer", + "format":"int64" + }, + "quantity":{ + "type":"integer", + "format":"int32" + }, + "shipDate":{ + "type":"string", + "format":"date-time" + }, + "status":{ + "type":"string", + "description":"Order Status", + "enum":[ + "placed", + "approved", + "delivered" + ] + }, + "complete":{ + "type":"boolean", + "default":false + } + }, + "xml":{ + "name":"Order" + } + }, + "Category":{ + "type":"object", + "properties":{ + "id":{ + "type":"integer", + "format":"int64" + }, + "name":{ + "type":"string" + } + }, + "xml":{ + "name":"Category" + } + }, + "User":{ + "type":"object", + "properties":{ + "id":{ + "type":"integer", + "format":"int64" + }, + "username":{ + "type":"string" + }, + "firstName":{ + "type":"string" + }, + "lastName":{ + "type":"string" + }, + "email":{ + "type":"string" + }, + "password":{ + "type":"string" + }, + "phone":{ + "type":"string" + }, + "userStatus":{ + "type":"integer", + "format":"int32", + "description":"User Status" + } + }, + "xml":{ + "name":"User" + } + }, + "Tag":{ + "type":"object", + "properties":{ + "id":{ + "type":"integer", + "format":"int64" + }, + "name":{ + "type":"string" + } + }, + "xml":{ + "name":"Tag" + } + }, + "Pet":{ + "type":"object", + "required":[ + "name", + "photoUrls" + ], + "properties":{ + "id":{ + "type":"integer", + "format":"int64" + }, + "category":{ + "$ref":"#/definitions/Category" + }, + "name":{ + "type":"string", + "example":"doggie" + }, + "photoUrls":{ + "type":"array", + "xml":{ + "name":"photoUrl", + "wrapped":true + }, + "items":{ + "type":"string" + } + }, + "tags":{ + "type":"array", + "xml":{ + "name":"tag", + "wrapped":true + }, + "items":{ + "$ref":"#/definitions/Tag" + } + }, + "status":{ + "type":"string", + "description":"pet status in the store", + "enum":[ + "available", + "pending", + "sold" + ] + } + }, + "xml":{ + "name":"Pet" + } + }, + "ApiResponse":{ + "type":"object", + "properties":{ + "code":{ + "type":"integer", + "format":"int32" + }, + "type":{ + "type":"string" + }, + "message":{ + "type":"string" + } + } + } + }, + "externalDocs":{ + "description":"Find out more about Swagger", + "url":"http://swagger.io" + } +} \ No newline at end of file