diff --git a/.gitignore b/.gitignore index 513ca6a879..615b76b4c3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,7 @@ /bower_components /dist /tooling/node_modules -cypress/screenshots +/cypress/screenshots +/cypress/videos +/.tmp +.DS_Store diff --git a/.travis.yml b/.travis.yml index 98b2e9ab9f..309b4936fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -183,6 +183,10 @@ jobs: env: - CYPRESS_framework=react-backbone <<: *defaults + - stage: test + env: + - CYPRESS_framework=react-redux + <<: *defaults - stage: test env: - CYPRESS_framework=reagent diff --git a/circle.yml b/circle.yml index 889a41dee3..9db2624a08 100644 --- a/circle.yml +++ b/circle.yml @@ -41,6 +41,8 @@ jobs: <<: *defaults react: <<: *defaults + react-redux: + <<: *defaults vue: <<: *defaults angularjs: @@ -150,6 +152,7 @@ workflows: - backbone - dojo - react + - react-redux - vue - angularjs - knockback diff --git a/examples/react-redux/.eslintrc b/examples/react-redux/.eslintrc new file mode 100644 index 0000000000..f5ee6e72a1 --- /dev/null +++ b/examples/react-redux/.eslintrc @@ -0,0 +1,17 @@ +{ + "env": { + "jest": true + }, + "extends": ["eslint:recommended", "plugin:react/recommended"], + "settings": { + "react": { + "version": "16.14.0" + } + }, + "rules": { + "no-extra-parens": 0, + "react/prop-types": 0, + "react/react-in-jsx-scope": 0 + // "react/jsx-max-props-per-line": [1, { "maximum": 2 }] + } +} diff --git a/examples/react-redux/.gitignore b/examples/react-redux/.gitignore new file mode 100644 index 0000000000..03e05e4c07 --- /dev/null +++ b/examples/react-redux/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +/node_modules diff --git a/examples/react-redux/README.md b/examples/react-redux/README.md new file mode 100644 index 0000000000..451477ece8 --- /dev/null +++ b/examples/react-redux/README.md @@ -0,0 +1,51 @@ +# TodoMVC: React-Redux + +## Description + +This application uses React in combination with Redux to implement the TodoMVC application. + +- [React](https://reactjs.org/) is a JavaScript library for creating user interfaces. +- [Redux](https://redux.js.org/) centralizes your application's state. +- [React-Redux](https://react-redux.js.org/) is designed to work with React's component model. + +## Implementation details + +This implementation uses Redux to manage state and data flow of the application. +The Redux pattern is similar to a mvc pattern, with the main difference that Redux is unidirectional. +Redux uses actions to dispatch a change, which is captured by reducers that update a central store. +Once the state in the store updates, the view receives the new state and can reflect those changes to the user. + +Redux:\ +Model: Redux store\ +View: React ui components\ +Controller: React connected components + Redux reducers + +MVC:\ +Model: maintains the data and behavior of an application\ +View: displays the model in the ui\ +Controller: serves as an interface between view & model components + +The storage solution uses an in-memory data object that implements a simple array to hold the todos. + +## Build steps + +To build the static files, this application utilizes webpack. It minifies and optimizes output files and copies all necessary files to a `dist` folder. + +## Requirements + +The only requirement is an installation of Node, to be able to install dependencies and run scripts to serve a local server. + +``` +* Node (min version: 18.13.0) +* NPM (min version: 8.19.3) +``` + +## Local preview + +``` +terminal: +1. npm install +2. npm run dev +browser: +1. http://localhost:7001/ +``` diff --git a/examples/react-redux/babel.config.js b/examples/react-redux/babel.config.js new file mode 100644 index 0000000000..997b25334b --- /dev/null +++ b/examples/react-redux/babel.config.js @@ -0,0 +1,7 @@ +// This file is used for Jest to function properly. +module.exports = { + presets: [ + ["@babel/preset-env", { targets: "defaults" }], + ["@babel/preset-react", { runtime: "automatic" }], + ], +}; diff --git a/examples/react-redux/dist/app.bundle.js b/examples/react-redux/dist/app.bundle.js new file mode 100644 index 0000000000..af896b5e4e --- /dev/null +++ b/examples/react-redux/dist/app.bundle.js @@ -0,0 +1,3 @@ +/*! For license information please see app.bundle.js.LICENSE.txt */ +(()=>{var e={814:(e,t)=>{var n;!function(){"use strict";var r={}.hasOwnProperty;function o(){for(var e=[],t=0;t{"use strict";var r=n(532),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},i={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},a={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},l={};function u(e){return r.isMemo(e)?a:l[e.$$typeof]||o}l[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},l[r.Memo]=a;var c=Object.defineProperty,s=Object.getOwnPropertyNames,f=Object.getOwnPropertySymbols,d=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,h=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(h){var o=p(n);o&&o!==h&&e(t,o,r)}var a=s(n);f&&(a=a.concat(f(n)));for(var l=u(t),m=u(n),v=0;v{"use strict";var t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(e){return!1}}()?Object.assign:function(e,o){for(var i,a,l=function(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}(e),u=1;u{"use strict";var r=n(134);function o(){}function i(){}i.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,i,a){if(a!==r){var l=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw l.name="Invariant Violation",l}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:i,resetWarningCache:o};return n.PropTypes=n,n}},526:(e,t,n)=>{e.exports=n(428)()},134:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},802:(e,t,n)=>{"use strict";var r=n(709),o=n(103),i=n(853);function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n