Revamping UI, Refactoring Shared Libraries and Testing

This is Part 4 of an article series that documents the process of building the Triple Tee App.

gohkhoonhiang
Jul 04, 2023 | 4 mins read

Time Flies

It’s been another month since I last wrote about wrapping the app in Electron and how to build it for client-side demo. The building of the app actually took just about 1 month, but the bulk of the work is really in polishing the app. I’m eager to share what has been done in the last 20% of the development to push through the remaining 80% of the app.

Looks Good, Feels Good

I was not quite satisifed with the UI components, in particular, the noisy overlay buttons for clearing the input fields, and the date picker which I thought was cool, but after 1 month of looking at it, I find it rather unappealing.

I’m also not very satisfied with the color scheme, because as much as I love dark mode as an engineer, I know it’s not appealing to the wider users base, who would want something a little more vibrant and lively.

So, I decided to spend some time to overhaul the look-and-feel of the entire app. First, I went to search for existing color palettes that can be used for dark mode. I found a site called Color Hunt which lists quite a few interesting color schemes, and I adapted from one of those schemes and use for both the light and dark modes.

Next, I re-implemented my custom Vue components, moving all the overlay buttons within the bounds of each input field. This makes the overall site cleaner as every input looks “contained”, and it’s much easier to align fields if there’s no additional “divs” sticking out.

This is a mundane process, but the outcome is very satisfying, and have visible benefits, so I’m glad to have invested the time to doing it.

Both light and dark schemes look more “modern” now.

Don’t Repeat Yourself

I shared in the previous post that I have both a desktop build and a web build for the app, so that users can first try it out on the browser without any installation. Both builds are meant to behave exactly the same, but at first, the business logic layer was implemented independently in the client-side and server-side. Some logic were copy-paste-able, but some must be re-implemented.

As conventional wisdom goes, Don’t Repeat Yourself if you can help it. But there was just one issue with sharing code between my client and server: one is written in ESModule syntax, the other is in CommonJS syntax. Fortunately, the only tricky part is module exports, the logic implementation itself is just plain o’ Javascript.

After some research online, I found out how to use esbuild to build CommonJS exports into ESModule files. So now the server-side code using CommonJS can import the shared libraries as-is, while the client-side code will import the compiled ESModule libraries.

I had to spend some time rewriting my common logic in sharable libraries, and then fixing the client-side code to use the new compiled imports. Again, it’s really time well spent because now I don’t have to test the logic twice when I make a change.

Shared libraries eg. data access will be built into ESModules for client-side use.

Test, Test, Test

It’s so important so I have to repeat myself 3 times. I can’t count the number of times how the test cases have saved me from some very fatal bugs, and I’m always glad to have spent the time to write the tests. At the point of this writing, I’ve written over 150 tests for the shared libraries and server-side logic, over 450 tests for the client-side logic and components, and still counting.

It may sound like a lot of effort and a waste of time to some, but being the only engineer of the project, there’s no second pair of eyes to review my code, and no way I could have manually tested every single case through clicking the app, so my only choice is to write automated tests, and give me the peace of mind that I will know it when I break some thing when changing code.

And because there’re client-side and server-side JS frameworks, there’re 2 test frameworks involved too: JestJS for the backend, and Vitest for the frontend. Fortunately, Vitest is pretty much an identical port from JestJS, so I didn’t have to re-learn the tests functions and utils.

Time invested in writing tests is time saved from pulling hairs over a buggy app.

That’s All For Now

This is a short piece, even though the time spent on building what is shared is almost half of the entire development journey. I would say that only 50% of the remaining 20% of work is done now, there’re still more tests to be written, and I still have to put the landing page and demo on a standalone domain.

So do stay tuned for more updates in the coming weeks (or months)!