お知らせ

現在サイトのリニューアル作業中のため、全体的にページの表示が乱れています。

maxlength

  • iOS Safariでは効かない
  • onInput()string.slice(0, maxlength)するとIMEの挙動が可笑しくなる
    • type="tel"など日本語が入力できない場合であれば有効
  • オートコンプリートやコピペ入力での字切れなどもあるため、根本的に使わないことが望ましい

type="number"

  • iOS Safariでは期待した動作にはならない
    • IMEが有効になり、全角入力が発生する
  • 使うならtype="tel"を使い、JSで数字以外の入力を弾くのが無難
  • 恐らく普及ブラウザの全てで半角入力を強制出来、スマホなどではNumPadが出てくる
    • アルファベットやハイフンなどの記号も打てるので必要に応じた入力制御が必要
投稿日:
言語::JavaScript言語::HTML

JavaScriptで添付ファイルを拾うのと、ファイルを落とす処理のサンプルコード

<html>
<head>
  <meta charset='utf-8'>
  <title>js file up/dl example</title>
  <script>
    window.onload = () => {
      const fr = new FileReader();
      const el = document.getElementById("test");

      fr.onload = (ev) => {
        const dl = document.createElement('a');
        dl.setAttribute('href', ev.target.result);
        dl.setAttribute('download', el.files[0].name);
        dl.style.display = 'none';
        document.body.appendChild(dl);
        dl.click();
        document.body.removeChild(dl);
      };

      el.onchange = () => {
        fr.readAsDataURL(el.files[0]);
      };
    };
  </script>
</head>
<body>
  <input type="file" id="test"></input>
</body>
</html>
投稿日:
言語::JavaScript::CommonJSNode.js::Jest開発::テスト

確認環境

Env Ver
Node.js 12.18.3
Jest 26.4.2

やりたいこと

以下の実装のときに、parentFunc()を呼んだ時にchildFunc()が呼ばれることをテストしたい

function parentFunc() {
  console.log('called parentFunc');
  childFunc('XXXX');
}

function childFunc(param) {
  console.log(`called childFunc ${param}`);
}

各ケース紹介

Case1 そもそも構文がおかしい

テストするためには関数をexportする必要あるが、愚直過ぎて構文的に実行不能になるケース

exports.parentFunc = () => {
  console.log('called parentFunc');
  // childFuncは別モジュールなので呼べない
  childFunc('XXXX');
};

exports.childFunc = (param) => {
  console.log(`called childFunc ${param}`);
};

Case2 スコープ違いでテストが失敗する

この実装を実行すると期待通り動作するので、一見すると大丈夫そうに見える

function parentFunc() {
  console.log('called parentFunc');
  childFunc('XXXX');
}

function childFunc(param) {
  console.log(`called childFunc ${param}`);
}

module.exports = { parentFunc, childFunc };

しかしこのテストを流すと失敗する
これはparentFunc()が呼び出すchildFunc()が下記case2の中にないため
parentFunc()のスコープ内にchildFunc()がいないことが原因

const case2 = require('./case2');
// こうするとjest.spyOn()の第一引数を満たせないので落ちる
// const { parentFunc, childFunc } = require('./case2');

describe('inside call test', function () {
  it('parentFunc', function () {
    const spy = jest.spyOn(case2, 'parentFunc');
    case2.parentFunc();
    expect(spy).toHaveBeenCalled();
  });
  it('childFunc', function () {
    const spy = jest.spyOn(case2, 'childFunc');
    case2.parentFunc();
    // childFuncはcase2に属していないため呼ばれない
    expect(spy).toHaveBeenCalled();
  });
});

Case3 テストが成功するケース

const parentFunc = () => {
  console.log('called parentFunc');
  // parentFunc()の中にchildオブジェクトを注入することで、
  // jestがchildFunc()を認識できるようにする
  child.childFunc('XXXX');
};

const child = {
  childFunc: (param) => {
    console.log(`called childFunc ${param}`);
  },
};

// childFuncでなく、childオブジェクトをexportするのが味噌
module.exports = { parentFunc, child };
const case3 = require('./case3');

describe('inside call test', function () {
  it('parentFunc', function () {
    const spy = jest.spyOn(case3, 'parentFunc');
    case3.parentFunc();
    expect(spy).toHaveBeenCalled();
  });
  it('childFunc', function () {
    // 注入している側のオブジェクトを参照する
    const spy = jest.spyOn(case3.child, 'childFunc');
    case3.parentFunc();
    // child.childFuncはcase3に属しているため呼ばれる
    expect(spy).toHaveBeenCalled();
  });
});