検索条件
お知らせ
現在サイトのリニューアル作業中のため、全体的にページの表示が乱れています。
fs
とかchild_process
とかそういうやつをモックする方法
- jest単体の機能では実現できないのでハマるポイント
- たぶん jest.MockedFunction でも同じことができる
import { execSync } from 'child_process';
// まず全体をモックする
jest.mock('child_process');
// モックにする
const mockExecSync = execSync as jest.MockedFunction<typeof execSync>;
describe('execSync', () => {
it('spyOn execSync', () => {
// 対象をコール
execSync('echo 1');
// 通る
expect(mockExecSync).toHaveBeenCalled();
// 通る, echo 2とかにするとちゃんとコケてくれる
expect(mockExecSync).toHaveBeenCalledWith('echo 1');
});
});
- 素のHTMLにJSを埋め込んでイベントコールバックの引数を取る方法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Example of DOM Event callback arguments</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script>
const test = (ev) => {
console.log(ev);
};
</script>
</head>
<body>
<p onclick="test(event)">aaa</p>
</body>
</html>
export EMAIL_SENDER_TRANSPORT=SMTP
export EMAIL_SENDER_TRANSPORT_host=smtp.example.com
export EMAIL_SENDER_TRANSPORT_port=1025
use strict;
use Email::MIME;
use Email::MIME::Creator;
use Email::Sender::Simple qw(sendmail);
my $subject = Encode::encode('MIME-Header-ISO_2022_JP', 'さぶじぇくと');
my $mail = Email::MIME->create(
'header' => [
'From' => Encode::encode('MIME-Header-ISO_2022_JP', 'foo@example.com'),
'To' => Encode::encode('MIME-Header-ISO_2022_JP', 'to@example.com'),
'Subject' => $subject,
],
'attributes' => {
'content_type' => 'text/plain',
'charset' => 'ISO-2022-JP',
'encoding' => '7bit',
},
'body' => Encode::encode('iso-2022-jp', 'ほんぶん!'),
);
- iOS Safariでは効かない
onInput()
でstring.slice(0, maxlength)
するとIMEの挙動が可笑しくなる
type="tel"
など日本語が入力できない場合であれば有効
- オートコンプリートやコピペ入力での字切れなどもあるため、根本的に使わないことが望ましい
- iOS Safariでは期待した動作にはならない
- 使うなら
type="tel"
を使い、JSで数字以外の入力を弾くのが無難
- 恐らく普及ブラウザの全てで半角入力を強制出来、スマホなどではNumPadが出てくる
- アルファベットやハイフンなどの記号も打てるので必要に応じた入力制御が必要
ReactでSPAを組んでいてブラウザバックしたときのフォームの入力内容が消し飛んで気になったので、ブラウザバックした時にどうなるのかというのを軽く調査した結果
確認したパターンとしては次の2つ
- フォームの入力値をDOMに保持させるステートレスな方式
- フォームの入力値をJSに保持させるステートフルな方式
LocalStorageに画面情報を保存して復元するとか、条件分岐を使ってDOMを隠して保持させるとか、そういう系は考慮しない
|
DOM 保持 |
JS 保持 |
SPA 内ブラウザバック |
消える |
保持される |
SPA 外ブラウザバック |
保持される |
消える |
コード記述量 |
少ない |
多い |
この方式だとhistory.push()
でDOMが消し飛ぶのでSPA内でのブラウザバックで入力したデータが保持されません
その代わりSPAの外、別のサイトに遷移してからブラウザバックしたときは、DOMが残っているので入力したデータが保持されます
この方式だとJSでステート管理をしているため、history.push()
で遷移してDOMが消し飛んでも、 defaultValue
に持ってる値を突っ込んであげれば、取り敢えず入力したデータを保持することが出来ます
反対にSPAの外、別のサイトに遷移してからブラウザバックしたときは、メモリの中身が飛んでるので入力したデータが保持されません
ちゃちゃっと書いたのでコードは超雑です
Env |
Ver |
react |
17.0.2 |
react-dom |
17.0.2 |
react-router-dom |
5.2.0 |
大正義ステートレスです
Function Componentはステートレスなので、こうあってほしいですよね~
コードもシンプルで管理しやすいのが素敵なところです
export const StatelessPage = () => {
const history = useHistory();
return (
<div>
<form>
<input type="text" />
<button onClick={() => history.push(AppRoute.dom2.path)}>submit</button>
</form>
</div>
);
};
ギルティなステートフル方式です
Class Componentを捨てたはずなのにどうしてこうなった…
コードが煩雑で管理が大変です
export const StatefullPage = () => {
const ctx = useContext(ExampleContext);
const history = useHistory();
const onChange = (ev: React.ChangeEvent<HTMLInputElement>) => {
ctx.text = ev.target.value;
};
return (
<div>
<form>
<input
type="text"
defaultValue={ctx.text}
onChange={(ev) => onChange(ev)}
/>
<button onClick={() => history.push(AppRoute.ctx2.path)}>submit</button>
</form>
</div>
);
};