Chrome拡張を作ってAWSハンズオンのフォーム入力を自動化する

## 経緯

AWSなんもわからんエンジニアの @gramin です。
そろそろAWSの勉強しないとなーと思いつつ同僚に聞いたところ「ハンズオンやっとけば良いんじゃないですかね」と雑な回答をいただいたので、何も考えずに実施する事にしました。

AWS ハンズオン資料
https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-hands-on/

申し込みフォームに会社の情報などをポチポチ入力し、送信後にハンズオン動画が視聴できます。
遷移後のURLをブクマしておけば、その動画はそれ以降も視聴可能だとか。
ハンズオンを実施するにあたり、大きな問題にぶち当たります。それは……

**同じような情報を何度も入力したくない問題（エンジニアは無駄な作業が大嫌い）**

同じ動画であればブクマしておけば済むのですが、観たい動画が結構な数あります。
どれも同じような入力内容ですが、入力項目が20個弱あり、毎回入力するのは面倒。

**よし、自動化しよう。**

## 目的

- AWSハンズオンのフォーム入力を簡単にする
- Qiita運営に怒られないようにエンジニアっぽい記事にする
- Chrome拡張作りたい（個人的な趣味）

これでいきましょう！

## 作ったもの

AWSハンズオンのフォーム入力を自動化するChrome拡張
https://github.com/ama-gramin/hands-on-automation
パッケージ化されていないので手動で追加する必要があります。
そもそも入力情報をjsのソースにベタ書きしているのでパッケージ化不可能。（入力画面作る気ゼロ）

JavaScriptは独学で覚えただけなので、お作法的によくないコード書いてるかもです。

## 使い方

### GitリポジトリをClone

```
$ git clone git@github.com:ama-gramin/hands-on-automation.git
```

### Chrome拡張に追加

- 設定 > 拡張機能
- デベロッパーモードをON
- パッケージ化されていない拡張機能を読み込む
- Cloneしたディレクトリを選択

![スクリーンショット 2021-12-17 9.08.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335253/826a02ab-c59b-a519-fadb-53e2fddf09cf.png)

追加されました

アイコンは[ICOOON MONO](https://icooon-mono.com/)からお借りしてます。
エビの選定理由は「可愛かった」ただそれだけ。十分な理由ですね。

### ハンズオンのページを表示

`https://pages.awscloud.com/` から始まるページを開くと拡張機能のボタンが表示されます

たとえばこのへん
[ハンズオンはじめの一歩: AWS アカウントの作り方 & IAM 基本のキ](https://pages.awscloud.com/event_JAPAN_Ondemand_Hands-on-for-Beginners-1st-Step_LP.html?trk=aws_introduction_page)

![スクリーンショット 2021-12-17 9.11.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335253/1edba89b-cfaf-191f-9b24-3f70f12706e3.png)

拡張機能のボタンからピン留めしておくと便利だと思います。エビかわいい。

### 拡張機能のボタンをポチる（動作確認）

![スクリーンショット 2021-12-17 9.12.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335253/21c53d29-f8e5-debe-cb2b-19469a0b82be.png)

こんな感じで情報が入力されます。
ちなみに利用規約への同意のチェックボックス、利用目的のラジオボタンは自力で選択する必要があります。

### 入力情報の変更

上記の通り、このままではサンプルの情報が入力されてしまいます。
`constants.js` を開いて自身の情報に変更しましょう。

![スクリーンショット 2021-12-17 9.24.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335253/d717251e-6883-738e-e3e3-be41b3d650fe.png)

ちなみに入力フォームは数種類存在しており、そのうち3パターンを定義してあります。
ご自身の受講したい動画に合わせて入力情報を変更してください。
`URL_TYPEX` が含まれるURLが入力対象となります。（後述）

コンボボックスの情報を変更したい場合は
デベロッパーモードで要素を確認してvalue値を拾ってきましょう

![スクリーンショット 2021-12-17 9.56.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335253/01e58b95-4dda-2150-e419-2df0f8edae4b.png)

### ソースコードの再読み込み

修正が終わったら拡張機能の設定ページを開き、`hands-on extension`の更新ボタンをポチりましょう。
これをしないと更新が反映されません。

### ハンズオンのページの再読み込み

拡張機能の更新後は、対象ページの再読み込みも必要です。
たぶんページ読み込み時に拡張機能のjsが実行されるから。
あとは動作確認の時と同じく拡張機能のボタンをポチって情報を入力しましょう。
やったー！これで会社の電話番号を暗記しなくて済むぞー！！

## ソースコード解説

### manifest.json

拡張機能の定義ファイル。
[【結構簡単】ブラウザアクションボタン発火の自作Chrome拡張機能の作り方＆サンプル](http://degitekunote.com/blog/2016/11/02/chrome-extension/)
こちらの記事を参考になんとなく作成しました。

```json
"icons": {
    "32": "icon_32.png",
    "48": "icon_48.png",
    "128": "icon_128.png"
},
```

えび
拡張機能の設定ページに表示されるヤツ（たぶん）

```json
"content_scripts": [{
    "matches": ["https://pages.awscloud.com/*"],
    "js": [
      "constants.js",
      "main.js"
    ]
}],
```

実行対象のURLと読み込むjsファイル
ボタンなしで自動実行の拡張機能を作った時もこれを設定した記憶

```json
"background": {
    "scripts": [
        "background.js"
    ]
},
```

拡張ボタンが実行された時とかに呼び出される処理の定義

```json
"browser_action": {
    "default_icon": "icon_32.png",
    "default_title": ""
}
```

えび
ボタンの設定

### background.js

```js
chrome.browserAction.onClicked.addListener(function(tab) {
	chrome.tabs.sendMessage(tab.id, "Action");
});
```

[参考サイト](http://degitekunote.com/blog/2016/11/02/chrome-extension/)まんま
拡張機能のボタンが押されたらメッセージを送信
`main.js` で受け取ります

### constants.js

```js
const URL_BASE = 'https://pages.awscloud.com/';
const URL_TYPE1 = URL_BASE + 'event_JAPAN_Ondemand_Hands-on-for-Beginners-';
const URL_TYPE2 = URL_BASE + 'JAPAN-event-OE-Hands-on-for-Beginners-';
const URL_TYPE3 = URL_BASE + 'event_JAPAN_Hands-on-for-Beginners-';
```

前述した通り、URLによってフォームの形式が複数ありました
ここで定義しておいて `main.js` の分岐に使っています

```js
const COLUMNS_TYPE1 = {
    // 姓
    LastName: '名字',
    // 名
    FirstName: '名前',
```

入力値の定義
IDの設定値をキーにしています
上記のURLパターンに紐づくように `COLUMNS_TYPEX` の形式で定義

### main.js

```js
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
	if (request == "Action") {
		inputForm();
	}
});
```

`background.js` で送信したメッセージの受け取り
`request` の値が `Action` だったらフォーム入力を行います

```js
let columns;

if (location.href.match(URL_TYPE1)) {
    columns = COLUMNS_TYPE1;
} else if (location.href.match(URL_TYPE2)) {
    columns = COLUMNS_TYPE2;
} else if (location.href.match(URL_TYPE3)) {
    columns = COLUMNS_TYPE3;
}

if (!columns) {
    return
}
```

URLの形式によって入力する情報を変更します
URLがマッチしなければ何もせずに終了

```js
for (let id in columns) {
    const element = document.getElementById(id);
    if (element) {
        element.value = columns[id];
    }
}
```

IDが一致する要素を拾ってきて
要素が存在したらvalueを設定
要素分繰り返して終了です

## 課題

- 入力情報がjsベタ書き
    - 情報を登録する画面があったら良いかも
    - とはいえ一回設定してしまえばその後変更することもあまりないので、そこまでやる気も起きず
    - 勉強がてら作るのはいいかも
- 複数パターン分設定をしないといけない
    - 1箇所に定数定義しておいてそれを参照、としたほうが良い
    - これも「どうせ最初の1回だけだし」でサボりました
    - あとコンボボックスのvalueが若干違うのでめんどくさい
- エビ
    - パッケージ化するなら意味のあるアイコンにしないとですね
    - とはいえエビは可愛い

## 最後に

Chrome拡張は結構簡単に作れるので、作業の自動化にオススメです。
作成時間的にはSeleniumIDEとか作った方が圧倒的に早いとは思うんですが、
いちいち起動する手間とか、JSの勉強になると思えば結構ありです。

さて、そろそろハンズオンの動画観るか……。（まだ最初の数秒しか見てない）