From 0201487431a2c2bdc9fc0c958a63448b1ba2dabe Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Fri, 6 Nov 2020 17:32:51 -0500 Subject: [PATCH 1/3] adding tests for special paging scenarios --- legacy/app.js | 2 + legacy/routes/pagingSpecial.js | 56 +++++++++++++++++ package.json | 2 +- swagger/paging-special.json | 108 +++++++++++++++++++++++++++++++++ 4 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 legacy/routes/pagingSpecial.js create mode 100644 swagger/paging-special.json diff --git a/legacy/app.js b/legacy/app.js index 5842308e..6e023149 100644 --- a/legacy/app.js +++ b/legacy/app.js @@ -31,6 +31,7 @@ var formData = require('./routes/formData'); var lros = require('./routes/lros'); var lroParameterizedEndpoints = require('./routes/lroParameterizedEndpoints.js'); var paging = require('./routes/paging'); +var pagingSpecial = require('./routes/pagingSpecial'); var modelFlatten = require('./routes/model-flatten'); var azureUrl = require('./routes/azureUrl'); var azureSpecial = require('./routes/azureSpecials'); @@ -548,6 +549,7 @@ app.use('/model-flatten', new modelFlatten(coverage).router); app.use('/lro', new lros(azurecoverage).router); app.use('/lroParameterizedEndpoints', new lroParameterizedEndpoints(azurecoverage).router); app.use('/paging', new paging(azurecoverage).router); +app.use('/pagingSpecial', new pagingSpecial(optionalCoverage).router) app.use('/azurespecials', new azureSpecial(azurecoverage).router); app.use('/report', new report(coverage, azurecoverage, optionalCoverage).router); app.use('/subscriptions', new azureUrl(azurecoverage).router); diff --git a/legacy/routes/pagingSpecial.js b/legacy/routes/pagingSpecial.js new file mode 100644 index 00000000..e69813e0 --- /dev/null +++ b/legacy/routes/pagingSpecial.js @@ -0,0 +1,56 @@ +var express = require('express'); +var router = express.Router(); +var util = require('util'); +var utils = require('../util/utils'); + +var pagingSpecial = function(optionalCoverage) { + optionalCoverage['PagingSpecialNextLinkInResponseHeaders'] = 0; + optionalCoverage["PagingSpecialContinuationTokenInResponseHeaders"] = 0; + + router.get('/nextLinkInResponseHeaders', function(req, res, next) { + var headers = { + 'x-ms-nextLink': '/pagingSpecial/nextLinkInResponseHeaders/page/2', + }; + res.set(headers).status(200).json({ "value" : [ {"properties":{"id": 1, "name": "Product" }}] }); + }); + + + router.get('/nextLinkInResponseHeaders/page/:pagenumber', function(req, res, next) { + if (req.params.pagenumber < 10) { + var headers = { + 'x-ms-nextLink': '/pagingSpecial/nextLinkInResponseHeaders/page/' + (++req.params.pagenumber), + }; + res.set(headers).status(200).json({"value": [ {"properties":{"id" : parseInt(req.params.pagenumber), "name": "product"}} ]}); + } else { + optionalCoverage['PagingSpecialNextLinkInResponseHeaders'] = 0; + res.status(200).json({"value": [ {"properties":{"id" : parseInt(req.params.pagenumber), "name": "product"}} ]}); + } + }); + + router.get('/continuationTokenInResponseHeaders', function(req, res, next) { + + if (req.headers['continuationtoken']) { + contToken = req.headers['continuationtoken'] + if (contToken < 10) { + var headers = { + 'continuationtoken': ++contToken, + }; + res.set(headers).status(200).json({ "value" : [ {"properties":{"id": contToken, "name": "Product" }}] }); + } else { + res.status(200).json({"value": [ {"properties":{"id" : contToken, "name": "product"}} ]}); + } + + } else { + console.log('first') + var headers = { + 'continuationtoken': 2, + }; + res.set(headers).status(200).json({ "value" : [ {"properties":{"id": 1, "name": "Product" }}] }); + } + + }); +}; + +pagingSpecial.prototype.router = router; + +module.exports = pagingSpecial; diff --git a/package.json b/package.json index 8e7bdd8e..528c7129 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft.azure/autorest.testserver", - "version": "2.10.62", + "version": "2.10.63", "main": "./legacy/startup/www.js", "bin": { "start-autorest-express": "./.scripts/start-autorest-express.js", diff --git a/swagger/paging-special.json b/swagger/paging-special.json new file mode 100644 index 00000000..8b3c7b3a --- /dev/null +++ b/swagger/paging-special.json @@ -0,0 +1,108 @@ +{ + "swagger": "2.0", + "info": { + "title": "AutoRest Special Paging Test Service", + "description": "Long-running Operation for AutoRest", + "version": "1.0.0" + }, + "host": "localhost:3000", + "schemes": [ + "http" + ], + "produces": [ + "application/json" + ], + "consumes": [ + "application/json" + ], + "paths": { + "/pagingSpecial/nextLinkInResponseHeaders": { + "get": { + "x-ms-pageable": { "nextLinkName": null}, + "operationId": "nextLinkInResponseHeaders", + "description": "A paging operation where the next link is found in the response headers, not in the response body", + "responses": { + "200": { + "headers": { + "x-ms-nextLink": { + "description": "Next link for subsequent calls", + "type": "string" + } + }, + "description": "Returns a list of products, where the next link for continued paging is located in response header x-ms-nextLink.", + "schema": { + "$ref": "#/definitions/ProductResultValue" + } + }, + "default": { + "description": "Unexpected error" + } + } + } + }, + "/pagingSpecial/continuationTokenInResponseHeaders": { + "get": { + "x-ms-pageable": { "nextLinkName": null}, + "operationId": "continuationTokenInResponseHeaders", + "description": "A paging operation where the continuation is found in the response headers, and needs to be passed into subsequent calls.", + "parameters": [ + { + "name": "continuationToken", + "in": "header", + "type": "string", + "description": "Continuation token for subsequent paging." + } + ], + "responses": { + "200": { + "headers": { + "x-ms-continuationToken": { + "description": "Next link for subsequent calls", + "type": "string" + } + }, + "description": "Returns a list of products, where the next link for continued paging is located in response header x-ms-nextLink.", + "schema": { + "$ref": "#/definitions/ProductResultValue" + } + }, + "default": { + "description": "Unexpected error" + } + } + } + } + }, + "definitions": { + "ProductResultValue": { + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/Product" + } + }, + "nextLink": { + "type": "string" + } + } + }, + "Product": { + "type": "object", + "properties": { + "properties": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + } + } + } + } + } + } From 74b866dad932d5c22d7f874ef762f5a5b4d69f66 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Fri, 13 Nov 2020 19:31:35 -0500 Subject: [PATCH 2/3] add tests for metadata and token --- legacy/routes/pagingSpecial.js | 62 +++++++++++++++++++++++++++------- swagger/paging-special.json | 55 +++++++++++++++++++++++++++--- 2 files changed, 100 insertions(+), 17 deletions(-) diff --git a/legacy/routes/pagingSpecial.js b/legacy/routes/pagingSpecial.js index e69813e0..76f03552 100644 --- a/legacy/routes/pagingSpecial.js +++ b/legacy/routes/pagingSpecial.js @@ -5,13 +5,16 @@ var utils = require('../util/utils'); var pagingSpecial = function(optionalCoverage) { optionalCoverage['PagingSpecialNextLinkInResponseHeaders'] = 0; + optionalCoverage['PagingSpecialContinuationToken'] = 0; optionalCoverage["PagingSpecialContinuationTokenInResponseHeaders"] = 0; + optionalCoverage["PagingSpecialContinuationTokenWithMetadata"] = 0; + router.get('/nextLinkInResponseHeaders', function(req, res, next) { var headers = { 'x-ms-nextLink': '/pagingSpecial/nextLinkInResponseHeaders/page/2', }; - res.set(headers).status(200).json({ "value" : [ {"properties":{"id": 1, "name": "Product" }}] }); + res.set(headers).status(200).json({ "value" : [ {"properties":{"name": "Product" }}] }); }); @@ -20,35 +23,68 @@ var pagingSpecial = function(optionalCoverage) { var headers = { 'x-ms-nextLink': '/pagingSpecial/nextLinkInResponseHeaders/page/' + (++req.params.pagenumber), }; - res.set(headers).status(200).json({"value": [ {"properties":{"id" : parseInt(req.params.pagenumber), "name": "product"}} ]}); + res.set(headers).status(200).json({"value": [ {"properties":{"name": "product"}} ]}); } else { - optionalCoverage['PagingSpecialNextLinkInResponseHeaders'] = 0; - res.status(200).json({"value": [ {"properties":{"id" : parseInt(req.params.pagenumber), "name": "product"}} ]}); + optionalCoverage['PagingSpecialNextLinkInResponseHeaders']++; + res.status(200).json({"value": [ {"properties":{"name": "product"}} ]}); } }); + router.get('/continuationToken', function(req, res, next) { + + if (req.headers["x-ms-token"]) { + contToken = req.headers["x-ms-token"] + if (contToken < 10) { + res.status(200).json({ "value": [ {"properties":{"name": "product"}} ], "token": ++contToken}); + } else { + res.status(200).json({"value": [ {"properties":{"name": "product"}} ]}); + } + + } else { + optionalCoverage['PagingSpecialContinuationToken']++; + res.status(200).json({ "value": [ {"properties":{"name": "product"}} ], "token": 2}); + } + + }); + router.get('/continuationTokenInResponseHeaders', function(req, res, next) { - - if (req.headers['continuationtoken']) { - contToken = req.headers['continuationtoken'] + + if (req.headers["x-ms-token"]) { + contToken = req.headers["x-ms-token"] if (contToken < 10) { var headers = { - 'continuationtoken': ++contToken, + "x-ms-token": ++contToken, }; - res.set(headers).status(200).json({ "value" : [ {"properties":{"id": contToken, "name": "Product" }}] }); + res.set(headers).status(200).json({ "value" : [ {"properties":{"name": "Product" }}] }); } else { - res.status(200).json({"value": [ {"properties":{"id" : contToken, "name": "product"}} ]}); + optionalCoverage["PagingSpecialContinuationTokenInResponseHeaders"]++; + res.status(200).json({"value": [ {"properties":{"name": "product"}} ]}); } } else { - console.log('first') var headers = { - 'continuationtoken': 2, + "x-ms-token": 2, }; - res.set(headers).status(200).json({ "value" : [ {"properties":{"id": 1, "name": "Product" }}] }); + res.set(headers).status(200).json({ "value" : [ {"properties":{"name": "Product" }}] }); } }); + + router.get('/tokenWithMetadata', function(req, res, next) { + if (req.headers["x-ms-token"]) { + contToken = req.headers["x-ms-token"] + if (contToken < 10) { + res.status(200).json({ "value": [ {"properties":{"name": "product"}} ], "token": ++contToken + ";10"}); + } else { + optionalCoverage['PagingSpecialContinuationTokenWithMetadata']++; + res.status(200).json({"value": [ {"properties":{"name": "product"}} ]}); + } + + } else { + res.status(200).json({ "value": [ {"properties":{"name": "product"}} ], "token": "2;10"}); + } + }); + }; pagingSpecial.prototype.router = router; diff --git a/swagger/paging-special.json b/swagger/paging-special.json index 8b3c7b3a..76da16f2 100644 --- a/swagger/paging-special.json +++ b/swagger/paging-special.json @@ -40,6 +40,24 @@ } } }, + "/pagingSpecial/continuationToken": { + "get": { + "x-ms-pageable": { "nextLinkName": "token"}, + "operationId": "continuationToken", + "description": "A paging operation where the token in the response body needs to be passed into subsequent calls.", + "responses": { + "200": { + "description": "Returns a list of products", + "schema": { + "$ref": "#/definitions/ProductResultValueWithToken" + } + }, + "default": { + "description": "Unexpected error" + } + } + } + }, "/pagingSpecial/continuationTokenInResponseHeaders": { "get": { "x-ms-pageable": { "nextLinkName": null}, @@ -63,7 +81,25 @@ }, "description": "Returns a list of products, where the next link for continued paging is located in response header x-ms-nextLink.", "schema": { - "$ref": "#/definitions/ProductResultValue" + "$ref": "#/definitions/ProductResultValueWithToken" + } + }, + "default": { + "description": "Unexpected error" + } + } + } + }, + "/pagingSpecial/tokenWithMetadata": { + "get": { + "x-ms-pageable": { "nextLinkName": "token"}, + "operationId": "tokenWithMetadata", + "description": "A paging operation that returns a continuation token, and metadata about the number of total results. Should be able to access metadata from pager.", + "responses": { + "200": { + "description": "Returns a list of products. Should be able to access the metadata from the pager returned by this operation, which is just the number 10 (the number of items)", + "schema": { + "$ref": "#/definitions/ProductResultValueWithToken" } }, "default": { @@ -88,15 +124,26 @@ } } }, + "ProductResultValueWithToken": { + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/Product" + } + }, + "token": { + "type": "string" + } + } + }, "Product": { "type": "object", "properties": { "properties": { "type": "object", "properties": { - "id": { - "type": "integer" - }, "name": { "type": "string" } From 6150870a56c0442e2513ab1d2c0cc73ead490c1d Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Fri, 13 Nov 2020 19:32:33 -0500 Subject: [PATCH 3/3] update version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0cf6d4b3..8f92aa0d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft.azure/autorest.testserver", - "version": "2.10.65", + "version": "2.10.66", "main": "./legacy/startup/www.js", "bin": { "start-autorest-express": "./.scripts/start-autorest-express.js",