ProtractorのテストコードをTypeScriptで書く

[前の記事](http://qiita.com/frost_star/items/9c2c4fa1ff8874980f8b)でProtractorの導入を行いました。
しかし、JavaScriptでそのまま書いていたので、できればTypeScriptで書きたい。
さらにその上で、webpackを使って複数のテストコードをbundle化し、一つのjsファイルにします。

# 準備
今回使うパッケージを一通り入れておきます。
前回入れたprotractor関連は書いてないので、そちらは前の記事を参考にしてください。

- typescript
- webpack
- ts-loader
- gulp 
- gulp-typescript
- gulp-webpack
- glob

`npm install typescript webpack ts-loader gulp gulp-typescript gulp-webpack glob`

# TypeScriptでコードを書く
今回も[Protractorのデモサイト](http://juliemr.github.io/protractor-demo/)を使ったテストコードを書きます。
とりあえず、前回のspec.jsを単純にspec.tsに移します。
また、2つめのテストケースspec2.tsを作成します。

```ts:spec.ts
describe("AngularJSホームページ", function() {
  it("タイトルを持つ", function() {
    // 接続先URLの設定
    browser.get("http://juliemr.github.io/protractor-demo/");
    // タイトルが指定文字列に一致するかどうかのテスト
    expect(browser.getTitle()).toEqual("Super Calculator");
  });
});

```

```ts:spec2.ts
describe("AngularJSホームページ", function() {
  it("1と2を加える", function() {
     browser.get("http://juliemr.github.io/protractor-demo/");
     element(by.model("first")).sendKeys(1);
     element(by.model("second")).sendKeys(2);

     element(by.id("gobutton")).click();

     expect(element(by.binding("latest")).getText()).
         toEqual("3");
   });
});
```

# コンパイル設定作成
TypeScriptをコンパイル、bundle化するための設定ファイルgulp.jsとwebpack.config.jsを作成します。

```js:gulp.js
var gulp = require('gulp');
var ts = require('gulp-typescript');
var webpack = require('gulp-webpack');
var webpackConfig = require('./webpack.config.js');

// TypeScriptのコンパイルとwebpackの実行
gulp.task('ts', function () {
    // TypeScriptのコンパイル
    var tsResult = gulp.src(['./*.ts'])
        .pipe(webpack(webpackConfig))
        .pipe(gulp.dest('./'));
});
```

```js:webpack.config.js
var path = require('path');
var webpack = require('webpack');
var glob = require('glob');

module.exports = {
    // エントリーポイント
    // ワイルドカードを使用するためにglobを使う
    entry:{
      'spec': glob.sync('./*.ts')
    },
    // 出力するファイル名
    output: {
        filename: './bundle.js'
    },
    // 依存関係
    resolve: {
        root:[path.join(__dirname,'node_modules')],
        extensions:['', '.webpack.js', 'web.js', '.js', '.ts']
    },
    // TypeScriptを読み込むためのloader
    module: {
        loaders: [
            { test: /\.ts$/, loader: 'ts-loader' }
        ]
    }
}

```

ここまで、設定が終わった後に`gulp ts`を実行すればtsファイルがコンパイルされ、spec.tsとspec2.tsの2つが1つのbundle.jsとして出力されます(ただし、コンパイル時にエラーがでます)。

# 構文エラーの解消
ts-linterなどの構文チェックツールを使っていると、Protractorの`browser`や`element`、Jasmineの`describe`や`it`で構文エラーが出ます。
これを解消するためには、それぞれの型定義ファイルを読み込む必要があります。

前者の場合は、Protractorをインストールディレクトリに型定義ファイルが含まれているので、
`import { browser, element, by } from "protractor/globals";`
を記述すれば構文エラーが解消できます。

後者の場合は、Jasmineパッケージには含まれていないので別途必要となりますが、npmパッケージとしては公開されていません。そのため、typings経由でインストールする必要があります。

まずはtypingsを入れます。
`npm install typings`

そして、typingsでJasmineの型定義ファイル([jasmine.d.ts](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/jasmine/jasmine.d.ts))をインストールします。
ただし、typingsのバージョンが1.3.0以後だと、普通のインストールコマンドだとエラーが出るようです。

通常のインストールコマンド
`typings install jasmine --save --ambient`

1.3.0以後
`typings install --save dt~jasmine --global`

typingsで入れた場合は、referenceで型定義を適用するようです。
`/// <reference path="../typings/index.d.ts" />`

これを適用したspec.ts、spec2.tsは以下のようになります。


```ts:spec.ts
/// <reference path="../typings/index.d.ts" />
import { browser } from "protractor/globals";

describe("AngularJSホームページ", function() {
  it("タイトルを持つ", function() {
    // 接続先URLの設定
    browser.get("http://juliemr.github.io/protractor-demo/");
    // タイトルが指定文字列に一致するかどうかのテスト
    expect(browser.getTitle()).toEqual("Super Calculator");
  });
});

```

```ts:spec2.ts
/// <reference path="../typings/index.d.ts" />
import { browser, element, by } from "protractor/globals";

describe("AngularJSホームページ", function() {
  it("1と2を加える", function() {
     browser.get("http://juliemr.github.io/protractor-demo/");
     element(by.model("first")).sendKeys(1);
     element(by.model("second")).sendKeys(2);

     element(by.id("gobutton")).click();

     expect(element(by.binding("latest")).getText()).
         toEqual("3");
   });
});
```

# 参考
[TypeScriptのtsdがオワコンになったのでtypingsを使ってみた](http://kuroeveryday.blogspot.jp/2016/02/typescript-typings.html)
[webpackのentryにワイルドカードを使うには](http://qiita.com/pegass85/items/2ddfd03b9e280c6caa2a)