Blockly Custom Blocks

# Blockly Custom Blocks
前回（[Blockly Python Code Generator(2)](https://qiita.com/tkhr68000/items/d9c71af74362325174e1)）に続き、今回は具体的にカスタマイズブロックを作っていきます。googleのガイドを参照して作成します。
[Custom Blocks](https://developers.google.com/blockly/guides/create-custom-blocks/overview)

## 目標
Pythonを使い、SeleniumでEdge起動し任意のURLを開くまでを作ります。
将来的にはテスト自動駆動をBlocklyで作ることができれば良いかな、と。

## 準備
EdgeをSeleniumで起動するための環境は先に作っておきます。
### インストール
Pythonの環境も設定します。pipでSeleniumを有効にしておいてください。
```pip install selenium
```

webdriver_managerも使用します。これは自動でwebdriverをインストールするためのモジュールです。
```pip install webdriver_manager
```

ただし、現状ではログ処理部分にバグがあるため、そのままでは動作しません。
Pullリクエストは出ているので、将来的には修正されると思われます。
それまでは、自分でパッチをあてることになります。
[Fixes edge and IE driver initialization issue](https://github.com/SergeyPirogov/webdriver_manager/pull/284/files)

### テスト
動作するかどうかをスクリプトで試してみます。

```python:edge_test.py
from selenium import webdriver
from webdriver_manager.microsoft import EdgeChromiumDriverManager

executable_path = EdgeChromiumDriverManager().install()
driver = webdriver.Edge(executable_path)

driver.get("http://www.google.co.jp/")
```
ブラウザが開けることを確認します。

# Blockly Custom Blocks 作成
実際にカスタマイズBlockを作っていきます。

## Blockの定義
Blocklyでブロックを作ることができます。
[Blockly Developer Tools](https://blockly-demo.appspot.com/static/demos/blockfactory/index.html)か、ローカルのBlockly DemoのBlockly Developer Toolsを開きます。
![01_blockly-demo.appspot.com_static_demos_blockfactory_index.html.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547019/6338540a-000d-5477-f51b-cd35d2a32d58.png)

### 開始ブロック
Seleniumを実行するためにはimportが必要です。
これを実装するためのブロックを作成します。
![02_blockly-demo.appspot.com_static_demos_blockfactory_index.html.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547019/dfbc284f-bda8-5b07-6f42-ccf7896dbbdf.png)

1. nameを「selenium_start」に変更します。
1. 入力は無いため、inputsにはdummy inputを設定し、text「開始」を接続します。
1. 接続は下のみのため、「bottom connection」にします。

右側に定義用のソースが作成されているのが見えます。
次のブロック作成前にSaveをクリックして保存するのを忘れないようにして下さい。

### Edge開始ブロック
Edgeを開始するためのブロックを作成します。
![03_blockly-demo.appspot.com_static_demos_blockfactory_index.html.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547019/1a66390b-d95c-8ec6-d084-aa86de7d6ba0.png)

1. nameを「selenium_edge_start」に変更します。
1. 入力は無いため、inputsにはdummy inputを設定し、text「Edge開始」を接続します。
1. 接続は上下必要なため、「top + bottom connection」にします。

### 開くブロック
URLを開くためのブロックを作成します。
![04_blockly-demo.appspot.com_static_demos_blockfactory_index.html.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547019/e03667f9-e0b5-0bff-80f5-0a4459e34a0d.png)

1.  nameを「selenium_get」に変更します。
1. URLを文字列で受け取るため、inputsにはvalue inputを設定します。
1. text「開く」を接続します。
1. 接続できるタイプを文字列に限定するため、typeはanyからStringに変更します。
1. これも接続は上下必要なため、「top + bottom connection」にします。

一通り作成したら、Download Block Librayで保存しておいて下さい。

## Block Exporter
作成したらBlock Exporterタブに切り替えます。
![05_blockly-demo.appspot.com_static_demos_blockfactory_index.html.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547019/6eb1c2b9-9525-c055-3442-17093e5daf46.png)
左側に作成したブロックがありますので、すべて選択してください。
中央のExport Settingsにそれぞれファイル名を設定し、Exportをクリックして下さい。
定義ファイルが出力されます。

## Workspace Factory
Workspace Factoryに切り替えます。
![06_blockly-demo.appspot.com_static_demos_blockfactory_index.html.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547019/98464ea8-6a6a-dd78-3cb1-3d09cc46abd6.png)
Toolboxに作成したブロックを並べ、表示確認をします。
Exportをクリックすると、参考ソースが出力されます。

## コード追加
CustomBlockPython.jsはコード出力ための定義ですが、現状ではダミーコードが入っていますので、それを実際に出力するコードへと変更します。


```javascript:CustomBlockPython.js
Blockly.Python['selenium_start'] = function(block) {
  var code = 'from selenium import webdriver\n';
  code += 'from webdriver_manager.microsoft import EdgeChromiumDriverManager\n'
  return code;
};

Blockly.Python['selenium_edge_start'] = function(block) {
  var code = 'executable_path = EdgeChromiumDriverManager().install()\n';
  code += 'driver = webdriver.Edge(executable_path)\n'
  return code;
};

Blockly.Python['selenium_get'] = function(block) {
  var value_url = Blockly.Python.valueToCode(block, 'url', Blockly.Python.ORDER_ATOMIC);
  var code = 'driver.get(' + value_url +')\n';
  return code;
};
```
前回（[Blockly Python Code Generator(2)](https://qiita.com/tkhr68000/items/d9c71af74362325174e1)）のソースを元にカスタマイズブロックを表示できるように改造していきます。

### ブロック定義ファイル
作成したCustomBlockDefine.jsとCustomBlockPython.jsは前回のindex.htmlと同じディレクトリに配置します。

### ToolBox
カスタマイズブロックをメニューに追加します。

```xml:ntoolbox.xml(追加分)
    <category name="Custom">
        <block type="selenium_start"></block>
        <block type="selenium_edge_start"></block>
        <block type="selenium_get"></block>
    </category>
```

### HTML
カスタマイズデータを読み込む処理をHTMLに追加します。

```html:index.html(追加分)
    <script src="./CustomBlockJson.js"></script>
    <script src="./CustomBlockPython.js"></script>
```

## 実行
実際に動作させてみます。
![10_localhost_8100_html.009_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547019/9cf77263-bf2e-b6f3-56a4-1e7c7d37c41d.png)
![11_localhost_8100_html.009_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547019/909cf149-55fd-4389-1ea5-827d32fcf169.png)
![12_localhost_8100_html.009_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547019/9877f79c-be91-3f98-6ac9-fe18149fc1c9.png)

出力されたPythonコードを実際に実行した結果、Edgeが起動しました。