パルカワ2

PerlとRubyとイチャラブ

Jestを使うことにした

Jest · 🃏 Delightful JavaScript Testing

  • ユニットテスト書きたい
  • DOM操作があるテストができる
  • 通信の処理があるのでモックとかもしたい
  • 導入がめんどくさくない

自分でkarma/jasmineの設定もしてみて先人の知恵のおかげで困りはしなかったんだけど、まあJestでええか…みたいな感じになった。

Jest+TypeScriptでDOMを操作するテストを書く

ここに書かれてる方法だと document がないよ!って言われる
DOM Manipulation · Jest
JSDOMでやってあげるとよさそう。

// Hoge.test.ts
import {JSDOM} from "jsdom";

declare global {
    namespace NodeJS {
        interface Global {
            document: Document
        }
    }
}

test('js dom', () => {
    global.document = new JSDOM(`<span id="username">yoshitaka-yuriko</span>`).window.document;
    expect(document.querySelector(`#username`).textContent).toBe("yoshitaka-yuriko")
});

ngrok を使う

自分向けにローカルにあるJSをhttps経由で配布したいが、自分であれこれ設定するのはだるい。ngrokというのがあるらしいので使ったらすぐできた。

ngrok は登録が必要で、登録するとコマンドのインストールや設定を促される。そのあと以下を実行するとよい

ngrok http 8000 -bind-tls=true

内容も瞬時に反映されるので便利 ちなみに手元のサーバはファイル配信のみなのでWebServer for Chromeを使った。

これが本来の用途っぽい?

api.slack.com

TypeScript の async/await

雰囲気でPromiseを使っていたが、雰囲気でTypeScriptを使い始め、雰囲気でasync/awaitを使い始めたが、よくわからないままだったので簡単に自分向けにまとめておく。 間違えていたら教えてほしい。ちなみにTSのtargetはes6

async をつけると

Promiseが返るようになるという認識

返り値

Promise.resolve() を返すかそのまま値を返すとよい。 Promise.resolve() が必要ないならわざわざラップして返す必要はなさそう。

 const t = async () => {
     return Promise.resolve("ok")
 };
 async function main() {
     await t().then(console.log);
     console.log("finish")
 }
 main();
 const t = async () => {
     return "ok"
 };
 async function main() {
     await t().then(console.log);
     console.log("finish")
 }
 main();
   const t = async () => {
       // returnしなくても次に進む
   };
   async function main() {
       await t().then(console.log);
       console.log("finish")
   }
   main();

エラーハンドリング

Promise.reject() を返すかthrowすればエラーが起きたことを知らせることが出来る。 try-catchを利用するので、エラーが起きた場合はthrowするのがわかりが良い気がする。

 const t = async () => {
     return Promise.reject(new Error("error!"))
 };
 async function main() {
     try {
       await t().then(console.log);
     } catch (error) {
         console.log("catch error", error)
     } finally {
       console.log("finish")
     }
 }
 main();
 const t = async () => {
     throw new Error("error!")
 };
 async function main() {
     try {
       await t().then(console.log);
     } catch (error) {
         console.log("catch error", error)
     } finally {
       console.log("finish")
     }
 }
 main();

また以下のようにthrowしただけであってもPromiseのcatchを使うことが可能である。 catchした場合は、try-catchのcatchには入らず、通常処理に戻る

  const t = async () => {
      throw new Error("error!")
  };
  async function main() {
      try {
        await t().catch(console.log)
        console.log("age") // 実行される
      } catch (error) {
          console.log("catch error", error)
      } finally {
        console.log("finish")
      }
  }
  main();

errorはなにも返さなくてもよい。 例えば Promise.reject() に何も渡さない場合catchされた error は undefined になる。エラーが起きたわけではないけど、なんらかの理由でこれ以上処理を進めたくない場合などに使うらしい。なるほど(Promiseのテクニック??)

 const t = async () => {
     return Promise.reject();
 };
 async function main() {
     try {
         await t()
         console.log("age") // 実行されない
     } catch (error) {
         console.log("catch error", error)
     } finally {
         console.log("finish")
     }
 }
 main();

個人的にはそれをやるならそれ用のエラーを作ったほうが明確でよいと思ったが好みかもしれない。

 class AbortError extends Error { 
 }
 const t = async () => {
     return Promise.reject(new AbortError("ほげほげだからAbortだよ"));
 };
 async function main() {
     try {
         await t()
         console.log("age")
     } catch (error) {
         if (error.constructor === AbortError) {
             console.log(error.message)
             return
         }
         console.log("catch error", error)
     } finally {
         console.log("finish")
     }
 }
 main();

HTMLにあるフォームをsubmitするのではなくfetchを使ってsubmitしたい

form.submit()するんじゃなくてfetchを使う必要があったのでやり方調べたらFromDataなるものがあった。便利

const form = document.querySelector("#form1");
form.querySelector(`input[name="hoge"]`).value = "hoge";
const data = new FormData(form);

fetch("...", {
    "credentials":"include",
    "headers":{
        "accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "accept-language":"ja-JP,ja;q=0.9,en-US;q=0.8,en;q=0.7",
        "cache-control":"max-age=0",
        "content-type":"application/x-www-form-urlencoded",
        "upgrade-insecure-requests":"1"
    },
    "body": data,
    "method":"POST",
    "mode":"cors"
}).then(res => res.text()).then(body => {
   // はい
})

FormData オブジェクトの利用 - ウェブデベロッパーガイド | MDN
FormData - Web API | MDN

Youtube Music使い始めて使うのをやめた

Spotifyを課金して使っていたけど、Youtube Musicを使ってみようと思って使い始めた。が、結局Spotifyに戻った。apple musicも課金してるけど、Android版の出来があんまよくなくてアプリが落ちたりするので最近あんま使ってない。

歌詞の表示がない

あるのかもしれないけど、どこにあるのかわからなかった。見ることがないので別になくてもいいけど。

動画を見ない

仕事中に聞くことが多いし、通勤時間も徒歩を除くと3分くらいなので見ることがない。

Google Home mini等との連携が微妙

家に帰ってきて「OK Google, 音楽かけて」というとSpotifyと連携している場合はスマホで流していた曲が流れる(気がする)
Youtube musicは連動せず違う曲が流れる。またSpotifyはPCからChromecast経由で流せるけど、Youtube musicは流せない。
Google Play musicだとまたちょっと違うかも。

MVを音源にしていることがある

MVを音源にしている曲がある。動画を見ていないのに突然話し始められるとびっくりする。星野源とか。
たぶん、他のサブスクリプションでは曲自体がないので便利に感じる人もいそう。例えば花譜 - YouTubeとか聞けるのは便利

まとめ

曲数とかは特に気にならなかった。曲のサジェストも特に不便を感じることはなかった。ただapple musicのFriends mixとかは面白いのでそういう面白さはなかった。
またYoutube Premiumで登録したので、Youtubeの広告が表示されなくなったのは想像以上によかった。なので、結局課金はしてる。

モーニンプラスを買った

前から気になっていたものの、カーテンを手動で開けれなくなるのは厳しいなあと思っていたら手動で開けれるようになっていたので買ってみた。
結構気に入ってる。

状態

左右ともに開くタイプのカーテンの左側につけている。

感想

朝の目覚めがよい

朝起きるのがめちゃくちゃ苦手なんだけど結構スッと起きれるようになった。
具体的には前までは8時半から15分毎にアラームを鳴らして9時半にやっとこさ体を起こせる状態になるという感じだったけど、今は7時半にカーテンが開いて8時半のアラームで体を起こせる状態になるという感じ。寝る時間は変わらず3時とか4時です(もっと早く寝なさい)

動作パワーの設定が出来るのはよい

カーテンを開けるときに音がうるさかったらやだなーと思ってたんだけど、動作パワーを弱めに設定すると気にならなくなった。

ホイールの昇降時の音がうるさい

手動でカーテンを開け閉めできる設定にしていると自動で開け閉めする時にホイールを昇降するのだけど、その音が結構うるさい。
昇降するときのパワーは設定できないのだろうか?と思って調べたらあった。一番小さくしてもあんま変わらない気がする…

セットアップ時にモーニンプラスの電源が入らなかった

最初電池をいれても電源が入らず「不良品か…?」と思って触ってたら、電池がうまくハマってなくて電池が入る面を下に向けると電池が落ちてしまう状態だった。
電池の接点部品(-)が潰れてるようだったので、それを開けたら電池が入るようになったが少し心配

カーテンの磁石が強すぎる

モーニンプラス関係ないけど、モーニンプラスの最強パワーでやっても開けなかった。
公式サポートには、磁石にテープを貼るとよいって書かれてるので、マスキングテープ貼ってみたら外れるようになった。