宮本さんjest導入 ~オブジェクト関数からclass構文への移行~

# 宮本さんjest導入の話 


## 最初の壁

最初にjestの方に宮本さんのscriptをimport してとりあえずテスト回そうとしたら
動かないんですよね...
てか、オブジェクト関行importできまへんやん!
となりclass構文への移行を決意。

## 移行

とりあえずソースのせる

```js:オブジェクト関数
loadDateUtils = function () {
  var DateUtils = {};

  // 今を返す
  var _now = new Date();
  var now = function(datetime) {
    if(typeof datetime != 'undefined') {
      _now = datetime;
    }
    return _now;
  };
  DateUtils.now = now;

  // テキストから時間を抽出
  DateUtils.parseTime = function(str) {
    str = String(str || "").toLowerCase().replace(/[Ａ-Ｚａ-ｚ０-９]/g, function(s) {
      return String.fromCharCode(s.charCodeAt(0) - 0xFEE0);
    });
    var reg = /((\d{1,2})\s*[:時]{1}\s*(\d{1,2})\s*(pm|)|(am|pm|午前|午後)\s*(\d{1,2})(\s*[:時]\s*(\d{1,2})|)|(\d{1,2})(\s*[:時]{1}\s*(\d{1,2})|)(am|pm)|(\d{1,2})\s*時)/;
    var matches = str.match(reg);
    if(matches) {
      var hour, min;

      // 1時20, 2:30, 3:00pm
      if(matches[2] != null) {
        hour = parseInt(matches[2], 10);
        min = parseInt((matches[3] ? matches[3] : '0'), 10);
        if(_.contains(['pm'], matches[4])) {
          hour += 12;
        }
      }

      // 午後1 午後2時30 pm3
      if(matches[5] != null) {
        hour = parseInt(matches[6], 10);
        min = parseInt((matches[8] ? matches[8] : '0'), 10);
        if(_.contains(['pm', '午後'], matches[5])) {
          hour += 12;
        }
      }

      // 1am 2:30pm
      if(matches[9] != null) {
        hour = parseInt(matches[9], 10);
        min = parseInt((matches[11] ? matches[11] : '0'), 10);
        if(_.contains(['pm'], matches[12])) {
          hour += 12;
        }
      }

      // 14時
      if(matches[13] != null) {
        hour = parseInt(matches[13], 10);
        min = 0;
      }

      return [hour, min];
    }
    return null;
  };
```

```js:class構文
import { contains, isNaN } from "underscore";

export class DateUtils {
  now: Number;
  setTime(now: any) {
    return (this.now = now);
  }
  dateUtilsNow(datetime: Date) {
    let _now = new Date();
    if (typeof datetime !== "undefined") {
      _now = datetime;
    }
    return this.setTime(_now);
  }

  dateUtilsParseTime(str: any) {
    str = String(str || "")
      .toLowerCase()
      .replace(/[Ａ-Ｚａ-ｚ０-９]/g, (s) => {
        return String.fromCharCode(s.charCodeAt(0) - 0xfee0);
      });
    const reg = /((\d{1,2})\s*[:時]{1}\s*(\d{1,2})\s*(pm|)|(am|pm|午前|午後)\s*(\d{1,2})(\s*[:時]\s*(\d{1,2})|)|(\d{1,2})(\s*[:時]{1}\s*(\d{1,2})|)(am|pm)|(\d{1,2})\s*時)/;
    const matches = str.match(reg);
    if (matches) {
      let hour, min;

      // 1時20, 2:30, 3:00pm
      if (matches[2] != null) {
        hour = parseInt(matches[2], 10);
        min = parseInt(matches[3] ? matches[3] : "0", 10);
        if (contains(["pm"], matches[4])) {
          hour += 12;
        }
      }

      // 午後1 午後2時30 pm3
      if (matches[5] != null) {
        hour = parseInt(matches[6], 10);
        min = parseInt(matches[8] ? matches[8] : "0", 10);
        if (contains(["pm", "午後"], matches[5])) {
          hour += 12;
        }
      }

      // 1am 2:30pm
      if (matches[9] != null) {
        hour = parseInt(matches[9], 10);
        min = parseInt(matches[11] ? matches[11] : "0", 10);
        if (contains(["pm"], matches[12])) {
          hour += 12;
        }
      }

      // 14時
      if (matches[13] != null) {
        hour = parseInt(matches[13], 10);
        min = 0;
      }

      return [hour, min];
    }
    return null;
  }
}
```

移行方法は簡単オブジェクト関数をclassのmethodに置き換えていくだけです。
`  DateUtils.now = now;` 時間をとってるところだったりしているとこはSetter使ったりして対応しています。

ただ、このようなSetter使用方法はESLintさんに怒られるのでconstructorに書き換える予定です。

オブジェクト関数からclass構文への移行のメリットは

- jestにインポートできる
- underscore.jsがimport経由で使えるので関数の前に_つけなくてすむのが地味に嬉しい


## jestでtest書く

とりあえずソース抜粋

```js
import { isEqual } from "../node_modules/underscore";
import { DateUtils } from "../_test_utils_/date_utils_test";

const dateUtils = new DateUtils();

describe("dateUtils_parseTime", () => {
  it("dateUtils_parseTime: #1", () => {
    const dateUtils_parseTime = () => {
      return isEqual([13, 1], dateUtils.dateUtilsParseTime("13:01"));
    };
    expect(dateUtils_parseTime()).toBe(true);
  });
  it("dateUtils_parseTime: #2", () => {
    const dateUtils_parseTime_test = () => {
      return isEqual([14, 2], dateUtils.dateUtilsParseTime("2:02pm"));
    };
    expect(dateUtils_parseTime_test()).toBe(true);
  });
  it("dateUtils_parseTime: #3", () => {
    const dateUtils_parseTime_test = () => {
      return isEqual([16, 3], dateUtils.dateUtilsParseTime("午後4:3"));
    };
    expect(dateUtils_parseTime_test()).toBe(true);
  });
  it("dateUtils_parseTime: #4", () => {
    const dateUtils_parseTime_test = () => {
      return isEqual([17, 0], dateUtils.dateUtilsParseTime("5pm"));
    };
    expect(dateUtils_parseTime_test()).toBe(true);
  });
  it("dateUtils_parseTime: #5", () => {
    const dateUtils_parseTime_test = () => {
      return isEqual([17, 1], dateUtils.dateUtilsParseTime("5:1pm"));
    };
    expect(dateUtils_parseTime_test()).toBe(true);
  });
  it("dateUtils_parseTime: #6", () => {
    const dateUtils_parseTime_test = () => {
      return isEqual([18, 0], dateUtils.dateUtilsParseTime("18時"));
    };
    expect(dateUtils_parseTime_test()).toBe(true);
  });
  it("dateUtils_parseTime: #7", () => {
    const dateUtils_parseTime_test = () => {
      return isEqual([19, 20], dateUtils.dateUtilsParseTime("19 : 20"));
    };
    expect(dateUtils_parseTime_test()).toBe(true);
  });
  it("dateUtils_parseTime: #8", () => {
    const dateUtils_parseTime_test = () => {
      return isEqual([20, 0], dateUtils.dateUtilsParseTime("午後８"));
    };
    expect(dateUtils_parseTime_test()).toBe(true);
  });
});

```
### Jestの使い方

`describe` テストの塊
`it` テスト
`expect` テストを指定
`tobo` 答え指定

という感じです。



describeはdateUtils_parseTime関数のテストを使いたいのでこんな感じで

```js
describe("dateUtils_parseTime", () => {

})
```

itはテスト名はよしなにこのテスト名良くないですがご容赦ください！

```js
describe("dateUtils_parseTime", () => {
 it("dateUtils_parseTime: #1", () => {
    });
})
```

ここでやり方の問題ですがexpectに直接関数書いてもいいのですが
僕の好みでit内で書いてます

```js
describe("dateUtils_parseTime", () => {
 it("dateUtils_parseTime: #1", () => {
       const dateUtils_parseTime = () => {
          return isEqual([13, 1], dateUtils.dateUtilsParseTime("13:01"));
        };
    });
})
```

次はexpectに先程書いた関数を記述

```js
describe("dateUtils_parseTime", () => {
 it("dateUtils_parseTime: #1", () => {
       const dateUtils_parseTime = () => {
          return isEqual([13, 1], dateUtils.dateUtilsParseTime("13:01"));
        };
    });
     expect(dateUtils_parseTime_test())
})
```

最後にtoBeで結果を指定する

```js
describe("dateUtils_parseTime", () => {
 it("dateUtils_parseTime: #1", () => {
       const dateUtils_parseTime = () => {
          return isEqual([13, 1], dateUtils.dateUtilsParseTime("13:01"));
        };
    });
     expect(dateUtils_parseTime_test()).toBe(true);
})
```






下記でテスト回す
`npm test date_utils_test.spec`


```
 PASS  _tests_/date_utils_test.spec.ts
  dateUtils_parseTime ←describe名
    ✓ dateUtils_parseTime: #1 (3ms)  ←it名
    ✓ dateUtils_parseTime: #2 (1ms)
    ✓ dateUtils_parseTime: #3 (1ms)
    ✓ dateUtils_parseTime: #4 (1ms)
    ✓ dateUtils_parseTime: #5
    ✓ dateUtils_parseTime: #6
    ✓ dateUtils_parseTime: #7 (1ms)
    ✓ dateUtils_parseTime: #8
  dateUtils_parseDate
    ✓ dateUtils_parseDate: #1 (1ms)
    ✓ dateUtils_parseDate: #2
    ✓ dateUtils_parseDate: #3 (1ms)
```

こんな感じで返ってきます。

jest導入の話はこんなところです


[次はTS化の話書きます〜](https://qiita.com/taichi0514/items/3e64837a3dcb9193e8cb)