How we build and operate Keboola data platform
Vladimír Kriška 2 min read

The worry-free way to convert Coffeescript to JSX

The UI of Keboola Connection dates back to 2015 and some React components are written in Coffeescript. We decided to rewrite those components to JSX.

Since there’s no converter which is able to do this job automatically (or with a satisfying result), we agreed to do this manually, in small steps. When we need to change (or fix) something in .coffee file, we rewrite it to .jsx, if possible.


Let’s call a React component a blackbox. This blackbox is responsible for one job — render a React tree (basically a HTML). That so-called HTML output may differ depending on passed props, so we want to stabilize this behavior and be sure that it will not change over time (especially while we’re rewriting to JSX).

So how we do it? By writing tests.

We’re using Jest library for running tests. In this case one special feature will help us to test the blackbox behavior mentioned above — Snapshot Testing. By creating a snapshot of the component output and testing new output against snapshot we’re able to tell if component is working as before.


I decided to rewrite CurrentUser component. It’s responsible for rendering user information (avatar, name and email) and simple “dropdown” with menu (not so important right now).

So I wrote a test for it.import React from 'react';
import CurrentUser from './CurrentUser';
import { fromJS } from 'immutable';

// few variables defined here, used later to pass as props

describe('<CurrentUser />', function() {
 it('should render 40x40 icon, with email, no admin links, no maintainers, dropup false (no mode passed)', function() {
   shallowSnapshot(
     <CurrentUser
       user={user}
       maintainers={fromJS([])}
       urlTemplates={urlTemplates}
       canManageApps={false}
       dropup={true}
     />
   );
 });
 // more tests here, not mentioned for simplicity
});

The shallowSnapshot function is responsible for rendering a snapshot and comparing it to the existing one. The first run of the test will create a snapshot (a .snap file) which will be stored in the __snapshots__ directory.

Here’s preview of a snapshot:exports[`<CurrentUser /> should render 40x40 icon, with email, no admin links, no maintainers, dropup false (no mode passed) 1`] = `
<div
 className="kbc-user"
 onClick={[Function]}>
 <img
   className="kbc-user-avatar"
   height={40}
   src="/user.png"
   width={40} />
 <div>
   <strong>
     dev user
   </strong>
   <DropdownButton
   ...
</div>
`;

Jest has a watch mode. It’s a mode, in which tests are executed every time the change of a related files is detected.

First run, 5 snapshots were added.

We start this mode by running the yarn tdd command (our alias for jest with --watch parameter).

And then, the boring part begins, from this point we can start rewriting to JSX.

After few iterations of seeing the tests failing, we should end up with a new JSX file and seeing tests passing again.

TL;DR

  1. Write tests and make sure you covered enough cases — especially cases without passing optional props
  2. Run Jest in watch mode (first run creates snapshots)
  3. Rewrite until seeing tests passing again
  4. Profit! :)

If you liked this article please share it.

Comments ()

Read next

MySQL + SSL + Doctrine

MySQL + SSL + Doctrine

Enabling and enforcing SSL connection on MySQL is easy: Just generate the certificates and configure the server to require secure…
Ondřej Popelka 8 min read