I've not been as active with web development recently as I would've liked, mainly because my work is mostly about local applications in Unix and Windows environments. I do have a pet project I'm dabbling in now and then, a character sheet for the role playing game we enjoy. It has rules that are pretty much fully house-rules, and therefore there are no existing applications to use or develop further. The rules are quite number-heavy, as the rules strive for a certain realistic approach to combat, but it has the downside that maintaining the sheet in pen and paper form is virtually impossible.
I've been building the character sheet for hundreds of hours and taught myself the rudimentaries of web application development with Django in the process. It has been great fun, and with our still active club, I get feedback about the UI from my friends.
As I've added more and more features to the sheet, it has become increasingly slow to load and do modifications. As the sheet was at first purely based on Django templates, the sheet has become basically a huge form, with the view function dispatching couple dozen different forms depending on the user input on the page. As my server is a hosted Atom linux, i.e. not locally hosted, with a slow disk and limited memory, this has become a problem. I have decided to move the sheet to a more client-side rendered one, with REST APIs for the key modifications. This fits well for me as a learning experience as well, as we are discussing various REST APIs at work. The work with the character sheet allows me to learn frameworks and tools.
I was introduced to React by a co-worker, who was very opinionated its superiority over AngularJS, mainly, as I recall, because of React's virtual DOM. Getting the basics to run -- unit-tests, tooling to build bundles from the source code, building initial component -- took some time, but it was definitely worth it. The application is really responsive, and IMO the experience is much more fluid than could ever be built with server-side rendering. But there are a few things that caused me to spend way too much time figuring out what went wrong, or things that just don't make sense.
The Jest tool could use with a more extensive helper utility library and definitely more examples on testing. Especially testing with Promises and async code, as I'm not using the Flux framework at the moment.
The source for the project is not currently publicly available, as it would not make much sense without the data and the rules. Hopefully we can get those published as well. At least, we need to check whether there are any licensing issues that would prevent disclosing them.
Jest automocking
I love unit-testing, so I was pleased to use Jest. Its automocking feature did bite me quite a bit when trying to use react-bootstrap component in my project. This nice snippet in package.json:
"<rootDir>/node_modules/react-bootstrap", "<rootDir>/node_modules/react-overlays", "<rootDir>/node_modules/react-prop-types", "<rootDir>/node_modules/classnames", "<rootDir>/node_modules/dom-helpers", "<rootDir>/node_modules/invariant", "<rootDir>/node_modules/keycode", "<rootDir>/node_modules/lodash-compat", "<rootDir>/node_modules/uncontrollable", "<rootDir>/node_modules/warning", "<rootDir>/node_modules/babel-runtime",
.. is there to allow react-bootstrap components to be used from my components without Jest causing errors in loading the components. Jest should have a feature to not mock any dependencies of a depended module, in this case react-bootstrap. The list above was generated by hand from react-bootstrap's npm dependencies, adding one which was not included, babel-runtime.
Jest/Jasmine error reporting
Mostly these work ok, but for example in the case above, omitting babel-runtime will give you
stats_to_react * % npm test -- xp-control > aesheet@0.0.0 test /Users/sjl/p/aesheet/sheet/static/react > jest --testRunner '<rootDir>/node_modules/jest-cli/src/testRunners/jasmine/jasmine2.js' "xp-control" Using Jest CLI v0.8.2, jasmine2 FAIL __tests__/xp-control-tests.js ● Runtime Error TypeError: Cannot read property 'default' of undefined npm ERR! Test failed. See above for more details.
which is not really helpful; running jest in verbose mode will give even less information:
stats_to_react * % npm test -- --verbose xp-control > aesheet@0.0.0 test /Users/sjl/p/aesheet/sheet/static/react > jest --testRunner '<rootDir>/node_modules/jest-cli/src/testRunners/jasmine/jasmine2.js' "--verbose" "xp-control" Using Jest CLI v0.8.2, jasmine2 FAIL __tests__/xp-control-tests.js npm ERR! Test failed. See above for more details.
Eh?
Emitting a syntax error, such as a missing or extraneous brace in the JSX, will give the following helpful message:
Using Jest CLI v0.8.2, jasmine2 FAIL __tests__/xp-control-tests.js npm ERR! Test failed. See above for more details.
And that is all. No traceback, line numbers, file info, nothing.
Bootstrapping React-bootstrap
After adding react-bootstrap to package.json and trying it out, I was still missing all the styling. I knew I could bundle it with webpack, but how? After much googling and trial and error, I found an excellent blog entry by The Ody Brothers http://blog.theodybrothers.com/2015/07/how-to-use-bootstrap-css-only-and.html , which saved me a lot of time. Thanks!
Bootstrap-react not following React event handler conventions
<Input/> not exposing onKeyDown, for example, is a bummer. Trying to work around that by using <ButtonInput type="submit" /> and enclosing the whole thing to a form, on the other hand, causes the buttons to be rendered in an ugly way:

Jest async testing
Jest uses Jasmine 1.3 by default, which uses waitsFor() and runs() and does not implement the done() interface. Jasmine 2.0 does not have waitsFor() or runs(), and expects async code to use setTimeout() and done() to achieve eventually completing test case; however, Jest mocks setTimeout also for tests and so the tests can't use it. Maybe there is a way, but I haven't found it so far.
Inline styles
The idea of inline styles felt heretical at first, but the upside is obvious; the CSS styles for the character sheet already contain lots of obsoleted items, but I can't be sure whether they are used without testing all views.
The downside: no @media print, at least not at this moment. I'm not willing to bring in yet another 3rd party library for this; Radium in this case.
package.json doesn't allow comments
This is just stupid. For example, now I have this block of
"jest": {
"scriptPreprocessor": "<rootDir>/jest/preprocessor.js",
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/react",
"<rootDir>/node_modules/react-dom",
"<rootDir>/node_modules/react-addons-test-utils",
"<rootDir>/node_modules/fbjs",
"<rootDir>/node_modules/react-bootstrap",
"<rootDir>/node_modules/react-overlays",
"<rootDir>/node_modules/react-prop-types",
"<rootDir>/node_modules/classnames",
"<rootDir>/node_modules/dom-helpers",
"<rootDir>/node_modules/invariant",
"<rootDir>/node_modules/keycode",
"<rootDir>/node_modules/lodash-compat",
"<rootDir>/node_modules/uncontrollable",
"<rootDir>/node_modules/warning",
"<rootDir>/node_modules/babel-runtime",
"<rootDir>/node_modules/core-js"
]
}
The whole block of 11 paths in the center to disable automocking for react-bootstrap. I would've really liked to add a comment about that.
npm ERR! Failed to parse json npm ERR! Unexpected token '/' at 46:7 npm ERR! /* This is for react-bootstrap. */ npm ERR! ^ npm ERR! File: /Users/sjl/p/aesheet/sheet/static/react/package.json npm ERR! Failed to parse package.json data. npm ERR! package.json must be actual JSON, not just JavaScript. npm ERR! npm ERR! This is not a bug in npm. npm ERR! Tell the package author to fix their package.json file. JSON.parse
Crockford justifies this as disallowing using comments as parsing directives to create parses with non-interoperating syntax (link here) but that reason does not hold water, due to the fact that you can add fields like "__field" or "____field" to your heart's content; allowing the same people who wanted to use comments to use the json fields. Except npm will complain about this usage too:
/Users/sjl/p/aesheet/sheet/static/react/node_modules/jest-cli/src/lib/utils.js:189 throw new Error('Unknown config option: ' + key); ^
Or perhaps, this IS a bug in npm, as they should be minifying the JSON before usage.
I've worked around this by adding a README for the package.json to explain some of the choices there. Perhaps I'll add a processing step from a file containing the comments to the actual package.json one, with, e.g., https://www.npmjs.com/package/strip-json-comments . But this is stupid, the format should allow for comments.