Compare commits

..
184 Commits
Author SHA1 Message Date
kyle 91e7ade059 Merge pull request #3945 from shockey/v/3.5.0
v3.5.0
2017-11-23 11:01:28 -08:00
Kyle Shockey 88e98ce281 fix tests 2017-11-23 12:55:29 -06:00
Kyle Shockey 6bb5a95424 Rebuild dist 2017-11-23 12:52:28 -06:00
Kyle Shockey 23fd8a4d73 v3.5.0 2017-11-23 12:50:08 -06:00
Kyle Shockey 640050e54e Add spacing between done and authorize button 2017-11-23 12:35:00 -06:00
Kyle Shockey c70e0f8c38 Display object model extensions correctly 2017-11-23 12:28:37 -06:00
Kyle Shockey b42e2a7045 Render non-primitive extension values more reliably 2017-11-23 11:58:46 -06:00
kyle d3cc636dde Merge pull request #3868 from thompsongl/ft/3052-extensions
parameter & operation extensions display
2017-11-22 22:30:50 -08:00
kyle 32ff344bdd Adjust formatting of method calls 2017-11-23 00:22:48 -06:00
kyle 40f8481127 Merge branch 'master' into ft/3052-extensions 2017-11-22 22:16:21 -08:00
kyle 7b13f41be7 Merge pull request #3938 from thompsongl/bug/3936-externaldocs
bug/3936-externaldocs
2017-11-22 21:10:04 -08:00
kyle 7f237f3b23 Merge branch 'master' into bug/3936-externaldocs 2017-11-22 20:38:35 -08:00
kyle dc7706e262 Merge pull request #3929 from k42b3/master
Add flow to make scope checkbox id unqiue
2017-11-22 12:25:47 -08:00
kyle 20cf8a3b1b Merge branch 'master' into master 2017-11-22 12:22:09 -08:00
kyle 4f13d6dda6 Merge pull request #3939 from swagger-api/ft/authmodelclosebtn
Auth modal close button addded
2017-11-21 14:57:46 -08:00
kyle 1695f655bb Merge branch 'master' into ft/authmodelclosebtn 2017-11-21 14:53:38 -08:00
kyle dc29e06d66 Merge pull request #3942 from shockey/master
Include `dist/oauth2-redirect.html` in `swagger-ui` module
2017-11-21 14:53:11 -08:00
Kyle Shockey be8ce8688e Reset dist 2017-11-21 14:49:41 -08:00
Kyle Shockey ef256de050 Include dist/oauth2-redirect.html in swagger-ui module 2017-11-21 14:44:54 -08:00
kyle 01d84cdc0f Merge pull request #3941 from shockey/bug/3932-schema-not-values
Don't treat `not` as an array (in contrast to `allOf`, `anyOf`, `oneOf`)
2017-11-21 14:33:29 -08:00
kyle 9f18e02ace Merge branch 'master' into bug/3932-schema-not-values 2017-11-21 14:22:21 -08:00
Kyle Shockey 44d9234971 Don't treat not as an array (in contrast to allOf, anyOf) 2017-11-21 14:08:55 -08:00
Greg Thompson 88eda43c46 resolve #3644 while in the file 2017-11-21 13:43:29 -06:00
Minasokoni a7818d5983 Auth modal close button addded 2017-11-21 14:10:22 -05:00
Greg Thompson a2f09896f7 stop using immutable getters for js obj 2017-11-21 12:50:37 -06:00
Greg Thompson 04daadafd5 Merge branch 'master' into ft/3052-extensions 2017-11-21 09:15:50 -06:00
kyle cfc7b1a192 Merge pull request #3930 from floriantraber/bug/3571-oas-3.0-doesnt-render-in-ie11-startsWith-function-missing
Fixes #3571 - add polyfill for startsWith function for IE11.
2017-11-20 15:17:15 -08:00
Greg Thompson 8ff2d77398 Merge branch 'master' into ft/3052-extensions 2017-11-20 09:48:33 -06:00
Florian Traber e2d0bd7628 Fixes #3571 - add polyfill for startsWith function for IE11. 2017-11-18 17:21:24 +01:00
Christoph Kappestein 774acb1f28 add flow to make scope checkbox id unqiue 2017-11-18 09:59:15 +01:00
kyle 2ad1bacf6f Merge pull request #3928 from shockey/v/3.4.5
v3.4.5
2017-11-17 23:11:06 -08:00
Kyle Shockey ce2b2ca9cb Rebuild with fixes 2017-11-17 23:05:50 -08:00
Kyle Shockey e5b2193708 Fix Callback Response markdown styling 2017-11-17 22:59:20 -08:00
Kyle Shockey c7a3520dc5 Fix AuthorizeOperationBtn staleness issue 2017-11-17 22:55:20 -08:00
Kyle Shockey e2de882a16 v3.4.5 2017-11-17 22:33:47 -08:00
kyle b740eee286 Merge pull request #3840 from Jaza/uri-encoded-scopes-fix
Don't URI-encode scopes when posting in oauth2 password flow
2017-11-17 21:05:19 -08:00
kyle 1d286394ec Merge branch 'master' into uri-encoded-scopes-fix 2017-11-17 20:59:47 -08:00
kyle 0d2dbae733 Merge pull request #3909 from hugo19941994/bug/3897-markdown-table-headings
Bug/3897 markdown table headings
2017-11-17 20:51:48 -08:00
kyle b3a602d3b0 Merge branch 'master' into bug/3897-markdown-table-headings 2017-11-17 20:47:34 -08:00
kyle a2f592d29b Merge pull request #3927 from shockey/master
Display `name` security scheme property for apiKey type
2017-11-17 20:46:07 -08:00
Kyle Shockey f382e8d72d Display name security scheme property for apiKey type 2017-11-17 20:39:38 -08:00
kyle b5da26856a Merge pull request #3926 from swagger-api/bug/editor-1565-callback-expansion
Callback expansion issues
2017-11-17 19:12:46 -08:00
Kyle Shockey 26eb07da33 Linter fixes 2017-11-17 18:52:39 -08:00
Kyle Shockey 33f8338560 Prevent RequestBody from accessing a media type that ceased to exist 2017-11-17 18:45:19 -08:00
Kyle Shockey 44bd85a5bb Wrap container components in render protection 2017-11-17 18:26:07 -08:00
Kyle Shockey 200b361328 Recalculate example value when requestBody value changes 2017-11-17 17:20:01 -08:00
Kyle Shockey f44dfebd2a Add empty string tag for Callback operations 2017-11-17 16:15:43 -08:00
Kyle Shockey b61cf558f3 Rewire ability to disable Try It Out from OperationContainer 2017-11-17 15:47:54 -08:00
Kyle Shockey 84db66eb94 Rewire Callbacks usage of Operation to match new interface 2017-11-17 14:43:14 -08:00
kyle c28b128fe3 Merge pull request #3922 from swagger-api/bug/3904-operation-not-updating
Update Operation content correctly
2017-11-17 14:21:30 -08:00
kyle f6727b42b3 Merge branch 'master' into bug/3904-operation-not-updating 2017-11-17 14:16:48 -08:00
Greg Thompson 31694d7533 Merge branch 'master' into ft/3052-extensions 2017-11-17 11:00:43 -06:00
kyle 170aa12349 Merge pull request #3894 from legrego/master
Update react-split-pane for React-16 support
2017-11-16 23:34:17 -08:00
Kyle Shockey ed76a10431 Linter fixes 2017-11-16 23:19:57 -08:00
Kyle Shockey 61a498969e Fix deep linking 2017-11-16 23:19:57 -08:00
Kyle Shockey a6bd0f45f8 Fix deep linking 2017-11-16 22:49:39 -08:00
kyle ad6a180ae5 Merge branch 'master' into bug/3904-operation-not-updating 2017-11-16 22:33:30 -08:00
Kyle Shockey 0ef0613020 Remove Response update logic; dispatch changeProducesValue correctly 2017-11-16 22:25:19 -08:00
Kyle Shockey d28bf86129 Skip toJS() call in default mapStateToProps function 2017-11-16 21:38:41 -08:00
Kyle Shockey d284a3d243 Use PureComponent default shouldcomponentUpdate in OperationContainer 2017-11-16 21:05:05 -08:00
Kyle Shockey 6ab3f9e938 Pass system to OperationContainer through getComponent 2017-11-16 21:03:31 -08:00
Kyle Shockey 2ce199c151 Ensure that connected containers get a System in mapStateToProps props
This will allow us to avoid system utility handaround in
connected containers.
2017-11-16 20:16:45 -08:00
Kyle Shockey 7624d6b5fc Add test for system injection with mapStateToProps containers 2017-11-16 20:10:54 -08:00
Kyle Shockey 054961bfc7 Merge branch 'ft/performance' into bug/3904-operation-not-updating 2017-11-16 18:55:17 -08:00
Kyle Shockey dc7f15ea1b Add missing core-js to dependencies
Not related to this bug, but needed to be done to silence an
error thrown by Webpack.
2017-11-16 17:55:15 -08:00
Larry Gregory 61663fd5ba Merge branch 'master' into master 2017-11-16 19:00:43 -05:00
kyle 60989190d7 Merge pull request #3919 from thompsongl/ft/deprecated-schema
Ft/deprecated schema
2017-11-16 15:36:47 -08:00
Greg Thompson db1ad02a64 strikethrough for deprecated property name 2017-11-16 13:26:38 -06:00
Greg Thompson 86680825af add deprecated class to tr of deprecated schema 2017-11-16 13:26:07 -06:00
kyle 6041c419c9 Merge branch 'master' into uri-encoded-scopes-fix 2017-11-14 15:18:41 -08:00
Hugo Ferrando Seage 3139f3a9d7 Change color of <th>'s border-bottom elements in markdown content 2017-11-14 17:36:06 +01:00
Owen Conti 4b6a89dd53 Fixes #3897 - Change color of <th> elements in markdown content. 2017-11-13 17:29:05 -07:00
Greg Thompson 0d0b3279bb Merge branch 'master' into ft/3052-extensions 2017-11-13 09:29:19 -06:00
Larry Gregory 91a3707c13 Update react-split-pane for React-16 support 2017-11-12 14:19:40 -05:00
kyle 859edbf7f7 Merge pull request #3892 from swagger-api/v/3.4.4
v3.4.4
2017-11-10 23:25:31 -08:00
Kyle Shockey 81e7193eaf Build for v3.4.4 2017-11-10 23:21:20 -08:00
Kyle Shockey fadc522f56 v3.4.4 2017-11-10 23:16:51 -08:00
Kyle Shockey e45b9b82a8 Fix docExpansion: full regression 2017-11-10 22:34:55 -08:00
kyle b0420729c9 Merge pull request #3825 from heldersepu/feature/validation_tooltips
Add validation error tooltips
2017-11-10 19:12:07 -08:00
kyle b2c41e1e07 Merge branch 'master' into feature/validation_tooltips 2017-11-10 18:40:14 -08:00
kyle 0432828c56 Merge pull request #3885 from swagger-api/ft/big-spec-performance
Improve performance of big API definitions
2017-11-10 18:11:17 -08:00
Kyle Shockey 82a2ee9a34 Add safe string method access for toTitleCase 2017-11-10 16:57:14 -08:00
kyle c3b7f071c8 Merge branch 'master' into ft/big-spec-performance 2017-11-10 16:45:20 -08:00
kyle 9020ee1efa Merge pull request #3884 from swagger-api/fix/model-longtext-fix
Removed set width from Model prop
2017-11-10 16:30:01 -08:00
kyle 12fd5d7c8d Merge branch 'master' into fix/model-longtext-fix 2017-11-10 16:23:31 -08:00
kyle e83344e0a2 Merge pull request #3889 from swagger-api/bug/3299-param-validation-regression
Validate number and integer parameter value `0` correctly
2017-11-10 11:25:24 -08:00
kyle 4041689c1d Merge branch 'master' into bug/3299-param-validation-regression 2017-11-10 10:52:56 -08:00
Kyle Shockey 365585ceea Add check for 0 value for number and integer parameter values 2017-11-10 10:45:19 -08:00
Kyle Shockey d92a27bdab Add failing tests 2017-11-10 10:40:03 -08:00
kyle bfe2667326 Remove unused Immutable.List import 2017-11-09 19:28:20 -08:00
kyle 6a2659c5d0 Merge branch 'master' into ft/big-spec-performance 2017-11-09 19:17:37 -08:00
Kyle Shockey f4f3b25d8f Create newSpecErrBatch for more wealth and prosperity 2017-11-09 16:48:22 -08:00
Kyle Shockey e33de3049f Refactor Operation component to not trigger its own re-render 2017-11-09 16:28:53 -08:00
Helder Sepulveda 61a9fa0fcc Merge branch 'master' into feature/validation_tooltips 2017-11-09 15:41:15 -05:00
Minasokoni 5b6cd88557 removed set width 2017-11-09 12:18:10 -08:00
Greg Thompson 40c2c28a7d add showExtensions to config table 2017-11-09 10:44:30 -06:00
Greg Thompson ee5d9a8c34 propType test fix 2017-11-09 10:23:02 -06:00
Greg Thompson 91dab7b166 getConfigs prop expansion; limit extension render based on config setting 2017-11-09 10:22:41 -06:00
Greg Thompson 83dd9f3dfc showExtensions config param 2017-11-09 10:21:08 -06:00
Greg Thompson 7b83f64676 Merge branch 'master' into ft/3052-extensions 2017-11-09 08:31:04 -06:00
kyle 75d482f27f Merge pull request #3869 from feenr/bug/3658-add-enzyme-test-for-objectmodel
Bug/3658 add enzyme test for objectmodel
2017-11-08 22:53:46 -08:00
kyle 49457fe089 Correct typo in test description 2017-11-08 22:48:20 -08:00
kyle f7be20f42c Merge branch 'master' into bug/3658-add-enzyme-test-for-objectmodel 2017-11-08 22:47:13 -08:00
kyle fdc8313433 Merge pull request #3872 from ninja-inc/bug/solve-react-warning
adding a key prop to solve React.js warning
2017-11-08 22:45:51 -08:00
Kyle Shockey d063987883 Use React.cloneElement to give array elements keys instead of hardcoding 2017-11-08 22:41:29 -08:00
kyle c0f80ebdf2 Merge branch 'master' into bug/solve-react-warning 2017-11-08 22:34:46 -08:00
kyle 76617a5ee7 Merge pull request #3875 from thompsongl/bug/misc-proptype-fixes
Bug/misc proptype fixes
2017-11-08 22:32:04 -08:00
kyle 1d6b8e3892 Merge branch 'master' into bug/misc-proptype-fixes 2017-11-08 22:28:24 -08:00
kyle 4fa4e0f3e3 Merge pull request #3880 from legrego/ft/3714-dependencies-not-compatible-with-React-16
Fixes #3714: Update react-collapse and react-motion for React 16 support
2017-11-08 22:26:25 -08:00
Greg Thompson a7531a245c Merge branch 'master' into bug/misc-proptype-fixes 2017-11-08 16:09:31 -06:00
Ryan Feeney 1f11b3e4ac Merge branch 'master' into bug/3658-add-enzyme-test-for-objectmodel 2017-11-08 16:16:12 -05:00
Greg Thompson 233dacde71 Merge branch 'ft/3052-extensions' of https://github.com/thompsongl/swagger-ui into ft/3052-extensions 2017-11-08 08:52:55 -06:00
Greg Thompson 45a0295c0e use correct immutable map size 2017-11-08 08:52:34 -06:00
Larry Gregory 57a3be28b0 Update react-collapse and react-motion 2017-11-08 07:41:23 -05:00
Iida, Takaaki | Tak | TRVDD 6fb9d0b465 Merge remote-tracking branch 'upstream/master' into bug/solve-react-warning 2017-11-08 15:57:46 +09:00
kyle 5231c13579 Merge branch 'master' into ft/3052-extensions 2017-11-07 21:33:05 -08:00
kyle 362f1392b5 Merge pull request #3878 from swagger-api/bug/3219-parameter-value-performance
Make `Model` a PureComponent
2017-11-07 21:24:02 -08:00
Kyle Shockey 8b8c9b744d Make Model a PureComponent 2017-11-07 20:12:19 -08:00
Ryan Feeney 1aabdded97 Merge branch 'master' into bug/3658-add-enzyme-test-for-objectmodel 2017-11-07 15:06:22 -05:00
Greg Thompson f2cbfd0e51 contentType prop not required 2017-11-07 11:17:05 -06:00
Greg Thompson d96bd29d0c pass required getConfig to parameter-row 2017-11-07 11:16:41 -06:00
Greg Thompson 16e756bed7 disallow null value 2017-11-07 11:15:37 -06:00
takaaki.iida 6664058dbe https://github.com/swagger-api/swagger-ui/issues/3871 adding a key prop to solve React.js warning 2017-11-07 20:03:56 +09:00
kyle 076f32b1f0 Merge pull request #3870 from swagger-api/bug/auth-operation-btn-error
Bug/auth operation btn error
2017-11-06 22:46:24 -08:00
Kyle Shockey 531d0337ac Remove describe.only 2017-11-06 22:13:29 -08:00
Kyle Shockey 8f7b582f95 Improve junk data handling 2017-11-06 22:09:20 -08:00
Kyle Shockey 3536f2d518 Add tests for modified selectors 2017-11-06 22:08:42 -08:00
Kyle Shockey 533fd75501 Deprecate authSelectors.getDefinitionsByNames 2017-11-06 21:53:57 -08:00
Kyle Shockey ed34a8dae9 Linter: Remove unused import 2017-11-06 21:24:16 -08:00
Kyle Shockey cfc030d07d Rework filtering logic for definitionsForRequirements 2017-11-06 21:13:14 -08:00
Kyle Shockey 86db21515e Save nyc as a devDependency 2017-11-06 21:01:46 -08:00
Kyle Shockey 21bf5919a9 Rewire AuthorizeOperationBtn; create new selector for filtering definitions 2017-11-06 20:42:47 -08:00
Kyle Shockey cca8ddb5d5 Add nyc coverage reporting 2017-11-06 14:39:21 -08:00
feenr bcad5b583e Remove commented out and debug code 2017-11-06 12:41:14 -05:00
Ryan Feeney d291d75d2c Merge branch 'master' into bug/3658-add-enzyme-test-for-objectmodel 2017-11-06 12:38:50 -05:00
feenr 7fe07591b2 Update the pre-req version of node in CONTRIBUTING.md 2017-11-06 12:32:32 -05:00
feenr e9d94e02d8 Add new tests for object-model 2017-11-06 10:43:43 -05:00
Greg Thompson a58cd25f08 Merge branch 'master' into ft/3052-extensions 2017-11-06 09:18:51 -06:00
Greg Thompson fc3ac17710 imports 2017-11-06 09:18:16 -06:00
Greg Thompson 9a66acf37f operation extensions display 2017-11-06 09:18:05 -06:00
Greg Thompson 44c422eba3 parameter extensions display 2017-11-06 09:17:30 -06:00
HelderSepu 58dcce497e e2e test for the validation 2017-11-04 18:40:46 -04:00
Helder Sepulveda e10b01c6ff Merge branch 'master' into feature/validation_tooltips 2017-11-04 09:19:41 -04:00
Helder Sepulveda 59464de58e Merge branch 'master' into feature/validation_tooltips 2017-11-03 21:43:27 -04:00
Helder Sepulveda 8731ff7512 Merge branch 'master' into feature/validation_tooltips 2017-11-01 09:32:30 -04:00
Jeremy Epstein a5193a5b5b Don't URI-encode scopes when posting in oauth2 password flow 2017-10-29 12:04:43 +11:00
Helder Sepulveda 24cd95cf54 Merge branch 'master' into feature/validation_tooltips 2017-10-28 12:30:05 -04:00
Helder Sepulveda 6f876bcb12 Merge branch 'master' into feature/validation_tooltips 2017-10-27 15:51:20 -04:00
Helder Sepulveda 866e4d5a9e Merge branch 'master' into feature/validation_tooltips 2017-10-25 21:07:50 -04:00
HelderSepu ba32f60dec Add validation error tooltips
If there is an error put it on the tooltip
2017-10-25 21:02:14 -04:00
Owen Conti b15942dfe1 Merge branch 'ft/performance' of github.com:swagger-api/swagger-ui into ft/performance
# Conflicts:
#	src/core/components/responses.jsx
2017-10-22 12:55:51 -06:00
Owen Conti be209841f6 Merge branch 'master' of github.com:swagger-api/swagger-ui into ft/performance 2017-10-22 12:37:10 -06:00
kyle 6368e90c16 Merge pull request #3599 from owenconti/ft/3598-responses-shouldComponentUpdate
shouldComponentUpdate for response components
2017-09-29 13:58:55 -07:00
kyle c3aab2927a Merge pull request #3597 from owenconti/ft/3584-operation-container-component
OperationContainer component introduction
2017-09-20 14:57:07 -07:00
Owen Conti 6f98fa9f3b Fixes after merge with ft/3584 branch 2017-09-15 22:31:02 -06:00
Owen Conti f4efae0145 Merge branch 'ft/performance' into ft/3598-responses-shouldComponentUpdate
# Conflicts:
#	src/core/components/operation.jsx
#	src/core/components/operations.jsx
#	src/core/components/response.jsx
#	src/core/components/responses.jsx
2017-09-15 22:30:23 -06:00
Owen Conti 18cc3c84a2 Merge branch 'ft/performance' into ft/3584-operation-container-component 2017-09-15 22:18:59 -06:00
Owen Conti 5b87af7e7f Merge branch 'ft/performance' of github.com:swagger-api/swagger-ui into ft/performance 2017-09-15 22:18:30 -06:00
Owen Conti 9f473cd862 Merge pull request #3672 from swagger-api/master
master into ft/performance
2017-09-15 22:16:07 -06:00
Owen Conti 91a4794ab5 Merge ft/performance (#3670)
* Updated docs for correct usage of SWAGGER_JSON

* Removed href attribute from anchor tag if deeplinking is disabled

* If deeplinking is disabled the anchor tag has no href attribute as a result the mouse pointer is not a pointer as it is no longer a hyperlink, setting the cursor explicitly to pointer.

* Refactor: use ternary operators at attribute level instead of element level

* Only polyfill Promise if it doesn't exist at all

* v3.1.7

* Typo fix

* fix #3624

* Squash commit: OAS3 Try-It-Out changes

* Parse JSON requestBodies so Client can consume them correctly

* Use Client branch

* Fix typo in swagger-client dependency

* Fix property names being displayed in array models

* Working on refactoring of model.jsx

* Fit linter and tests

* Add comment to array-model for to clarify change. Rework logic in `Model.render()` to fix bug with overriding name and schema from `$ref` definition.

* v3.2.0

* fromJS does not maintain order of object properties. Use a reviver function with fromJS inside the response.jsx component for the passed down schema prop.

* OAS3 Accept header control: Component-side

* OAS3 Accept header control: State-side

* Update response.jsx to use already existing, fromJSOrdered function

* Added test for response.jsx to make sure properties are passed to `ModelExample` component in the correct order

* Remove `it.only` from new test

* Fixes #3596

Wrap `isShownKey` values in a function that replaces spaces with underscores. When parsing the hash on route change, replace the spaces in the values with underscores again.

* Replace spaces with underscores when setting the hash value and inserting the ID into the DOM. Escape the deep link path when querying for the DOM element on hash change.

* Handle null value in createDeepLinkPath

* Add extra check for String types in `createDeepLinkPath`. Add `trim()` call on passed-in value in `createDeepLinkPath`. Added unit tests for new deep link util functions.

* LINTING!

* Roll back win import removal

Lost in merge conflict....

* More merge oversights...
2017-09-15 22:09:35 -06:00
Owen Conti 9f5a307fce Merge branch 'ft/performance' into ft/3584-operation-container-component
# Conflicts:
#	src/core/components/operation.jsx
#	src/core/components/operations.jsx
#	src/core/components/responses.jsx
2017-09-15 22:03:14 -06:00
Owen Conti 46b5ae6070 Merge branch 'master' of github.com:swagger-api/swagger-ui into ft/performance 2017-09-15 21:53:00 -06:00
Owen Conti 32c96e348b Merge pull request #3602 from swagger-api/master
Merge master into ft/performance
2017-08-21 19:23:52 -06:00
Owen Conti 2c5a0a7816 Merge branch 'ft/3584-operation-container-component' into ft/3598-responses-shouldComponentUpdate 2017-08-21 19:17:41 -06:00
Owen Conti 95461ed697 Merge branch 'ft/performance' of github.com:swagger-api/swagger-ui into ft/3584-operation-container-component 2017-08-21 19:07:58 -06:00
Kyle 56ff3afc5d Merge pull request #3565 from owenconti/ft/map-state-to-props-for-components
`mapStateToProps` for container components
2017-08-21 17:09:00 -07:00
Owen Conti 0a45649834 Fixed mapStateToProps test to handle non-static mapStateToProps 2017-08-20 18:57:59 -06:00
Owen Conti cfb4625eb0 Add shouldComponentUpdate to response.jsx and live-response.jsx. Remove isShownKey from shouldComponentUpdate of OperationContainer. Moved response and request out to separate props for operation.jsx. Removed unused request prop from responses.jsx. 2017-08-20 18:50:49 -06:00
Owen Conti 017a26af1e Merge branch 'ft/3584-operation-container-component' into ft/3598-responses-shouldComponentUpdate 2017-08-20 17:03:16 -06:00
Owen Conti 050f4d1918 Clean up OperationContainer props. 2017-08-20 17:02:51 -06:00
Owen Conti bcefb6eb3e Convert pathMethod prop to two separate props. 2017-08-20 15:25:13 -06:00
Owen Conti 8426dcdf7b Fix failed test due to removed getConfigs 2017-08-20 08:16:02 -06:00
Owen Conti 2946baf2bd Merge branch 'master' into ft/3584-operation-container-component 2017-08-20 08:07:15 -06:00
Owen Conti 0d90305550 Remove unnecessary div in app.jsx 2017-08-20 08:06:59 -06:00
Owen Conti 7cc9f9a4db Update Operations component to call OperationContainer instead of Operation.jsx 2017-08-20 07:57:07 -06:00
Owen Conti dd414534f9 Update Operation component to be dumb, update responses to accept Immutable prop types 2017-08-20 07:56:40 -06:00
Owen Conti d4d66b80ca Add OperationContainer component 2017-08-20 07:55:54 -06:00
Owen Conti 0b41c917d1 Revert Perf tool back to core/index.js 2017-08-19 13:59:24 -06:00
Owen Conti ff2ed2584e Revert Perf tool back to core/index.js 2017-08-19 13:59:09 -06:00
Owen Conti e61c12fe18 Move performance debugging tools to app.jsx 2017-08-19 08:33:03 -06:00
Owen Conti c0cfaabd7e Remove unused getComponent as prop to <Execute 2017-08-19 08:32:21 -06:00
Owen Conti c0185ca6e2 Merge branch 'master' into ft/map-state-to-props-for-components 2017-08-14 18:46:11 -06:00
Owen Conti d9918f9f31 Add test for getComponent() and mapStateToProps in a container component 2017-08-14 18:44:26 -06:00
Owen Conti d9b0632d16 Add ability for container components to register their own mapStateToProps function. 2017-08-11 16:01:01 -06:00
68 changed files with 1263 additions and 393 deletions
+1
View File
@@ -2,6 +2,7 @@ node_modules
.idea
.deps_check
.DS_Store
.nyc_output
npm-debug.log*
.eslintcache
package-lock.json
+1
View File
@@ -6,3 +6,4 @@
!dist/swagger-ui.js.map
!dist/swagger-ui.css
!dist/swagger-ui.css.map
!dist/oauth2-redirect.html
+1 -1
View File
@@ -4,7 +4,7 @@ We love contributions from our community of users! This document explains our gu
#### Environment setup
0. Install Node.js (4 or newer) and npm (3 or newer).
0. Install Node.js (6 or newer) and npm (3 or newer).
1. Make a fork of Swagger-UI on GitHub, then clone your fork to your machine.
2. Run `npm install` in your Swagger-UI directory.
3. Run `npm run dev`. `localhost:3200` should open automatically.
+2 -1
View File
@@ -22,7 +22,7 @@ The OpenAPI Specification has undergone 5 revisions since initial creation in 20
Swagger UI Version | Release Date | OpenAPI Spec compatibility | Notes
------------------ | ------------ | -------------------------- | -----
3.4.3 | 2017-11-03 | 2.0, 3.0 | [tag v3.4.3](https://github.com/swagger-api/swagger-ui/tree/v3.4.3)
3.5.0 | 2017-11-23 | 2.0, 3.0 | [tag v3.5.0](https://github.com/swagger-api/swagger-ui/tree/v3.5.0)
3.0.21 | 2017-07-26 | 2.0 | [tag v3.0.21](https://github.com/swagger-api/swagger-ui/tree/v3.0.21)
2.2.10 | 2017-01-04 | 1.1, 1.2, 2.0 | [tag v2.2.10](https://github.com/swagger-api/swagger-ui/tree/v2.2.10)
2.1.5 | 2016-07-20 | 1.1, 1.2, 2.0 | [tag v2.1.5](https://github.com/swagger-api/swagger-ui/tree/v2.1.5)
@@ -165,6 +165,7 @@ deepLinking | If set to `true`, enables dynamic deep linking for tags and operat
requestInterceptor | MUST be a function. Function to intercept try-it-out requests. Accepts one argument requestInterceptor(request) and must return the potentially modified request.
responseInterceptor | MUST be a function. Function to intercept try-it-out responses. Accepts one argument responseInterceptor(response) and must return the potentially modified response.
showMutatedRequest | If set to `true` (the default), uses the mutated request returned from a rquestInterceptor to produce the curl command in the UI, otherwise the request before the requestInterceptor was applied is used.
showExtensions | Controls the display of vendor extension (`x-`) fields and values for Operations, Parameters, and Schema. The default is `false`.
### Plugins
+50 -76
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+14 -5
View File
@@ -1,6 +1,6 @@
{
"name": "swagger-ui",
"version": "3.4.3",
"version": "3.5.0",
"main": "dist/swagger-ui.js",
"repository": "git@github.com:swagger-api/swagger-ui.git",
"contributors": [
@@ -33,6 +33,7 @@
"test-in-node": "npm run lint-errors && npm run just-test-in-node",
"just-test": "karma start --config karma.conf.js",
"just-test-in-node": "mocha --recursive --compilers js:babel-core/register test/core test/components test/bugs test/swagger-ui-dist-package test/xss",
"just-check-coverage": "nyc npm run just-test-in-node",
"test-e2e": "sleep 3 && nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json",
"e2e-initial-render": "nightwatch test/e2e/scenarios/ --config test/e2e/nightwatch.json --group initial-render",
"mock-api": "json-server --watch test/e2e/db.json --port 3204",
@@ -44,6 +45,7 @@
"brace": "0.7.0",
"classnames": "^2.2.5",
"commonmark": "^0.28.1",
"core-js": "^2.5.1",
"css.escape": "1.5.1",
"deep-extend": "0.4.1",
"expect": "1.20.2",
@@ -60,16 +62,16 @@
"react-addons-perf": "^15.4.0",
"react-addons-shallow-compare": "0.14.8",
"react-addons-test-utils": "^15.6.2",
"react-collapse": "2.3.1",
"react-collapse": "^4.0.3",
"react-dom": "^15.6.2",
"react-height": "^2.0.0",
"react-hot-loader": "1.3.1",
"react-immutable-proptypes": "2.1.0",
"react-markdown": "^2.5.0",
"react-motion": "0.4.4",
"react-motion": "^0.5.2",
"react-object-inspector": "0.2.1",
"react-redux": "^4.x.x",
"react-split-pane": "0.1.57",
"react-split-pane": "0.1.70",
"redux": "^3.x.x",
"redux-immutable": "3.0.8",
"redux-logger": "*",
@@ -79,7 +81,7 @@
"scroll-to-element": "^2.0.0",
"serialize-error": "2.0.0",
"shallowequal": "0.2.2",
"swagger-client": "^3.3.2",
"swagger-client": "^3.3.5",
"url-parse": "^1.1.8",
"whatwg-fetch": "0.11.1",
"worker-loader": "^0.7.1",
@@ -127,6 +129,7 @@
"node-sass": "^4.5.0",
"npm-run-all": "4.0.2",
"null-loader": "0.1.1",
"nyc": "^11.3.0",
"open": "0.0.5",
"postcss-loader": "2.0.6",
"raw-loader": "0.5.1",
@@ -152,5 +155,11 @@
],
"optionalDependencies": {
"webpack-dev-server": "2.5.0"
},
"nyc": {
"all": true,
"include": [
"**/src/core/plugins/**.js"
]
}
}
+3 -2
View File
@@ -7,6 +7,7 @@ export default class ArrayModel extends Component {
static propTypes = {
schema: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired,
specSelectors: PropTypes.object.isRequired,
name: PropTypes.string,
required: PropTypes.bool,
@@ -15,7 +16,7 @@ export default class ArrayModel extends Component {
}
render(){
let { getComponent, schema, depth, expandDepth, name } = this.props
let { getComponent, getConfigs, schema, depth, expandDepth, name } = this.props
let description = schema.get("description")
let items = schema.get("items")
let title = schema.get("title") || name
@@ -46,7 +47,7 @@ export default class ArrayModel extends Component {
!description ? null :
<Markdown source={ description } />
}
<span><Model { ...this.props } name={null} schema={ items } required={ false } depth={ depth + 1 } /></span>
<span><Model { ...this.props } getConfigs={ getConfigs } name={null} schema={ items } required={ false } depth={ depth + 1 } /></span>
]
</ModelCollapse>
</span>
@@ -60,6 +60,9 @@ export default class ApiKeyAuth extends React.Component {
<Row>
<Markdown source={ schema.get("description") } />
</Row>
<Row>
<p>Name: <code>{ schema.get("name") }</code></p>
</Row>
<Row>
<p>In: <code>{ schema.get("in") }</code></p>
</Row>
@@ -1,25 +1,23 @@
import React from "react"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
export default class AuthorizeOperationBtn extends React.Component {
static propTypes = {
isAuthorized: PropTypes.bool.isRequired,
onClick: PropTypes.func
}
onClick =(e) => {
e.stopPropagation()
let { onClick } = this.props
let { security, authActions, authSelectors } = this.props
let definitions = authSelectors.getDefinitionsByNames(security)
authActions.showDefinitions(definitions)
if(onClick) {
onClick()
}
}
render() {
let { security, authSelectors } = this.props
let isAuthorized = authSelectors.isAuthorized(security)
if(isAuthorized === null) {
return null
}
let { isAuthorized } = this.props
return (
<button className={isAuthorized ? "authorization__btn locked" : "authorization__btn unlocked"} onClick={ this.onClick }>
@@ -30,10 +28,4 @@ export default class AuthorizeOperationBtn extends React.Component {
)
}
static propTypes = {
authSelectors: PropTypes.object.isRequired,
authActions: PropTypes.object.isRequired,
security: ImPropTypes.iterable.isRequired
}
}
+8
View File
@@ -41,6 +41,13 @@ export default class Auths extends React.Component {
authActions.logout(auths)
}
close =(e) => {
e.preventDefault()
let { authActions } = this.props
authActions.showDefinitions(false)
}
render() {
let { definitions, getComponent, authSelectors, errSelectors } = this.props
const AuthItem = getComponent("AuthItem")
@@ -74,6 +81,7 @@ export default class Auths extends React.Component {
}).toArray()
}
<div className="auth-btn-wrapper">
<Button className="btn modal-btn auth btn-done" onClick={ this.close }>Done</Button>
{
nonOauthDefinitions.size === authorizedAuth.size ? <Button className="btn modal-btn auth" onClick={ this.logoutClick }>Logout</Button>
: <Button type="submit" className="btn modal-btn auth authorize">Authorize</Button>
+2 -2
View File
@@ -200,11 +200,11 @@ export default class Oauth2 extends React.Component {
<Row key={ name }>
<div className="checkbox">
<Input data-value={ name }
id={`${name}-checkbox-${this.state.name}`}
id={`${name}-${flow}-checkbox-${this.state.name}`}
disabled={ isAuthorized }
type="checkbox"
onChange={ this.onScopeChange }/>
<label htmlFor={`${name}-checkbox-${this.state.name}`}>
<label htmlFor={`${name}-${flow}-checkbox-${this.state.name}`}>
<span className="item"></span>
<div className="text">
<p className="name">{name}</p>
+11 -1
View File
@@ -27,6 +27,16 @@ export default class ContentType extends React.Component {
}
}
componentWillReceiveProps(nextProps) {
if(!nextProps.contentTypes || !nextProps.contentTypes.size) {
return
}
if(!nextProps.contentTypes.includes(nextProps.value)) {
nextProps.onChange(nextProps.contentTypes.first())
}
}
onChangeWrapper = e => this.props.onChange(e.target.value)
render() {
@@ -37,7 +47,7 @@ export default class ContentType extends React.Component {
return (
<div className={ "content-type-wrapper " + ( className || "" ) }>
<select className="content-type" value={value} onChange={this.onChangeWrapper} >
<select className="content-type" value={value || ""} onChange={this.onChangeWrapper} >
{ contentTypes.map( (val) => {
return <option key={ val } value={ val }>{ val }</option>
}).toArray()}
+1 -1
View File
@@ -1,6 +1,6 @@
import React from "react"
import PropTypes from "prop-types"
import Collapse from "react-collapse"
import { Collapse } from "react-collapse"
import { presets } from "react-motion"
import ObjectInspector from "react-object-inspector"
import Perf from "react-addons-perf"
+2 -2
View File
@@ -1,7 +1,7 @@
import React from "react"
import PropTypes from "prop-types"
import { List } from "immutable"
import Collapse from "react-collapse"
import { Collapse } from "react-collapse"
export default class Errors extends React.Component {
@@ -113,7 +113,7 @@ const SpecErrorItem = ( { error, jumpToLine } ) => {
}
function toTitleCase(str) {
return str
return (str || "")
.split(" ")
.map(substr => substr[0].toUpperCase() + substr.slice(1))
.join(" ")
-1
View File
@@ -8,7 +8,6 @@ export default class Execute extends Component {
specActions: PropTypes.object.isRequired,
operation: PropTypes.object.isRequired,
path: PropTypes.string.isRequired,
getComponent: PropTypes.func.isRequired,
method: PropTypes.string.isRequired,
onExecute: PropTypes.func
}
+1 -1
View File
@@ -1,6 +1,6 @@
import React from "react"
import PropTypes from "prop-types"
import OriCollapse from "react-collapse"
import { Collapse as OriCollapse } from "react-collapse"
function xclass(...args) {
return args.filter(a => !!a).join(" ").trim()
+17 -7
View File
@@ -1,6 +1,7 @@
import React from "react"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
import { Iterable } from "immutable"
const Headers = ( { headers } )=>{
return (
@@ -28,19 +29,29 @@ Duration.propTypes = {
export default class LiveResponse extends React.Component {
static propTypes = {
response: PropTypes.object.isRequired,
specSelectors: PropTypes.object.isRequired,
pathMethod: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired,
response: PropTypes.instanceOf(Iterable).isRequired,
path: PropTypes.string.isRequired,
method: PropTypes.string.isRequired,
displayRequestDuration: PropTypes.bool.isRequired,
specSelectors: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired
}
shouldComponentUpdate(nextProps) {
// BUG: props.response is always coming back as a new Immutable instance
// same issue as responses.jsx (tryItOutResponse)
return this.props.response !== nextProps.response
|| this.props.path !== nextProps.path
|| this.props.method !== nextProps.method
|| this.props.displayRequestDuration !== nextProps.displayRequestDuration
}
render() {
const { response, getComponent, getConfigs, displayRequestDuration, specSelectors, pathMethod } = this.props
const { response, getComponent, getConfigs, displayRequestDuration, specSelectors, path, method } = this.props
const { showMutatedRequest } = getConfigs()
const curlRequest = showMutatedRequest ? specSelectors.mutatedRequestFor(pathMethod[0], pathMethod[1]) : specSelectors.requestFor(pathMethod[0], pathMethod[1])
const curlRequest = showMutatedRequest ? specSelectors.mutatedRequestFor(path, method) : specSelectors.requestFor(path, method)
const status = response.get("status")
const url = response.get("url")
const headers = response.get("headers").toJS()
@@ -118,7 +129,6 @@ export default class LiveResponse extends React.Component {
static propTypes = {
getComponent: PropTypes.func.isRequired,
request: ImPropTypes.map,
response: ImPropTypes.map
}
}
+1
View File
@@ -52,6 +52,7 @@ export default class ModelExample extends React.Component {
{
!isExecute && this.state.activeTab === "model" && <ModelWrapper schema={ schema }
getComponent={ getComponent }
getConfigs={ getConfigs }
specSelectors={ specSelectors }
expandDepth={ defaultModelExpandDepth } />
+3 -4
View File
@@ -6,18 +6,17 @@ export default class ModelComponent extends Component {
schema: PropTypes.object.isRequired,
name: PropTypes.string,
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired,
specSelectors: PropTypes.object.isRequired,
expandDepth: PropTypes.number
}
render(){
let { getComponent } = this.props
let { getComponent, getConfigs } = this.props
const Model = getComponent("Model")
return <div className="model-box">
<Model { ...this.props } depth={ 1 } expandDepth={ this.props.expandDepth || 0 }/>
<Model { ...this.props } getConfigs={ getConfigs } depth={ 1 } expandDepth={ this.props.expandDepth || 0 }/>
</div>
}
}
+12 -7
View File
@@ -1,10 +1,12 @@
import React, { Component } from "react"
import React, { PureComponent } from "react"
import ImPropTypes from "react-immutable-proptypes"
import PropTypes from "prop-types"
export default class Model extends Component {
export default class Model extends PureComponent {
static propTypes = {
schema: PropTypes.object.isRequired,
schema: ImPropTypes.orderedMap.isRequired,
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired,
specSelectors: PropTypes.object.isRequired,
name: PropTypes.string,
isRef: PropTypes.bool,
@@ -29,13 +31,13 @@ export default class Model extends Component {
}
render () {
let { getComponent, specSelectors, schema, required, name, isRef } = this.props
let { getComponent, getConfigs, specSelectors, schema, required, name, isRef } = this.props
const ObjectModel = getComponent("ObjectModel")
const ArrayModel = getComponent("ArrayModel")
const PrimitiveModel = getComponent("PrimitiveModel")
let type = "object"
let $$ref = schema && schema.get("$$ref")
// If we weren't passed a `name` but have a ref, grab the name from the ref
if ( !name && $$ref ) {
name = this.getModelName( $$ref )
@@ -44,15 +46,16 @@ export default class Model extends Component {
if ( !schema && $$ref ) {
schema = this.getRefSchema( name )
}
const deprecated = specSelectors.isOAS3() && schema.get("deprecated")
isRef = isRef !== undefined ? isRef : !!$$ref
type = schema && schema.get("type") || type
switch(type) {
case "object":
return <ObjectModel
className="object" { ...this.props }
getConfigs={ getConfigs }
schema={ schema }
name={ name }
deprecated={deprecated}
@@ -60,6 +63,7 @@ export default class Model extends Component {
case "array":
return <ArrayModel
className="array" { ...this.props }
getConfigs={ getConfigs }
schema={ schema }
name={ name }
deprecated={deprecated}
@@ -72,6 +76,7 @@ export default class Model extends Component {
return <PrimitiveModel
{ ...this.props }
getComponent={ getComponent }
getConfigs={ getConfigs }
schema={ schema }
name={ name }
deprecated={deprecated}
+1
View File
@@ -36,6 +36,7 @@ export default class Models extends Component {
expandDepth={ defaultModelExpandDepth }
schema={ model }
getComponent={ getComponent }
getConfigs={ getConfigs }
specSelectors={ specSelectors }/>
</div>
}).toArray()
+46 -8
View File
@@ -9,6 +9,7 @@ export default class ObjectModel extends Component {
static propTypes = {
schema: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired,
specSelectors: PropTypes.object.isRequired,
name: PropTypes.string,
isRef: PropTypes.bool,
@@ -17,10 +18,16 @@ export default class ObjectModel extends Component {
}
render(){
let { schema, name, isRef, getComponent, depth, expandDepth, ...otherProps } = this.props
let { schema, name, isRef, getComponent, getConfigs, depth, expandDepth, ...otherProps } = this.props
let { specSelectors } = otherProps
let { isOAS3 } = specSelectors
if(!schema) {
return null
}
const { showExtensions } = getConfigs()
let description = schema.get("description")
let properties = schema.get("properties")
let additionalProperties = schema.get("additionalProperties")
@@ -72,13 +79,14 @@ export default class ObjectModel extends Component {
{
!(properties && properties.size) ? null : properties.entrySeq().map(
([key, value]) => {
let isDeprecated = isOAS3() && value.get("deprecated")
let isRequired = List.isList(requiredProperties) && requiredProperties.contains(key)
let propertyStyle = { verticalAlign: "top", paddingRight: "0.2em" }
if ( isRequired ) {
propertyStyle.fontWeight = "bold"
}
return (<tr key={key}>
return (<tr key={key} className={isDeprecated && "deprecated"}>
<td style={ propertyStyle }>
{ key }{ isRequired && <span style={{ color: "red" }}>*</span> }
</td>
@@ -86,12 +94,37 @@ export default class ObjectModel extends Component {
<Model key={ `object-${name}-${key}_${value}` } { ...otherProps }
required={ isRequired }
getComponent={ getComponent }
getConfigs={ getConfigs }
schema={ value }
depth={ depth + 1 } />
</td>
</tr>)
}).toArray()
}
{
// empty row befor extensions...
!showExtensions ? null : <tr>&nbsp;</tr>
}
{
!showExtensions ? null :
schema.entrySeq().map(
([key, value]) => {
if(key.slice(0,2) !== "x-") {
return
}
const normalizedValue = !value ? null : value.toJS ? value.toJS() : value
return (<tr key={key} style={{ color: "#777" }}>
<td>
{ key }
</td>
<td style={{ verticalAlign: "top" }}>
{ JSON.stringify(normalizedValue) }
</td>
</tr>)
}).toArray()
}
{
!additionalProperties || !additionalProperties.size ? null
: <tr>
@@ -99,6 +132,7 @@ export default class ObjectModel extends Component {
<td>
<Model { ...otherProps } required={ false }
getComponent={ getComponent }
getConfigs={ getConfigs }
schema={ additionalProperties }
depth={ depth + 1 } />
</td>
@@ -112,6 +146,7 @@ export default class ObjectModel extends Component {
{anyOf.map((schema, k) => {
return <div key={k}><Model { ...otherProps } required={ false }
getComponent={ getComponent }
getConfigs={ getConfigs }
schema={ schema }
depth={ depth + 1 } /></div>
})}
@@ -126,6 +161,7 @@ export default class ObjectModel extends Component {
{oneOf.map((schema, k) => {
return <div key={k}><Model { ...otherProps } required={ false }
getComponent={ getComponent }
getConfigs={ getConfigs }
schema={ schema }
depth={ depth + 1 } /></div>
})}
@@ -137,12 +173,14 @@ export default class ObjectModel extends Component {
: <tr>
<td>{ "not ->" }</td>
<td>
{not.map((schema, k) => {
return <div key={k}><Model { ...otherProps } required={ false }
getComponent={ getComponent }
schema={ schema }
depth={ depth + 1 } /></div>
})}
<div>
<Model { ...otherProps }
required={ false }
getComponent={ getComponent }
getConfigs={ getConfigs }
schema={ not }
depth={ depth + 1 } />
</div>
</td>
</tr>
}
@@ -0,0 +1,17 @@
import React from "react"
import PropTypes from "prop-types"
export const OperationExtRow = ({ xKey, xVal }) => {
const xNormalizedValue = !xVal ? null : xVal.toJS ? xVal.toJS() : xVal
return (<tr>
<td>{ xKey }</td>
<td>{ JSON.stringify(xNormalizedValue) }</td>
</tr>)
}
OperationExtRow.propTypes = {
xKey: PropTypes.string,
xVal: PropTypes.any
}
export default OperationExtRow
@@ -0,0 +1,35 @@
import React from "react"
import PropTypes from "prop-types"
export const OperationExt = ({ extensions, getComponent }) => {
let OperationExtRow = getComponent("OperationExtRow")
return (
<div className="opblock-section">
<div className="opblock-section-header">
<h4>Extensions</h4>
</div>
<div className="table-container">
<table>
<thead>
<tr>
<td className="col col_header">Field</td>
<td className="col col_header">Value</td>
</tr>
</thead>
<tbody>
{
extensions.entrySeq().map(([k, v]) => <OperationExtRow key={`${k}-${v}`} xKey={k} xVal={v} />)
}
</tbody>
</table>
</div>
</div>
)
}
OperationExt.propTypes = {
extensions: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired
}
export default OperationExt
+76 -119
View File
@@ -1,30 +1,22 @@
import React, { PureComponent } from "react"
import PropTypes from "prop-types"
import { getList } from "core/utils"
import * as CustomPropTypes from "core/proptypes"
import { sanitizeUrl } from "core/utils"
//import "less/opblock"
import { getExtensions, sanitizeUrl } from "core/utils"
import { Iterable } from "immutable"
export default class Operation extends PureComponent {
static propTypes = {
path: PropTypes.string.isRequired,
method: PropTypes.string.isRequired,
operation: PropTypes.object.isRequired,
showSummary: PropTypes.bool,
operation: PropTypes.instanceOf(Iterable).isRequired,
response: PropTypes.instanceOf(Iterable),
request: PropTypes.instanceOf(Iterable),
isShownKey: CustomPropTypes.arrayOrString.isRequired,
jumpToKey: CustomPropTypes.arrayOrString.isRequired,
allowTryItOut: PropTypes.bool,
displayOperationId: PropTypes.bool,
displayRequestDuration: PropTypes.bool,
response: PropTypes.object,
request: PropTypes.object,
toggleShown: PropTypes.func.isRequired,
onTryoutClick: PropTypes.func.isRequired,
onCancelClick: PropTypes.func.isRequired,
onExecute: PropTypes.func.isRequired,
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired,
authActions: PropTypes.object,
authSelectors: PropTypes.object,
specActions: PropTypes.object.isRequired,
@@ -32,108 +24,68 @@ export default class Operation extends PureComponent {
oas3Actions: PropTypes.object.isRequired,
layoutActions: PropTypes.object.isRequired,
layoutSelectors: PropTypes.object.isRequired,
fn: PropTypes.object.isRequired,
getConfigs: PropTypes.func.isRequired
fn: PropTypes.object.isRequired
}
static defaultProps = {
showSummary: true,
operation: null,
response: null,
allowTryItOut: true,
displayOperationId: false,
displayRequestDuration: false
}
constructor(props, context) {
super(props, context)
this.state = {
tryItOutEnabled: false
}
}
componentWillReceiveProps(nextProps) {
const defaultContentType = "application/json"
let { specActions, path, method, operation } = nextProps
let producesValue = operation.get("produces_value")
let produces = operation.get("produces")
let consumes = operation.get("consumes")
let consumesValue = operation.get("consumes_value")
if(nextProps.response !== this.props.response) {
this.setState({ executeInProgress: false })
}
if (producesValue === undefined) {
producesValue = produces && produces.size ? produces.first() : defaultContentType
specActions.changeProducesValue([path, method], producesValue)
}
if (consumesValue === undefined) {
consumesValue = consumes && consumes.size ? consumes.first() : defaultContentType
specActions.changeConsumesValue([path, method], consumesValue)
}
}
toggleShown =() => {
let { layoutActions, isShownKey } = this.props
layoutActions.show(isShownKey, !this.isShown())
}
isShown =() => {
let { layoutSelectors, isShownKey, getConfigs } = this.props
let { docExpansion } = getConfigs()
return layoutSelectors.isShown(isShownKey, docExpansion === "full" ) // Here is where we set the default
}
onTryoutClick =() => {
this.setState({tryItOutEnabled: !this.state.tryItOutEnabled})
}
onCancelClick =() => {
let { specActions, path, method } = this.props
this.setState({tryItOutEnabled: !this.state.tryItOutEnabled})
specActions.clearValidateParams([path, method])
}
onExecute = () => {
this.setState({ executeInProgress: true })
request: null
}
render() {
let {
isShownKey,
jumpToKey,
path,
method,
operation,
showSummary,
response,
request,
allowTryItOut,
displayOperationId,
displayRequestDuration,
toggleShown,
onTryoutClick,
onCancelClick,
onExecute,
fn,
getComponent,
getConfigs,
specActions,
specSelectors,
authActions,
authSelectors,
getConfigs,
oas3Actions
} = this.props
let operationProps = this.props.operation
let summary = operation.get("summary")
let description = operation.get("description")
let deprecated = operation.get("deprecated")
let externalDocs = operation.get("externalDocs")
let {
isShown,
isAuthorized,
jumpToKey,
path,
method,
op,
tag,
showSummary,
operationId,
allowTryItOut,
displayOperationId,
displayRequestDuration,
isDeepLinkingEnabled,
tryItOutEnabled,
executeInProgress
} = operationProps.toJS()
let {
summary,
description,
deprecated,
externalDocs,
schemes
} = op.operation
let operation = operationProps.getIn(["op", "operation"])
let security = operationProps.get("security")
let responses = operation.get("responses")
let security = operation.get("security") || specSelectors.security()
let produces = operation.get("produces")
let schemes = operation.get("schemes")
let parameters = getList(operation, ["parameters"])
let operationId = operation.get("__originalOperationId")
let operationScheme = specSelectors.operationScheme(path, method)
let isShownKey = ["operations", tag, operationId]
let extensions = getExtensions(operation)
const Responses = getComponent("responses")
const Parameters = getComponent( "parameters" )
@@ -144,10 +96,9 @@ export default class Operation extends PureComponent {
const Collapse = getComponent( "Collapse" )
const Markdown = getComponent( "Markdown" )
const Schemes = getComponent( "schemes" )
const OperationExt = getComponent( "OperationExt" )
const { deepLinking } = getConfigs()
const isDeepLinkingEnabled = deepLinking && deepLinking !== "false"
const { showExtensions } = getConfigs()
// Merge in Live Response
if(responses && response && response.size > 0) {
@@ -155,19 +106,17 @@ export default class Operation extends PureComponent {
response = response.set("notDocumented", notDocumented)
}
let { tryItOutEnabled } = this.state
let shown = this.isShown()
let onChangeKey = [ path, method ] // Used to add values to _this_ operation ( indexed by path and method )
return (
<div className={deprecated ? "opblock opblock-deprecated" : shown ? `opblock opblock-${method} is-open` : `opblock opblock-${method}`} id={isShownKey.join("-")} >
<div className={`opblock-summary opblock-summary-${method}`} onClick={this.toggleShown} >
<div className={deprecated ? "opblock opblock-deprecated" : isShown ? `opblock opblock-${method} is-open` : `opblock opblock-${method}`} id={isShownKey.join("-")} >
<div className={`opblock-summary opblock-summary-${method}`} onClick={toggleShown} >
<span className="opblock-summary-method">{method.toUpperCase()}</span>
<span className={ deprecated ? "opblock-summary-path__deprecated" : "opblock-summary-path" } >
<a
className="nostyle"
onClick={isDeepLinkingEnabled ? (e) => e.preventDefault() : null}
href={isDeepLinkingEnabled ? `#/${isShownKey[1]}/${isShownKey[2]}` : null}>
href={isDeepLinkingEnabled ? `#/${isShownKey.join("/")}` : null}>
<span>{path}</span>
</a>
<JumpToPath path={jumpToKey} />
@@ -183,13 +132,17 @@ export default class Operation extends PureComponent {
{
(!security || !security.count()) ? null :
<AuthorizeOperationBtn authActions={ authActions }
security={ security }
authSelectors={ authSelectors }/>
<AuthorizeOperationBtn
isAuthorized={ isAuthorized }
onClick={() => {
const applicableDefinitions = authSelectors.definitionsForRequirements(security)
authActions.showDefinitions(applicableDefinitions)
}}
/>
}
</div>
<Collapse isOpened={shown}>
<Collapse isOpened={isShown}>
<div className="opblock-body">
{ deprecated && <h4 className="opblock-title_normal"> Warning: Deprecated</h4>}
{ description &&
@@ -200,23 +153,24 @@ export default class Operation extends PureComponent {
</div>
}
{
externalDocs && externalDocs.get("url") ?
externalDocs && externalDocs.url ?
<div className="opblock-external-docs-wrapper">
<h4 className="opblock-title_normal">Find more details</h4>
<div className="opblock-external-docs">
<span className="opblock-external-docs__description">
<Markdown source={ externalDocs.get("description") } />
<Markdown source={ externalDocs.description } />
</span>
<a className="opblock-external-docs__link" href={ sanitizeUrl(externalDocs.get("url")) }>{ externalDocs.get("url") }</a>
<a target="_blank" className="opblock-external-docs__link" href={ sanitizeUrl(externalDocs.url) }>{ externalDocs.url }</a>
</div>
</div> : null
}
<Parameters
parameters={parameters}
operation={operation}
onChangeKey={onChangeKey}
onTryoutClick = { this.onTryoutClick }
onCancelClick = { this.onCancelClick }
onTryoutClick = { onTryoutClick }
onCancelClick = { onCancelClick }
tryItOutEnabled = { tryItOutEnabled }
allowTryItOut={allowTryItOut}
@@ -241,25 +195,23 @@ export default class Operation extends PureComponent {
{ !tryItOutEnabled || !allowTryItOut ? null :
<Execute
getComponent={getComponent}
operation={ operation }
specActions={ specActions }
specSelectors={ specSelectors }
path={ path }
method={ method }
onExecute={ this.onExecute } />
onExecute={ onExecute } />
}
{ (!tryItOutEnabled || !response || !allowTryItOut) ? null :
<Clear
onClick={ this.onClearClick }
specActions={ specActions }
path={ path }
method={ method }/>
}
</div>
{this.state.executeInProgress ? <div className="loading-container"><div className="loading"></div></div> : null}
{executeInProgress ? <div className="loading-container"><div className="loading"></div></div> : null}
{ !responses ? null :
<Responses
@@ -273,10 +225,15 @@ export default class Operation extends PureComponent {
specActions={ specActions }
produces={ produces }
producesValue={ operation.get("produces_value") }
pathMethod={ [path, method] }
path={ path }
method={ method }
displayRequestDuration={ displayRequestDuration }
fn={fn} />
}
{ !showExtensions || !extensions.size ? null :
<OperationExt extensions={ extensions } getComponent={ getComponent } />
}
</div>
</Collapse>
</div>
+10 -52
View File
@@ -1,8 +1,6 @@
import React from "react"
import PropTypes from "prop-types"
import { helpers } from "swagger-client"
import { createDeepLinkPath, sanitizeUrl } from "core/utils"
const { opId } = helpers
export default class Operations extends React.Component {
@@ -21,28 +19,20 @@ export default class Operations extends React.Component {
render() {
let {
specSelectors,
specActions,
oas3Actions,
getComponent,
layoutSelectors,
layoutActions,
authActions,
authSelectors,
getConfigs,
fn
getConfigs
} = this.props
let taggedOps = specSelectors.taggedOperations()
const Operation = getComponent("operation")
const OperationContainer = getComponent("OperationContainer", true)
const Collapse = getComponent("Collapse")
const Markdown = getComponent("Markdown")
let showSummary = layoutSelectors.showSummary()
let {
docExpansion,
displayOperationId,
displayRequestDuration,
maxDisplayedTags,
deepLinking
} = getConfigs()
@@ -120,47 +110,15 @@ export default class Operations extends React.Component {
<Collapse isOpened={showTag}>
{
operations.map( op => {
const path = op.get("path")
const method = op.get("method")
const path = op.get("path", "")
const method = op.get("method", "")
const jumpToKey = `paths.${path}.${method}`
const operationId =
op.getIn(["operation", "operationId"]) || op.getIn(["operation", "__originalOperationId"]) || opId(op.get("operation"), path, method) || op.get("id")
const isShownKey = ["operations", createDeepLinkPath(tag), createDeepLinkPath(operationId)]
const allowTryItOut = specSelectors.allowTryItOutFor(op.get("path"), op.get("method"))
const response = specSelectors.responseFor(op.get("path"), op.get("method"))
const request = specSelectors.requestFor(op.get("path"), op.get("method"))
return <Operation
{...op.toObject()}
isShownKey={isShownKey}
jumpToKey={jumpToKey}
showSummary={showSummary}
key={isShownKey}
response={ response }
request={ request }
allowTryItOut={allowTryItOut}
displayOperationId={displayOperationId}
displayRequestDuration={displayRequestDuration}
specActions={ specActions }
specSelectors={ specSelectors }
oas3Actions={oas3Actions}
layoutActions={ layoutActions }
layoutSelectors={ layoutSelectors }
authActions={ authActions }
authSelectors={ authSelectors }
getComponent={ getComponent }
fn={fn}
getConfigs={ getConfigs }
return <OperationContainer
key={`${path}-${method}`}
op={op}
path={path}
method={method}
tag={tag}
/>
}).toArray()
}
@@ -0,0 +1,12 @@
import React from "react"
import PropTypes from "prop-types"
export const ParameterExt = ({ xKey, xVal }) => {
return <div className="parameter__extension">{ xKey }: { String(xVal) }</div>
}
ParameterExt.propTypes = {
xKey: PropTypes.string,
xVal: PropTypes.any
}
export default ParameterExt
+6
View File
@@ -2,6 +2,7 @@ import React, { Component } from "react"
import { Map } from "immutable"
import PropTypes from "prop-types"
import win from "core/window"
import { getExtensions } from "core/utils"
export default class ParameterRow extends Component {
static propTypes = {
@@ -72,6 +73,8 @@ export default class ParameterRow extends Component {
let { isOAS3 } = specSelectors
const { showExtensions } = getConfigs()
// const onChangeWrapper = (value) => onChange(param, value)
const JsonSchemaForm = getComponent("JsonSchemaForm")
const ParamBody = getComponent("ParamBody")
@@ -91,6 +94,7 @@ export default class ParameterRow extends Component {
const ModelExample = getComponent("modelExample")
const Markdown = getComponent("Markdown")
const ParameterExt = getComponent("ParameterExt")
let schema = param.get("schema")
let type = isOAS3 && isOAS3() ? param.getIn(["schema", "type"]) : param.get("type")
@@ -100,6 +104,7 @@ export default class ParameterRow extends Component {
let itemType = param.getIn(isOAS3 && isOAS3() ? ["schema", "items", "type"] : ["items", "type"])
let parameter = specSelectors.getParameter(pathMethod, param.get("name"), param.get("in"))
let value = parameter ? parameter.get("value") : ""
let extensions = getExtensions(param)
return (
<tr>
@@ -113,6 +118,7 @@ export default class ParameterRow extends Component {
{ isOAS3 && isOAS3() && param.get("deprecated") ? "deprecated": null }
</div>
<div className="parameter__in">({ param.get("in") })</div>
{ !showExtensions || !extensions.size ? null : extensions.map((v, key) => <ParameterExt key={`${key}-${v}`} xKey={key} xVal={v} /> )}
</td>
<td className="col parameters-col_description">
+12 -2
View File
@@ -1,5 +1,6 @@
import React, { Component } from "react"
import PropTypes from "prop-types"
import { getExtensions } from "core/utils"
const propStyle = { color: "#999", fontStyle: "italic" }
@@ -7,12 +8,15 @@ export default class Primitive extends Component {
static propTypes = {
schema: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired,
name: PropTypes.string,
depth: PropTypes.number
}
render(){
let { schema, getComponent, name, depth } = this.props
let { schema, getComponent, getConfigs, name, depth } = this.props
const { showExtensions } = getConfigs()
if(!schema || !schema.get) {
// don't render if schema isn't correctly formed
@@ -25,7 +29,10 @@ export default class Primitive extends Component {
let enumArray = schema.get("enum")
let title = schema.get("title") || name
let description = schema.get("description")
let properties = schema.filter( ( v, key) => ["enum", "type", "format", "description", "$$ref"].indexOf(key) === -1 )
let extensions = getExtensions(schema)
let properties = schema
.filter( ( v, key) => ["enum", "type", "format", "description", "$$ref"].indexOf(key) === -1 )
.filterNot( (v, key) => extensions.has(key) )
const Markdown = getComponent("Markdown")
const EnumModel = getComponent("EnumModel")
const Property = getComponent("Property")
@@ -38,6 +45,9 @@ export default class Primitive extends Component {
{
properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <Property key={`${key}-${v}`} propKey={ key } propVal={ v } propStyle={ propStyle } />) : null
}
{
showExtensions && extensions.size ? extensions.entrySeq().map( ( [ key, v ] ) => <Property key={`${key}-${v}`} propKey={ key } propVal={ v } propStyle={ propStyle } />) : null
}
{
!description ? null :
<Markdown source={ description } />
+2 -2
View File
@@ -1,7 +1,7 @@
import React from "react"
import PropTypes from "prop-types"
import cx from "classnames"
import { fromJS, Seq } from "immutable"
import { fromJS, Seq, Iterable } from "immutable"
import { getSampleSchema, fromJSOrdered } from "core/utils"
const getExampleComponent = ( sampleResponse, examples, HighlightCode ) => {
@@ -42,7 +42,7 @@ export default class Response extends React.Component {
static propTypes = {
code: PropTypes.string.isRequired,
response: PropTypes.object,
response: PropTypes.instanceOf(Iterable),
className: PropTypes.string,
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired,
+26 -16
View File
@@ -1,41 +1,52 @@
import React from "react"
import PropTypes from "prop-types"
import { fromJS } from "immutable"
import { fromJS, Iterable } from "immutable"
import { defaultStatusCode, getAcceptControllingResponse } from "core/utils"
export default class Responses extends React.Component {
static propTypes = {
request: PropTypes.object,
tryItOutResponse: PropTypes.object,
responses: PropTypes.object.isRequired,
produces: PropTypes.object,
tryItOutResponse: PropTypes.instanceOf(Iterable),
responses: PropTypes.instanceOf(Iterable).isRequired,
produces: PropTypes.instanceOf(Iterable),
producesValue: PropTypes.any,
displayRequestDuration: PropTypes.bool.isRequired,
path: PropTypes.string.isRequired,
method: PropTypes.string.isRequired,
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired,
specSelectors: PropTypes.object.isRequired,
specActions: PropTypes.object.isRequired,
oas3Actions: PropTypes.object.isRequired,
pathMethod: PropTypes.array.isRequired,
displayRequestDuration: PropTypes.bool.isRequired,
fn: PropTypes.object.isRequired
}
static defaultProps = {
request: null,
tryItOutResponse: null,
produces: fromJS(["application/json"]),
displayRequestDuration: false
}
onChangeProducesWrapper = ( val ) => this.props.specActions.changeProducesValue(this.props.pathMethod, val)
shouldComponentUpdate(nextProps) {
// BUG: props.tryItOutResponse is always coming back as a new Immutable instance
let render = this.props.tryItOutResponse !== nextProps.tryItOutResponse
|| this.props.responses !== nextProps.responses
|| this.props.produces !== nextProps.produces
|| this.props.producesValue !== nextProps.producesValue
|| this.props.displayRequestDuration !== nextProps.displayRequestDuration
|| this.props.path !== nextProps.path
|| this.props.method !== nextProps.method
return render
}
onChangeProducesWrapper = ( val ) => this.props.specActions.changeProducesValue([this.props.path, this.props.method], val)
onResponseContentTypeChange = ({ controlsAcceptHeader, value }) => {
const { oas3Actions, pathMethod } = this.props
const { oas3Actions, path, method } = this.props
if(controlsAcceptHeader) {
oas3Actions.setResponseContentType({
value,
pathMethod
path,
method
})
}
}
@@ -43,7 +54,6 @@ export default class Responses extends React.Component {
render() {
let {
responses,
request,
tryItOutResponse,
getComponent,
getConfigs,
@@ -81,12 +91,12 @@ export default class Responses extends React.Component {
{
!tryItOutResponse ? null
: <div>
<LiveResponse request={ request }
response={ tryItOutResponse }
<LiveResponse response={ tryItOutResponse }
getComponent={ getComponent }
getConfigs={ getConfigs }
specSelectors={ specSelectors }
pathMethod={ this.props.pathMethod }
path={ this.props.path }
method={ this.props.method }
displayRequestDuration={ displayRequestDuration } />
<h4>Responses</h4>
</div>
+203
View File
@@ -0,0 +1,203 @@
import React, { PureComponent } from "react"
import PropTypes from "prop-types"
import { helpers } from "swagger-client"
import { Iterable, fromJS } from "immutable"
const { opId } = helpers
export default class OperationContainer extends PureComponent {
constructor(props, context) {
super(props, context)
this.state = {
tryItOutEnabled: false,
executeInProgress: false
}
}
static propTypes = {
op: PropTypes.instanceOf(Iterable).isRequired,
tag: PropTypes.string.isRequired,
path: PropTypes.string.isRequired,
method: PropTypes.string.isRequired,
operationId: PropTypes.string.isRequired,
showSummary: PropTypes.bool.isRequired,
isShown: PropTypes.bool.isRequired,
jumpToKey: PropTypes.string.isRequired,
allowTryItOut: PropTypes.bool,
displayOperationId: PropTypes.bool,
isAuthorized: PropTypes.bool,
displayRequestDuration: PropTypes.bool,
response: PropTypes.instanceOf(Iterable),
request: PropTypes.instanceOf(Iterable),
security: PropTypes.instanceOf(Iterable),
isDeepLinkingEnabled: PropTypes.bool.isRequired,
getComponent: PropTypes.func.isRequired,
authActions: PropTypes.object,
oas3Actions: PropTypes.object,
authSelectors: PropTypes.object,
specActions: PropTypes.object.isRequired,
specSelectors: PropTypes.object.isRequired,
layoutActions: PropTypes.object.isRequired,
layoutSelectors: PropTypes.object.isRequired,
fn: PropTypes.object.isRequired,
getConfigs: PropTypes.func.isRequired
}
static defaultProps = {
showSummary: true,
response: null,
allowTryItOut: true,
displayOperationId: false,
displayRequestDuration: false
}
mapStateToProps(nextState, props) {
const { op, layoutSelectors, getConfigs } = props
const { docExpansion, deepLinking, displayOperationId, displayRequestDuration } = getConfigs()
const showSummary = layoutSelectors.showSummary()
const operationId = op.getIn(["operation", "operationId"]) || op.getIn(["operation", "__originalOperationId"]) || opId(op.get("operation"), props.path, props.method) || op.get("id")
const isShownKey = ["operations", props.tag, operationId]
const isDeepLinkingEnabled = deepLinking && deepLinking !== "false"
const allowTryItOut = typeof props.allowTryItOut === "undefined" ?
props.specSelectors.allowTryItOutFor(props.path, props.method) : props.allowTryItOut
const security = op.getIn(["operation", "security"]) || props.specSelectors.security()
return {
operationId,
isDeepLinkingEnabled,
showSummary,
displayOperationId,
displayRequestDuration,
allowTryItOut,
security,
isAuthorized: props.authSelectors.isAuthorized(security),
isShown: layoutSelectors.isShown(isShownKey, docExpansion === "full" ),
jumpToKey: `paths.${props.path}.${props.method}`,
response: props.specSelectors.responseFor(props.path, props.method),
request: props.specSelectors.requestFor(props.path, props.method)
}
}
componentWillReceiveProps(nextProps) {
const defaultContentType = "application/json"
let { specActions, path, method, op } = nextProps
let operation = op.get("operation")
let producesValue = operation.get("produces_value")
let produces = operation.get("produces")
let consumes = operation.get("consumes")
let consumesValue = operation.get("consumes_value")
if(nextProps.response !== this.props.response) {
this.setState({ executeInProgress: false })
}
if (producesValue === undefined) {
producesValue = produces && produces.size ? produces.first() : defaultContentType
specActions.changeProducesValue([path, method], producesValue)
}
if (consumesValue === undefined) {
consumesValue = consumes && consumes.size ? consumes.first() : defaultContentType
specActions.changeConsumesValue([path, method], consumesValue)
}
}
toggleShown =() => {
let { layoutActions, tag, operationId, isShown } = this.props
layoutActions.show(["operations", tag, operationId], !isShown)
}
onTryoutClick =() => {
this.setState({tryItOutEnabled: !this.state.tryItOutEnabled})
}
onCancelClick =() => {
let { specActions, path, method } = this.props
this.setState({tryItOutEnabled: !this.state.tryItOutEnabled})
specActions.clearValidateParams([path, method])
}
onExecute = () => {
this.setState({ executeInProgress: true })
}
render() {
let {
op,
tag,
path,
method,
security,
isAuthorized,
operationId,
showSummary,
isShown,
jumpToKey,
allowTryItOut,
response,
request,
displayOperationId,
displayRequestDuration,
isDeepLinkingEnabled,
specSelectors,
specActions,
getComponent,
getConfigs,
layoutSelectors,
layoutActions,
authActions,
authSelectors,
oas3Actions,
fn
} = this.props
const Operation = getComponent( "operation" )
const operationProps = fromJS({
op,
tag,
path,
method,
security,
isAuthorized,
operationId,
showSummary,
isShown,
jumpToKey,
allowTryItOut,
request,
displayOperationId,
displayRequestDuration,
isDeepLinkingEnabled,
executeInProgress: this.state.executeInProgress,
tryItOutEnabled: this.state.tryItOutEnabled
})
return (
<Operation
operation={operationProps}
response={response}
request={request}
isShown={isShown}
toggleShown={this.toggleShown}
onTryoutClick={this.onTryoutClick}
onCancelClick={this.onCancelClick}
onExecute={this.onExecute}
specActions={ specActions }
specSelectors={ specSelectors }
oas3Actions={oas3Actions}
layoutActions={ layoutActions }
layoutSelectors={ layoutSelectors }
authActions={ authActions }
authSelectors={ authSelectors }
getComponent={ getComponent }
getConfigs={ getConfigs }
fn={fn}
/>
)
}
}
+2 -2
View File
@@ -7,8 +7,7 @@ import * as AllPlugins from "core/plugins/all"
import { parseSearch } from "core/utils"
if (process.env.NODE_ENV !== "production") {
const Perf = require("react-addons-perf")
window.Perf = Perf
window.Perf = require("react-addons-perf")
}
// eslint-disable-next-line no-undef
@@ -47,6 +46,7 @@ module.exports = function SwaggerUI(opts) {
showMutatedRequest: true,
defaultModelRendering: "example",
defaultModelExpandDepth: 1,
showExtensions: false,
// Initial set of plugins ( TODO rename this, or refactor - we don't need presets _and_ plugins. Its just there for performance.
// Instead, we can compile the first plugin ( it can be a collection of plugins ), then batch the rest.
+20 -7
View File
@@ -58,6 +58,7 @@ export class JsonSchema_string extends Component {
if ( enumValue ) {
const Select = getComponent("Select")
return (<Select className={ errors.length ? "invalid" : ""}
title={ errors.length ? errors : ""}
allowedValues={ enumValue }
value={ value }
allowEmptyValue={ !required }
@@ -67,10 +68,20 @@ export class JsonSchema_string extends Component {
const isDisabled = schema["in"] === "formData" && !("FormData" in window)
const Input = getComponent("Input")
if (schema["type"] === "file") {
return <Input type="file" className={ errors.length ? "invalid" : ""} onChange={ this.onChange } disabled={isDisabled}/>
return (<Input type="file"
className={ errors.length ? "invalid" : ""}
title={ errors.length ? errors : ""}
onChange={ this.onChange }
disabled={isDisabled}/>)
}
else {
return <Input type={ schema.format === "password" ? "password" : "text" } className={ errors.length ? "invalid" : ""} value={value} placeholder={description} onChange={ this.onChange } disabled={isDisabled}/>
return (<Input type={ schema.format === "password" ? "password" : "text" }
className={ errors.length ? "invalid" : ""}
title={ errors.length ? errors : ""}
value={value}
placeholder={description}
onChange={ this.onChange }
disabled={isDisabled}/>)
}
}
}
@@ -134,11 +145,12 @@ export class JsonSchema_array extends PureComponent {
if ( enumValue ) {
const Select = getComponent("Select")
return (<Select className={ errors.length ? "invalid" : ""}
multiple={ true }
value={ value }
allowedValues={ enumValue }
allowEmptyValue={ !required }
onChange={ this.onEnumChange }/>)
title={ errors.length ? errors : ""}
multiple={ true }
value={ value }
allowedValues={ enumValue }
allowEmptyValue={ !required }
onChange={ this.onEnumChange }/>)
}
return (
@@ -175,6 +187,7 @@ export class JsonSchema_boolean extends Component {
const Select = getComponent("Select")
return (<Select className={ errors.length ? "invalid" : ""}
title={ errors.length ? errors : ""}
value={ String(value) }
allowedValues={ fromJS(["true", "false"]) }
allowEmptyValue={ true }
+1 -1
View File
@@ -73,7 +73,7 @@ export const authorizePassword = ( auth ) => ( { authActions } ) => {
let { schema, name, username, password, passwordType, clientId, clientSecret } = auth
let form = {
grant_type: "password",
scope: encodeURIComponent(auth.scopes.join(scopeSeparator))
scope: auth.scopes.join(scopeSeparator)
}
let query = {}
let headers = {}
+9 -1
View File
@@ -11,7 +11,7 @@ export const shownDefinitions = createSelector(
export const definitionsToAuthorize = createSelector(
state,
() => ( { specSelectors } ) => {
let definitions = specSelectors.securityDefinitions()
let definitions = specSelectors.securityDefinitions() || Map({})
let list = List()
//todo refactor
@@ -28,6 +28,7 @@ export const definitionsToAuthorize = createSelector(
export const getDefinitionsByNames = ( state, securities ) => ( { specSelectors } ) => {
console.warn("WARNING: getDefinitionsByNames is deprecated and will be removed in the next major version.")
let securityDefinitions = specSelectors.securityDefinitions()
let result = List()
@@ -58,6 +59,13 @@ export const getDefinitionsByNames = ( state, securities ) => ( { specSelectors
return result
}
export const definitionsForRequirements = (state, securities = List()) => ({ authSelectors }) => {
const allDefinitions = authSelectors.definitionsToAuthorize() || List()
return allDefinitions.filter((def) => {
return securities.some(sec => sec.get(def.keySeq().first()))
})
}
export const authorized = createSelector(
state,
auth => auth.get("authorized") || Map()
+8
View File
@@ -3,6 +3,7 @@ import serializeError from "serialize-error"
export const NEW_THROWN_ERR = "err_new_thrown_err"
export const NEW_THROWN_ERR_BATCH = "err_new_thrown_err_batch"
export const NEW_SPEC_ERR = "err_new_spec_err"
export const NEW_SPEC_ERR_BATCH = "err_new_spec_err_batch"
export const NEW_AUTH_ERR = "err_new_auth_err"
export const CLEAR = "err_clear"
@@ -27,6 +28,13 @@ export function newSpecErr(err) {
}
}
export function newSpecErrBatch(errArray) {
return {
type: NEW_SPEC_ERR_BATCH,
payload: errArray
}
}
export function newAuthErr(err) {
return {
type: NEW_AUTH_ERR,
+10
View File
@@ -2,6 +2,7 @@ import {
NEW_THROWN_ERR,
NEW_THROWN_ERR_BATCH,
NEW_SPEC_ERR,
NEW_SPEC_ERR_BATCH,
NEW_AUTH_ERR,
CLEAR
} from "./actions"
@@ -45,6 +46,15 @@ export default function(system) {
.update("errors", errors => transformErrors(errors, system.getSystem()))
},
[NEW_SPEC_ERR_BATCH]: (state, { payload }) => {
payload = payload.map(err => {
return fromJS(Object.assign(DEFAULT_ERROR_STRUCTURE, err, { type: "spec" }))
})
return state
.update("errors", errors => (errors || List()).concat( fromJS( payload )) )
.update("errors", errors => transformErrors(errors, system.getSystem()))
},
[NEW_AUTH_ERR]: (state, { payload }) => {
let error = fromJS(Object.assign({}, payload))
+2 -2
View File
@@ -28,10 +28,10 @@ export function setRequestContentType ({ value, pathMethod }) {
}
}
export function setResponseContentType ({ value, pathMethod }) {
export function setResponseContentType ({ value, path, method }) {
return {
type: UPDATE_RESPONSE_CONTENT_TYPE,
payload: { value, pathMethod }
payload: { value, path, method }
}
}
+12 -12
View File
@@ -1,10 +1,12 @@
import React from "react"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
import { fromJS } from "immutable"
const Callbacks = (props) => {
let { callbacks, getComponent } = props
// const Markdown = getComponent("Markdown")
const Operation = getComponent("operation", true)
const OperationContainer = getComponent("OperationContainer", true)
if(!callbacks) {
return <span>No callbacks</span>
@@ -16,24 +18,22 @@ const Callbacks = (props) => {
{ callback.map((pathItem, pathItemName) => {
return <div key={pathItemName}>
{ pathItem.map((operation, method) => {
return <Operation
operation={operation}
let op = fromJS({
operation
})
return <OperationContainer
{...props}
op={op}
key={method}
tag={""}
method={method}
isShownKey={["callbacks", operation.get("id"), callbackName]}
path={pathItemName}
allowTryItOut={false}
{...props}></Operation>
// return <pre>{JSON.stringify(operation)}</pre>
/>
}) }
</div>
}) }
</div>
// return <div>
// <h2>{name}</h2>
// {callback.description && <Markdown source={callback.description}/>}
// <pre>{JSON.stringify(callback)}</pre>
// </div>
})
return <div>
{callbackElements}
@@ -42,7 +42,7 @@ const Callbacks = (props) => {
Callbacks.propTypes = {
getComponent: PropTypes.func.isRequired,
callbacks: PropTypes.array.isRequired
callbacks: ImPropTypes.iterable.isRequired
}
@@ -48,6 +48,13 @@ export default class RequestBodyEditor extends PureComponent {
}
}
componentDidUpdate(prevProps) {
if(this.props.requestBody !== prevProps.requestBody) {
// force recalc of value if the request body definition has changed
this.setValueToSample(this.props.mediaType)
}
}
setValueToSample = (explicitMediaType) => {
this.onChange(this.sample(explicitMediaType))
}
@@ -22,6 +22,10 @@ const RequestBody = ({
const mediaTypeValue = requestBodyContent.get(contentType)
if(!mediaTypeValue) {
return null
}
return <div>
{ requestBodyDescription &&
<Markdown source={requestBodyDescription} />
@@ -50,7 +54,7 @@ RequestBody.propTypes = {
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired,
specSelectors: PropTypes.object.isRequired,
contentType: PropTypes.string.isRequired,
contentType: PropTypes.string,
isExecute: PropTypes.bool.isRequired,
onChange: PropTypes.func.isRequired
}
+1 -2
View File
@@ -18,8 +18,7 @@ export default {
let [path, method] = pathMethod
return state.setIn( [ "requestData", path, method, "requestContentType" ], value)
},
[UPDATE_RESPONSE_CONTENT_TYPE]: (state, { payload: { value, pathMethod } } ) =>{
let [path, method] = pathMethod
[UPDATE_RESPONSE_CONTENT_TYPE]: (state, { payload: { value, path, method } } ) =>{
return state.setIn( [ "requestData", path, method, "responseContentType" ], value)
},
[UPDATE_SERVER_VARIABLE_VALUE]: (state, { payload: { server, key, val } } ) =>{
@@ -8,12 +8,13 @@ class ModelComponent extends Component {
schema: PropTypes.object.isRequired,
name: PropTypes.string,
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired,
specSelectors: PropTypes.object.isRequired,
expandDepth: PropTypes.number
}
render(){
let { schema } = this.props
let { getConfigs, schema } = this.props
let classes = ["model-box"]
let isDeprecated = schema.get("deprecated") === true
let message = null
@@ -26,6 +27,7 @@ class ModelComponent extends Component {
return <div className={classes.join(" ")}>
{message}
<Model { ...this.props }
getConfigs={ getConfigs }
depth={ 1 }
expandDepth={ this.props.expandDepth || 0 }
/>
@@ -22,6 +22,7 @@ class Parameters extends Component {
specActions: PropTypes.object.isRequired,
operation: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired,
getConfigs: PropTypes.func.isRequired,
specSelectors: PropTypes.object.isRequired,
oas3Actions: PropTypes.object.isRequired,
oas3Selectors: PropTypes.object.isRequired,
@@ -86,6 +87,7 @@ class Parameters extends Component {
fn,
getComponent,
getConfigs,
specSelectors,
oas3Actions,
oas3Selectors,
@@ -137,6 +139,7 @@ class Parameters extends Component {
eachMap(parameters, (parameter) => (
<ParameterRow fn={ fn }
getComponent={ getComponent }
getConfigs={ getConfigs }
param={ parameter }
key={ parameter.get( "name" ) }
onChange={ this.onChange }
+8 -2
View File
@@ -20,8 +20,14 @@ const RootWrapper = (reduxStore, ComponentToWrap) => class extends Component {
}
const makeContainer = (getSystem, component, reduxStore) => {
const mapStateToProps = function(state, ownProps) {
const propsForContainerComponent = Object.assign({}, ownProps, getSystem())
const ori = component.prototype.mapStateToProps || (state => { return {state} })
return ori(state, propsForContainerComponent)
}
let wrappedWithSystem = SystemWrapper(getSystem, component, reduxStore)
let connected = connect(state => ({state}))(wrappedWithSystem)
let connected = connect( mapStateToProps )(wrappedWithSystem)
if(reduxStore)
return RootWrapper(reduxStore, connected)
return connected
@@ -114,5 +120,5 @@ export const getComponent = (getSystem, getStore, getComponents, componentName,
return makeContainer(getSystem, component, getStore())
// container == truthy
return makeContainer(getSystem, component)
return makeContainer(getSystem, wrapRender(component))
}
+10 -1
View File
@@ -13,6 +13,8 @@ import downloadUrlPlugin from "core/plugins/download-url"
import configsPlugin from "plugins/configs"
import deepLinkingPlugin from "core/plugins/deep-linking"
import OperationContainer from "core/containers/OperationContainer"
import App from "core/components/app"
import AuthorizationPopup from "core/components/auth/authorization-popup"
import AuthorizeBtn from "core/components/auth/authorize-btn"
@@ -28,11 +30,14 @@ import LiveResponse from "core/components/live-response"
import OnlineValidatorBadge from "core/components/online-validator-badge"
import Operations from "core/components/operations"
import Operation from "core/components/operation"
import OperationExt from "core/components/operation-extensions"
import OperationExtRow from "core/components/operation-extension-row"
import HighlightCode from "core/components/highlight-code"
import Responses from "core/components/responses"
import Response from "core/components/response"
import ResponseBody from "core/components/response-body"
import Parameters from "core/components/parameters"
import ParameterExt from "core/components/parameter-extension"
import ParameterRow from "core/components/parameter-row"
import Execute from "core/components/execute"
import Headers from "core/components/headers"
@@ -112,7 +117,11 @@ export default function() {
TryItOutButton,
Markdown,
BaseLayout,
VersionStamp
VersionStamp,
OperationExt,
OperationExtRow,
ParameterExt,
OperationContainer
}
}
+1 -2
View File
@@ -289,8 +289,7 @@ export default class Store {
getMapStateToProps() {
return () => {
let obj = Object.assign({}, this.getSystem())
return obj
return Object.assign({}, this.getSystem())
}
}
+4 -2
View File
@@ -494,8 +494,8 @@ export const validateParam = (param, isXml, isOAS3 = false) => {
let listCheck = type === "array" && Im.List.isList(value) && value.count()
let fileCheck = type === "file" && value instanceof win.File
let booleanCheck = type === "boolean" && (value || value === false)
let numberCheck = type === "number" && value
let integerCheck = type === "integer" && value
let numberCheck = type === "number" && (value || value === 0)
let integerCheck = type === "integer" && (value || value === 0)
if ( required && !(stringCheck || arrayCheck || listCheck || fileCheck || booleanCheck || numberCheck || integerCheck) ) {
errors.push("Required field is not provided")
@@ -692,3 +692,5 @@ export function getAcceptControllingResponse(responses) {
export const createDeepLinkPath = (str) => typeof str == "string" || str instanceof String ? str.trim().replace(/\s/g, "_") : ""
export const escapeDeepLinkPath = (str) => cssEscape( createDeepLinkPath(str) )
export const getExtensions = (defObj) => defObj.filter((v, k) => /^x-/.test(k))
+2 -2
View File
@@ -1,4 +1,4 @@
import React from "react"
import React, { cloneElement } from "react"
import PropTypes from "prop-types"
//import "./topbar.less"
@@ -134,7 +134,7 @@ export default class Topbar extends React.Component {
<span>swagger</span>
</Link>
<form className="download-url-wrapper" onSubmit={formOnSubmit}>
{control}
{control.map((el, i) => cloneElement(el, { key: i }))}
</form>
</div>
</div>
+5
View File
@@ -3,3 +3,8 @@
if(!window.Promise) {
require("core-js/fn/promise")
}
// Required by IE 11
if(!String.prototype.startsWith) {
require("core-js/es6/string")
}
+4
View File
@@ -5,6 +5,10 @@
padding: 10px 0;
justify-content: center;
.btn-done {
margin-right: 1em;
}
}
.auth-wrapper
+7
View File
@@ -565,6 +565,7 @@
p
{
margin: 0;
@include text_code($response-col-description-inner-markdown-font-color);
}
a
@@ -575,6 +576,12 @@
color: $response-col-description-inner-markdown-link-font-color-hover;
}
}
th
{
@include text_code($response-col-description-inner-markdown-font-color);
border-bottom: 1px solid $response-col-description-inner-markdown-font-color;
}
}
}
+20 -10
View File
@@ -3,14 +3,20 @@
font-size: 12px;
font-weight: 300;
@include text_code();
.deprecated
{
span, td {
color: $model-deprecated-font-color !important;
}
}
span,
td
{
color: $model-deprecated-font-color !important;
}
@include text_code();
> td:first-of-type {
text-decoration: line-through;
}
}
&-toggle
{
font-size: 10px;
@@ -87,7 +93,8 @@
background: rgba($model-hint-background-color,.7);
}
p {
p
{
margin: 0 0 1em 0;
}
}
@@ -106,6 +113,7 @@ section.models
h4
{
margin: 0 0 5px 0;
border-bottom: 1px solid rgba($section-models-isopen-h4-border-bottom-color, .3);
}
}
@@ -114,6 +122,7 @@ section.models
font-size: 16px;
display: flex;
align-items: center;
margin: 0;
padding: 10px 20px 10px 10px;
@@ -122,7 +131,6 @@ section.models
transition: all .2s;
@include text_headline($section-models-h4-font-color);
align-items: center;
svg
{
@@ -202,7 +210,7 @@ section.models
&.deprecated
{
opacity: .5;
opacity: .5;
}
}
@@ -218,14 +226,16 @@ section.models
{
font-size: 16px;
font-weight: 600;
margin-right: 1em;
@include text_headline($_color-delete);
}
span
{
> span.model
> span.model
{
.brace-close
{
@@ -237,8 +247,8 @@ span
.prop-name
{
display: inline-block;
margin-right: 1em;
width: 8em;
}
.prop-type
+3 -2
View File
@@ -19,7 +19,7 @@ table
&:first-of-type
{
width: 124px;
width: 174px;
padding: 0 0 0 2em;
}
}
@@ -131,7 +131,8 @@ table
}
}
.parameter__in
.parameter__in,
.parameter__extension
{
font-size: 12px;
font-style: italic;
+68
View File
@@ -0,0 +1,68 @@
import React from "react"
import expect from "expect"
import { shallow } from "enzyme"
import { fromJS } from "immutable"
import ObjectModel from "components/object-model"
import ModelExample from "components/model-example"
import Immutable from "immutable"
import Model from "components/model"
import ModelCollapse from "components/model-collapse"
import { inferSchema } from "corePlugins/samples/fn"
describe("<ObjectModel />", function() {
const dummyComponent = () => null
const components = {
"JumpToPath" : dummyComponent,
"Markdown" : dummyComponent,
"Model" : Model,
"ModelCollapse" : ModelCollapse
}
const props = {
getComponent: c => components[c],
getConfigs: () => {
return {
showExtensions: true
}
},
isRef : false,
schema: Immutable.fromJS(
{
"properties": {
// Note reverse order: c, b, a
c: {
type: "integer",
name: "c"
},
b: {
type: "boolean",
name: "b"
},
a: {
type: "string",
name: "a"
}
}
}
),
specSelectors: {
isOAS3(){
return false
}
},
className: "for-test"
}
it("renders a collapsible header", function(){
const wrapper = shallow(<ObjectModel {...props}/>)
const renderedModelCollapse = wrapper.find(ModelCollapse)
expect(renderedModelCollapse.length).toEqual(1)
})
it("renders the object properties in order", function() {
const wrapper = shallow(<ObjectModel {...props}/>)
const renderedModel = wrapper.find(Model)
expect(renderedModel.length).toEqual(3)
expect(renderedModel.get(0).props.schema.get("name")).toEqual("c")
expect(renderedModel.get(1).props.schema.get("name")).toEqual("b")
expect(renderedModel.get(2).props.schema.get("name")).toEqual("a")
})
})
+4 -1
View File
@@ -14,6 +14,9 @@ describe("<PrimitiveModel/>", function() {
}
const props = {
getComponent: c => components[c],
getConfigs: () => ({
showExtensions: false
}),
name: "Name from props",
depth: 1,
schema: fromJS({
@@ -46,4 +49,4 @@ describe("<PrimitiveModel/>", function() {
})
})
} )
} )
+133
View File
@@ -0,0 +1,133 @@
/* eslint-env mocha */
import expect from "expect"
import { fromJS } from "immutable"
import { definitionsToAuthorize, definitionsForRequirements } from "corePlugins/auth/selectors"
describe("auth plugin - selectors", () => {
describe("definitionsToAuthorize", () => {
it("should return securityDefinitions as a List", () => {
const securityDefinitions = {
"petstore_auth": {
"type": "oauth2",
"authorizationUrl": "http://petstore.swagger.io/oauth/dialog",
"flow": "implicit",
"scopes": {
"write:pets": "modify pets in your account",
"read:pets": "read your pets"
}
},
"api_key": {
"type": "apiKey",
"name": "api_key",
"in": "header"
}
}
const system = {
specSelectors: {
securityDefinitions() {
return fromJS(securityDefinitions)
}
}
}
const res = definitionsToAuthorize({})(system)
expect(res.toJS()).toEqual([
{
"petstore_auth": securityDefinitions["petstore_auth"]
},
{
"api_key": securityDefinitions["api_key"]
},
])
})
it("should fail gracefully with bad data", () => {
const securityDefinitions = null
const system = {
specSelectors: {
securityDefinitions() {
return fromJS(securityDefinitions)
}
}
}
const res = definitionsToAuthorize({})(system)
expect(res.toJS()).toEqual([])
})
})
describe("definitionsForRequirements", () => {
it("should return applicable securityDefinitions as a List", () => {
const securityDefinitions = {
"petstore_auth": {
"type": "oauth2",
"authorizationUrl": "http://petstore.swagger.io/oauth/dialog",
"flow": "implicit",
"scopes": {
"write:pets": "modify pets in your account",
"read:pets": "read your pets"
}
},
"api_key": {
"type": "apiKey",
"name": "api_key",
"in": "header"
}
}
const system = {
authSelectors: {
definitionsToAuthorize() {
return fromJS([
{
"petstore_auth": securityDefinitions["petstore_auth"]
},
{
"api_key": securityDefinitions["api_key"]
},
])
}
}
}
const securities = fromJS([
{
"petstore_auth": [
"write:pets",
"read:pets"
]
}
])
const res = definitionsForRequirements({}, securities)(system)
expect(res.toJS()).toEqual([
{
"petstore_auth": securityDefinitions["petstore_auth"]
}
])
})
it("should fail gracefully with bad data", () => {
const securityDefinitions = null
const system = {
authSelectors: {
definitionsToAuthorize() {
return null
}
}
}
const securities = null
const res = definitionsForRequirements({}, securities)(system)
expect(res.toJS()).toEqual([])
})
})
})
+239
View File
@@ -1,7 +1,11 @@
/* eslint-env mocha */
import React, { PureComponent } from "react"
import expect from "expect"
import System from "core/system"
import { fromJS } from "immutable"
import { render } from "enzyme"
import ViewPlugin from "core/plugins/view/index.js"
import { connect, Provider } from "react-redux"
describe("bound system", function(){
@@ -444,4 +448,239 @@ describe("bound system", function(){
})
describe("getComponent", function() {
it("returns a component from the system", function() {
const system = new System({
plugins: [
ViewPlugin,
{
components: {
test: ({ name }) => <div>{name} component</div>
}
}
]
})
// When
var Component = system.getSystem().getComponent("test")
const renderedComponent = render(<Component name="Test" />)
expect(renderedComponent.text()).toEqual("Test component")
})
it("allows container components to provide their own `mapStateToProps` function", function() {
// Given
class ContainerComponent extends PureComponent {
mapStateToProps(nextState, props) {
return {
"fromMapState": "This came from mapStateToProps"
}
}
static defaultProps = {
"fromMapState" : ""
}
render() {
const { exampleSelectors, fromMapState, fromOwnProps } = this.props
return (
<div>{ fromMapState } {exampleSelectors.foo()} {fromOwnProps}</div>
)
}
}
const system = new System({
plugins: [
ViewPlugin,
{
components: {
ContainerComponent
}
},
{
statePlugins: {
example: {
selectors: {
foo() { return "and this came from the system" }
}
}
}
}
]
})
// When
var Component = system.getSystem().getComponent("ContainerComponent", true)
const renderedComponent = render(
<Provider store={system.getStore()}>
<Component fromOwnProps="and this came from my own props" />
</Provider>
)
// Then
expect(renderedComponent.text()).toEqual("This came from mapStateToProps and this came from the system and this came from my own props")
})
it("gives the system and own props as props to a container's `mapStateToProps` function", function() {
// Given
class ContainerComponent extends PureComponent {
mapStateToProps(nextState, props) {
const { exampleSelectors, fromMapState, fromOwnProps } = props
return {
"fromMapState": `This came from mapStateToProps ${exampleSelectors.foo()} ${fromOwnProps}`
}
}
static defaultProps = {
"fromMapState" : ""
}
render() {
const { fromMapState } = this.props
return (
<div>{ fromMapState }</div>
)
}
}
const system = new System({
plugins: [
ViewPlugin,
{
components: {
ContainerComponent
}
},
{
statePlugins: {
example: {
selectors: {
foo() { return "and this came from the system" }
}
}
}
}
]
})
// When
var Component = system.getSystem().getComponent("ContainerComponent", true)
const renderedComponent = render(
<Provider store={system.getStore()}>
<Component fromOwnProps="and this came from my own props" />
</Provider>
)
// Then
expect(renderedComponent.text()).toEqual("This came from mapStateToProps and this came from the system and this came from my own props")
})
it("should catch errors thrown inside of React Component Class render methods", function() {
// Given
// eslint-disable-next-line react/require-render-return
class BrokenComponent extends React.Component {
render() {
throw new Error("This component is broken")
}
}
const system = new System({
plugins: [
ViewPlugin,
{
components: {
BrokenComponent
}
}
]
})
// When
var Component = system.getSystem().getComponent("BrokenComponent")
const renderedComponent = render(<Component />)
// Then
expect(renderedComponent.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
})
it("should catch errors thrown inside of pure component render methods", function() {
// Given
// eslint-disable-next-line react/require-render-return
class BrokenComponent extends PureComponent {
render() {
throw new Error("This component is broken")
}
}
const system = new System({
plugins: [
ViewPlugin,
{
components: {
BrokenComponent
}
}
]
})
// When
var Component = system.getSystem().getComponent("BrokenComponent")
const renderedComponent = render(<Component />)
// Then
expect(renderedComponent.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
})
it("should catch errors thrown inside of stateless component functions", function() {
// Given
// eslint-disable-next-line react/require-render-return
let BrokenComponent = function BrokenComponent() { throw new Error("This component is broken") }
const system = new System({
plugins: [
ViewPlugin,
{
components: {
BrokenComponent
}
}
]
})
// When
var Component = system.getSystem().getComponent("BrokenComponent")
const renderedComponent = render(<Component />)
// Then
expect(renderedComponent.text().startsWith("😱 Could not render")).toEqual(true)
})
it("should catch errors thrown inside of container components", function() {
// Given
// eslint-disable-next-line react/require-render-return
class BrokenComponent extends React.Component {
render() {
throw new Error("This component is broken")
}
}
const system = new System({
plugins: [
ViewPlugin,
{
components: {
BrokenComponent
}
}
]
})
// When
var Component = system.getSystem().getComponent("BrokenComponent", true)
const renderedComponent = render(
<Provider store={system.getStore()}>
<Component />
</Provider>
)
// Then
expect(renderedComponent.text()).toEqual("😱 Could not render BrokenComponent, see the console.")
})
})
})
+8
View File
@@ -700,6 +700,14 @@ describe("utils", function() {
}
assertValidateParam(param, ["Required field is not provided"])
// valid integer, but 0 is falsy in JS
param = {
required: true,
type: "integer",
value: 0
}
assertValidateParam(param, [])
// valid integer
param = {
required: true,
+32 -5
View File
@@ -93,6 +93,7 @@ module.exports = {
petAPIWrapperBar: {
selector: ".swagger-ui .opblock-tag-section:nth-child(1) .opblock-tag"
},
/**
* Post pet/ api
*/
@@ -141,6 +142,7 @@ module.exports = {
petOperationPostStatus: {
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-addPet pre.microlight span:nth-child(70)"
},
/**
* Put pet/ api
*/
@@ -189,8 +191,9 @@ module.exports = {
petOperationPutStatus: {
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-updatePet pre.microlight span:nth-child(70)"
},
/**
* Get pet/
* Get /pet/findByTags
*/
petOperationGetByTagContainer: {
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags"
@@ -237,6 +240,34 @@ module.exports = {
petOperationGetByTagStatus: {
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-findPetsByTags pre.microlight span:nth-child(70)"
},
/**
* Get /pet/{petId}
*/
petOperationGetByIdContainer: {
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-getPetById"
},
petOperationGetByIdTitle: {
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-getPetById .opblock-summary-get span.opblock-summary-path span"
},
petOperationGetByIdCollpase: {
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-getPetById .opblock-summary-get"
},
petOperationGetByIdCollapseContainer: {
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-getPetById .ReactCollapse--collapse"
},
petOperationGetByIdTryBtn: {
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-getPetById button.try-out__btn"
},
petOperationGetByIdExecuteBtn: {
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-getPetById button.execute"
},
petOperationGetByIdParameter: {
selector: ".swagger-ui .opblock-tag-section:nth-child(3) div#operations-pet-getPetById div.parameters-col_description input"
},
petOperationGetByIdResultsBox: {
selector: ".swagger-ui .opblock-tag-section:nth-child(1) div#operations-pet-getPetById pre.microlight"
},
/**
* Delete pet/
@@ -497,9 +528,5 @@ module.exports = {
},
}
}
}
}
+34
View File
@@ -84,6 +84,7 @@ describe("render pet api container", function () {
client.end()
})
it("Testing put /pet api Mock data", function (client) {
apiWrapper.waitForElementVisible("@petOperationPutContainer", 5000)
.click("@petOperationPutCollpase")
@@ -137,6 +138,38 @@ describe("render pet api container", function () {
client.end()
})
it("render get by ID /pet/{petId} api container", function (client) {
apiWrapper.waitForElementVisible("@petOperationGetByIdContainer", 5000)
.assert.containsText("@petOperationGetByIdTitle", "/pet/{petId}")
.click("@petOperationGetByIdCollpase")
.waitForElementVisible("@petOperationGetByIdCollapseContainer", 3000)
.click("@petOperationGetByIdTryBtn")
.waitForElementVisible("@petOperationGetByTagExecuteBtn", 1000)
.click("@petOperationGetByTagTryBtn")
.assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel")
client.end()
})
it("render get by ID /pet/{petId} api Mock data", function (client) {
apiWrapper.waitForElementVisible("@petOperationGetByIdContainer", 5000)
.assert.containsText("@petOperationGetByIdTitle", "/pet/{petId}")
.click("@petOperationGetByIdCollpase")
.waitForElementVisible("@petOperationGetByIdCollapseContainer", 3000)
.click("@petOperationGetByIdTryBtn")
.waitForElementVisible("@petOperationGetByTagExecuteBtn", 1000)
.setValue("@petOperationGetByIdParameter", "abc")
.click("@petOperationGetByIdExecuteBtn")
.waitForElementVisible("@petOperationGetByIdResultsBox")
.assert.containsText("@petOperationGetByIdParameter", "abc")
.assert.cssClassPresent("@petOperationGetByIdParameter", "invalid")
.assert.attributeEquals("@petOperationGetByIdParameter", "title", "Value must be an integer")
.click("@petOperationGetByTagTryBtn")
.assert.cssClassNotPresent("@petOperationGetByTagTryBtn", "cancel")
client.end()
})
it("render delete /pet api container", function (client) {
apiWrapper.waitForElementVisible("@petOperationDeleteContainer")
@@ -150,6 +183,7 @@ describe("render pet api container", function () {
client.end()
})
it("Testing delete /pet api Mock data", function (client) {
apiWrapper.waitForElementVisible("@petOperationDeleteContainer", 3000)
.click("@petOperationDeleteCollpase")