Mats Bryntse
27 November 2018

Our Javascript Bug Fixing Process

At Bryntum we try to eat our own dog food as much as possible. If you have followed us a […]

At Bryntum we try to eat our own dog food as much as possible. If you have followed us a while you may have heard about our RootCause debugging service which we use to monitor our websites and demos for JavaScript errors.

Why RootCause?

For a small company like Bryntum, having full time QA staff is simply not feasible. Luckily, we had great test suites covering our products for a long time but even with a good test suite there will always be bugs sneaking out into production. When our company started making JavaScript components, we had an idea to log all such JS errors happening in our online examples into a database. This is a trivial thing to do in any web app, the code snippet below will send error messages to a URL.

window.addEventListener('error', (event) => {
    new Image().src = `log.php?message=${encodeURIComponent(event.error.message)}`);

This gave us awareness of how many errors actually occurred in production (bit scary). With the message, file, line and call stack we could fix some easy errors in little time but most of the time we didn’t receive substantial help from the error logs. Then we realised that our Siesta tool had the parts required (event recorder + playback engine) to really make a kick-ass debugging tool capable of turning errors into test cases. Fast forward a few years, and we are now using the RootCause tool for all our debugging of production errors.

How does Bryntum use RootCause?

We have enabled RootCause for all our online product samples, such as those found in the new Bryntum Scheduler kitchensink. When you open a sample you’ll note a small recording icon in the bottom right corner of the screen.

We record all user interaction and we also capture a screenshot of the page so we can see what it looked like when the page crashed. We also let users enable video recording if they want to show us a bug or some issue, by adding ?video=1 to the URL. This greatly speeds up our communication with our users, and reduces the need of typing a manual step-by-step description to create a bug report.

A real world bug report

Recently we announced a new Excel export feature in Bryntum Scheduler. As with all new code, there’s bound to be some bugs in it somewhere. Shortly after the release of the Export feature, we saw an error report in RootCause. The error message was a bit cryptic and call stack didn’t exactly help:

Uncaught TypeError: Cannot read property 'name' of null
    at (ExcelExporter.module.js?428605:203)
    at ()
    at (scheduler.module.js?428605:24)
    at ExcelExporter.generateRowData (ExcelExporter.module.js?428605:197)
    at ExcelExporter.export (ExcelExporter.module.js?428605:134)
    at Button.onAction (app.module.js?428605:14)
    at Button.trigger (scheduler.module.js?428605:10)
    at Button.onInternalClick (scheduler.module.js?428605:19)
    at HTMLButtonElement._0x50525d (scheduler.module.js?428605:10)

Generally, a call stack is only useful for errors that don’t involve state. Most web apps these days have tons of state, so we needed more information to debug this issue. A look at the screenshot gave us a clue, the user grouped the rows by “Staff” and then collapsed a group before exporting.

To confirm this hypothesis, we simply hit Replay and watch the error happen live:

This replay took 11 seconds, I can’t think of a faster way of reproducing any bug.

Exporting to Siesta

Now that we have reproduced it, we need to make sure this does not happen again unnoticed. We do this by using the “Export to Siesta” button, which gives us a runnable test case. After copying it to the clipboard and removing the irrelevant lines, we now have a test case:

    {"action":"contextmenu","target":"#container .b-grid-header-resizable:nth-of-type(1) .b-grid-header-text" },
    {"action":"click","target":".b-menu-text:textEquals(Group ascending)" },
    {"action":"click","target":"#excelExportBtn1" },
    {"action":"click","target":"#container .b-grid-cell:textEquals(Arcady (1))" },
    {"action":"click","target":"#excelExportBtn1" }

Summing up

We believe RootCause offers the best in class debugging experience and we utilise it daily to fix errors found by our existing customers and potential new clients. If you have not tried it, we recommend you to sign up for free using the button below or try a few samples in the online sandbox.

Sign up for free!

Mats Bryntse

RootCause Testing