Mistakes during development of our React/TS/Electron Application

QueryPie Development #12: A Memoir of Preparing the Open-Beta

I’ve been working in software development for a long time, and one of my biggest regrets is that over the last 16 years, I’ve never kept a proper record of the work I developed. What I’ve worked on may not be so great as to be recorded, but looking back, it might seem like I lacked affection for my past work.

So when I started developing QueryPie, I thought that I should properly document my process and write a developer log similar to the previous articles.

A quick look back: QueryPie Development Process

Before starting new projects, developers will always consider the joy they will feel while making new things versus the physical and mental pain they will suffer in the process of making them. In my case, I’m not sensitive to pain so I tend to only think of the joy aspect before starting a project. Sometimes, that leads to me overdoing it and creating unexpected results (both good and bad).

QueryPie Contribution Graph

The preparation for QueryPie began in June 2018. Since then, we’ve been working on full-scale development since November and are currently in the process of developing. Unlike the projects I experienced before, the development process was conducted by all the planning/design/developers in one mind and was able to effectively manage what was to be done and what was going on. It also enabled smooth communication between team members to minimize team members losing pace or moving in the wrong direction.

QueryPie Issue board and Sprint’s Burn Up chart, which has a release date for March 1st

While it may take at least six months to become what we think will be a good application, our Sprint is still continuing today. Everyone in the CHEQUER Crew is genuinely doing their best to make better software.

Mistakes I’ve made during Development

Now let’s get down to business and sort out the mistakes we made while developing QueryPie.

Collection of mistakes while developing QueryPie (Korean only)

As I mentioned earlier, I really regretted not recording my process with earlier projects. So this time, I decided to write down the details in a notebook whenever I realized I made a mistake or discovered something while developing the code. And I put together all the things I could share on from those notes.

1. CSS

Scrolling Issues in FlexBox (overflowing layouts phenomenon)

Using Web fonts in an Electron application

AntD Christmas Egg

(1.1) Scrolling Issues in FlexBox

QueryPie Editor Panel Tab Bars

QueryPie’s editor had to support multiple tabs, and it was a structure that had to be scrolled when the sum of the widths of the tab items exceeded the width of the layout. This is simplified and described below.

The width of the left and right aside should remain the same size even if the width of the parent container changes, and the width of the middle scroll area should change accordingly with the size of the parent container. I wrote the sample code and thought it would be a simple problem to solve, but when I applied the code to the actual project… my hardships began.

To give a brief description of the solution; I took the divthat corresponded with scroll, added the surrounding divand processed the position:absolute of the scrollDiv, then modified the relevant style properties accordingly.

There is probably a better solution to this problem than I came up with.. If you know a better way, please share it with me!

(1.2) Using Web Fonts in a Electron Application

I had many discussions with our design team about which web fonts to use inside QueryPie. But it was hard to find the best web font that would work with Windows, Mac and Linux. Not to mention the burden of putting large-capacity web fonts in an already small-capacity Electronic application.

So in the end we decided it was best to not use any fonts. Using the user’s OS default font was the most efficient choice for a smooth, lag-free experience.

(1.3) Ant Design Christmas Egg

snowed-on buttons

In December 2018, I had to continue working on Christmas Eve because of our tight schedule. At that time, the shape of the button mysteriously changed. It was a style that I’ve never worked on before. When I looked up the reason, I learned that the Button component changed according to the date — since it was Christmas, the interface had added ‘snow’ to the tops of the buttons.

At that time, I wasn’t sure if it would be right to pick apart the AntD project and fix the code, or if I should just wait for the modified code to be written to the AntD Git. Then, I realized that there might be people like me so I went on a search. Apparently there were many issues posted, and fortunately they were patched quickly. It wasn’t until I upgraded to the latest the version of AntD that I could solve the problem.

2. React Component & TS, AntDesign

Using Mobx’s Observable and this.state together caused an infinite loop (using them together is not a good idea)

Not abstracting components (is possible, should be abstracted)

Moment timezone problem (the time value of the database was UTC+9. Not my fault!)

Hasty conclusion that enum is not needed

Incorrect use of async confirmModal

Complex structure’s component unit design mistake

Incorrect use of AntD Popover content

(2.1) A Hasty Conclusion: Enum is not necessary

TypeScript Enum

If you use TypeScript, you can use enum (you can also use enum for ES6, but this method works better). So I can code better than the existing code.

The more you write enum, the better. But early development codes couldn’t use enum. A valuable lesson I learned is that before comparing factor values, consider first that the relevant factors need to use enum and then write the code.

(2.2) Using ‘async confirmModal’ incorrectly (should have used ‘try catch’)

incorrect code

I thought that returning AntD Modal.method() to new Promise would solve user interaction UI problems such as alert and Confirm easily. And at first, it worked well.

But I later found out that I was using an old method. onOk : resolve, onCancel : reject and tryCatch was thought to be better method where ConfirmDialog is used. You can view the new code in the image below:

modified code

(2.3) Design Mistake: Component Unit of Complex Structure

Modifying QueryPie Table UI

The UI that modifies the table schema in QueryPie can simultaneously check and modify the column information, as well as the Indexes and Relations information in the table. After editing the column, indexes, or relations information, users can click the “Save” button to check which SQL Scripts have changed. If the user is happy with the outcome, they can click “Execute” to process the request.

Check changed Schema Scripts

When a child component’s Prop is manipulated in a parent component, the state of the parent component must be changed in a structure that makes it easier to manage. However when building a component, I only focused on how the state used within the component should not go outside, and in the process I made a mistake.

before and after component design structure changes

By assigning a mobx observable object to a parent component and passing it on to the child component’s prop for use in a child component, a component of a complex structure can be created without separate state management.

It is not possible to modify the value of observable object in the child component, but as with const, the key value of object can be modified. If the key value of object is modified, it will detect the change in mobx observable object and re-renders the object.

Even if mobx is not used, it can be implemented in the same way. In this case, however, caution is needed because a change in state is not detected automatically. In most cases, it does not matter because changes in child components occur and only data needs to be changed on the parent component’s side.

(2.4) Wrong use of AntD Popover Content

PopoverContent should be displayed according to the popover visible status. So I thought I had to do the necessary work at PopoverContentcomponentWillUnmount. When I wrote this code, I wasn’t aware that there was a problem with Popover when it was closed.

We could solve the problem by modifying the content of Popover to express the desired state by passing visible prop to content instead of unmount according to the visible state. (In my defense, it was more convenient to use unmount to detect events that would cause Popover to disappear than to determine whether or not didUpdate changed the apps.)

3. End to End Test

Many developers emphasize the importance of testing in software development. But I have very little experience in creating a proper test environment and code. Most of the time, because I have worked in SI environments, I have to develop them as error-free as possible and rely on feedback by customers and PMs to check errors directly.

But because QueryPie is a multi-platform software and handles databases that should not be tampered with, an environment and code that could be tested properly were essential.

(3.1) Testing Front-End Codes

The front-end test code is usually referred to as the unit test. In my opinion, the front-end test can be said to be the most important E2E test. Because in actuality, we must create a real-life scenario such as a user using the software, and verify that it matches our expected results without problems, to know if the software is ready.

Another problem is while users will be able to use QueryPie in a variety of environments, we can’t increase the number of people that test it. And any time a code is modified or a function is added, a feature that previously worked may fail as a side effect.

(3.2) TestCafe

We were thinking about how to test QueryPie, so we looked at Cypress and TestCafe to see which one would fit us better.

Both projects were well-made and I thought I could use either one, but Cypress doesn’t support Electron projects so in the end we chose TestCafe.

E2E Test Run

E2E Test Code Structure

Fixture can define the Metadata to be delivered to the sub-test or the actions to be performed before and after each test is started.

# Mistakes made in writing Test Code

ReactSelector’s selectorString should be ClassName, but tried to find by JSX Name

Difficulty managing test units (difficult to re-run only the tests under development among multiple tests)

Trying to manipulate the invisible element

Failure to understand situations in which no dialogue or main menu is visible during test code progress

📌ReactSelector‘s selectorString should be ClassName, but tried to find by JSX Name

In TestCafe, there is a structure called Selector. This feature allows Element Node to be found in Web View, just like CSS Selector.

How to use TestCafe Selector

In the TestCafe document, it states that there are not only CSS Selectors but also Framework-Specific Selectors. Of course, there is also a React Selector.

How to use TestCafe React Selector

I was excited, so I decided to try this method right away. But even though I searched for a few hours, I couldn’t find the Element I wanted. Plus, I had to wait a few minutes each time I put Electron back up because it was the first time I made the test unit.

After a substantial amount of hard work, I decided to return to the document for answers. There, I found the section “name of the component class”.

As always, my habit of not properly reading the documents resulted in me senselessly wasting time. To make matters worse, the names of the JSX syntax using the component class and even the names of the component files were different.

It was a silly mistake.

📌Trying to manipulate an invisible element

Side panel resize test syntax

I wanted to find #lsidebar-resizer and test Drag. The above code fixed my problem, but it took a lot of time and energy to find it.

Finding the Element as Selector was successful, but it was not possible to issue a hover or drag command to an element that was not visible in the web view (the exact width value is zero so there’s no size element).

I used the eval function to force the element’s style to be adjusted, and solved the problem.

📌Failure to understand situations in which no dialogue or main menu is visible during test code progression

To select a file

I had to write a test code that allowed users to select a file on their computer using the system dialog. Before writing the test code, I checked to see if TestCafe supports Electron (it does!) so I wasn’t too worried.

When I wrote the test code, I expected the system dialog to occur when the code was executed. But there was no change and the test code just stopped.

I didn’t know at the time that TestCafe uses the system dial during the test code process, and it doesn’t show it. So I struggled with getting the test code to work for a long time.

As shown in the code above, the problem was solved by declaring setElectronDialogHandler first and while the test code is in progress, a system Dialog is requested. The problem is solved by using return to give back the predetermined value to match the DialogType.

Wrap-up

After all these long processes, QueryPie’s Open Beta has finally launched. Check out the preview below, and if you like what you see, download it here!

Come to think of it, we’ve been developing QueryPie for a really long time. And there are still many features to be implemented in the future, as well as more ways to perfect and modify the functions already created. Looking back, I don’t know how I was able to continue working so hard for so long.