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).
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.
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.
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.
- Scrolling Issues in FlexBox (overflowing layouts phenomenon)
- Using Web fonts in an Electron application
- AntD Christmas Egg
(1.1) Scrolling Issues in FlexBox
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.
When I overlaid display:flex, the style worked differently than expected. The size of the scrolling area has increased, contrary to expectations, by the size of the content in scrolling.
I had to spend quite a lot of time trying to find a solution. It wasn’t really a difficult problem, but I was a little frustrated. (It’s like a browser bug. Has anyone else run into this problem?)
To give a brief description of the solution; I took the
divthat corresponded with scroll, added the surrounding
divand processed the
position:absoluteof 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
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
this.statetogether 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
enumis not needed
- Incorrect use of
- Complex structure’s component unit design mistake
- Incorrect use of AntD Popover content
(2.1) A Hasty Conclusion: Enum is not necessary
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’)
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:
(2.3) Design Mistake: Component Unit of Complex Structure
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.
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.
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.
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
componentWillUnmount. 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.
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.
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.
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.
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
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
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
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.
- Electron browser provider plugin for TestCafe : https://github.com/DevExpress/testcafe-browser-provider-electron
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
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.
Who made all this possible?
My family and my amazing CHEQUER crew members.
Thanks for your support!