# Falcoma > My Profile ## Posts - ["Vincent from China aka Malaysia"](https://falcoma.com/archives/2618): A former manager once called me “Vincent from China aka Malaysia.” Maybe it sounded harmless to others. To me, it exposed how easily people reduce identity into stereotypes and assumptions. This is a personal reflection on racism, belonging, and the quiet frustration of constantly being seen as “other” despite knowing exactly who you are. - [The Danger of “Cultural Fit”: When Hiring Becomes Vague, Subjective, and Risky](https://falcoma.com/archives/2612): WHat is Cultural Fit? I’ve been rejected multiple times at the final stage of interviews under the label of “cultural fit.” Each company used different language: After hearing enough versions of the same vague theme, I started asking a serious question: Is cultural fit a useful hiring signal, or a dangerous excuse? Why “Cultural Fit” Can Be Problematic 1. It is often undefined Many companies cannot clearly explain what cultural fit actually means. Is it communication style? Values? Personality? Confidence? Similar hobbies? Speaking style? If interviewers themselves cannot define it, candidates are judged by moving targets. 2. It invites bias When […] - [String Handling in TypeScript Without Losing Your Mind](https://falcoma.com/archives/2558): A practical guide to trim, split, join, and friends String manipulation shows up everywhere, interviews included.Yet many developers freeze because strings feel “magical”. They’re not. Once you see the patterns, it becomes mechanical. The Core Mental Model Strings are immutable.You don’t change them, you create new ones. Most string problems follow one of these flows: That’s it. trim() – Clean the edges Removes whitespace at the start and end only. Use it: Interview habit: This is a senior move. split() – Cut into pieces Turns one string into an array. Use it when: Rule:Strings don’t loop. Arrays do. join() – Glue […] - [Common Code Mistakes Every Engineer Eventually Learns the Hard Way](https://falcoma.com/archives/2554): As engineers grow, the biggest shift is not learning new syntax, but learning to recognize bad code early. These mistakes have names for a reason, they show up everywhere, across teams, languages, and seniority levels. This post is a practical breakdown of common code mistakes, why they happen, and why seniors care so much about them. 1. Dead Code What it is Code that never runs or is no longer used. ‘If this condition is never true, why is it still here?’ Why it’s bad Why it happens Old features, rushed fixes, fear of deleting things. 2. Unreachable Code What it […] - [Playwright vs CodeceptJS](https://falcoma.com/archives/2551): A clear, practical comparison for modern E2E testing End-to-end testing is table stakes now. Two big options you’ll hear about are Playwright and CodeceptJS. Both help you automate full user flows in browsers. But they take very different approaches. For clarity, Playwright is a test automation library from Microsoft. CodeceptJS is a framework that can run on different drivers (WebDriver, Puppeteer, Playwright). Let’s break down the real pros and cons. BDD (Behavior-Driven Development) is a way to write tests in plain language that describe how the system should behave from the user’s point of view. What They Are Playwright Playwright is […] - [Stop Putting Parameterized Locators in Constructors](https://falcoma.com/archives/2548): If you’re using Playwright with Page Objects, you’ve probably seen something like this: It works. But it’s a bad pattern. This article explains what this pattern is, why it causes problems, and what to do instead. What Is This Pattern Called? That code is a parameterized locator factory defined in the constructor. Key traits: It’s often confused with “dynamic locators”, but that’s not the real issue. The problem is where it lives and how it’s structured. Why This Is a Problem 1. Constructors Should Be Dumb A constructor should: That’s it. When you put logic, parameters, or behavior into the constructor, […] - [Type vs Interface vs Class vs Tuple (and When to Use Each)](https://falcoma.com/archives/2545): TypeScript gives you many ways to describe data. That’s powerful, but also confusing. If you’ve ever asked “why does this exist when that already works”, this post is for you. I’ll explain what each one really is, what it’s good at, and when not to use it. Mental model first (important) If you mix these roles, your code becomes hard to reason about. type What it is A type alias. It gives a name to a shape, union, or primitive. What makes type powerful Limitations interface What it is A contract for object shape, designed for extension. Why interfaces exist They were designed […] - [data-testid Is Not a Smell. Misusing It Is.](https://falcoma.com/archives/2542): data-testid gets a bad reputation. Some people say it’s lazy. Others say it’s an anti-pattern. Both are wrong. data-testid is a tool. Like any tool, it’s either used with intent or abused. Let’s be honest about when it’s the right choice and when it’s not. What data-testid actually is data-testid is a testing-only attribute added to the DOM. Example: Used in Playwright: That’s it. Nothing magical. Why people hate data-testid The usual arguments: These complaints come from bad usage, not the attribute itself. The real problem: unstable selectors Most flaky tests don’t fail because of Playwright. They fail because selectors are tied to: […] - [What the DOM Really Is (and Why Your Tests Keep Breaking)](https://falcoma.com/archives/2538): “DOM” is one of those words everyone uses and half the people misunderstand. If you write UI tests and don’t truly get the DOM, you will write fragile tests. Period. Let’s fix that. DOM does NOT mean HTML DOM = Document Object Model HTML is a file. The DOM is a live, in-memory structure created by the browser after loading that file. Once the page is loaded, everything talks to the DOM, not the HTML: If you are selecting HTML, you are already too late. The DOM is a tree, not a string This HTML: Becomes this DOM structure: That button […] - [6 Custom ESLint Rules That Forced My Playwright Tests to Grow Up](https://falcoma.com/archives/2535): Playwright is powerful. That’s also the problem. It lets teams move fast, and when teams move fast, test quality quietly degrades. You end up with unreadable assertions, inconsistent page objects, slow test runs, and Allure reports nobody trusts. I stopped trying to “educate” people in code reviews. Instead, I wrote ESLint rules. These six custom rules now guard our Playwright codebase. They are strict, sometimes annoying, and absolutely worth it. 1. Require descriptive assertion messages The problem This failure tells you nothing: At scale, missing assertion messages are a tax on every failure. What the rule enforces Bad Good Why it […] - [Stop using waitFor* as a crutch in Playwright E2E](https://falcoma.com/archives/2500): If your Playwright tests are full of waitForTimeout() or “wait a bit then click”, you are buying flakiness and slow runs. Playwright already has smarter waiting built in. Your job is to wait for a condition, not wait for time. What’s wrong with waitForTimeout() (hard waits) page.waitForTimeout(2000) just sleeps. It does not care whether the app is ready at 50 ms or still loading at 10 s. That creates 3 predictable problems: Why waitForSelector() is usually the wrong “explicit wait” A lot of people replace waitForTimeout() with waitForSelector() and call it a day. Better, but still often unnecessary. Playwright’s Locators already […] - [Conflict handling is a senior skill](https://falcoma.com/archives/2425): Most conflicts at work aren’t really about people. They’re about pressure, unclear ownership, and timing. But when something breaks, pipelines turn red, or deadlines get tight, the conversation often shifts from facts to tone. That’s when conflict starts. I’ve learned this the hard way. In one situation, a technical discussion slowly turned into something else. The questions I received weren’t about the problem anymore, they were framed as reminders of past conversations, expectations, or assumptions. The intent may not have been bad, but the impact was real. I felt interrogated rather than supported. Old triggers show up fast in moments like […] - [Page Objects are not enough. Page Actions matter.](https://falcoma.com/archives/2423): Page Objects solved one problem: locators.They did not solve behavior, readability, or long-term maintenance. In many Playwright projects, Page Objects slowly turn into dumping grounds. Locators, clicks, assertions, waits, logic, and workarounds all mixed together. It works at the beginning. It always does. Until it doesn’t. That’s when tests become hard to read, harder to change, and impossible to reason about. In my project, we separated what the page is from what the user does. Page Objects define structure Page Objects contain only: Nothing else. They don’t click.They don’t assert.They don’t make decisions. They describe the UI as it exists. This […] - [What does “senior” even mean in the AI era?](https://falcoma.com/archives/2421): Not long ago, being senior meant years.More years, more tickets, more systems survived. That definition is dying. AI didn’t just speed things up. It compressed experience. Tasks that used to take years to master can now be done in weeks with the right tools. Writing tests, scaffolding code, generating docs, even debugging. AI leveled the execution field. So if everyone can execute faster, what separates a senior from everyone else? It’s not speed.It’s not output.And it’s definitely not job title. A senior today is someone who understands impact. They know what not to build.They know what not to automate.They know when […] - [Why my website is called Falcoma](https://falcoma.com/archives/2416): Falcoma is a name I didn’t invent. I saw it online, couldn’t find a real meaning, and that was exactly the point. It sounded unique, slightly feminine, and open enough to grow into something personal. The name reminds me of a falcon, or an eagle. People often mix them up, and I don’t mind. What matters is what they represent to me: vision, sharp focus, and precision. Birds that see what others miss. Birds that don’t rush, but strike exactly when it matters. That’s also how I see quality engineering. QA doesn’t slow things down. QA sees things earlier, clearer, and […] - [Jira Skipper, stop pushing code just to skip tests](https://falcoma.com/archives/2406): When E2E is flaky, the worst workflow is this: someone changes code to skip a scenario, pushes, waits for CI, then changes it back later. It’s slow, noisy, and it pollutes git history. So we built Jira Skipper. Idea: control skipping from a single Jira ticket description. No code changes needed. Update Jira, rerun pipeline, done. How it works This is the core helper: And it runs in globalSetup: Fresh project setup guide (Playwright + TypeScript) 1) Create the project Create a basic TS config: Make sure these are set in tsconfig.json (keep it simple): 2) Add Playwright config with globalSetup […] - [QE is not the bottleneck. Reality is.](https://falcoma.com/archives/2396): Quality Engineering often gets blamed when pipelines are slow or E2E tests are flaky. It’s an easy target. A red pipeline is visible, the real cause often isn’t. What’s usually ignored is this:test automation is hard and expensive to maintain.ISTQB is very clear on this. Automation is not a one-time setup. It requires continuous maintenance due to system changes, environment instability, and data dependencies. When the system is unstable, tests simply expose it. E2E tests don’t create problems. They surface them. Most failures fall into a few boring but important categories. App Behaviour Issues “E2E failed due to unexpected application behavior. […] - [My CPAP Journey in Germany](https://falcoma.com/archives/2233): Snoring. Breath-holding. A tired partner. That’s how it all started. What followed was a months-long journey through doctors, wires, eye-rolls, and, finally—sleep. - [End-to-End Testing](https://falcoma.com/archives/182): End-to-end tests leverage the power of CodeceptJS, a modern, scenario-driven testing framework designed to write simple and clean tests. CodeceptJS is the successor of Codeception, a widely adopted full-stack testing framework in the PHP ecosystem. - [Visual Testing](https://falcoma.com/archives/180): While end-to-end and functional testing assesses the underlying functionality, flow, and integration of an application or website, they may overlook the visual presentation. The visual appearance of a website plays a critical role in user experience, and small visual discrepancies can lead to user confusion or mistrust. This is where visual testing becomes vital. ## Pages - [Unlock](https://falcoma.com/tetsing-lab/unlock) - [My account](https://falcoma.com/my-account) - [Checkout](https://falcoma.com/checkout) - [Cart](https://falcoma.com/cart) - [Shop](https://falcoma.com/shop) - [Drag & Drop Kanban](https://falcoma.com/tetsing-lab/drag-drop-demo) - [Infinite Scroll](https://falcoma.com/tetsing-lab/infinite-scroll-demo) - [Multi-Step Form](https://falcoma.com/tetsing-lab/multistep-form-demo) - [Modal Dialog](https://falcoma.com/tetsing-lab/modal-demo) - [Toast Notifications](https://falcoma.com/tetsing-lab/toast-demo) - [File Upload Demo](https://falcoma.com/tetsing-lab/file-upload-demo) - [Delayed Table Demo](https://falcoma.com/tetsing-lab/delayed-table-demo) - [Broken Form Demo](https://falcoma.com/tetsing-lab/broken-form-demo) - [Login Demo](https://falcoma.com/tetsing-lab/login-demo) - [Tetsing Lab](https://falcoma.com/tetsing-lab) - [My Blog](https://falcoma.com/my-blog-3): My blog My headspace This is my main writing space.Thoughts on tech, quality, systems, and life, mixed with things I find useful, interesting, or worth questioning. Some posts are practical, some are reflective. All of them are written with clarity, not noise. - [Life](https://falcoma.com/my-blog-2): My Life What’s Happening in my life? Just observations from daily life, relationships, work, mistakes, growth, and the quiet parts in between. Some posts are reflective, some are messy, some are lessons I’m still figuring out. It’s not a diary. It’s perspective over time. If Falcoma is about vision and focus, My Life is about everything that shapes them. - [Quality Engineering](https://falcoma.com/my-blog): Knowledge sharing What’s new on QE? This is where I write about everything related to QE that matters to me. Work, knowledge, skills, and things I wish I knew earlier. Some posts are practical, some are from my experience. All of them are real, useful, and written to be shared, not polished for perfection. - [Stock Screener](https://falcoma.com/stock-screener): Stock Screener My Calculator This stock screener gives each company a clear 0–100 score based on fundamentals and momentum. It filters out noise, highlights quality, and helps you compare stocks quickly without overthinking. - [Contacts](https://falcoma.com/contacts): Contact me Find me on Linkedin Berlin, germany Let’s talk about your project Have a project, role, or idea you want to discuss?Drop me a message and I’ll get back to you as soon as I can. - [Home](https://falcoma.com/): Hey, my name is VincentWONG QA/QE Years of experience 9+ Projects done 5 Playwright 99% Codeceptjs 95% Typescript 97% CI/CD 75% API Testing 98% Quality EngineerING? I once told my mum I “break things so they work better.” She’s still confused, but it sums up my job as a Quality Engineer at Thomann.io, where I use Playwright to catch bugs before they matter. From Manual Insight to Automated Confidence I combine human intuition with Playwright precision. Quality Engineer Who Actually Breaks Things I test products the way real users behave, not the way specs assume. Building Tools, Breaking Stereotypes You can […] ## Products - [drag-drop-demo](https://falcoma.com/product/drag-drop-demo) - [infinite-scroll-demo](https://falcoma.com/product/infinite-scroll-demo) - [multistep-form-demo](https://falcoma.com/product/multistep-form-demo) - [toast-demo](https://falcoma.com/product/toast-demo) - [file-upload-demo](https://falcoma.com/product/file-upload-demo) ## Optional - [Agent (MCP protocol)](websites-agents.hostinger.com/falcoma.com/mcp) [comment]: # (Generated by Hostinger Tools Plugin)