E2Eテスト -マークアップチェック編 clientScriptsメソッド-

これまで、

- 各ページのスクリーンショットを撮る
- フォーム送信の動作確認
- metaなどの情報取得チェック

をTestcafeで実装してきました。


今回はさらに「h1があるか」「画像のaltが抜けていないか」などSEOにも関わってくるマークアップチェックも行いましたので実装方法を書いていこうと思います！

。。。が、その前に！今回はTestcafeの`.clientScripts`メソッドを使って実装していくので、まずはこのメソッドについて公式ドキュメントから抜粋した内容を書いていきます。


#.clientScriptsメソッド

##Fixture.clientScripts / Test.clientScripts
テスト中にアクセスしたすべてのページにスクリプトを挿入します

**【Fixtureの場合】**

`fixture.clientScripts( script[, script2[, ...[, scriptN]]] ) → this`

```sample.js
fixture `My fixture`
  .page `http://example.com`
  .clientScripts('assets/jquery.js');

fixture
  .clientScripts({
    page: /\/user\/profile\//,
    content: 'Geolocation.prototype.getCurrentPosition = () => new Positon(0, 0);'
  });
```

**【Testの場合】**
`test.clientScripts( script[, script2[, ...[, scriptN]]] ) → this`

```sample.js
test
  ('My test', async t => { /* ... */ })
  .clientScripts({ module: 'async' });

test
  ('My test', async t => { /* ... */ })
  .clientScripts({
    page: /\/user\/profile\//,
    content: 'Geolocation.prototype.getCurrentPosition = () => new Positon(0, 0);'
  });
```

＊`page`オプションを利用して、スクリプトを挿入するページを指定できます。
このオプションがない場合は、テスト中にアクセスしたすべてのページにスクリプトを挿入します。

###Javascriptファイルを挿入する
`path`プロパティを使用して文字列またはオブジェクトを渡すことができます。

**【Fixtureの場合】**
`fixture.clientScripts(filePath | { path: filePath })`
`fixture.clientScripts(filePath | { path: filePath }, ...)`
`fixture.clientScripts([ filePath | { path: filePath } ])`

``````sample.js
fixture `My fixture`
  .page `https://example.com`
  .clientScripts('assets/jquery.js');
```

**【Testの場合】**

`test.clientScripts(filePath | { path: filePath })`
`test.clientScripts(filePath | { path: filePath }, ...)`
`test.clientScripts([ filePath | { path: filePath } ])`

```sample.js
test
  ('My test', async t => { /* ... */ })
  .clientScripts('assets/jquery.js');
```

####モジュールを挿入する
テストされたページにコンテンツを注入するNode.jsモジュールの名前を指定します。
`module`プロパティを持つオブジェクトを使用します。
TestCafeはNode.jsの仕組みを利用してモジュールのエントリーポイントを検索し、その内容をテストされたページに注入します。

**【Fixtureの場合】**
`fixture.clientScripts( { module: moduleName } )`
`fixture.clientScripts( { module: moduleName }, ... )`
`fixture.clientScripts([ { module: moduleName } ])`

```sample.js
fixture `My fixture`
  .page `https://example.com`
  .clientScripts({ module: 'lodash' });
```

**【Testの場合】**
`test.clientScripts( { module: moduleName } )`
`test.clientScripts( { module: moduleName }, ... )`
`test.clientScripts([ { module: moduleName } ])`

```sample.js
test
  ('My test', async t => { /* ... */ })
  .clientScripts({ module: 'lodash' });
```

####スクリプトコードを挿入する
`content`プロパティを持つオブジェクトを渡して、挿入されたスクリプトを文字列として提供できます。

**【Fixtureの場合】**
`fixture.clientScripts({ content: code })`
`fixture.clientScripts({ content: code }, ...)`
`fixture.clientScripts([ { content: code } ])`

```sample.js
const mockDate = `
  Date.prototype.getTime = function () {
    return 42;
  };
`;

fixture `My fixture`
  .page `https://example.com`
  .clientScripts({ content: mockDate });
```

**【Testの場合】**
`test.clientScripts({ content: code })`
`test.clientScripts({ content: code }, ...)`
`test.clientScripts([ { content: code } ])`

```sample.js
const mockDate = `
  Date.prototype.getTime = function () {
    return 42;
  };
`;

test
  ('My test', async t => { /* ... */ })
  .clientScripts({ content: mockDate });
```


####特定のページにスクリプトを提供する
スクリプトを挿入するページを指定することもできます。これにより、指定したページでブラウザAPIをモックし、他のすべての場所でデフォルトの動作を使用できるようになります。
スクリプトのターゲットページを指定するには、`clientScripts`に渡すオブジェクトに`page`プロパティを追加します。

**【Fixtureの場合】**

```
fixture.clientScripts({
  page: url,
  path: filePath | module: moduleName | content: code
})

fixture.clientScripts({
  page: url,
  path: filePath | module: moduleName | content: code
}, ...)

fixture.clientScripts([
  {
    page: url,
    path: filePath | module: moduleName | content: code
  }
])
```

```sample.js
fixture `My fixture`
  .page `https://example.com`
  .clientScripts({
    page: /\/user\/profile\//,
    path: 'dist/jquery.js'
  });
```

**【Testの場合】**

```
test.clientScripts({
  page: url,
  path: filePath | module: moduleName | content: code
})

test.clientScripts({
  page: url,
  path: filePath | module: moduleName | content: code
}, ...)

test.clientScripts([
  {
    page: url,
    path: filePath | module: moduleName | content: code
  }
])
```

```sample.js
test
  ('My test', async t => { /* ... */ })
  .clientScripts({
    page: /\/user\/profile\//,
    path: 'dist/jquery.js'
  });
```

###挿入されたスクリプトでDOMにアクセスする

TestCafe はカスタムスクリプトを head タグに注入します。
これらのスクリプトは、DOM がロードされる前に実行されます。
これらのスクリプトでDOMにアクセスするには、`DOMContentLoaded`イベントが発生するまで待ちます。

```sample.js
const scriptContent = `
window.addEventListener('DOMContentLoaded', function () {
  document.body.style.backgroundColor = 'green';
});
`;

fixture `My fixture`
  .clientScripts({ content: scriptContent });
```

##その他の方法

###コマンドラインオプション

#### `--cs(--client-scripts)`

コマンドラインオプションは、同様に複数の引数をサポートしています。

```
testcafe chrome test.js --client-scripts mockDate.js,assets/react-helpers.js
```

- **JSファイルを挿入する場合**

```
testcafe chrome my-tests --cs assets/jquery.js
```

- **複数のスクリプトを指定する場合**

```
testcafe chrome test.js --client-scripts mockDate.js,assets/react-helpers.js
```

###APIメソッド

#### `runner.clientScripts`

`page`、`content`および`module`プロパティは配列を取ることができないことに注意してください。同じページに複数のスクリプトを挿入するには、スクリプトごとに1つの引数を渡します。

```
runner.clientScripts('mockDate.js', 'scripts/react-helpers.js');
```

- **JSファイルを挿入する場合**

```
runner.clientScripts('assets/jquery.js');
```

- **特定のページにスクリプトを提供する場合**

```
runner.clientScripts({
  page: /\/user\/profile\//,
  path: 'dist/jquery.js'
});
```

- **スクリプトをiframeに挿入する場合**

```
runner.clientScripts({
  path: 'scripts/helpers.js',
  page: 'https://example.com/iframe/'
}));
```

- **複数のスクリプトを指定する場合**

```
runner.clientScripts(['scripts/react-helpers.js', 'dist/jquery.js']);
```

```
const scripts = ['test1.js', 'test2.js', 'test3.js'];
runner.clientScripts(scripts.map(script => {
    path: script,
    page: 'http://example.com'
}));
```

###設定ファイルのプロパティ
`clientScripts`設定ファイルのプロパティは、配列を取ることができます。

```testcaferc.json
{
  "clientScripts": ["mockDate.js", "scripts/react-helpers.js"]
}
```

- **JSファイルを挿入する場合**

```testcaferc.json
{
  "clientScripts": "assets/jquery.js"
}
```

- **モジュールを挿入する場合**

```testcaferc.json
{
  "clientScripts": {
      "module": "lodash"
  }
}
```

- **スクリプトコードを挿入する場合**

```testcaferc.json
{
  "clientScripts": {
    "content": "Date.prototype.getTime = () => 42;"
  }
}
```

- **特定のページにスクリプトを提供する場合**

```testcaferc.json
{
  "clientScripts": {
    "page": "https://myapp.com/page/",
    "content": "Geolocation.prototype.getCurrentPosition = () => new Positon(0, 0);"
  }
}
```

- **複数のスクリプトを指定する場合**

```testcaferc.json
{
  "clientScripts": ["vue-helpers.js", {
    "page": "https://mycorp.com/login/",
    "module": "lodash"
  }]
}
```


以上が公式から参照した`.clientScriptsメソッド`についてのドキュメントになります。
次回の記事ではこのメソッドを使ったマークアップチェックの実装方法を書いていきますので併せてご覧いただけると嬉しいです。



#####参照
[公式ドキュメント](https://devexpress.github.io/testcafe/documentation/guides/advanced-guides/inject-client-scripts.html)