August 10, 2026

Checking code with lint, formatting it with prettier

Now that we've installed bun, Anthropic's package manager, scaffolded a Playwright framework and closely examined the results, and added typechecking with TypeScript's compiler, it's time to add ways to check the code with lint, and reformat the code with prettier

We will be using:
  • ESLint, as the static-analysis tool to review the code without running it. Little bits of fluff -- like syntax errors, structural bugs, anti-patterns, and code style violations -- can collect on your code, so it helps to run a linter to help catch it all, such as ESLint. There is also a linter,  eslint-plugin-playwright, for Playwright tests.
  • Prettier enforces a consistent code style across your entire codebase. Because ESLint and Prettier can conflict, we will be using Prettier's eslint-config-prettier, which turns off all rules that are unnecessary or might conflict with ESLint.

What is a Linter? 

According to the Wikiwand entry for Lint, "Stephen C. Johnson, a computer scientist at Bell Labs, came up with the term 'lint' in 1978 while debugging the yacc grammar he was writing for C and dealing with portability issues stemming from porting Unix to a 32-bit machine. The term was borrowed from lint, the tiny bits of fiber and fluff shed by clothing, as the command he wrote would act like a lint trap in a clothes dryer, capturing waste fibers while leaving whole fabrics intact. The lint program was released outside of Bell Labs in Unix V7, in 1979.

"In his 1978 paper, Johnson explained his reasons for creating a new program to detect errors: '...the general notion of having two programs is a good one' because they concentrate on different things, thereby allowing the programmer to 'concentrate at one stage of the programming process solely on the algorithms, data structures, and correctness of the program, and then later retrofit, with the aid of lint, the desirable properties of universality and portability' "


What is ESLint?

According to ESLint.org / About, "ESLint is an open source JavaScript linting utility originally created by Nicholas C. Zakas in June 2013. Code linting is a type of static analysis that is frequently used to find problematic patterns or code that doesn’t adhere to certain style guidelines. There are code linters for most programming languages, and compilers sometimes incorporate linting into the compilation process.

"JavaScript, being a dynamic and loosely-typed language, is especially prone to developer error. Without the benefit of a compilation process, JavaScript code is typically executed in order to find syntax or other errors. Linting tools like ESLint allow developers to discover problems with their JavaScript code without executing it.

"The primary reason ESLint was created was to allow developers to create their own linting rules. ESLint is designed to have all rules completely pluggable. The default rules are written just like any plugin rules would be. They can all follow the same pattern, both for the rules themselves as well as tests. While ESLint will ship with some built-in rules to make it useful from the start, you’ll be able to dynamically load rules at any point in time".

What is ES Lint for Playwright? 

ESLint for Playwright was initially written by open-source developer Mark Skelton, a senior staff software engineer at Cursor. It is now maintained by the Playwright Community Organization. 

From BrowserStack.com's Setting Up ESLint fpr Playwright Projects
Have you ever returned to a Playwright project after a few weeks and felt the tests were suddenly unstable or difficult to trust?

In most cases the problem isn’t Playwright. It comes from small issues that slip in unnoticed.

Missing awaits. Inconsistent patterns. Promise errors that never surface. Test files that grow without any structure.

Playwright ESLint is a linting setup that helps ESLint understand Playwright’s testing patterns and catch issues that commonly appear in UI automation.

What is Prettier?

According to James Long's January 2017 blog entry, A Prettier Script Formatter, "Prettier gets rid of all original styling and guarantees consistency by parsing JavaScript into an AST and pretty-printing the AST. Unlike eslint, there aren't a million configuration options and rules. But more importantly: everything is fixable [...]"

In JavaScript, an Abstract Syntax Tree (AST) is a nested object structure that maps out the semantic meaning of your code -- such as identifying variable declarations, function calls, and loops -- while ignoring visual styling. Because Prettier is strictly a code formatter, it parses your source code into an AST and then regenerates entirely new text based on its own style rules. Since Prettier only modifies surface-level elements like indentation, line breaks, quotes, and semicolons, the underlying logic remains untouched, resulting in an identical AST before and after formatting

Installing ESLint


According to ESLint.org, you can install it with NPM, Yarn, PNPM (package managers we saw that Playwright all have listed in their installation documentation. They also mention one we have seen already... bun. To install ESLint with bun, they suggest running the command:
  • bun create @eslint/config@latest
It then asked me a series of questions: 
  • What do you want to lint? ... I selected Markdown. 
  • How would you like to use ESLint? ... To check syntax and find problems. 
  • What type of modules does your project use? ... I selected "JavaScript modules" since we seem to use import/ export, and not require/ exports anywhere. 
  • Which framework does your project use? ... None of these. 
  • Does your project use TypeScript? ... Yes. 
  • Where does your code run? Browser? Node? ... it actually runs in both, so let's check off both. 
  • Which language do you want your configuration file to be written in? ... JavaScript. 
Why did I pick JavaScript? If I picked TypeScript, I would then have to install a library called Jiti to load the TypeScript Config file. Keeping it as a JavaScript file would make it easier. 

Then it asked: 
  • The config that you've selected requires the following dependencies: eslint, @eslint/js, globals, typescript-eslint.
  • Would you like to install them now? ... Yes. 
It continued: 
  • Which package manager do you want to use? ... npm, yarn, pnpm, bun ... I selected "bun". 
Finally, it installed everything. When it was finished, it set up a new file...

eslint.config.mjs
import js from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";
import { defineConfig } from "eslint/config";

export default defineConfig([
  { files: ["**/*.{js,mjs,cjs,ts,mts,cts}"], plugins: { js }, extends: ["js/recommended"], languageOptions: { globals: {...globals.browser, ...globals.node} } },
  tseslint.configs.recommended,
]);

js/recommended gives us ESLint’s standard default rules for JavaScript catching mistakes like using variables before they’re defined, using undeclared variables, unreachable code, confusing or invalid syntax patterns, some common logic and scope problems.

tseslint.configs.recommended adds the recommended rules for TypeScript. It catches stuff like: unsafe or incorrect type usage, confusing any usage, unnecessary type assertions, some patterns that are likely to cause bugs in TypeScript code.

Installing ESLint for Playwright


According to the NPMJS.com entry on eslint-plugin-playwright
  • bun add -D eslint-plugin-playwright
This adds eslint-plugin-playwright to your package.json. 

The docs mention that eslint-plugin-playwright, "The recommended setup is to use the files field to target only Playwright test files. In the examples below, this is done by targeting files in the tests directory and only applying the Playwright rules to those files. In your project, you may need to change the files field to match your Playwright test file patterns".

Following their directions, our eslint.config.jts now looks like:
import js from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";
import { defineConfig } from "eslint/config";
import playwright from "eslint-plugin-playwright";

export default defineConfig([
  {
    files: ["**/*.{js,mjs,cjs,ts,mts,cts}"],
    plugins: { js },
    extends: ["js/recommended"],
    languageOptions: {
      globals: { ...globals.browser, ...globals.node },
    },
  },
  {
    files: ["tests/**"],
    extends: [playwright.configs["flat/recommended"]],
  },
  tseslint.configs.recommended,
]);

... If we wanted to pick and choose which rules to follow, we could add a rules block, but let's leave it as is for now. 

To run the linter:
  • bunx eslint . --ext .ts,.mts,.js,.mjs
... No output? No problems detected! 

ESLint for Prettier

We are using ESLint for our code linter, ESLint for Playwright as our Playwright linter. 

Both of these packages would step on the toes of our code formatter, Prettier, so Prettier came up with eslint-config-prettier, which had some Prettier rules that would conflict turned off. 

We are going to add Prettier and eslint-config-prettier at the same time with:
  • bun add -D prettier eslint-config-prettier
To check if Prettier installed:
  • bunx prettier --version
Check with Prettier if there are any errors:
  • bunx prettier --check .
... And it looks like there are four warnings.

What are they? 
  • bunx prettier --list-different .
  • bunx prettier --check . --log-level debug
Okay, they are minor spacing issues. Let's fix them:
  • bunx prettier --write .
Want to see more options? 

Add Scripts to the Package.json


You know, "bunx eslint ." and all the rest is kinda complicated. 

Let's add some more scripts that are lint related to our package.json, which already has our test script and typecheck script where we added the TypeScript compiler. 

"scripts": {
    "test": "playwright test",
    "lint": "eslint .",
    "lint:ci": "eslint . --max-warnings 0",
    "lint:fix": "eslint . --fix",
    "format": "prettier --write .",
    "format:check": "prettier --check .",
    "format:debug": "prettier --check . --log-level debug",
    "format:diff": "prettier --list-different",
    "typecheck": "tsc --noEmit"
  },

... All we need to do is run "bun run test", "bun run format", or "bun run typecheck" to run tests, format the code, or run typecheck. 

Also, I added lint:ci, for our CI/CD pipeline we will be adding later, so it does not allow any warnings with lint. 


Happy Testing!

-T.J. Maher
Software Engineer in Test

BlueSky | YouTubeLinkedIn | Articles

No comments:

Post a Comment