diff --git a/codegens/dart-dio/.gitignore b/codegens/dart-dio/.gitignore new file mode 100644 index 000000000..34f4d897c --- /dev/null +++ b/codegens/dart-dio/.gitignore @@ -0,0 +1,50 @@ +.DS_Store + +#Obj-c files +*.m +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Coverage directory used by tools like istanbul +.coverage + +# node-waf configuration +.lock-wscript + + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +out/ +/.idea/ +pubspec.lock +pubspec.yaml +.packages +snippet.dart +.dart_tool/ diff --git a/codegens/dart-dio/.npmignore b/codegens/dart-dio/.npmignore new file mode 100644 index 000000000..79ad2ba5f --- /dev/null +++ b/codegens/dart-dio/.npmignore @@ -0,0 +1,76 @@ +### NPM Specific: Disregard recursive project files +### =============================================== +/.editorconfig +/.gitmodules +/test + +### Borrowed from .gitignore +### ======================== + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Prevent IDE stuff +.idea +.vscode +*.sublime-* + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +.coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +snippet.swift + +out/ diff --git a/codegens/dart-dio/README.md b/codegens/dart-dio/README.md new file mode 100644 index 000000000..579d735c5 --- /dev/null +++ b/codegens/dart-dio/README.md @@ -0,0 +1,42 @@ + +> Converts Postman-SDK Request into code snippet for Dart dio. + +#### Prerequisites +To run Code-Gen, ensure that you have NodeJS >= v12. A copy of the NodeJS installable can be downloaded from https://nodejs.org/en/download/package-manager. + +## Using the Module +The module will expose an object which will have property `convert` which is the function for converting the Postman-SDK request to swift code snippet. + +### convert function +Convert function takes three parameters + +* `request` - Postman-SDK Request Object + +* `options` - options is an object which hsa following properties + * `indentType` - String denoting type of indentation for code snippet. eg: 'Space', 'Tab' + * `indentCount` - The number of indentation characters to add per code level + * `trimRequestBody` - Whether or not request body fields should be trimmed + +* `callback` - callback function with first parameter as error and second parameter as string for code snippet + +##### Example: +```js +var request = new sdk.Request('www.google.com'), //using postman sdk to create request + options = { + indentCount: 3, + indentType: 'Space', + requestTimeout: 200, + trimRequestBody: true + }; +convert(request, options, function(error, snippet) { + if (error) { + // handle error + } + // handle snippet +}); +``` +### Guidelines for using generated snippet + +* Since Postman-SDK Request object doesn't provide complete path of the file, it needs to be manually inserted in case of uploading a file. + +* This module doesn't support cookies. \ No newline at end of file diff --git a/codegens/dart-dio/index.js b/codegens/dart-dio/index.js new file mode 100644 index 000000000..bb0a047c4 --- /dev/null +++ b/codegens/dart-dio/index.js @@ -0,0 +1 @@ +module.exports = require('./lib'); diff --git a/codegens/dart-dio/lib/index.js b/codegens/dart-dio/lib/index.js new file mode 100644 index 000000000..fef51cae9 --- /dev/null +++ b/codegens/dart-dio/lib/index.js @@ -0,0 +1,346 @@ +var _ = require('lodash'), + sanitizeOptions = require('./util').sanitizeOptions, + sanitize = require('./util').sanitize, + addFormParam = require('./util').addFormParam, + path = require('path'), + self; + +/** + * Parses Url encoded data + * + * @param {Object} body body data + * @param {String} indent indentation required for code snippet + * @param {Boolean} trim indicates whether to trim string or not + */ +function parseUrlEncoded (body, indent, trim) { + var bodySnippet = 'var data = {', + enabledBodyList = _.reject(body, 'disabled'), + bodyDataMap; + if (!_.isEmpty(enabledBodyList)) { + bodyDataMap = _.map(enabledBodyList, function (value) { + return `${indent}'${sanitize(value.key, trim)}': '${sanitize(value.value, trim)}'`; + }); + bodySnippet += '\n' + bodyDataMap.join(',\n') + '\n'; + } + bodySnippet += '};'; + return bodySnippet; +} + +/** + * Parses Raw data + * + * @param {Object} body Raw body data + * @param {Boolean} trim indicates whether to trim string or not + * @param {String} contentType the content-type of request body + * @param {Integer} indentCount the number of space to use + */ +function parseRawBody (body, trim, contentType, indentCount) { + if (contentType && (contentType === 'application/json' || contentType.match(/\+json$/))) { + try { + let jsonBody = JSON.parse(body); + return `var data = json.encode(${JSON.stringify(jsonBody, null, indentCount)});`; + + } + catch (error) { + // Do nothing + } + } + return `var data = '''${sanitize(body, trim)}''';`; +} + +/** + * Parses GraphQL body + * + * @param {Object} body GraphQL body + * @param {Boolean} trim indicates whether to trim string or not + */ +function parseGraphQLBody (body, trim) { + var bodySnippet = '', + query = body ? body.query : '', + graphqlVariables; + try { + graphqlVariables = JSON.parse(body.variables); + } + catch (e) { + graphqlVariables = {}; + } + + bodySnippet += `var data = '''${sanitize(JSON.stringify({ + query: query, + variables: graphqlVariables + }), trim)}''';\n`; + + return bodySnippet; +} + +/** + * Parses form data body from request + * + * @param {Object} body form data Body + * @param {String} indent indentation required for code snippet + * @param {Boolean} trim indicates whether to trim string or not + */ +function parseFormData (body, indent, trim) { + let bodySnippet = '', + formDataArray = [], + formDataFileArray = [], + key, + value; + + if (_.isEmpty(body)) { + return bodySnippet; + } + + _.forEach(body, function (data) { + key = trim ? data.key.trim() : data.key; + value = trim ? data.value.trim() : data.value; + if (!data.disabled) { + if (data.type === 'file') { + var pathArray = data.src.split(path.sep), + fileName = pathArray[pathArray.length - 1]; + formDataFileArray.push(`await MultipartFile.fromFile('${data.src}', filename: '${sanitize(fileName, trim)}')`); + } + else { + formDataArray.push(`${indent}'${sanitize(key)}': '${sanitize(value, trim)}'`); + } + } + }); + + if (formDataArray.length > 0 || formDataFileArray.length > 0) { + bodySnippet += 'var data = FormData.fromMap({\n'; + if (formDataFileArray.length > 0) { + bodySnippet += `${indent}'files': [\n${indent}${indent}`; + bodySnippet += formDataFileArray.join(`,\n${indent}${indent}`); + bodySnippet += `\n${indent}],\n`; + } + bodySnippet += formDataArray.join(',\n'); + bodySnippet += '\n});\n'; + } + + return bodySnippet; +} + +/** + * Parses Body from the Request + * + * @param {Object} body body object from request. + * @param {String} indent indentation required for code snippet + * @param {Boolean} trim indicates whether to trim string or not + * @param {String} contentType the content-type of the request body + */ +function parseBody (body, indent, trim, contentType) { + if (!_.isEmpty(body)) { + switch (body.mode) { + case 'urlencoded': + return parseUrlEncoded(body.urlencoded, indent, trim); + case 'raw': + return parseRawBody(body.raw, trim, contentType, indent.length); + case 'formdata': + return parseFormData(body.formdata, indent, trim); + case 'graphql': + return parseGraphQLBody(body.graphql, trim); + case 'file': + return 'var data = r\'\';\n'; + default: + return ''; + } + } + return ''; +} + +/** + * Parses headers from the request. + * + * @param {Object} headersArray array containing headers + * @param {String} indent indentation required for code snippet + * @param {Boolean} trim indicates whether to trim string or not + */ +function parseHeaders (headersArray, indent, trim) { + var headerString = '', + headerDictionary = []; + if (_.isEmpty(headersArray)) { + return headerString; + } + + headerString += 'var headers = {\n'; + + _.forEach(headersArray, function (header) { + if (!header.disabled) { + headerDictionary.push(indent + '\'' + header.key + '\': \'' + sanitize(header.value, trim) + '\''); + } + }); + + headerString += headerDictionary.join(',\n'); + headerString += '\n};\n'; + + return headerString; +} + + +self = module.exports = { + convert: function (request, options, callback) { + var indent, + codeSnippet = '', + headerSnippet = '', + footerSnippet = '', + trim, + timeout, + followRedirect, + contentType; + options = sanitizeOptions(options, self.getOptions()); + + trim = options.trimRequestBody; + indent = options.indentType === 'Tab' ? '\t' : ' '; + indent = indent.repeat(options.indentCount); + timeout = options.requestTimeout; + followRedirect = options.followRedirect; + + if (!_.isFunction(callback)) { + throw new Error('Callback is not valid function'); + } + + if (request.body && !request.headers.has('Content-Type')) { + if (request.body.mode === 'file') { + request.addHeader({ + key: 'Content-Type', + value: 'text/plain' + }); + } + else if (request.body.mode === 'graphql') { + request.addHeader({ + key: 'Content-Type', + value: 'application/json' + }); + } + } + + contentType = request.headers.get('Content-Type'); + if (options.includeBoilerplate) { + headerSnippet = 'import \'dart:convert\';\n'; + headerSnippet += 'import \'package:dio/dio.dart\';\n\n'; + headerSnippet += 'void main() async {\n'; + footerSnippet = '}\n'; + } + + if (request.body && request.body.mode === 'formdata') { + let formdata = request.body.formdata, + formdataArray = []; + formdata.members.forEach((param) => { + let key = param.key, + type = param.type, + disabled = param.disabled, + contentType = param.contentType; + // check if type is file or text + if (type === 'file') { + // if src is not of type string we check for array(multiple files) + if (typeof param.src !== 'string') { + // if src is an array(not empty), iterate over it and add files as separate form fields + if (Array.isArray(param.src) && param.src.length) { + param.src.forEach((filePath) => { + addFormParam(formdataArray, key, param.type, filePath, disabled, contentType); + }); + } + // if src is not an array or string, or is an empty array, add a placeholder for file path(no files case) + else { + addFormParam(formdataArray, key, param.type, '/path/to/file', disabled, contentType); + } + } + // if src is string, directly add the param with src as filepath + else { + addFormParam(formdataArray, key, param.type, param.src, disabled, contentType); + } + } + // if type is text, directly add it to formdata array + else { + addFormParam(formdataArray, key, param.type, param.value, disabled, contentType); + } + }); + request.body.update({ + mode: 'formdata', + formdata: formdataArray + }); + } + + const headers = parseHeaders(request.headers.toJSON(), indent, trim), + requestBody = request.body ? request.body.toJSON() : {}, + body = parseBody(requestBody, indent, trim, contentType); + + codeSnippet += headers; + + if (body !== '') { + codeSnippet += body + '\n'; + } + + codeSnippet += 'var dio = Dio();\n'; + codeSnippet += 'var response = await dio.request(\n'; + codeSnippet += `${indent}'${request.url.toString()}',\n`; + codeSnippet += `${indent}options: Options(\n`; + codeSnippet += `${indent}${indent}method: '${request.method.toUpperCase()}',\n`; + codeSnippet += `${headers !== '' ? `${indent}${indent}headers: headers,\n` : ''}`; + codeSnippet += `${followRedirect ? '' : `${indent}${indent}followRedirects: false,\n`}`; + codeSnippet += `${timeout ? `${indent}${indent}receiveTimeout: ${timeout},\n` : ''}`; + codeSnippet += `${indent}),\n`; + codeSnippet += `${body !== '' ? `${indent}data: data,\n` : ''}`; + codeSnippet += ');'; + + codeSnippet += '\n\n'; + codeSnippet += 'if (response.statusCode == 200) {\n'; + codeSnippet += `${indent}print(json.encode(response.data));\n`; + codeSnippet += '}\nelse {\n'; + codeSnippet += `${indent}print(response.statusMessage);\n`; + codeSnippet += '}'; + + (options.includeBoilerplate) && + (codeSnippet = indent + codeSnippet.split('\n').join('\n' + indent) + '\n'); + + callback(null, headerSnippet + codeSnippet + footerSnippet); + }, + getOptions: function () { + return [ + { + name: 'Set indentation count', + id: 'indentCount', + type: 'positiveInteger', + default: 2, + description: 'Set the number of indentation characters to add per code level' + }, + { + name: 'Set indentation type', + id: 'indentType', + type: 'enum', + availableOptions: ['Tab', 'Space'], + default: 'Space', + description: 'Select the character used to indent lines of code' + }, + { + name: 'Set request timeout', + id: 'requestTimeout', + type: 'positiveInteger', + default: 0, + description: 'Set number of milliseconds the request should wait for a response' + + ' before timing out (use 0 for infinity)' + }, + { + name: 'Trim request body fields', + id: 'trimRequestBody', + type: 'boolean', + default: false, + description: 'Remove white space and additional lines that may affect the server\'s response' + }, + { + name: 'Include boilerplate', + id: 'includeBoilerplate', + type: 'boolean', + default: false, + description: 'Include class definition and import statements in snippet' + }, + { + name: 'Follow redirects', + id: 'followRedirect', + type: 'boolean', + default: true, + description: 'Automatically follow HTTP redirects' + } + ]; + } +}; diff --git a/codegens/dart-dio/lib/util.js b/codegens/dart-dio/lib/util.js new file mode 100644 index 000000000..4d1801f91 --- /dev/null +++ b/codegens/dart-dio/lib/util.js @@ -0,0 +1,123 @@ +module.exports = { + /** + * sanitizes input string by handling escape characters eg: converts '''' to '\'\'' + * and trim input if required + * + * @param {String} inputString + * @param {Boolean} [trim] - indicates whether to trim string or not + * @returns {String} + */ + sanitize: function (inputString, trim) { + if (typeof inputString !== 'string') { + return ''; + } + inputString = inputString.replace(/\\/g, '\\\\') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/\t/g, '\\t') + .replace(/'/g, '\\\'') + .replace(/\$/g, '\\$'); + return trim ? inputString.trim() : inputString; + + }, + + /** + * sanitizes input options + * + * @param {Object} options - Options provided by the user + * @param {Array} optionsArray - options array received from getOptions function + * + * @returns {Object} - Sanitized options object + */ + sanitizeOptions: function (options, optionsArray) { + var result = {}, + defaultOptions = {}, + id; + optionsArray.forEach((option) => { + defaultOptions[option.id] = { + default: option.default, + type: option.type + }; + if (option.type === 'enum') { + defaultOptions[option.id].availableOptions = option.availableOptions; + } + }); + + for (id in options) { + if (options.hasOwnProperty(id)) { + if (defaultOptions[id] === undefined) { + continue; + } + switch (defaultOptions[id].type) { + case 'boolean': + if (typeof options[id] !== 'boolean') { + result[id] = defaultOptions[id].default; + } + else { + result[id] = options[id]; + } + break; + case 'positiveInteger': + if (typeof options[id] !== 'number' || options[id] < 0) { + result[id] = defaultOptions[id].default; + } + else { + result[id] = options[id]; + } + break; + case 'enum': + if (!defaultOptions[id].availableOptions.includes(options[id])) { + result[id] = defaultOptions[id].default; + } + else { + result[id] = options[id]; + } + break; + default: + result[id] = options[id]; + } + } + } + + for (id in defaultOptions) { + if (defaultOptions.hasOwnProperty(id)) { + if (result[id] === undefined) { + result[id] = defaultOptions[id].default; + } + } + } + return result; + }, + + /** + * + * @param {Array} array - form data array + * @param {String} key - key of form data param + * @param {String} type - type of form data param(file/text) + * @param {String} val - value/src property of form data param + * @param {String} disabled - Boolean denoting whether the param is disabled or not + * @param {String} contentType - content type header of the param + * + * Appends a single param to form data array + */ + addFormParam: function (array, key, type, val, disabled, contentType) { + if (type === 'file') { + array.push({ + key: key, + type: type, + src: val, + disabled: disabled, + contentType: contentType + }); + } + else { + array.push({ + key: key, + type: type, + value: val, + disabled: disabled, + contentType: contentType + }); + } + } +}; diff --git a/codegens/dart-dio/npm/test-lint.js b/codegens/dart-dio/npm/test-lint.js new file mode 100644 index 000000000..2f4db0cb8 --- /dev/null +++ b/codegens/dart-dio/npm/test-lint.js @@ -0,0 +1,56 @@ +#!/usr/bin/env node +var shell = require('shelljs'), + chalk = require('chalk'), + async = require('async'), + ESLintCLIEngine = require('eslint').CLIEngine, + + /** + * The list of source code files / directories to be linted. + * + * @type {Array} + */ + LINT_SOURCE_DIRS = [ + './lib', + './test', + './npm/*.js', + './index.js' + ]; + +module.exports = function (exit) { + // banner line + console.info(chalk.yellow.bold('\nLinting files using eslint...')); + + async.waterfall([ + + /** + * Instantiates an ESLint CLI engine and runs it in the scope defined within LINT_SOURCE_DIRS. + * + * @param {Function} next - The callback function whose invocation marks the end of the lint test run. + * @returns {*} + */ + function (next) { + next(null, (new ESLintCLIEngine()).executeOnFiles(LINT_SOURCE_DIRS)); + }, + + /** + * Processes a test report from the Lint test runner, and displays meaningful results. + * + * @param {Object} report - The overall test report for the current lint test. + * @param {Object} report.results - The set of test results for the current lint run. + * @param {Function} next - The callback whose invocation marks the completion of the post run tasks. + * @returns {*} + */ + function (report, next) { + var errorReport = ESLintCLIEngine.getErrorResults(report.results); + // log the result to CLI + console.info(ESLintCLIEngine.getFormatter()(report.results)); + // log the success of the parser if it has no errors + (errorReport && !errorReport.length) && console.info(chalk.green('eslint ok!')); + // ensure that the exit code is non zero in case there was an error + next(Number(errorReport && errorReport.length) || 0); + } + ], exit); +}; + +// ensure we run this script exports if this is a direct stdin.tty run +!module.parent && module.exports(shell.exit); diff --git a/codegens/dart-dio/npm/test-newman.js b/codegens/dart-dio/npm/test-newman.js new file mode 100644 index 000000000..0c8559a8e --- /dev/null +++ b/codegens/dart-dio/npm/test-newman.js @@ -0,0 +1,59 @@ +#!/usr/bin/env node +/* eslint-env node, es6 */ +// --------------------------------------------------------------------------------------------------------------------- +// This script is intended to execute all unit tests. +// --------------------------------------------------------------------------------------------------------------------- + +var shell = require('shelljs'), + + // set directories and files for test and coverage report + path = require('path'), + + NYC = require('nyc'), + chalk = require('chalk'), + recursive = require('recursive-readdir'), + + COV_REPORT_PATH = '.coverage', + SPEC_SOURCE_DIR = path.join(__dirname, '..', 'test', 'newman'); + +module.exports = function (exit) { + // banner line + console.info(chalk.yellow.bold('Running newman tests using mocha on node...')); + + shell.test('-d', COV_REPORT_PATH) && shell.rm('-rf', COV_REPORT_PATH); + shell.mkdir('-p', COV_REPORT_PATH); + + var Mocha = require('mocha'), + nyc = new NYC({ + reportDir: COV_REPORT_PATH, + tempDirectory: COV_REPORT_PATH, + reporter: ['text', 'lcov', 'text-summary'], + exclude: ['config', 'test'], + hookRunInContext: true, + hookRunInThisContext: true + }); + + nyc.wrap(); + // add all spec files to mocha + recursive(SPEC_SOURCE_DIR, function (err, files) { + if (err) { console.error(err); return exit(1); } + + var mocha = new Mocha({ timeout: 1000 * 60 }); + + files.filter(function (file) { // extract all test files + return (file.substr(-8) === '.test.js'); + }).forEach(mocha.addFile.bind(mocha)); + + mocha.run(function (runError) { + runError && console.error(runError.stack || runError); + + nyc.reset(); + nyc.writeCoverageFile(); + nyc.report(); + exit(runError ? 1 : 0); + }); + }); +}; + +// ensure we run this script exports if this is a direct stdin.tty run +!module.parent && module.exports(shell.exit); diff --git a/codegens/dart-dio/npm/test.js b/codegens/dart-dio/npm/test.js new file mode 100644 index 000000000..ee0be8b7d --- /dev/null +++ b/codegens/dart-dio/npm/test.js @@ -0,0 +1,19 @@ +#!/usr/bin/env node +var chalk = require('chalk'), + exit = require('shelljs').exit, + prettyms = require('pretty-ms'), + startedAt = Date.now(), + name = require('../package.json').name; + +require('async').series([ + require('./test-lint'), + require('./test-newman') + // Add a separate folder for every new suite of tests + // require('./test-unit') + // require('./test-browser') + // require('./test-integration') +], function (code) { + // eslint-disable-next-line max-len + console.info(chalk[code ? 'red' : 'green'](`\n${name}: duration ${prettyms(Date.now() - startedAt)}\n${name}: ${code ? 'not ok' : 'ok'}!`)); + exit(code && (typeof code === 'number' ? code : 1) || 0); +}); diff --git a/codegens/dart-dio/package-lock.json b/codegens/dart-dio/package-lock.json new file mode 100644 index 000000000..c1166ce89 --- /dev/null +++ b/codegens/dart-dio/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "@postman/codegen-dart-dio", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + } + } +} diff --git a/codegens/dart-dio/package.json b/codegens/dart-dio/package.json new file mode 100644 index 000000000..2dd1dd22f --- /dev/null +++ b/codegens/dart-dio/package.json @@ -0,0 +1,36 @@ +{ + "name": "@postman/codegen-dart-dio", + "version": "0.0.1", + "description": "Converts Postman SDK Requests to Dart Dio code snippet", + "main": "index.js", + "com_postman_plugin": { + "type": "code_generator", + "lang": "Dart", + "variant": "dio", + "syntax_mode": "dart" + }, + "directories": { + "lib": "lib", + "test": "test" + }, + "scripts": { + "test": "node npm/test.js", + "test-lint": "node npm/test-lint.js", + "test-unit": "node npm/test-unit.js", + "test-newman": "node npm/test-newman.js" + }, + "repository": { + "type": "git", + "url": "" + }, + "author": "Postman Labs ", + "license": "Apache-2.0", + "homepage": "https://github.com/postmanlabs/code-generators/tree/master/codegens/dart-dio", + "dependencies": { + "lodash": "4.17.21" + }, + "devDependencies": {}, + "engines": { + "node": ">=12" + } +} diff --git a/codegens/dart-dio/test/newman/newman.test.js b/codegens/dart-dio/test/newman/newman.test.js new file mode 100644 index 000000000..e8b238678 --- /dev/null +++ b/codegens/dart-dio/test/newman/newman.test.js @@ -0,0 +1,18 @@ +var runNewmanTest = require('../../../../test/codegen/newman/newmanTestUtil').runNewmanTest, + convert = require('../../lib/index').convert; + + +describe('Dart-dio Converter', function () { + describe('convert for different request types', function () { + var options = {indentCount: 2, indentType: 'Space', includeBoilerplate: true }, + testConfig = { + runScript: 'dart snippet.dart', + fileName: 'snippet.dart', + headerSnippet: '', + // http uses Map to store headers, so there is no way to + // keep multiple headers with the same key + skipCollections: ['sameNameHeadersCollection', 'unsupportedMethods'] + }; + runNewmanTest(convert, options, testConfig); + }); +}); diff --git a/codegens/dart-dio/test/unit/convert.test.js b/codegens/dart-dio/test/unit/convert.test.js new file mode 100644 index 000000000..3936eebef --- /dev/null +++ b/codegens/dart-dio/test/unit/convert.test.js @@ -0,0 +1,121 @@ +var convert = require('../../index').convert, + expect = require('chai').expect, + sdk = require('postman-collection'); + +// Disable check with expected snippets as we now have proper newman tests +describe('Dart Converter', function () { + it('should add timeout if requestTimeout options is used', function () { + var request = new sdk.Request({ + 'method': 'POST', + 'header': [ + { + 'key': 'Content-Type', + 'value': 'application/json' + } + ], + 'body': { + 'mode': 'raw', + 'raw': '{\n "json": "Test-Test"\n}' + }, + 'url': { + 'raw': 'https://postman-echo.com/post', + 'protocol': 'https', + 'host': [ + 'postman-echo', + 'com' + ], + 'path': [ + 'post' + ] + } + }); + + convert(request, {requestTimeout: 5000}, function (err, snippet) { + if (err) { + expect.fail(err); + } + expect(snippet).to.be.a('string'); + expect(snippet).to.contain('receiveTimeout: 50000'); + }); + }); + + it('should add code for followRedirects if given in the option', function () { + var request = new sdk.Request({ + 'method': 'GET', + 'header': [], + 'url': { + 'raw': 'https://postman-echo.com/', + 'protocol': 'https', + 'host': [ + 'postman-echo', + 'com' + ] + } + }); + convert(request, { followRedirect: false }, function (err, snippet) { + if (err) { + expect.fail(err); + } + expect(snippet).to.be.a('string'); + expect(snippet).to.contain('followRedirects: false;'); + }); + }); + + it('should add boilerplate if given in the option', function () { + var request = new sdk.Request({ + 'method': 'GET', + 'header': [], + 'url': { + 'raw': 'https://postman-echo.com/', + 'protocol': 'https', + 'host': [ + 'postman-echo', + 'com' + ] + } + }); + convert(request, { includeBoilerplate: true }, function (err, snippet) { + if (err) { + expect.fail(err); + } + expect(snippet).to.be.a('string'); + expect(snippet).to.contain('import \'package:dio/dio.dart\';'); + expect(snippet).to.contain('void main() async {'); + }); + }); + + it('should add correct indentation', function () { + var request = new sdk.Request({ + 'method': 'POST', + 'header': [], + 'body': { + 'mode': 'formdata', + 'formdata': [ + { + 'key': 'hello', + 'value': 'world', + 'type': 'text' + } + ] + }, + 'url': { + 'raw': 'https://postman-echo.com/post', + 'protocol': 'https', + 'host': [ + 'postman-echo', + 'com' + ], + 'path': [ + 'post' + ] + } + }); + convert(request, { includeBoilerplate: true, indentType: 'Tab' }, function (err, snippet) { + if (err) { + expect.fail(err); + } + expect(snippet).to.be.a('string'); + expect(snippet).to.contain('\t\t\'hello\': \'world\''); + }); + }); +}); diff --git a/npm/ci-requirements.sh b/npm/ci-requirements.sh index 98cac2042..69d612a51 100755 --- a/npm/ci-requirements.sh +++ b/npm/ci-requirements.sh @@ -80,13 +80,28 @@ echo "Installing curl" echo "Installing dependencies required for tests in codegens/shell-httpie" sudo apt-get install httpie -echo "Installing dependencies required for tests in codegens/dart" +echo "Installing dependencies required for tests in codegens/dart-http" pushd ./codegens/dart-http &>/dev/null; - wget -q https://storage.googleapis.com/dart-archive/channels/stable/release/2.10.2/linux_packages/dart_2.10.2-1_amd64.deb - sudo dpkg -i dart_2.10.2-1_amd64.deb + wget -q https://storage.googleapis.com/dart-archive/channels/stable/release/3.0.4/linux_packages/dart_3.0.4-1_amd64.deb + sudo dpkg -i dart_3.0.4-1_amd64.deb echo '''name: test +version: 1.0.0 +environment: + sdk: ^3.0.3 dependencies: - http: ^0.12.2 + http: ^1.0.0 +''' > pubspec.yaml + dart pub get +popd &>/dev/null; + +echo "Installing dependencies required for tests in codegens/dart-dio" +pushd ./codegens/dart-dio &>/dev/null; + echo '''name: test +version: 1.0.0 +environment: + sdk: ^3.0.3 +dependencies: + dio: ^5.2.0 ''' > pubspec.yaml dart pub get popd &>/dev/null;