E2E Testing with Playwright 1.49 2025-01-17

みんな大好きPlaywright、テストを新規作成する度に、変更の激しいESLint, Prettierへの対応に振り回されることも多いのでは無いでしょうか。おそらく。

ということで、定期的に初期段階の設定を記録しておく目的の投稿です。

今回は、Playwright 1.49 が対象。

# Playwright

Fast and reliable end-to-end testing for modern web apps | Playwright
https://playwright.dev/

現在の最新版は 1.49

Release notes | Playwright
https://playwright.dev/docs/release-notes#version-149


## 所感

- ついにクライアント証明書が利用出来るようになったのは密かに嬉しい [1\.46](https://playwright.dev/docs/release-notes#version-146)
    - 個人的にはこれでPostmanを使う機会が無くなりそう

# Linter 今回はどうするか問題

以前はPlaywright公式ドキュメント(かどこかうろ覚え)において、 [eslint-plugin-playwright](https://github.com/playwright-community/eslint-plugin-playwright) の利用が推奨されていたような気がするのだが、最新版では、以下の記載がある。

> a## Lint your tests
> 
> We recommend TypeScript and linting with ESLint for your tests to catch errors early. Use [@typescript-eslint/no-floating-promises](https://typescript-eslint.io/rules/no-floating-promises/) [ESLint](https://eslint.org/) rule to make sure there are no missing awaits before the asynchronous calls to the Playwright API. On your CI you can run tsc --noEmit to ensure that functions are called with the right signature.


ということで、今回は typescript-eslint を採用。

typescript-eslint
https://typescript-eslint.io/

GitHub - playwright-community/eslint-plugin-playwright: ESLint plugin for Playwright
https://github.com/playwright-community/eslint-plugin-playwright



# セットアップ

## 対象環境

```shell
user@host: /path/to/dir

$ date
Fri Jan 17 13:39:04 JST 2025

$ sw_vers
ProductName:    macOS
ProductVersion: 15.2
BuildVersion:   24C101

$ node --version 
v22.3.0

$ npm --version
10.8.1
```


## Playwright


```shell
user@host: /path/to/dir
$ npm init playwright@latest

> npx
> create-playwright

Getting started with writing end-to-end tests with Playwright:
Initializing project in '.'
✔ Do you want to use TypeScript or JavaScript? · TypeScript
✔ Where to put your end-to-end tests? · tests
✔ Add a GitHub Actions workflow? (y/N) · true
✔ Install Playwright browsers (can be done manually via 'npx playwright install')? (Y/n) · true
Initializing NPM project (npm init -y)…
Wrote to /path/to/package.json:

{
  "name": "test",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": ""
}



Installing Playwright Test (npm install --save-dev @playwright/test)…

added 3 packages, and audited 4 packages in 7s

found 0 vulnerabilities
Installing Types (npm install --save-dev @types/node)…

added 3 packages, and audited 7 packages in 528ms

found 0 vulnerabilities
Writing playwright.config.ts.
Writing .github/workflows/playwright.yml.
Writing tests/example.spec.ts.
Writing tests-examples/demo-todo-app.spec.ts.
Writing package.json.
Downloading browsers (npx playwright install)…
✔ Success! Created a Playwright Test project at /path/to/dir

Inside that directory, you can run several commands:

  npx playwright test
    Runs the end-to-end tests.

  npx playwright test --ui
    Starts the interactive UI mode.

  npx playwright test --project=chromium
    Runs the tests only on Desktop Chrome.

  npx playwright test example
    Runs the tests in a specific file.

  npx playwright test --debug
    Runs the tests in debug mode.

  npx playwright codegen
    Auto generate tests with Codegen.

We suggest that you begin by typing:

    npx playwright test

And check out the following files:
  - ./tests/example.spec.ts - Example end-to-end test
  - ./tests-examples/demo-todo-app.spec.ts - Demo Todo App end-to-end tests
  - ./playwright.config.ts - Playwright Test configuration

Visit https://playwright.dev/docs/intro for more information. ✨

Happy hacking! 🎭
```


## typescript-eslint


```shell
user@host: /path/to/dir
$ npm install --save-dev eslint @eslint/js typescript typescript-eslint

added 116 packages, and audited 123 packages in 6s

35 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
```

### typescript-eslint/no-floating-promises 

no-floating-promises | typescript-eslint
https://typescript-eslint.io/rules/no-floating-promises/

を参照し以下のような `eslint.config.mjs` を用意。


```javascript:eslint.config.mjs
// @ts-check

import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';


export default tseslint.config(
  eslint.configs.recommended,

  // tseslint.configs.stylistic,
  tseslint.configs.stylisticTypeChecked,

  // tseslint.configs.recommended,
  tseslint.configs.recommendedTypeChecked,
  // tseslint.configs.strict,
  // tseslint.configs.strictTypeChecked,

  {
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },
);
```

### tsconfig.json

`tsconfig.json` が存在しないとlint時にエラーが発生するので、最低限の内容で用意。

```json:tsconfig.json
{
  "compilerOptions": {
    "strict": true,
    "module": "NodeNext",
    "allowJs": true
  }
}
```

### eslint 実行

事前に `tests/example.spec.ts` を少し変更済み。

```shell
user@host: /path/to/dir
$ npx eslint tests/example.spec.ts 

/path/to/dir/tests/example.spec.ts
   4:4  error  Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator  @typescript-eslint/no-floating-promises
  14:4  error  Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator  @typescript-eslint/no-floating-promises

✖ 2 problems (2 errors, 0 warnings)
```

Playwright公式の意図通りであることを確認。


## package.json

この時点での `package.json`


```json:package.json
{
  "name": "test",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {},
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "devDependencies": {
    "@eslint/js": "^9.18.0",
    "@playwright/test": "^1.49.1",
    "@types/node": "^22.10.7",
    "eslint": "^9.18.0",
    "typescript": "^5.7.3",
    "typescript-eslint": "^8.20.0"
  }
}
```

# 所感

- ESLint の [(Flat) Configuration Files](https://eslint.org/docs/latest/use/configure/configuration-files#typescript-configuration-files) もTypeScript対応済みだし、 typescript-eslint よりも ESLint を使った方が結局安定しそうな懸念があるが、まぁ今回はここからやってみようかと
- しかし毎度振り回されるなぁ...


# 追記

Prettier 関連も追記

## Prettier

Prettier · Opinionated Code Formatter
https://prettier.io/


```shell
# user@host: /path/to/dir
$ npm install --save-dev --save-exact prettier
```

### prettier.config.mjs

今回はmjsで。

```javascript:prettier.config.mjs
/**
 * @see https://prettier.io/docs/en/configuration.html
 * @type {import("prettier").Config}
 */
const config = {
  trailingComma: 'all',
  tabWidth: 2,
  // tabWidth: 4,
  semi: true,
  singleQuote: true,
  // singleQuote: false,
  printWidth: 80,
  useTabs: false,

  // singleAttributePerLine:true,

  bracketSameLine: false,
};

export default config;
```

### .prettierignore

`.prettierignore` も追加しておく。

```:.prettierignore
# https://prettier.io/docs/en/ignore.html

## Node.js
node_modules/

# Playwright
playwright-report/
playwright-results/

## IDE
.vscode/
.idea/

# Ignore artifacts:
build
coverage
```

## eslint-config-prettier

prettier/eslint-config-prettier: Turns off all rules that are unnecessary or might conflict with Prettier.
https://github.com/prettier/eslint-config-prettier


```shell
# user@host: /path/to/dir
$ npm install --save-dev eslint-config-prettier @types/eslint-config-prettier
```