diff --git a/.npmignore b/.npmignore index 110cce49..f66b4783 100644 --- a/.npmignore +++ b/.npmignore @@ -1,4 +1,12 @@ -build -demo +.DS_Store +**/.* +.tmp + +node_modules +jspm_packages + tests lib +demo +build +coverage diff --git a/.travis.yml b/.travis.yml index 07ef6494..0c1c5103 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,27 @@ language: node_js node_js: - '4.0' +branches: + except: + - releases +matrix: + include: + - env: JOB=e2e + fast_finish: true + allow_failures: + - env: JOB=e2e env: global: - GH_REF: github.com/Rebilly/ReDoc.git - - secure: ijk9zRQxw1XKVt1zjuJ4uc3iyU622HB0qSPdwVECqhUMm3Gh3MAmTH1bqubsSHKZbfNNIehUvu+X/3LeKZNUK+zBS8qbLXWQKZ4ime4RHT8ADjZV+NY2GdQUxs5rklb3kjVK6cOQ8A51jU/8Zw738iFDDPz3NxbXC+MP3CQANxYCeX2axdxVFzQcldA89vZr0K8DBMPW1EZP+e1jORB3YFwyKZMppB9XvI7GAjt2OQvZDQegNuVaPuECZcJjPh2VBopQ3+Giun2AIe3C0Q/DmU+rZd8M2/t2VEv0e6BZNtbpycq8ST3mWloTPhmL9F2xlm4ZuWUVWuxB3LgOTZUw11KRg51MUTv/9Xfrqf16CUvR4TJ7EDYAKt5NwVFNUJsIy9cpuI6fsndFeI7EWFFYN7m4FX/SWLhVzFcrZeWpwbMn+qFCE0S+VgUjwYwMMA667YgRPhIAGoJfL5MxrhE/HPUIDJU91t9ON7UpFcdcUex6jX9pKUvyP52uJQKIwP10ZgehvL3S0iutMYVYY0YNkKF4tIPiQPsCK4lx7Up4D/tR9jSZl11CLMBZ0jLk1sEtgMf9+v0emOiGIgmBBYwVec6Jy1kSJyEeAJThmLjdVtAVgT0T3jPhM0Z8BE0xkwFY/5myQeoo8QWdBcDZw3iAxgatHXnPLqoa5rViuA1thyw= + - GIT_AUTHOR_EMAIL: redoc-bot@users.noreply.github.com + - GIT_AUTHOR_NAME: RedocBot + - SAUCE_USERNAME: redoc + - secure: OgYIXlyF3tvHVrMjqIMR7UPhNvMzNZRkKE++LsQPUT4aoUmHoeukjgE9tKCZac3Z+PcAlgHQ6dPUqjqij2d/emYBIrCx4ABvTOnxQYHbk+8GriwPvQjV33MCfKvRQAf3XPNcga02aOO/EEGejrtY/i5sz86XPZFXap4scxbvnF0rzOwGU9/A40JLsvKjtfdRxJ3aC2QBnUHP9JkfBOzbs3jjwEWYN7HdUBqtYU+wiUwvHhpEPQ8BVNF5ETp5OxxkTdqJlMRf3azC4U/Rl8dhUXZP2l1ZBdpgahDvSkx1zXPwKRg1jos88jahqH/v8DLHtXNuYQy4S48nKWZfaRtQegG/XsYAftYPtYage7L9D0nFQW9YZI0vwUBEzh2YTf+QNpVwUSyZhVuS1oS+scTb8RU8BVVZd6hRpJiaI2YiPM6ZFN7a69deV0cASov3yI7GSfeq4MmB4hu72Le+GhemQMLRxNgtr32c18XW1XoHEnpV7s0eKXnZrevnM06tW/nX9TQXGloaMUeQzoZY0AuF00zmrHDaNgwT63ULjY0W591Ey1Ztfq4ixdCoi6IPAtl49vTnNMMMqatI7Si/haI6hGyTy+H0xK1GlUpBCe5CGusXDSKUqrlKS5Izreepfj1G+12391ixiapkwV3SbYdQEhcDt7HWupyI4Zfkvg8EwwE= + - secure: H2GClDJ7TEQaWgnk8d2fIVDpLwG3rTmN8TalUzrCqXGoG6ylCVmlwzKLgfPPWrVgSA7QTdfNV0ab7c2KyPoZBinHmeGMSuKNLVbhOXRc2VFxTBntBTuyJhfCgQEpUKvJesJUuv5RuBn//wC7VZcVVNc06TZDEe8+aDVYQuCRMXZJ4X3e6nSZ64QX2veyVcr+TjnRsZPkeBVcK9hngvuaxLb/hbJ85CvjiseZRt47PGIcrEpMn9n2GMw1m0fNnPoN+MBTSCnIklTmdjPG7t4GUSLmD6H0lNLdXuehYqmQAHgYrLec1aiFlV57QaDoDZrq2hSf4vDmCB/FVydGhD5JunI67pujoV2OnD1V80eUZhYNWOYsJ2Nfp4NxgXsPUcE6zWLYsLfktMPZADhOXInQRACt1cnx8zMYKLnch1RY/ZqjSg0nPtRjLzQ0lNsw5leixvBdBnMjxYHVyAWVwg8WiJMaLO9vog2Qnxg1NTacHO2CsOmm2rw6stpg7ndp/+nOleRlfUKggjt0Tn3FjwCIXeGup2P2EBa+WW2YMAaoMFofYviR5vRlKBgdKo9fsAruaO1r6nm2EdAjOlniyw92bEfU/qOey1nVp/oK2S82uT5In8KB7vl6rF3ak7WAsT9Q5vZUhsrG+eE4PVyIyWNBhs4A7pSwZGHDR/MYtp0E2ug= - secure: QiSLFxMS0fNLQAuG081Oi22OkL8BqCDnZVGk0a69azNzl5vv3PCcYO2Sjbloe48gPVH3p5AonDTtDEtnUbMcCJjtrhggqs5gSilO+UVgDb+4LfrYDnJ8ffaeVGIugay9wl2aJVz3iNbnIovGP7Nw+M/OWtLc2xq6zE1rIJkdRJ4K55PYfO8EMDvzI7hjZxSZ+Kgglcdl/wdBSKXy/qG0atALQU9ilJnk/DcobCjaUjgH/v0HXTSO8K3TNso6Zo4HOO6xWXHDZnJ2sLNltW1jveBpfCr/ZlccgPASU03nIudJyKvX8V4fXQ+2Z2Rj3JtR0x95SSH3M7ixx3s4teiXNFe9HPMfN1NLh/zf8UmgWIN1uwyYecsjRVzz+ZsfnrNBjGyXdEJg5c6SZGIa/UMSxaQFdRzEA419qw2eJ9qcmfNPyIvijugEBupJsxK6MW+mrD8qaGKQDzEP1dD7PUlr1BBckFNI8SZKD0gEaqM/ibebxrMS2IcGE5Nk7qLdaOAdB1plXAhMl+PGNaPx4+cniUqIIpgDTX8hlmd/Qk8ThyN5Z4aQyWI2WfH1BSqwg8dQfB5B6WNUDbJh/4Z6AX7e7ACiMLKoRkBTWpQ1FIwEJh5j8X/mtMBjf4+HSf8kfnAWFCmPTpRcYz9i4ZUDfa/9QKMoumCjokfItU7Ue2UE5v4= - secure: apiavCfCQngL9Een1m7MIXMf3bqO3rY4YY59TMBl/yFKi80CEsHPHhgVUkl6hC+aM5PeBt/vgjh37rHMX31j/pcSZ4Z8SO/4Bwr36iHfhSxSEuAQog8P07qWqH7wYYWGIVmF682stgl0fYF+GN92sx/6edFVzsWVECf2G7imtICKSTbhKGm3Dhn2JwGnhD7eyfgZ33omgiaswumdu0xABoXDfqSZR+16fC4Ap5rhv3fXO9ndvRNy1STn376nT+my6e86UrQL4aS/S+HNHgIe1BUs+5cOp6Jgw6t0ie7phY0EAiECsRxy9K4e3Dctv9m6+Wma4+vy65MS0zGyrqey6oyV4l827sCOjrD1qcqc9bX6FlMSouVoNfE4ZjINNAbgigTaiLSoDSPcf5I5smkkM2ezzFOMSZwZxNdaNL2LKb97vc8m/ZUkv0sKZyT7oqVL7aJweEivsSHj5l2KR8Z7XrVB1y2eI6GvyTSa/d+CL4dSRzjh8+IRN047YBrdTKD5IkdT0upfoBu14WPUfFmLKxX+iMCslXRWb6kwojhrWNYmZvL65KRAzJ6+eIPDG/W5QUOpYyYT77bLlBQjVo6NmVvl9v3HMECq9CHH0ivKFBGPiKMOx7cJkTax3FuyznOW2WCXB9kTb5Zk9toaiNlSp9L6ll/h2Eyxa6n6sWUgmmM= +addons: + sauce_connect: true cache: directories: - node_modules @@ -17,14 +32,19 @@ before_install: before_deploy: - npm run build-dist deploy: - skip_cleanup: true - provider: script - script: ./build/deploy_gh_pages.sh - on: - branch: master -deploy: - skip_cleanup: true - provider: script - script: "npm run branch-release" - on: - branch: master + - skip_cleanup: true + provider: script + script: ./build/deploy_gh_pages.sh + on: + branch: master + - skip_cleanup: true + provider: script + script: npm run branch-release + on: + branch: master + - provider: npm + skip_cleanup: true + api_key: + secure: PuhWLERrCEFmXmdFpw2OVFlqpOIVDmgwk5JUJOYaFdVCh/smp0+jZCQ4vrdFpuG96rnDVirD+A8xvW6NgsNNaRthLgOB/LRdFN69rU6Gvn3At6wlnC55t5dlhxPvCfnzJcHVBLXX4EmMkjnZqDg2uczXTzPodr3FnQJNuXmP8B33fzDVLyHccvXZ90abwXWVrgRIXPU28niqCR8DOC2OTzs7wqz+BLNkYDRRbyYXsg62HWuD33x5iof5IqBmhzBt3usCGmF3QGcgHrXHdZw3sZnit8+Bua++3KrXR0x6HGXXN1AoXVmCAkCa5OTQ5R3tCRxiJN3P2KLnvWeZR74sTFkovJB/6pGCvbJ/c7Wnuw6sD7SgOUBD359ULB6lAf5OnxBLoNebX4JxxVXF+zA4E3Bl44VxkzDpPWc15xqBPMB5vBREzMVmJ5mExn2s5cmLQjADbl9h0y6gZnhnNJ+iTmqtrVyM0ZkF2rPrzrTdGD+ULmRIlTMkdD1bh+/TJ3RdXT3P4/zNUJmiNnvgnnJVYYvsGaXWF+7uCVHT/8k2RsoSHqgkqh0gkDqGSwVix55y5mC7T2Vk9lMBhm6MvFJXaonOX0kxJS4EDQ3plPd6/ybG+TLhwggYnQ8o9msU5Nt6FpUShKiezjKurIhbQZdwlVivX3tahjW2QjNDO58xGgY= + on: + tags: true diff --git a/README.md b/README.md index 28338342..b4f9343e 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,15 @@ # ReDoc -[![travis-ci-status]](https://travis-ci.org/Rebilly/ReDoc) [![coverage-status-badge]](https://coveralls.io/github/Rebilly/ReDoc?branch=master) [![code-climate-badge]](https://codeclimate.com/github/Rebilly/ReDoc) [![dev-dependency-badge]](https://david-dm.org/Rebilly/ReDoc#info=devDependencies) [![license-badge]](https://github.com/Rebilly/ReDoc/blob/master/LICENSE) +[![Build Status](https://travis-ci.org/Rebilly/ReDoc.svg?branch=master)](https://travis-ci.org/Rebilly/ReDoc) [![Coverage Status](https://coveralls.io/repos/Rebilly/ReDoc/badge.svg?branch=master&service=github)](https://coveralls.io/github/Rebilly/ReDoc?branch=master) [![Code Climate](https://codeclimate.com/github/Rebilly/ReDoc/badges/gpa.svg)](https://codeclimate.com/github/Rebilly/ReDoc) [![David](https://david-dm.org/Rebilly/ReDoc/dev-status.svg)](https://david-dm.org/Rebilly/ReDoc#info=devDependencies) + +[![npm](http://img.shields.io/npm/v/redoc.svg)](https://www.npmjs.com/package/swagger-parser) [![Bower](http://img.shields.io/bower/v/redoc.svg)](http://bower.io/) [![License](https://img.shields.io/npm/l/redoc.svg)](https://github.com/Rebilly/ReDoc/blob/master/LICENSE) + +[![Browser Compatibility](https://saucelabs.com/browser-matrix/redoc.svg)](https://saucelabs.com/u/redoc) Swagger-generated API Reference Documentation **Under development** -[Live demo][demo] +[Live demo](http://rebilly.github.io/ReDoc/) ## Running locally 1. Clone repository @@ -18,11 +22,3 @@ Swagger-generated API Reference Documentation 5. Start the server `npm start` 6. Open `http://localhost:9000` - - -[travis-ci-status]: https://travis-ci.org/Rebilly/ReDoc.svg?branch=master "TravisCI Status" -[license-badge]: https://img.shields.io/github/license/rebilly/redoc.svg "Github license" -[coverage-status-badge]:https://coveralls.io/repos/Rebilly/ReDoc/badge.svg?branch=master&service=github) "Coverage Status" -[dev-dependency-badge]: https://david-dm.org/Rebilly/ReDoc/dev-status.svg -[code-climate-badge]: https://codeclimate.com/github/Rebilly/ReDoc/badges/gpa.svg "Code Climate" -[demo]: http://rebilly.github.io/ReDoc/ diff --git a/build/run_tests.sh b/build/run_tests.sh new file mode 100755 index 00000000..308641bf --- /dev/null +++ b/build/run_tests.sh @@ -0,0 +1,6 @@ +#!/bin/bash +if [ "$JOB" = "e2e" ]; then + npm run e2e +else + npm run unit +fi diff --git a/build/tasks/build.js b/build/tasks/build.js index c37fc467..0e29efa4 100644 --- a/build/tasks/build.js +++ b/build/tasks/build.js @@ -10,11 +10,19 @@ var concat = require('gulp-concat'); var gulp = require('gulp'); var sass = require('gulp-sass'); var replace = require('gulp-replace'); -var uglify = require('gulp-uglify'); var rename = require('gulp-rename'); -paths.redocBuilt = path.join(paths.output, paths.outputName) + '.js'; +paths.redocBuilt = path.join(paths.output, paths.outputName); + gulp.task('build', function (callback) { + return runSequence( + 'clean', + 'bundleProd', + callback + ); +}); + +gulp.task('buildDev', function (callback) { return runSequence( 'clean', 'bundle', @@ -22,7 +30,9 @@ gulp.task('build', function (callback) { ); }); -gulp.task('bundle', ['bundleSfx', 'concatDeps', 'uglify']); + +gulp.task('bundle', ['buildStatic', 'concatDeps']); +gulp.task('bundleProd', ['bundle', 'buildStaticMin', 'concatDepsMin']); gulp.task('inlineTemplates', ['sass'], function() { return gulp.src(paths.source, { base: './' }) @@ -31,21 +41,18 @@ gulp.task('inlineTemplates', ['sass'], function() { .pipe(gulp.dest(paths.tmp)); }); -// produces minimized verstion of sfx bundle -gulp.task('uglify', ['concatDeps'], function() { - return gulp.src(paths.redocBuilt) - .pipe(sourcemaps.init()) - .pipe(uglify()) - .pipe(rename(paths.outputName + '.min.js')) - .pipe(sourcemaps.write('./')) - .pipe(gulp.dest(paths.output)); -}); - var JS_DEV_DEPS = [ 'node_modules/zone.js/dist/zone-microtask.js', - 'node_modules/reflect-metadata/Reflect.js' + 'node_modules/reflect-metadata/Reflect.js', + 'node_modules/babel-polyfill/dist/polyfill.js' ]; +var JS_DEV_DEPS_MIN = [ + 'node_modules/zone.js/dist/zone-microtask.min.js', + 'node_modules/reflect-metadata/Reflect.js', + 'node_modules/babel-polyfill/dist/polyfill.min.js' +] + gulp.task('sass', function () { return gulp.src(paths.scss, { base: './' }) .pipe(sass.sync().on('error', sass.logError)) @@ -53,15 +60,31 @@ gulp.task('sass', function () { }); // concatenate angular2 deps -gulp.task('concatDeps', ['bundleSfx'], function() { - gulp.src(JS_DEV_DEPS.concat([paths.redocBuilt])) - .pipe(sourcemaps.init({loadMaps: true})) - .pipe(concat(paths.outputName + '.js')) - .pipe(sourcemaps.write('.')) - .pipe(gulp.dest(paths.output)) +gulp.task('concatDeps', ['buildStatic'], function() { + return concatDeps(JS_DEV_DEPS, paths.redocBuilt + '.js'); }); -gulp.task('bundleSfx', ['inlineTemplates'], function(cb) { +gulp.task('concatDepsMin', ['buildStatic'], function() { + return concatDeps(JS_DEV_DEPS_MIN, paths.redocBuilt + '.min.js'); +}); + +gulp.task('buildStatic', ['inlineTemplates'], function(cb) { + bundle(paths.redocBuilt + '.js', false, cb); +}); + +gulp.task('buildStaticMin', ['inlineTemplates'], function(cb) { + bundle(paths.redocBuilt + '.min.js', true, cb); +}); + +function concatDeps(deps, file) { + return gulp.src(deps.concat([file])) + .pipe(sourcemaps.init({loadMaps: true})) + .pipe(concat(file)) + .pipe(sourcemaps.write('.')) + .pipe(gulp.dest('.')) +} + +function bundle(outputFile, minify, cb) { fs.existsSync('dist') || fs.mkdirSync('dist'); var builder = new Builder('./', 'system.config.js'); builder.config({ @@ -70,8 +93,8 @@ gulp.task('bundleSfx', ['inlineTemplates'], function(cb) { builder .buildStatic(path.join(paths.tmp, paths.sourceEntryPoint), - paths.redocBuilt, - { format:'amd', sourceMaps: true, lowResSourceMaps: true } + outputFile, + { format:'umd', sourceMaps: true, lowResSourceMaps: true, minify: minify } ) .then(function() { cb(); @@ -79,4 +102,4 @@ gulp.task('bundleSfx', ['inlineTemplates'], function(cb) { .catch(function(err) { cb(new Error(err)); }); -}); +} diff --git a/build/tasks/e2e.js b/build/tasks/e2e.js new file mode 100644 index 00000000..8888188e --- /dev/null +++ b/build/tasks/e2e.js @@ -0,0 +1,34 @@ +var gulp = require('gulp'); +var gp = require('gulp-protractor'); +var browserSync = require('browser-sync').create('bs-e2e'); + +gulp.task('test-server', function (done) { + browserSync.init({ + open: false, + notify: false, + port: 3000, + ghostMode: false, + server: { + baseDir: './tests/e2e', + routes: { + '/dist': './dist', + '/swagger.json': './demo/swagger.json' + }, + } + }, done); +}); + + +gulp.task('e2e', ['bundleProd', 'test-server'], function(done) { + gulp.src(['tests/e2e/**/*.js'], { read:false }) + .pipe(gp.protractor({ + configFile: './protractor.conf.js' + })).on('error', function(e) { + browserSync.exit(); + throw e; + done(); + }).on('end', function() { + browserSync.exit(); + done(); + }); +}); diff --git a/build/tasks/watch.js b/build/tasks/watch.js index 9d2aa503..77eec19d 100644 --- a/build/tasks/watch.js +++ b/build/tasks/watch.js @@ -6,7 +6,7 @@ function changed(event) { console.log('File ' + event.path + ' was ' + event.type + ', running tasks...'); } -gulp.task('watch', ['build'], function () { +gulp.task('watch', ['buildDev'], function () { gulp.watch([ paths.source ], [ 'bundle', browserSync.reload ]).on('change', changed); gulp.watch([ paths.html ], [ 'bundle', browserSync.reload]).on('change', changed); gulp.watch([ paths.scss ], [ 'bundle', browserSync.reload]).on('change', changed); diff --git a/demo/index.html b/demo/index.html index 1095cdaf..b863a23c 100644 --- a/demo/index.html +++ b/demo/index.html @@ -1,4 +1,4 @@ - + ReDoc diff --git a/demo/main.css b/demo/main.css index d5325a9e..888fc739 100644 --- a/demo/main.css +++ b/demo/main.css @@ -7,10 +7,6 @@ body { padding-top: 50px; } -p { - margin: 0; -} - nav input, nav button { font-size: 16px; height: 28px; @@ -50,20 +46,3 @@ nav { top: 0; z-index: 1; } - -redoc { - display: block; - box-sizing: border-box; -} - -pre { - white-space: pre-wrap; - background-color: #f2f2f2; - padding: 10px; - overflow-x: auto; - line-height: normal; -} - -code { - background-color: #f2f2f2; -} diff --git a/demo/swagger.json b/demo/swagger.json index 5dd2d676..adb0c45f 100644 --- a/demo/swagger.json +++ b/demo/swagger.json @@ -773,7 +773,11 @@ "Pet": { "type": "object", "required": ["name", "photoUrls"], + "discriminator": "petType", "properties": { + "petType": { + "type": "string" + }, "id": { "type": "integer", "format": "int64" @@ -815,6 +819,56 @@ "name": "Pet" } }, + "Cat": { + "description": "A representation of a cat", + "allOf": [ + { + "$ref": "#/definitions/Pet" + }, + { + "type": "object", + "properties": { + "huntingSkill": { + "type": "string", + "description": "The measured skill for hunting", + "default": "lazy", + "enum": [ + "clueless", + "lazy", + "adventurous", + "aggressive" + ] + } + }, + "required": [ + "huntingSkill" + ] + } + ] + }, + "Dog": { + "description": "A representation of a dog", + "allOf": [ + { + "$ref": "#/definitions/Pet" + }, + { + "type": "object", + "properties": { + "packSize": { + "type": "integer", + "format": "int32", + "description": "the size of the pack the dog is from", + "default": 0, + "minimum": 0 + } + }, + "required": [ + "packSize" + ] + } + ] + }, "ApiResponse": { "type": "object", "properties": { diff --git a/karma.conf.js b/karma.conf.js index 1523bcf9..3fbf51b8 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -54,7 +54,7 @@ module.exports = function (config) { jspm: { config: 'system.config.js', - loadFiles: ['tests/**/*.spec.js', 'tests/helpers.js', 'lib/**/*.js'], + loadFiles: ['tests/unit/*.spec.js', 'tests/helpers.js', 'lib/**/*.js'], serveFiles: ['tests/schemas/**/*.json', 'lib/**/*.html', '.tmp/lib/**/*.css'], nocache: true }, diff --git a/lib/common/components/StickySidebar/sticky-sidebar.js b/lib/common/components/StickySidebar/sticky-sidebar.js index 76637c03..345d1d8e 100644 --- a/lib/common/components/StickySidebar/sticky-sidebar.js +++ b/lib/common/components/StickySidebar/sticky-sidebar.js @@ -46,7 +46,7 @@ export default class StickySidebar { stick() { this.adapter.setStyle(this.element, 'position', 'fixed'); - this.adapter.setStyle(this.element, 'top', this.scrollYOffset()); + this.adapter.setStyle(this.element, 'top', this.scrollYOffset() + 'px'); } unstick() { @@ -55,7 +55,7 @@ export default class StickySidebar { } get scrollY() { - return this.scrollParent.scrollY || this.scrollParent.scrollTop || 0; + return (this.scrollParent.pageYOffset !== null) ? this.scrollParent.pageYOffset : this.scrollParent.scrollTop; } ngOnInit() { diff --git a/lib/common/components/StickySidebar/sticky-sidebar.spec.js b/lib/common/components/StickySidebar/sticky-sidebar.spec.js index 266f23a2..96bc5b3a 100644 --- a/lib/common/components/StickySidebar/sticky-sidebar.spec.js +++ b/lib/common/components/StickySidebar/sticky-sidebar.spec.js @@ -49,7 +49,9 @@ describe('Common components', () => { it('should stick if scrolled more than scrollYOffset', () => { spyOn(component, 'stick').and.callThrough(); fixture.detectChanges(); - window.scrollY = 40; + component.scrollParent = { + pageYOffset: 40 + }; component.updatePosition(); expect(component.stick).toHaveBeenCalled(); }); diff --git a/lib/common/components/Tabs/tabs.js b/lib/common/components/Tabs/tabs.js index be638353..f091afa9 100644 --- a/lib/common/components/Tabs/tabs.js +++ b/lib/common/components/Tabs/tabs.js @@ -10,8 +10,7 @@ import {CORE_DIRECTIVES} from 'angular2/common'; template: ` `, diff --git a/lib/common/components/Tabs/tabs.scss b/lib/common/components/Tabs/tabs.scss index d2ea6989..dc2f5e53 100644 --- a/lib/common/components/Tabs/tabs.scss +++ b/lib/common/components/Tabs/tabs.scss @@ -3,24 +3,16 @@ ul { display: block; margin: 0; - padding: 10px 0px 0 0; + padding: 0; } li { - font-size: 13px; list-style: none; - margin: 2px 0; - padding: 2px 5px; display: inline-block; cursor: pointer; - color: #8A9094; - line-height: 1.25; - color: $sample-panel-headers-color; } li.active { - background-color: white; - color: #666; } .tab-success, .tab-error, .tab-redirect, .tab-info { @@ -31,9 +23,8 @@ li.active { height: 6px; width: 6px; border-radius: 50%; + margin-right: 0.5em; } - - } .tab-success:before { diff --git a/lib/common/components/Zippy/zippy.html b/lib/common/components/Zippy/zippy.html index 127ccac4..62563b02 100644 --- a/lib/common/components/Zippy/zippy.html +++ b/lib/common/components/Zippy/zippy.html @@ -1,6 +1,6 @@
- {{ visible ? '▾' : '▸' }} + {{ visible ? '▾' : '▸' }} {{title}}
diff --git a/lib/components/JsonSchema/json-schema.html b/lib/components/JsonSchema/json-schema.html index ae6663e7..58e947c5 100644 --- a/lib/components/JsonSchema/json-schema.html +++ b/lib/components/JsonSchema/json-schema.html @@ -1,8 +1,7 @@ -{{errorMessage}} {{_displayType}}
-
+
{{prop._name}}
@@ -12,6 +11,7 @@ Required
+
This field value determines the exact schema:
@@ -19,4 +19,12 @@
+
+ + + + + + +
diff --git a/lib/components/JsonSchema/json-schema.js b/lib/components/JsonSchema/json-schema.js index 68e0f253..dee18747 100644 --- a/lib/components/JsonSchema/json-schema.js +++ b/lib/components/JsonSchema/json-schema.js @@ -1,6 +1,7 @@ 'use strict'; import {RedocComponent, BaseComponent} from '../base'; +import {Tabs, Tab} from '../../common/components/Tabs/tabs'; import {ElementRef} from 'angular2/core'; import JsonPointer from '../../utils/JsonPointer'; @@ -8,24 +9,23 @@ import JsonPointer from '../../utils/JsonPointer'; selector: 'json-schema', templateUrl: './lib/components/JsonSchema/json-schema.html', styleUrls: ['./lib/components/JsonSchema/json-schema.css'], - directives: [JsonSchema], - inputs: ['isArray'] + directives: [JsonSchema, Tabs, Tab], + inputs: ['isArray', 'final'] }) export default class JsonSchema extends BaseComponent { constructor(schemaMgr, elementRef) { super(schemaMgr); this.element = elementRef.nativeElement; + this.final = false; } prepareModel() { this.data = {}; this.data.properties = []; + this.data.derived = []; if (!this.componentSchema) { - // TODO - this.errorMessage = 'Can\'t load component schema'; - console.warn(`${this.errorMessage}: ${this.pointer}`); - return; + throw new Error(`Can't load component schema at ${this.pointer}`); } this.dereference(); @@ -33,9 +33,19 @@ export default class JsonSchema extends BaseComponent { if (schema.type === 'array') { this.isArray = true; + if (schema._pointer) { + this.pointer = JsonPointer.join(schema._pointer, 'items'); + } schema = schema.items; } - this.joinAllOf(schema); + let normPtr = schema._pointer || this.pointer; + let derived = this.schemaMgr.findDerivedDefinitions( normPtr ); + if (!this.final && derived.length) { + this.data.derived = derived; + this.data.discriminator = schema.discriminator; + } + + this.joinAllOf(schema, {omitParent: true}); if (schema.type !== 'object') { this.isTrivial = true; @@ -56,11 +66,19 @@ export default class JsonSchema extends BaseComponent { this._displayType = `${schema.type} (Custom key-value pairs)`; return; } - let props = Object.keys(schema.properties).map(prop => { + + let discriminatorFieldIdx = -1; + let props = Object.keys(schema.properties).map((prop, idx) => { let propData = schema.properties[prop]; - this.injectPropData(prop, propData); + this.injectPropData(prop, propData, schema); + if (propData.isDiscriminator) discriminatorFieldIdx = idx; return propData; }); + // Move discriminator field to the end of properties list + if (discriminatorFieldIdx > -1) { + let discrProp = props.splice(discriminatorFieldIdx, 1); + props.push(discrProp[0]); + } this.data.properties = props; } @@ -73,16 +91,20 @@ export default class JsonSchema extends BaseComponent { names.forEach(el => { el.style.minWidth = maxWidth + 'px'; }); + + let discrValues = this.element.querySelector('tabs ul'); + if (discrValues) discrValues.style.paddingLeft = maxWidth + 'px'; } - injectPropData(prop, propData) { + injectPropData(prop, propData, schema) { propData._name = prop; propData.isRequired = this.requiredMap[prop]; propData._displayType = propData.type; + propData.isDiscriminator = (schema.discriminator === prop); if (propData.type === 'array') { let itemType = propData.items.type; let itemFormat = propData.items.format; - if (itemType === 'object') { + if (itemType === 'object' || !itemType) { itemType = propData.items.title || 'object'; propData._pointer = propData.items._pointer || JsonPointer.join(this.pointer, ['properties', prop, 'items']); } diff --git a/lib/components/JsonSchema/json-schema.scss b/lib/components/JsonSchema/json-schema.scss index 9fd368f6..da4fe420 100644 --- a/lib/components/JsonSchema/json-schema.scss +++ b/lib/components/JsonSchema/json-schema.scss @@ -5,7 +5,7 @@ $cell-spacing: 25px; $cell-padding: 10px; $bullet-margin: 10px; $line-border: $lines-width solid $tree-lines-color; -$line-border-erase: $lines-width solid white; +$line-border-erase: ($lines-width + 1px) solid white; $param-name-height: 20px; @@ -38,10 +38,6 @@ $sub-schema-offset: ($bullet-size/2) + $bullet-margin; border-left: $line-border; white-space: nowrap; position: relative; - - > span { - vertical-align: middle; - } } .param-info { @@ -74,7 +70,7 @@ $sub-schema-offset: ($bullet-size/2) + $bullet-margin; .param-type-trivial { margin: 10px 10px 0; - display: inline-block; + display: inline-block; } /* tree */ @@ -113,7 +109,7 @@ $sub-schema-offset: ($bullet-size/2) + $bullet-margin; content: ""; display: block; position: absolute; - left: -$lines-width; + left: -$lines-width - 1px; border-left: $line-border-erase; top: ($param-name-height/2) + $cell-padding + $lines-width; background-color: white; @@ -146,6 +142,7 @@ $array-marker-line-height: 1.5; .params-wrap.params-array:before { content: "Array ["; + padding-top: 1em; } .params-wrap.params-array { @@ -168,3 +165,37 @@ $array-marker-line-height: 1.5; border-left: $line-border-erase; height: ($param-name-height/2) + $cell-padding; } + +.param.discriminator { + > div { + padding-bottom: 0; + border-bottom: 0; + } +} + +.discriminator-info { + font-weight: bold; +} + +:host tabs { + display: block; + border-left: 1px solid $tree-lines-color; +} + +:host tabs li { + margin: 0.2em 0.5em 0.2em 0; + font-size: 14px; + border: 0; + color: white; + padding: 0 15px; + border-radius: 10px; + background-color: #8A9094; + + &:last-of-type { + margin: 0; + } + + &.active { + background-color: $headers-color; + } +} diff --git a/lib/components/Method/method.js b/lib/components/Method/method.js index a42cafc5..05674deb 100644 --- a/lib/components/Method/method.js +++ b/lib/components/Method/method.js @@ -31,6 +31,7 @@ export default class Method extends BaseComponent { filterMainTags(tags) { var tagsMap = this.schemaMgr.getTagsMap(); + if (!tags) return []; return tags.filter(tag => tagsMap[tag] && tagsMap[tag]['x-traitTag']); } diff --git a/lib/components/Redoc/redoc.js b/lib/components/Redoc/redoc.js index 3c7dc32f..cf50f815 100644 --- a/lib/components/Redoc/redoc.js +++ b/lib/components/Redoc/redoc.js @@ -82,29 +82,44 @@ export default class Redoc extends BaseComponent { } static init(schemaUrl, options) { - var promise = new Promise(function(resolve, reject) { + if (Redoc.appRef) { + Redoc.dispose(); + } + return SchemaManager.instance().load(schemaUrl) + .then(() => { + (new OptionsManager()).options = options; + return bootstrap(Redoc); + }) + .then( + (appRef) => { + Redoc.appRef = appRef; + redocEvents.bootstrapped.next(); + console.log('ReDoc bootstrapped!'); + }, + error => { + console.log(error); + throw error; + } + ); + } - SchemaManager.instance().load(schemaUrl) - .then(() => { - (new OptionsManager()).options = options; - return bootstrap(Redoc); - }) - .then( - () => { - redocEvents.bootstrapped.next(); - console.log('ReDoc bootstrapped!'); - resolve(); - }, - error => { - console.log(error); - reject(); - } - ); - }); - return promise; + static dispose() { + let dom = new BrowserDomAdapter(); + let el = dom.query('redoc'); + let parent = el.parentElement; + let nextSibling = el.nextElementSibling; + + Redoc.appRef && Redoc.appRef.dispose(); + Redoc.appRef = null; + + // Redoc dispose removes host element, so need to restore it + el = dom.createElement('redoc'); + el.innerText = 'Loading...'; + parent.insertBefore(el, nextSibling); } } Redoc.parameters = Redoc.parameters.concat([[OptionsManager], [ElementRef], [BrowserDomAdapter]]); +// TODO // this doesn't work in side-menu.js because of some circular references issue SideMenu.parameters = SideMenu.parameters.concat([[Redoc]]); diff --git a/lib/components/Redoc/redoc.scss b/lib/components/Redoc/redoc.scss index 96a60806..b62d179b 100644 --- a/lib/components/Redoc/redoc.scss +++ b/lib/components/Redoc/redoc.scss @@ -1,5 +1,28 @@ @import '../../common/styles/variables'; +:host { + display: block; + box-sizing: border-box; +} + +:host { + pre { + white-space: pre-wrap; + background-color: #f2f2f2; + padding: 10px; + overflow-x: auto; + line-height: normal; + } + + code { + background-color: #f2f2f2; + } + + p { + margin: 0; + } +} + .redoc-wrap { position: relative; } diff --git a/lib/components/ResponsesSamples/responses-samples.scss b/lib/components/ResponsesSamples/responses-samples.scss index c6139acb..a8b3481f 100644 --- a/lib/components/ResponsesSamples/responses-samples.scss +++ b/lib/components/ResponsesSamples/responses-samples.scss @@ -14,3 +14,21 @@ header { color: $sample-panel-headers-color; text-transform: uppercase; } + +:host tabs li { + font-size: 13px; + margin: 2px 0; + padding: 2px 5px; + color: #8A9094; + line-height: 1.25; + color: $sample-panel-headers-color; + + &.active { + background-color: white; + color: #666; + } +} + +:host tabs ul { + padding-top: 10px; +} diff --git a/lib/components/SideMenu/side-menu.js b/lib/components/SideMenu/side-menu.js index 740f4d8d..3280e6ee 100644 --- a/lib/components/SideMenu/side-menu.js +++ b/lib/components/SideMenu/side-menu.js @@ -48,7 +48,7 @@ export default class SideMenu extends BaseComponent { } scrollY() { - return (this.scrollParent.scrollY != null) ? this.scrollParent.scrollY : this.scrollParent.scrollTop; + return (this.scrollParent.pageYOffset != null) ? this.scrollParent.pageYOffset : this.scrollParent.scrollTop; } hashScroll(evt) { diff --git a/lib/components/base.js b/lib/components/base.js index e6e3ef81..46070370 100644 --- a/lib/components/base.js +++ b/lib/components/base.js @@ -15,6 +15,22 @@ function safeConcat(a, b) { return res.concat(b); } +function snapshot(obj) { + if(obj == null || typeof(obj) != 'object') { + return obj; + } + + var temp = new obj.constructor(); + + for(var key in obj) { + if (obj.hasOwnProperty(key)) { + temp[key] = snapshot(obj[key]); + } + } + + return temp; +} + /** * Class decorator * Simplifies setup of component metainfo @@ -72,7 +88,7 @@ export class BaseComponent { * onInit method is run by angular2 after all component inputs are resolved */ ngOnInit() { - this.componentSchema = this.schemaMgr.byPointer(this.pointer || ''); + this.componentSchema = snapshot(this.schemaMgr.byPointer(this.pointer || '')); this.prepareModel(); this.init(); } @@ -83,31 +99,57 @@ export class BaseComponent { /** * simple in-place schema dereferencing. Schema is already bundled so no need in global dereferencing. - * TODO: doesn't support circular references */ dereference(schema = Object.assign({}, this.componentSchema)) { - //schema = Object.assign({}, schema); - if (schema && schema.$ref) { - let resolved = this.schemaMgr.byPointer(schema.$ref); - let baseName = JsonPointer.baseName(schema.$ref); - // if resolved schema doesn't have title use name from ref - resolved = Object.assign({}, resolved); - resolved.title = resolved.title || baseName; - resolved._pointer = schema.$ref; - Object.assign(schema, resolved); - delete schema.$ref; - } + let dereferencedCache = {}; - Object.keys(schema).forEach((key) => { - let value = schema[key]; - if (value && typeof value === 'object') { - this.dereference(value); + let resolve = (schema) => { + if (schema && schema.$ref) { + let resolved = this.schemaMgr.byPointer(schema.$ref); + let baseName = JsonPointer.baseName(schema.$ref); + if (!dereferencedCache[schema.$ref]) { + // if resolved schema doesn't have title use name from ref + resolved = Object.assign({}, resolved); + resolved._pointer = schema.$ref; + } else { + // for circular referenced save only title and type + resolved = { + title: resolved.title + }; + } + + dereferencedCache[schema.$ref] = true; + + resolved.title = resolved.title || baseName; + + let keysCount = Object.keys(schema).length; + if ( keysCount > 2 || (keysCount === 2 && !schema.description) ) { + // allow only description field on the same level as $ref because it is + // common pattern over specs in the wild + console.warn(`other properties defined at the same level as $ref at '${this.pointer}'. + They are IGNORRED according to JsonSchema spec`); + } + + schema = schema.description ? { + description: schema.description + } : {}; + //for (var prop in schema) delete schema[prop]; + Object.assign(schema, resolved); } - }); - this.componentSchema = schema; + + Object.keys(schema).forEach((key) => { + let value = schema[key]; + if (value && typeof value === 'object') { + schema[key] = resolve(value); + } + }); + return schema; + }; + + this.componentSchema = resolve(schema); } - joinAllOf(schema = this.componentSchema) { + joinAllOf(schema = this.componentSchema, opts) { var self = this; function merge(into, schemas) { if (into.required || into.properties) { @@ -118,6 +160,7 @@ export class BaseComponent { into.required = []; into.properties = {}; for (let subSchema of schemas) { + if (opts && opts.omitParent && subSchema.discriminator) continue; // TODO: add support for merge array schemas if (typeof subSchema !== 'object' || subSchema.type !== 'object') { diff --git a/lib/components/base.spec.js b/lib/components/base.spec.js index b1dc17f3..800ad5e7 100644 --- a/lib/components/base.spec.js +++ b/lib/components/base.spec.js @@ -26,7 +26,7 @@ describe('Redoc components', () => { it('should set componentSchema based on pointer on ngOnInit', () => { component.pointer = '/tags'; component.ngOnInit(); - component.componentSchema.should.be.equal(schemaMgr._schema.tags); + component.componentSchema.should.be.deepEqual(schemaMgr._schema.tags); }); it('should call prepareModel and init virtual methods after init', () => { @@ -111,6 +111,47 @@ describe('Redoc components', () => { paramWithRef.items.schema.type.should.be.equal('object'); }); }); + + describe('circular dereference', () => { + let paramWithRef; + beforeAll(() => { + component.pointer = '/paths/test4/get'; + component.ngOnInit(); + component.dereference(); + paramWithRef = component.componentSchema.parameters[0]; + }); + + it('should resolve circular schema', () => { + expect(paramWithRef.$ref).toBeUndefined(); + expect(paramWithRef.items.schema.$ref).toBeUndefined(); + paramWithRef.type.should.be.equal('array'); + paramWithRef._pointer.should.be.equal('#/definitions/Circular'); + expect(paramWithRef.items.schema._pointer).toBeUndefined(); + paramWithRef.items.schema.title.should.be.equal('Circular'); + }); + }); + + describe('$ref with other fields on the same level', () => { + let paramWithRef; + beforeAll(() => { + component.pointer = '/paths/test5/get'; + component.ngOnInit(); + component.dereference(); + paramWithRef = component.componentSchema.parameters[0]; + }); + + it('should skip other fields', () => { + expect(paramWithRef.$ref).toBeUndefined(); + expect(paramWithRef.title).toBeDefined(); + paramWithRef.title.should.be.equal('Simple'); + }); + + it('should preserve description field', () => { + expect(paramWithRef.$ref).toBeUndefined(); + expect(paramWithRef.description).toBeDefined(); + paramWithRef.description.should.be.equal('test'); + }); + }); }); describe('mergeAllOf', () => { diff --git a/lib/index.js b/lib/index.js index d2af96ce..5e8735fa 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,7 +1,9 @@ 'use strict'; import {Redoc} from './components/index'; +import {enableProdMode} from 'angular2/core'; export var init = Redoc.init; window.Redoc = Redoc; +enableProdMode(); diff --git a/lib/utils/SchemaManager.js b/lib/utils/SchemaManager.js index 856a43d7..254fd88d 100644 --- a/lib/utils/SchemaManager.js +++ b/lib/utils/SchemaManager.js @@ -52,7 +52,8 @@ export default class SchemaManager { byPointer(pointer) { let res = null; try { - res = JsonPointer.get(this._schema, pointer); + // TODO: remove decodeURIComponent after this issue is fixed: https://github.com/BigstickCarpet/swagger-parser/issues/31 + res = JsonPointer.get(this._schema, decodeURIComponent(pointer)); } catch(e) {/*skip*/ } return res; } @@ -156,4 +157,26 @@ export default class SchemaManager { return tag2MethodMapping; } + findDerivedDefinitions(defPointer) { + let definition = this.byPointer(defPointer); + if (!definition) throw new Error(`Can't load schema at ${defPointer}`); + if (!definition.discriminator) return []; + + let globalDefs = this._schema.definitions || {}; + let res = []; + for (let defName of Object.keys(globalDefs)) { + if (!globalDefs[defName].allOf) continue; + + let subTypes = globalDefs[defName].allOf; + let idx = subTypes.findIndex((subType) => { + if (subType.$ref === defPointer) return true; + return false; + }); + if (idx < 0) continue; + + res.push({name: defName, $ref: `#/definitions/${defName}`}); + } + return res; + } + } diff --git a/package.json b/package.json index e439e4e0..ce96a48a 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,21 @@ { - "name": "ReDoc", + "name": "redoc", "description": "Swagger-generated API Reference Documentation", - "version": "0.0.1", - "private": true, + "version": "0.1.0", "repository": { "type": "git", "url": "git://github.com/Rebilly/ReDoc" }, + "main": "dist/redoc.full.min.js", "scripts": { - "test": "gulp lint && gulp test", + "test": "gulp lint && ./build/run_tests.sh", + "prepublish": "gulp build", "postinstall": "jspm install", "start": "gulp serve", "build-dist": "gulp build", - "branch-release": "branch-release" + "branch-release": "git reset --hard && branch-release", + "unit": "gulp test", + "e2e": "gulp e2e" }, "keywords": [ "Swagger", @@ -26,16 +29,15 @@ "jspm": { "configFile": "system.config.js", "dependencies": { - "RomanGotsiy/json-schema-ref-parser": "github:RomanGotsiy/json-schema-ref-parser@master", "angular2": "npm:angular2@^2.0.0-beta.0", "es6-shim": "github:es-shims/es6-shim@^0.33.6", "json-formatter-js": "npm:json-formatter-js@^0.2.0", "json-pointer": "npm:json-pointer@^0.3.0", "json-schema-instantiator": "npm:json-schema-instantiator@^0.3.0", - "json-schema-view-js": "npm:json-schema-view-js@^0.2.0", + "json-schema-ref-parser": "npm:json-schema-ref-parser@2.2.0", "marked": "npm:marked@^0.3.5", "scrollparent": "npm:scrollparent@^0.1.0", - "swagger-parser": "npm:swagger-parser@^3.3.0" + "swagger-parser": "npm:swagger-parser@^3.4.0" }, "devDependencies": { "babel": "npm:babel-core@^5.8.34", @@ -44,31 +46,27 @@ "core-js": "npm:core-js@^1.2.6", "css": "github:systemjs/plugin-css@^0.1.18", "systemjs/plugin-json": "github:systemjs/plugin-json@^0.1.0" - }, - "overrides": { - "github:RomanGotsiy/json-schema-ref-parser@master": { - "registry": "npm" - } } }, "devDependencies": { "babel-eslint": "^4.1.6", "babel-polyfill": "^6.3.14", - "branch-release": "^0.2.1", + "branch-release": "^0.3.1", "browser-sync": "^2.10.1", "del": "^2.2.0", "gulp": "^3.9.0", "gulp-concat": "^2.6.0", "gulp-eslint": "^1.1.1", "gulp-inline-ng2-template": "^0.0.9", + "gulp-protractor": "^2.1.0", "gulp-rename": "^1.2.2", "gulp-replace": "^0.5.4", "gulp-sass": "^2.1.1", "gulp-sourcemaps": "^1.6.0", - "gulp-uglify": "^1.5.1", "isparta": "^4.0.0", "istanbul": "github:gotwarlost/istanbul#source-map", "jasmine-core": "^2.4.1", + "jasmine-spec-reporter": "^2.4.0", "jspm": "^0.16.19", "karma": "^0.13.15", "karma-babel-preprocessor": "^5.2.2", @@ -84,12 +82,13 @@ "karma-should": "^1.0.0", "karma-sinon": "^1.0.4", "phantomjs": "^1.9.19", + "protractor": "^3.0.0", "reflect-metadata": "^0.1.2", "require-dir": "^0.3.0", "run-sequence": "^1.1.5", "should": "^8.0.2", "sinon": "^1.17.2", - "systemjs-builder": "^0.14.15", + "systemjs-builder": "^0.15.2", "vinyl-paths": "^2.0.0", "zone.js": "^0.5.10" } diff --git a/protractor.conf.js b/protractor.conf.js new file mode 100644 index 00000000..f50b1ec2 --- /dev/null +++ b/protractor.conf.js @@ -0,0 +1,69 @@ +'use strict'; +const loadJson = require('./tests/e2e/helpers').loadJson; +const travis = process.env.TRAVIS; + +let config = { + specs: ['./tests/e2e/**/*.js'], + baseUrl: 'http://localhost:3000', + framework: 'jasmine2', + onPrepare: function() { + var SpecReporter = require('jasmine-spec-reporter'); + // add jasmine spec reporter + jasmine.getEnv().addReporter(new SpecReporter({displaySpecDuration: true})); + // load APIs.guru list + return loadJson('https://apis-guru.github.io/api-models/api/v1/list.json').then((list) => { + global.apisGuruList = list; + return browser.getCapabilities().then(function (cap) { + browser.isIE = cap.caps_.browserName === 'internet explorer'; + }); + }); + }, + //directConnect: true, + useAllAngular2AppRoots: true, + allScriptsTimeout: 180000, + jasmineNodeOpts: { + showTiming: true, + showColors: true, + defaultTimeoutInterval: 180000, + print: function() {} + }, + multiCapabilities: [ + { browserName: 'chrome' }, + { browserName: 'firefox' } + ] +}; + +if (travis) { + config.sauceUser = process.env.SAUCE_USERNAME; + config.sauceKey = process.env.SAUCE_ACCESS_KEY; + config.sauceSeleniumAddres = 'localhost:4445/wd/hub'; + config.multiCapabilities = [{ + browserName: 'chrome', + 'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER, + build: process.env.TRAVIS_BUILD_NUMBER, + name: 'Redoc Chrome/Linux build ' + process.env.TRAVIS_BUILD_NUMBER + },{ + browserName: 'safari', + platform: 'OS X 10.11', + version: '9.0', + 'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER, + build: process.env.TRAVIS_BUILD_NUMBER, + name: 'Redoc Safari Latest/OSX build ' + process.env.TRAVIS_BUILD_NUMBER, + idleTimeout: 180 + },{ + browserName: 'firefox', + 'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER, + build: process.env.TRAVIS_BUILD_NUMBER, + name: 'Redoc Firefox Latest/Win build ' + process.env.TRAVIS_BUILD_NUMBER + },{ + browserName: 'internet explorer', + version: '11.0', + 'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER, + build: process.env.TRAVIS_BUILD_NUMBER, + name: 'Redoc IE11/Win build ' + process.env.TRAVIS_BUILD_NUMBER + }]; +} else { + config.directConnect = true; +} + +exports.config = config; diff --git a/system.config.js b/system.config.js index f4d0544e..c2663cd8 100644 --- a/system.config.js +++ b/system.config.js @@ -16,7 +16,7 @@ System.config({ }, packages: { - "npm:swagger-schema-official@2.0.0-d79c205": { + "npm:swagger-schema-official@2.0.0-bab6bed": { "defaultExtension": "json", "main": "schema.json", "meta": { @@ -37,7 +37,6 @@ System.config({ }, map: { - "RomanGotsiy/json-schema-ref-parser": "github:RomanGotsiy/json-schema-ref-parser@master", "angular2": "npm:angular2@2.0.0-beta.0", "babel": "npm:babel-core@5.8.34", "babel-runtime": "npm:babel-runtime@5.8.34", @@ -49,40 +48,16 @@ System.config({ "json-formatter-js": "npm:json-formatter-js@0.2.0", "json-pointer": "npm:json-pointer@0.3.0", "json-schema-instantiator": "npm:json-schema-instantiator@0.3.0", - "json-schema-view-js": "npm:json-schema-view-js@0.2.0", + "json-schema-ref-parser": "npm:json-schema-ref-parser@2.2.0", "marked": "npm:marked@0.3.5", "scrollparent": "npm:scrollparent@0.1.0", - "swagger-parser": "npm:swagger-parser@3.3.0", + "swagger-parser": "npm:swagger-parser@3.4.0", "systemjs/plugin-json": "github:systemjs/plugin-json@0.1.0", - "github:RomanGotsiy/json-schema-ref-parser@master": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "call-me-maybe": "npm:call-me-maybe@1.0.1", - "child_process": "github:jspm/nodelibs-child_process@0.1.0", - "debug": "npm:debug@2.2.0", - "es6-promise": "npm:es6-promise@3.0.2", - "events": "github:jspm/nodelibs-events@0.1.1", - "fs": "github:jspm/nodelibs-fs@0.1.2", - "http": "github:jspm/nodelibs-http@1.7.1", - "https": "github:jspm/nodelibs-https@0.1.0", - "js-yaml": "npm:js-yaml@3.4.3", - "ono": "npm:ono@1.0.22", - "os": "github:jspm/nodelibs-os@0.1.0", - "path": "github:jspm/nodelibs-path@0.1.0", - "process": "github:jspm/nodelibs-process@0.1.2", - "punycode": "github:jspm/nodelibs-punycode@0.1.0", - "querystring": "github:jspm/nodelibs-querystring@0.1.0", - "stream": "github:jspm/nodelibs-stream@0.1.0", - "string_decoder": "github:jspm/nodelibs-string_decoder@0.1.0", - "systemjs-json": "github:systemjs/plugin-json@0.1.0", - "tty": "github:jspm/nodelibs-tty@0.1.0", - "url": "github:jspm/nodelibs-url@0.1.0", - "util": "github:jspm/nodelibs-util@0.1.0" - }, "github:jspm/nodelibs-assert@0.1.0": { "assert": "npm:assert@1.3.0" }, "github:jspm/nodelibs-buffer@0.1.0": { - "buffer": "npm:buffer@3.5.5" + "buffer": "npm:buffer@3.6.0" }, "github:jspm/nodelibs-constants@0.1.0": { "constants-browserify": "npm:constants-browserify@0.0.1" @@ -177,15 +152,15 @@ System.config({ "sprintf-js": "npm:sprintf-js@1.0.3", "util": "github:jspm/nodelibs-util@0.1.0" }, - "npm:asn1.js@4.2.1": { + "npm:asn1.js@4.3.0": { "assert": "github:jspm/nodelibs-assert@0.1.0", - "bn.js": "npm:bn.js@4.5.2", + "bn.js": "npm:bn.js@4.6.4", "buffer": "github:jspm/nodelibs-buffer@0.1.0", "inherits": "npm:inherits@2.0.1", "minimalistic-assert": "npm:minimalistic-assert@1.0.0", "vm": "github:jspm/nodelibs-vm@0.1.0" }, - "npm:asn1@0.1.11": { + "npm:asn1@0.2.3": { "assert": "github:jspm/nodelibs-assert@0.1.0", "buffer": "github:jspm/nodelibs-buffer@0.1.0", "sys": "github:jspm/nodelibs-util@0.1.0", @@ -198,13 +173,20 @@ System.config({ "stream": "github:jspm/nodelibs-stream@0.1.0", "util": "github:jspm/nodelibs-util@0.1.0" }, + "npm:assert-plus@0.2.0": { + "assert": "github:jspm/nodelibs-assert@0.1.0", + "buffer": "github:jspm/nodelibs-buffer@0.1.0", + "process": "github:jspm/nodelibs-process@0.1.2", + "stream": "github:jspm/nodelibs-stream@0.1.0", + "util": "github:jspm/nodelibs-util@0.1.0" + }, "npm:assert@1.3.0": { "util": "npm:util@0.10.3" }, - "npm:async@1.4.2": { + "npm:async@1.5.2": { "process": "github:jspm/nodelibs-process@0.1.2" }, - "npm:aws-sign2@0.5.0": { + "npm:aws-sign2@0.6.0": { "crypto": "github:jspm/nodelibs-crypto@0.1.0", "url": "github:jspm/nodelibs-url@0.1.0" }, @@ -213,13 +195,10 @@ System.config({ }, "npm:bl@1.0.0": { "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "readable-stream": "npm:readable-stream@2.0.2", + "readable-stream": "npm:readable-stream@2.0.5", "util": "github:jspm/nodelibs-util@0.1.0" }, - "npm:bluebird@2.10.2": { - "process": "github:jspm/nodelibs-process@0.1.2" - }, - "npm:boom@2.9.0": { + "npm:boom@2.10.1": { "hoek": "npm:hoek@2.16.3", "http": "github:jspm/nodelibs-http@1.7.1" }, @@ -249,14 +228,14 @@ System.config({ "inherits": "npm:inherits@2.0.1" }, "npm:browserify-rsa@4.0.0": { - "bn.js": "npm:bn.js@4.5.2", + "bn.js": "npm:bn.js@4.6.4", "buffer": "github:jspm/nodelibs-buffer@0.1.0", "constants": "github:jspm/nodelibs-constants@0.1.0", "crypto": "github:jspm/nodelibs-crypto@0.1.0", - "randombytes": "npm:randombytes@2.0.1" + "randombytes": "npm:randombytes@2.0.2" }, "npm:browserify-sign@4.0.0": { - "bn.js": "npm:bn.js@4.5.2", + "bn.js": "npm:bn.js@4.6.4", "browserify-rsa": "npm:browserify-rsa@4.0.0", "buffer": "github:jspm/nodelibs-buffer@0.1.0", "create-hash": "npm:create-hash@1.1.2", @@ -272,14 +251,14 @@ System.config({ "buffer": "github:jspm/nodelibs-buffer@0.1.0", "pako": "npm:pako@0.2.8", "process": "github:jspm/nodelibs-process@0.1.2", - "readable-stream": "npm:readable-stream@1.1.13", + "readable-stream": "npm:readable-stream@2.0.5", "util": "github:jspm/nodelibs-util@0.1.0" }, "npm:buffer-xor@1.0.3": { "buffer": "github:jspm/nodelibs-buffer@0.1.0", "systemjs-json": "github:systemjs/plugin-json@0.1.0" }, - "npm:buffer@3.5.5": { + "npm:buffer@3.6.0": { "base64-js": "npm:base64-js@0.0.8", "child_process": "github:jspm/nodelibs-child_process@0.1.0", "fs": "github:jspm/nodelibs-fs@0.1.2", @@ -292,7 +271,7 @@ System.config({ }, "npm:chalk@1.1.1": { "ansi-styles": "npm:ansi-styles@2.1.0", - "escape-string-regexp": "npm:escape-string-regexp@1.0.3", + "escape-string-regexp": "npm:escape-string-regexp@1.0.4", "has-ansi": "npm:has-ansi@2.0.0", "process": "github:jspm/nodelibs-process@0.1.2", "strip-ansi": "npm:strip-ansi@3.0.0", @@ -331,6 +310,14 @@ System.config({ "path": "github:jspm/nodelibs-path@0.1.0", "process": "github:jspm/nodelibs-process@0.1.2" }, + "npm:commander@2.9.0": { + "child_process": "github:jspm/nodelibs-child_process@0.1.0", + "events": "github:jspm/nodelibs-events@0.1.1", + "fs": "github:jspm/nodelibs-fs@0.1.2", + "graceful-readlink": "npm:graceful-readlink@1.0.1", + "path": "github:jspm/nodelibs-path@0.1.0", + "process": "github:jspm/nodelibs-process@0.1.2" + }, "npm:constants-browserify@0.0.1": { "systemjs-json": "github:systemjs/plugin-json@0.1.0" }, @@ -340,14 +327,11 @@ System.config({ "process": "github:jspm/nodelibs-process@0.1.2", "systemjs-json": "github:systemjs/plugin-json@0.1.0" }, - "npm:core-util-is@1.0.1": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0" - }, "npm:core-util-is@1.0.2": { "buffer": "github:jspm/nodelibs-buffer@0.1.0" }, "npm:create-ecdh@4.0.0": { - "bn.js": "npm:bn.js@4.5.2", + "bn.js": "npm:bn.js@4.6.4", "buffer": "github:jspm/nodelibs-buffer@0.1.0", "crypto": "github:jspm/nodelibs-crypto@0.1.0", "elliptic": "npm:elliptic@6.0.2" @@ -369,7 +353,7 @@ System.config({ "stream": "github:jspm/nodelibs-stream@0.1.0" }, "npm:cryptiles@2.0.5": { - "boom": "npm:boom@2.9.0", + "boom": "npm:boom@2.10.1", "crypto": "github:jspm/nodelibs-crypto@0.1.0" }, "npm:crypto-browserify@3.11.0": { @@ -378,16 +362,18 @@ System.config({ "create-ecdh": "npm:create-ecdh@4.0.0", "create-hash": "npm:create-hash@1.1.2", "create-hmac": "npm:create-hmac@1.1.4", - "diffie-hellman": "npm:diffie-hellman@5.0.0", + "diffie-hellman": "npm:diffie-hellman@5.0.1", "inherits": "npm:inherits@2.0.1", "pbkdf2": "npm:pbkdf2@3.0.4", "public-encrypt": "npm:public-encrypt@4.0.0", - "randombytes": "npm:randombytes@2.0.1" + "randombytes": "npm:randombytes@2.0.2" }, - "npm:ctype@0.5.3": { - "assert": "github:jspm/nodelibs-assert@0.1.0", - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "process": "github:jspm/nodelibs-process@0.1.2" + "npm:dashdash@1.12.1": { + "assert-plus": "npm:assert-plus@0.1.5", + "fs": "github:jspm/nodelibs-fs@0.1.2", + "path": "github:jspm/nodelibs-path@0.1.0", + "process": "github:jspm/nodelibs-process@0.1.2", + "util": "github:jspm/nodelibs-util@0.1.0" }, "npm:debug@2.2.0": { "fs": "github:jspm/nodelibs-fs@0.1.2", @@ -406,16 +392,21 @@ System.config({ "inherits": "npm:inherits@2.0.1", "minimalistic-assert": "npm:minimalistic-assert@1.0.0" }, - "npm:diffie-hellman@5.0.0": { - "bn.js": "npm:bn.js@4.5.2", + "npm:diffie-hellman@5.0.1": { + "bn.js": "npm:bn.js@4.6.4", "buffer": "github:jspm/nodelibs-buffer@0.1.0", "crypto": "github:jspm/nodelibs-crypto@0.1.0", "miller-rabin": "npm:miller-rabin@4.0.0", - "randombytes": "npm:randombytes@2.0.1", + "randombytes": "npm:randombytes@2.0.2", "systemjs-json": "github:systemjs/plugin-json@0.1.0" }, + "npm:ecc-jsbn@0.1.1": { + "buffer": "github:jspm/nodelibs-buffer@0.1.0", + "crypto": "github:jspm/nodelibs-crypto@0.1.0", + "jsbn": "npm:jsbn@0.1.0" + }, "npm:elliptic@6.0.2": { - "bn.js": "npm:bn.js@4.5.2", + "bn.js": "npm:bn.js@4.6.4", "brorand": "npm:brorand@1.0.5", "hash.js": "npm:hash.js@1.0.3", "inherits": "npm:inherits@2.0.1", @@ -427,7 +418,7 @@ System.config({ "npm:es6-shim@0.33.13": { "process": "github:jspm/nodelibs-process@0.1.2" }, - "npm:esprima@2.7.0": { + "npm:esprima@2.7.1": { "fs": "github:jspm/nodelibs-fs@0.1.2", "process": "github:jspm/nodelibs-process@0.1.2" }, @@ -436,6 +427,10 @@ System.config({ "create-hash": "npm:create-hash@1.1.2", "crypto": "github:jspm/nodelibs-crypto@0.1.0" }, + "npm:extsprintf@1.0.2": { + "assert": "github:jspm/nodelibs-assert@0.1.0", + "util": "github:jspm/nodelibs-util@0.1.0" + }, "npm:forever-agent@0.6.1": { "http": "github:jspm/nodelibs-http@1.7.1", "https": "github:jspm/nodelibs-https@0.1.0", @@ -444,13 +439,13 @@ System.config({ "util": "github:jspm/nodelibs-util@0.1.0" }, "npm:form-data@1.0.0-rc3": { - "async": "npm:async@1.4.2", + "async": "npm:async@1.5.2", "buffer": "github:jspm/nodelibs-buffer@0.1.0", "combined-stream": "npm:combined-stream@1.0.5", "fs": "github:jspm/nodelibs-fs@0.1.2", "http": "github:jspm/nodelibs-http@1.7.1", "https": "github:jspm/nodelibs-https@0.1.0", - "mime-types": "npm:mime-types@2.1.7", + "mime-types": "npm:mime-types@2.1.9", "path": "github:jspm/nodelibs-path@0.1.0", "process": "github:jspm/nodelibs-process@0.1.2", "url": "github:jspm/nodelibs-url@0.1.0", @@ -465,11 +460,11 @@ System.config({ "npm:graceful-readlink@1.0.1": { "fs": "github:jspm/nodelibs-fs@0.1.2" }, - "npm:har-validator@1.8.0": { - "bluebird": "npm:bluebird@2.10.2", + "npm:har-validator@2.0.5": { "chalk": "npm:chalk@1.1.1", - "commander": "npm:commander@2.8.1", - "is-my-json-valid": "npm:is-my-json-valid@2.12.2", + "commander": "npm:commander@2.9.0", + "is-my-json-valid": "npm:is-my-json-valid@2.12.3", + "pinkie-promise": "npm:pinkie-promise@2.0.0", "systemjs-json": "github:systemjs/plugin-json@0.1.0" }, "npm:has-ansi@2.0.0": { @@ -478,8 +473,8 @@ System.config({ "npm:hash.js@1.0.3": { "inherits": "npm:inherits@2.0.1" }, - "npm:hawk@3.1.0": { - "boom": "npm:boom@2.9.0", + "npm:hawk@3.1.2": { + "boom": "npm:boom@2.10.1", "cryptiles": "npm:cryptiles@2.0.5", "crypto": "github:jspm/nodelibs-crypto@0.1.0", "hoek": "npm:hoek@2.16.3", @@ -495,13 +490,13 @@ System.config({ "process": "github:jspm/nodelibs-process@0.1.2", "util": "github:jspm/nodelibs-util@0.1.0" }, - "npm:http-signature@0.11.0": { - "asn1": "npm:asn1@0.1.11", + "npm:http-signature@1.1.0": { "assert-plus": "npm:assert-plus@0.1.5", "buffer": "github:jspm/nodelibs-buffer@0.1.0", "crypto": "github:jspm/nodelibs-crypto@0.1.0", - "ctype": "npm:ctype@0.5.3", "http": "github:jspm/nodelibs-http@1.7.1", + "jsprim": "npm:jsprim@1.2.2", + "sshpk": "npm:sshpk@1.7.3", "util": "github:jspm/nodelibs-util@0.1.0" }, "npm:https-browserify@0.0.0": { @@ -510,26 +505,30 @@ System.config({ "npm:inherits@2.0.1": { "util": "github:jspm/nodelibs-util@0.1.0" }, - "npm:is-my-json-valid@2.12.2": { + "npm:is-my-json-valid@2.12.3": { "fs": "github:jspm/nodelibs-fs@0.1.2", "generate-function": "npm:generate-function@2.0.0", "generate-object-property": "npm:generate-object-property@1.2.0", "jsonpointer": "npm:jsonpointer@2.0.0", "path": "github:jspm/nodelibs-path@0.1.0", - "xtend": "npm:xtend@4.0.0" + "xtend": "npm:xtend@4.0.1" }, "npm:isstream@0.1.2": { "events": "github:jspm/nodelibs-events@0.1.1", "stream": "github:jspm/nodelibs-stream@0.1.0", "util": "github:jspm/nodelibs-util@0.1.0" }, - "npm:js-yaml@3.4.3": { + "npm:jodid25519@1.0.2": { + "buffer": "github:jspm/nodelibs-buffer@0.1.0", + "crypto": "github:jspm/nodelibs-crypto@0.1.0", + "jsbn": "npm:jsbn@0.1.0" + }, + "npm:js-yaml@3.5.2": { "argparse": "npm:argparse@1.0.3", - "esprima": "npm:esprima@2.7.0", + "esprima": "npm:esprima@2.7.1", "fs": "github:jspm/nodelibs-fs@0.1.2", "process": "github:jspm/nodelibs-process@0.1.2", - "systemjs-json": "github:systemjs/plugin-json@0.1.0", - "util": "github:jspm/nodelibs-util@0.1.0" + "systemjs-json": "github:systemjs/plugin-json@0.1.0" }, "npm:json-formatter-js@0.2.0": { "fs": "github:jspm/nodelibs-fs@0.1.2", @@ -539,14 +538,55 @@ System.config({ "npm:json-pointer@0.3.0": { "foreach": "npm:foreach@2.0.5" }, - "npm:json-schema-view-js@0.2.0": { + "npm:json-schema-ref-parser@1.4.1": { + "buffer": "github:jspm/nodelibs-buffer@0.1.0", + "call-me-maybe": "npm:call-me-maybe@1.0.1", + "debug": "npm:debug@2.2.0", + "es6-promise": "npm:es6-promise@3.0.2", + "events": "github:jspm/nodelibs-events@0.1.1", "fs": "github:jspm/nodelibs-fs@0.1.2", + "http": "github:jspm/nodelibs-http@1.7.1", + "https": "github:jspm/nodelibs-https@0.1.0", + "js-yaml": "npm:js-yaml@3.5.2", + "ono": "npm:ono@2.0.1", "process": "github:jspm/nodelibs-process@0.1.2", - "systemjs-json": "github:systemjs/plugin-json@0.1.0" + "punycode": "github:jspm/nodelibs-punycode@0.1.0", + "querystring": "github:jspm/nodelibs-querystring@0.1.0", + "stream": "github:jspm/nodelibs-stream@0.1.0", + "string_decoder": "github:jspm/nodelibs-string_decoder@0.1.0", + "url": "github:jspm/nodelibs-url@0.1.0", + "util": "github:jspm/nodelibs-util@0.1.0" + }, + "npm:json-schema-ref-parser@2.2.0": { + "buffer": "github:jspm/nodelibs-buffer@0.1.0", + "call-me-maybe": "npm:call-me-maybe@1.0.1", + "debug": "npm:debug@2.2.0", + "es6-promise": "npm:es6-promise@3.0.2", + "events": "github:jspm/nodelibs-events@0.1.1", + "fs": "github:jspm/nodelibs-fs@0.1.2", + "http": "github:jspm/nodelibs-http@1.7.1", + "https": "github:jspm/nodelibs-https@0.1.0", + "js-yaml": "npm:js-yaml@3.5.2", + "ono": "npm:ono@2.0.1", + "process": "github:jspm/nodelibs-process@0.1.2", + "punycode": "github:jspm/nodelibs-punycode@0.1.0", + "querystring": "github:jspm/nodelibs-querystring@0.1.0", + "stream": "github:jspm/nodelibs-stream@0.1.0", + "string_decoder": "github:jspm/nodelibs-string_decoder@0.1.0", + "url": "github:jspm/nodelibs-url@0.1.0", + "util": "github:jspm/nodelibs-util@0.1.0" }, "npm:jsonpointer@2.0.0": { "assert": "github:jspm/nodelibs-assert@0.1.0" }, + "npm:jsprim@1.2.2": { + "assert": "github:jspm/nodelibs-assert@0.1.0", + "extsprintf": "npm:extsprintf@1.0.2", + "json-schema": "npm:json-schema@0.2.2", + "process": "github:jspm/nodelibs-process@0.1.2", + "util": "github:jspm/nodelibs-util@0.1.0", + "verror": "npm:verror@1.3.6" + }, "npm:lodash._baseget@3.7.2": { "process": "github:jspm/nodelibs-process@0.1.2" }, @@ -562,18 +602,19 @@ System.config({ "process": "github:jspm/nodelibs-process@0.1.2" }, "npm:miller-rabin@4.0.0": { - "bn.js": "npm:bn.js@4.5.2", + "bn.js": "npm:bn.js@4.6.4", "brorand": "npm:brorand@1.0.5" }, - "npm:mime-db@1.19.0": { + "npm:mime-db@1.21.0": { "systemjs-json": "github:systemjs/plugin-json@0.1.0" }, - "npm:mime-types@2.1.7": { - "mime-db": "npm:mime-db@1.19.0", + "npm:mime-types@2.1.9": { + "mime-db": "npm:mime-db@1.21.0", "path": "github:jspm/nodelibs-path@0.1.0" }, - "npm:node-uuid@1.4.3": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0" + "npm:node-uuid@1.4.7": { + "buffer": "github:jspm/nodelibs-buffer@0.1.0", + "crypto": "github:jspm/nodelibs-crypto@0.1.0" }, "npm:oauth-sign@0.8.0": { "assert": "github:jspm/nodelibs-assert@0.1.0", @@ -581,7 +622,7 @@ System.config({ "process": "github:jspm/nodelibs-process@0.1.2", "querystring": "github:jspm/nodelibs-querystring@0.1.0" }, - "npm:ono@1.0.22": { + "npm:ono@2.0.1": { "process": "github:jspm/nodelibs-process@0.1.2", "util": "github:jspm/nodelibs-util@0.1.0" }, @@ -593,7 +634,7 @@ System.config({ "process": "github:jspm/nodelibs-process@0.1.2" }, "npm:parse-asn1@5.0.0": { - "asn1.js": "npm:asn1.js@4.2.1", + "asn1.js": "npm:asn1.js@4.3.0", "browserify-aes": "npm:browserify-aes@1.0.5", "buffer": "github:jspm/nodelibs-buffer@0.1.0", "create-hash": "npm:create-hash@1.1.2", @@ -613,25 +654,31 @@ System.config({ "process": "github:jspm/nodelibs-process@0.1.2", "systemjs-json": "github:systemjs/plugin-json@0.1.0" }, - "npm:process-nextick-args@1.0.3": { + "npm:pinkie-promise@2.0.0": { + "pinkie": "npm:pinkie@2.0.1" + }, + "npm:pinkie@2.0.1": { + "process": "github:jspm/nodelibs-process@0.1.2" + }, + "npm:process-nextick-args@1.0.6": { "process": "github:jspm/nodelibs-process@0.1.2" }, "npm:process@0.11.2": { "assert": "github:jspm/nodelibs-assert@0.1.0" }, "npm:public-encrypt@4.0.0": { - "bn.js": "npm:bn.js@4.5.2", + "bn.js": "npm:bn.js@4.6.4", "browserify-rsa": "npm:browserify-rsa@4.0.0", "buffer": "github:jspm/nodelibs-buffer@0.1.0", "create-hash": "npm:create-hash@1.1.2", "crypto": "github:jspm/nodelibs-crypto@0.1.0", "parse-asn1": "npm:parse-asn1@5.0.0", - "randombytes": "npm:randombytes@2.0.1" + "randombytes": "npm:randombytes@2.0.2" }, "npm:punycode@1.3.2": { "process": "github:jspm/nodelibs-process@0.1.2" }, - "npm:randombytes@2.0.1": { + "npm:randombytes@2.0.2": { "buffer": "github:jspm/nodelibs-buffer@0.1.0", "crypto": "github:jspm/nodelibs-crypto@0.1.0", "process": "github:jspm/nodelibs-process@0.1.2" @@ -646,23 +693,23 @@ System.config({ "stream-browserify": "npm:stream-browserify@1.0.0", "string_decoder": "npm:string_decoder@0.10.31" }, - "npm:readable-stream@2.0.2": { + "npm:readable-stream@2.0.5": { "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "core-util-is": "npm:core-util-is@1.0.1", + "core-util-is": "npm:core-util-is@1.0.2", "events": "github:jspm/nodelibs-events@0.1.1", "inherits": "npm:inherits@2.0.1", "isarray": "npm:isarray@0.0.1", "process": "github:jspm/nodelibs-process@0.1.2", - "process-nextick-args": "npm:process-nextick-args@1.0.3", + "process-nextick-args": "npm:process-nextick-args@1.0.6", "string_decoder": "npm:string_decoder@0.10.31", - "util-deprecate": "npm:util-deprecate@1.0.1" + "util-deprecate": "npm:util-deprecate@1.0.2" }, "npm:reflect-metadata@0.1.2": { "assert": "github:jspm/nodelibs-assert@0.1.0", "process": "github:jspm/nodelibs-process@0.1.2" }, - "npm:request@2.64.0": { - "aws-sign2": "npm:aws-sign2@0.5.0", + "npm:request@2.67.0": { + "aws-sign2": "npm:aws-sign2@0.6.0", "bl": "npm:bl@1.0.0", "buffer": "github:jspm/nodelibs-buffer@0.1.0", "caseless": "npm:caseless@0.11.0", @@ -672,23 +719,24 @@ System.config({ "forever-agent": "npm:forever-agent@0.6.1", "form-data": "npm:form-data@1.0.0-rc3", "fs": "github:jspm/nodelibs-fs@0.1.2", - "har-validator": "npm:har-validator@1.8.0", - "hawk": "npm:hawk@3.1.0", + "har-validator": "npm:har-validator@2.0.5", + "hawk": "npm:hawk@3.1.2", "http": "github:jspm/nodelibs-http@1.7.1", - "http-signature": "npm:http-signature@0.11.0", + "http-signature": "npm:http-signature@1.1.0", "https": "github:jspm/nodelibs-https@0.1.0", + "is-typedarray": "npm:is-typedarray@1.0.0", "isstream": "npm:isstream@0.1.2", "json-stringify-safe": "npm:json-stringify-safe@5.0.1", - "mime-types": "npm:mime-types@2.1.7", - "node-uuid": "npm:node-uuid@1.4.3", + "mime-types": "npm:mime-types@2.1.9", + "node-uuid": "npm:node-uuid@1.4.7", "oauth-sign": "npm:oauth-sign@0.8.0", "process": "github:jspm/nodelibs-process@0.1.2", - "qs": "npm:qs@5.1.0", + "qs": "npm:qs@5.2.0", "querystring": "github:jspm/nodelibs-querystring@0.1.0", "stream": "github:jspm/nodelibs-stream@0.1.0", - "stringstream": "npm:stringstream@0.0.4", - "tough-cookie": "npm:tough-cookie@2.1.0", - "tunnel-agent": "npm:tunnel-agent@0.4.1", + "stringstream": "npm:stringstream@0.0.5", + "tough-cookie": "npm:tough-cookie@2.2.1", + "tunnel-agent": "npm:tunnel-agent@0.4.2", "url": "github:jspm/nodelibs-url@0.1.0", "util": "github:jspm/nodelibs-util@0.1.0", "zlib": "github:jspm/nodelibs-zlib@0.1.0" @@ -718,6 +766,19 @@ System.config({ "amdefine": "npm:amdefine@1.0.0", "process": "github:jspm/nodelibs-process@0.1.2" }, + "npm:sshpk@1.7.3": { + "asn1": "npm:asn1@0.2.3", + "assert-plus": "npm:assert-plus@0.2.0", + "buffer": "github:jspm/nodelibs-buffer@0.1.0", + "crypto": "github:jspm/nodelibs-crypto@0.1.0", + "dashdash": "npm:dashdash@1.12.1", + "ecc-jsbn": "npm:ecc-jsbn@0.1.1", + "jodid25519": "npm:jodid25519@1.0.2", + "jsbn": "npm:jsbn@0.1.0", + "stream": "github:jspm/nodelibs-stream@0.1.0", + "tweetnacl": "npm:tweetnacl@0.13.3", + "util": "github:jspm/nodelibs-util@0.1.0" + }, "npm:stream-browserify@1.0.0": { "events": "github:jspm/nodelibs-events@0.1.1", "inherits": "npm:inherits@2.0.1", @@ -726,7 +787,7 @@ System.config({ "npm:string_decoder@0.10.31": { "buffer": "github:jspm/nodelibs-buffer@0.1.0" }, - "npm:stringstream@0.0.4": { + "npm:stringstream@0.0.5": { "buffer": "github:jspm/nodelibs-buffer@0.1.0", "fs": "github:jspm/nodelibs-fs@0.1.2", "process": "github:jspm/nodelibs-process@0.1.2", @@ -741,7 +802,7 @@ System.config({ "npm:supports-color@2.0.0": { "process": "github:jspm/nodelibs-process@0.1.2" }, - "npm:swagger-parser@3.3.0": { + "npm:swagger-parser@3.4.0": { "buffer": "github:jspm/nodelibs-buffer@0.1.0", "call-me-maybe": "npm:call-me-maybe@1.0.1", "debug": "npm:debug@2.2.0", @@ -750,31 +811,31 @@ System.config({ "fs": "github:jspm/nodelibs-fs@0.1.2", "http": "github:jspm/nodelibs-http@1.7.1", "https": "github:jspm/nodelibs-https@0.1.0", - "json-schema-ref-parser": "github:RomanGotsiy/json-schema-ref-parser@master", - "ono": "npm:ono@1.0.22", + "json-schema-ref-parser": "npm:json-schema-ref-parser@2.2.0", + "ono": "npm:ono@2.0.1", "process": "github:jspm/nodelibs-process@0.1.2", "punycode": "github:jspm/nodelibs-punycode@0.1.0", "querystring": "github:jspm/nodelibs-querystring@0.1.0", "stream": "github:jspm/nodelibs-stream@0.1.0", "string_decoder": "github:jspm/nodelibs-string_decoder@0.1.0", "swagger-methods": "npm:swagger-methods@1.0.0", - "swagger-schema-official": "npm:swagger-schema-official@2.0.0-d79c205", + "swagger-schema-official": "npm:swagger-schema-official@2.0.0-bab6bed", "systemjs-json": "github:systemjs/plugin-json@0.1.0", "url": "github:jspm/nodelibs-url@0.1.0", "util": "github:jspm/nodelibs-util@0.1.0", - "z-schema": "npm:z-schema@3.15.3" + "z-schema": "npm:z-schema@3.16.1" }, "npm:timers-browserify@1.4.2": { "process": "npm:process@0.11.2" }, - "npm:tough-cookie@2.1.0": { + "npm:tough-cookie@2.2.1": { "net": "github:jspm/nodelibs-net@0.1.2", "punycode": "github:jspm/nodelibs-punycode@0.1.0", "systemjs-json": "github:systemjs/plugin-json@0.1.0", "url": "github:jspm/nodelibs-url@0.1.0", "util": "github:jspm/nodelibs-util@0.1.0" }, - "npm:tunnel-agent@0.4.1": { + "npm:tunnel-agent@0.4.2": { "assert": "github:jspm/nodelibs-assert@0.1.0", "buffer": "github:jspm/nodelibs-buffer@0.1.0", "events": "github:jspm/nodelibs-events@0.1.1", @@ -791,27 +852,33 @@ System.config({ "querystring": "npm:querystring@0.2.0", "util": "github:jspm/nodelibs-util@0.1.0" }, - "npm:util-deprecate@1.0.1": { + "npm:util-deprecate@1.0.2": { "util": "github:jspm/nodelibs-util@0.1.0" }, "npm:util@0.10.3": { "inherits": "npm:inherits@2.0.1", "process": "github:jspm/nodelibs-process@0.1.2" }, - "npm:validator@4.1.0": { + "npm:validator@4.5.0": { "systemjs-json": "github:systemjs/plugin-json@0.1.0" }, + "npm:verror@1.3.6": { + "assert": "github:jspm/nodelibs-assert@0.1.0", + "extsprintf": "npm:extsprintf@1.0.2", + "fs": "github:jspm/nodelibs-fs@0.1.2", + "util": "github:jspm/nodelibs-util@0.1.0" + }, "npm:vm-browserify@0.0.4": { "indexof": "npm:indexof@0.0.1" }, - "npm:z-schema@3.15.3": { - "commander": "npm:commander@2.8.1", + "npm:z-schema@3.16.1": { + "commander": "npm:commander@2.9.0", "lodash.get": "npm:lodash.get@3.7.0", "process": "github:jspm/nodelibs-process@0.1.2", - "request": "npm:request@2.64.0", + "request": "npm:request@2.67.0", "systemjs-json": "github:systemjs/plugin-json@0.1.0", "util": "github:jspm/nodelibs-util@0.1.0", - "validator": "npm:validator@4.1.0" + "validator": "npm:validator@4.5.0" }, "npm:zone.js@0.5.10": { "es6-promise": "npm:es6-promise@3.0.2", diff --git a/tests/e2e/.eslintrc b/tests/e2e/.eslintrc new file mode 100644 index 00000000..59cc258f --- /dev/null +++ b/tests/e2e/.eslintrc @@ -0,0 +1,12 @@ +{ + "parser": "babel-eslint", + "extends": "eslint:recommended", + "env": { + "node": true, + "jasmine": true, + "protractor": true + }, + "rules": { + "no-console": 0, + } +} diff --git a/tests/e2e/favicon.ico b/tests/e2e/favicon.ico new file mode 100644 index 00000000..f2cfb88a Binary files /dev/null and b/tests/e2e/favicon.ico differ diff --git a/tests/e2e/helpers.js b/tests/e2e/helpers.js new file mode 100644 index 00000000..0b570074 --- /dev/null +++ b/tests/e2e/helpers.js @@ -0,0 +1,90 @@ +'use strict'; + +var https = require('https'); + +function loadJson(url) { + let promise = new Promise((resolve, reject) => { + https.get(url, function(res){ + var body = ''; + + res.on('data', function(chunk){ + body += chunk; + }); + + res.on('end', function(){ + let resp = JSON.parse(body); + resolve(resp); + }); + }).on('error', function(e){ + reject(e); + }); + }); + return promise; +} + +const LogLevel = { + INFO: 800, + WARNING: 900 +}; + +const MAX_ERROR_MESSAGE_SYMBOLS = 128; +//copied from angular/modules/angular2/src/testing/e2e_util.ts +function verifyNoBrowserErrors() { + // IE doesn't support logs method + if (browser.isIE) { + let err = browser.executeScript('return window.redocError'); + expect(err).toBeNull(); + return; + } + + // Bug in ChromeDriver: Need to execute at least one command + // so that the browser logs can be read out! + browser.executeScript('1+1'); + browser.manage().logs().get('browser').then(function(browserLog) { + let filteredLog = browserLog.filter((logEntry) => { + let message = logEntry.message; + + // skip browser-sync errors + if (message.indexOf('browser-sync') > -1) return false; + // skip firefox-specific warning + if (message.indexOf('mutating the [[Prototype]]') > -1) return false; + + if (logEntry.level.value >= LogLevel.INFO) { + if (message.length > MAX_ERROR_MESSAGE_SYMBOLS) { + message = message.substr(0, MAX_ERROR_MESSAGE_SYMBOLS) + '...'; + } + console.log('>> ' + message); + } + + return logEntry.level.value > LogLevel.WARNING; + }); + expect(filteredLog.length).toEqual(0, `Found ${filteredLog.length} browser errors`); + }); +} + +function scrollToEl(selector) { + let script = ` + document.querySelector('${selector}').scrollIntoView(true); + window.scrollBy(0, 10); + `; + + return browser.driver.executeScript(script); +} + +function fixFFTest(done) { + // firefox issue. the first try to access something from webpage fails + // but the second works fine. So skipping first error + $('body').isPresent().then(()=> { + done(); + }, () => { + //error skipped + done(); + }) +} + +module.exports = { + loadJson: loadJson, + verifyNoBrowserErrors: verifyNoBrowserErrors, + scrollToEl: scrollToEl, + fixFFTest: fixFFTest +} diff --git a/tests/e2e/index.html b/tests/e2e/index.html new file mode 100644 index 00000000..1adf5db4 --- /dev/null +++ b/tests/e2e/index.html @@ -0,0 +1,23 @@ + + + + + ReDoc + + + + Loading... + + + + + + + diff --git a/tests/e2e/redoc.spec.js b/tests/e2e/redoc.spec.js new file mode 100644 index 00000000..0f88407d --- /dev/null +++ b/tests/e2e/redoc.spec.js @@ -0,0 +1,71 @@ +'use strict'; +const verifyNoBrowserErrors = require('./helpers').verifyNoBrowserErrors; +const scrollToEl = require('./helpers').scrollToEl; +const fixFFTest = require('./helpers').fixFFTest; + +const URL = 'index.html'; + +function basicTests(swaggerUrl, title) { + describe(`Basic suite for ${title}`, () => { + let specUrl = URL; + if (swaggerUrl) { + specUrl += `?url=${encodeURIComponent(swaggerUrl)}`; + } + + beforeEach((done) => { + browser.get(specUrl); + fixFFTest(done); + }); + + afterEach(() => { + verifyNoBrowserErrors(); + }); + + it('should init redoc without errors', () => { + let $redoc = $('redoc'); + expect($redoc.isPresent()).toBe(true); + let $methods = $$('method'); + expect($methods.count()).toBeGreaterThan(0); + }); + }); +} + +basicTests(null, 'Extended Petstore'); + + +describe('Scroll sync', () => { + let specUrl = URL; + + beforeEach((done) => { + browser.get(specUrl); + fixFFTest(done); + }); + + it('should update active menu entries on page scroll', () => { + scrollToEl('[tag="store"]').then(function() { + expect($('.menu-cat-header.active').getText()).toBe('STORE'); + }); + }); +}); + +describe('APIs.guru specs test', ()=> { + + // global.apisGuruList was loaded in onPrepare method of protractor config + let apisGuruList = global.apisGuruList; + + // Remove certain APIs that are known to cause problems + delete apisGuruList['motaword.com']; // invalid (see https://github.com/BigstickCarpet/swagger-parser/issues/26) + delete apisGuruList['learnifier.com']; // allof object and no type + delete apisGuruList['googleapis.com:mirror']; // bad urls in images + delete apisGuruList['googleapis.com:discovery']; // non-string references + + for (let apiName of Object.keys(apisGuruList)) { + let apiInfo = apisGuruList[apiName].versions[apisGuruList[apiName].preferred]; + let url = apiInfo.swaggerUrl; + + // temporary hack due to this issue: https://github.com/substack/https-browserify/issues/6 + url = url.replace('https://', 'http://'); + url = url.replace('apis-guru.github.io/', 'apis-guru.github.io:80/'); + basicTests(url, `${apiName}:${apiInfo.info.version}\n${url}`); + } +}); diff --git a/tests/schemas/base-component-dereference.json b/tests/schemas/base-component-dereference.json index bd721a15..78f9a598 100644 --- a/tests/schemas/base-component-dereference.json +++ b/tests/schemas/base-component-dereference.json @@ -31,6 +31,14 @@ "$ref": "#/definitions/Simple" } } + }, + "Circular": { + "type": "array", + "items": { + "schema": { + "$ref": "#/definitions/Circular" + } + } } }, "paths": { @@ -63,6 +71,28 @@ } ] } + }, + "test4": { + "get": { + "summary": "test get", + "parameters": [ + { + "$ref": "#/definitions/Circular" + } + ] + } + }, + "test5": { + "get": { + "summary": "test get", + "parameters": [ + { + "$ref": "#/definitions/Simple", + "title": "test", + "description": "test" + } + ] + } } } } diff --git a/tests/schemas/extended-petstore.json b/tests/schemas/extended-petstore.json index 83e3a040..d734204f 100644 --- a/tests/schemas/extended-petstore.json +++ b/tests/schemas/extended-petstore.json @@ -772,8 +772,12 @@ }, "Pet": { "type": "object", - "required": ["name", "photoUrls"], + "required": ["name", "photoUrls", "petType"], + "discriminator": "petType", "properties": { + "petType": { + "type": "string" + }, "id": { "type": "integer", "format": "int64" @@ -815,6 +819,33 @@ "name": "Pet" } }, + "Cat": { + "description": "A representation of a cat", + "allOf": [ + { + "type": "object", + "properties": { + "huntingSkill": { + "type": "string", + "description": "The measured skill for hunting", + "default": "lazy", + "enum": [ + "clueless", + "lazy", + "adventurous", + "aggressive" + ] + } + }, + "required": [ + "huntingSkill" + ] + }, + { + "$ref": "#/definitions/Pet" + }, + ] + }, "ApiResponse": { "type": "object", "properties": { diff --git a/tests/unit/SchemaManager.spec.js b/tests/unit/SchemaManager.spec.js index 94a0cf97..3df2b985 100644 --- a/tests/unit/SchemaManager.spec.js +++ b/tests/unit/SchemaManager.spec.js @@ -225,5 +225,27 @@ describe('Utils', () => { }); }); + describe('findDerivedDefinitions method', () => { + beforeAll((done) => { + schemaMgr.load('/tests/schemas/extended-petstore.json').then(() => { + done(); + }, () => { + done(new Error('Error handler should not be called')); + }); + }); + + it('should find derived definitions for Pet', () => { + let deriveDefs = schemaMgr.findDerivedDefinitions('#/definitions/Pet'); + deriveDefs.should.be.instanceof(Array); + deriveDefs.should.not.be.empty; + deriveDefs.should.be.deepEqual([{name: 'Cat', $ref: '#/definitions/Cat'}]); + }); + + it('should return emtpy array for definitions that dont have discriminator', () => { + let deriveDefs = schemaMgr.findDerivedDefinitions('#/definitions/Order'); + deriveDefs.should.be.instanceof(Array); + deriveDefs.should.be.empty; + }); + }); }); });