これだけはおさえておきたいPlaywrightコマンド集

# はじめに
この記事では、Playwrightでテストを書いていく上で「こんな時どう書く？」をまとめた記事です。
コマンド集は[公式ドキュメント](https://playwright.dev/docs/intro)にもあります。
コマンドがたくさんあり様々なことができます。
本記事ではその中からよく使いそうな**これだけはおさえておきたい**ものをピックアップして、要素の操作と検証など実践に使いやすい形のサンプルを用意してみました。
また、PlaywrightのテストコードだけでなくHTMLも合わせて載せておりますので参考にしていただけたらと思います。

以下のコマンドの紹介では、Playwrightのデモ用のページを利用しています。
* デモページ：https://demo.playwright.dev/todomvc

# 環境
以下の環境下で動作を確認しました。
* OS : Windows 10, Ubuntu 20.04 
* Node : v16.15.1

# Playwrightで扱えるロケータ
CSS, XPathはもちろんのこと、PlayWrightでは表記されている文字で要素を取得することができます。
本文書では、CSSを中心に扱っていますが表記文字による取得方法に関して少し触れておきます。
表記文字で要素を取得できるため、CSSやXpathに詳しくなくてもコードを書くことができます。

```html
<a class="getStarted_Sjon" href="/docs/intro">Get started</a>
```

## CSSセレクタで指定

```typescript
test('xxxx', async ({ page }) => {
  await page.goto('https://playwright.dev/'); // ページ遷移
  
  const ele = page.locator('.getStarted_Sjon');
  await expect(ele).toHaveAttribute('href','/docs/intro');
});
```

## 表示文字で取得
```typescript
test('xxxx', async ({ page }) => {
  await page.goto('https://playwright.dev/'); // ページ遷移
  
  const ele = page.locator('text=Get Started');
  await expect(ele).toHaveAttribute('href','/docs/intro');
});
```

# 覚えておきたいコマンド集
## ページ遷移
`page.goto([URL])` でページ遷移できます。

```typescript:example.spec.ts
import { test, expect } from '@playwright/test';

test('xxxx', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc');
});
```

※ 以降はimport文は割愛します。

## 要素の取得、要素の値を取得
### 要素の取得
`page.locator('[セレクタ]')`で要素を取得できます。

```html
<h1>todos</h1>
```

```typescript
test('xxxx', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc'); // ページ遷移

  const h1 = page.locator('h1'); // h1要素を取得
});
```

### 要素の値の取得
```html
<h1>todos</h1>
<input class="new-todo" placeholder="What needs to be done?">
```


```typescript
test('xxxx', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc'); // ページ遷移

  // 要素のテキストの取得
  console.log(await page.innerText('h1')); // => todos
  // 要素の属性値の取得
  console.log(await page.locator('.new-todo').getAttribute('placeholder')); // => What needs to be done?
});

```

### ページタイトルの取得
ページタイトルの取得は要素をセレクタ指定して`page.locator('title')`で取得、
または`page.title()`で取得することもできます。

```html
<title>React • TodoMVC</title>
```

```typescript
test('xxxx', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc'); // ページ遷移

  expect(await page.title()).toBe('React • TodoMVC'); // title()で取得
  const title = page.locator('title');                // locator()で要素指定して取得
  await expect(title).toHaveText('React • TodoMVC'); 
});
```

## 要素の操作
### 入力操作
`fill()`でテキストボックスに文字を入力することができます。

```html
<input class="new-todo">
```

```typescript
test('xxxx', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc'); // ページ遷移
  
  await page.locator('.new-todo').fill('sample'); // テキストボックスに入力
});
```

### クリック操作
ボタンをクリックすることができます。

```html
<input class="new-todo">
<ul class="todo-list">
  <li>
    <div class="view">
      <input class="toggle" type="checkbox">
      <label>sample</label>
      <button class="destroy"></button>
    </div>
  </li>
</ul>
```

```typescript
test('xxxx', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc'); // ページ遷移
  
  await page.locator('.new-todo').fill('sample'); // テキストボックスに入力
  await page.locator('.new-todo').press('Enter'); // Enterキー押下
  await page.locator('.view').hover(); // 要素にフォーカスをあてて削除ボタンを表示

  // [クリック操作] 
  await page.locator('.destroy').click(); // 削除ボタンをクリック
});
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19778/3ce6bbce-bc01-3981-3095-f625a29b5e84.png)


## 検証
### 要素の値の検証
`expect([ロケータ]).toHaveText()`で取得した要素のテキストが検証できます。
その他にも以下のように様々な検証が可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19778/b4dca69d-a7e2-906a-c39c-b27cdc22fbbd.png)


```html
<h1>todos</h1>
```

```typescript
test('xxxx', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc'); // ページ遷移

  await expect(page.locator('h1')).toHaveText('todos'); // h1要素のテキストを検証
});
```

### テキストの部分一致、完全一致の検証
マッチャーに正規表現を使うことができます。


```html
<title>React • TodoMVC</title>
```

```typescript
test('xxxx', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc'); // ページ遷移

  await expect(page).toHaveTitle(/TodoMVC/);         // タイトル検証(部分一致)
  await expect(page).toHaveTitle('React • TodoMVC'); // タイトル検証(完全一致)
});
```

### 要素が表示されている・いないことの検証

```html
<h1>todos</h1>
```

```typescript
test('xxxx', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc'); // ページ遷移

  await expect(page.locator('h1')).toBeVisible();     // 要素が表示されている
  await expect(page.locator('h2')).not.toBeVisible(); // 要素が表示されていない
});
```

## ロケーションの取得
`page.url()`で現在のページのロケーションを取得できます。

```typescript
test('xxxx', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc'); // ページ遷移

  await expect(page.url()).toBe('https://demo.playwright.dev/todomvc/#/');
});
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19778/3fe065ef-fc56-0ffd-391c-1bade2a99204.png)


## 待機処理
ある操作をしているときに、そこで処理を止めたいときは以下のようにすると処理を待機することができます。

### 一定時間待機
```typescript
test('xxxx', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc');
  
  await page.waitForTimeout(5000); // 5秒待機
});
```

### 一時停止
```typescript
test('xxxx', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc');
  
  await page.pause(); // 一時停止 
});
```