自動でブラウザを操作して、公開中の商品ページに文章を追記する作業をしていました。7商品ぶん。3件目で、商品名を19文字壊しました。
こうなって保存されていました。
…シームレスループ・商用OK────────────────■——
正しいのは「商用OK」までです。区切り線として打った記号が、説明文ではなく商品名の欄に入っていました。公開中の商品です。買いに来た人が最初に見るタイトルです。
なぜそうなったか
1. 座標クリックが外れた
説明欄をクリックしたつもりで、押した先は商品名の欄でした。ページの高さや読み込み具合で、要素の位置は数十ピクセル動きます。一度うまくいった座標が、次も同じとは限りません。
2.「入力が効かなかった」と誤解した
打ち終わって説明欄の文字数を見ると増えていない。そこで「入力が効かなかった」と判断しました。
これが間違いでした。入力は効いていました。別の欄に。
「効かなかった」と「どこにも行っていない」は別のことです。前者を確認して後者だと決めつけると、こうなります。効かなかったと思ったときこそ、全部の入力欄を見に行くべきでした。
3. 開き直しても消えなかった
やり直そうとページを再読み込みしました。普通なら未保存の入力は消えます。このサイトは復元しました。
そうとは知らず、説明欄に正しく追記して保存ボタンを押しました。復元されていた商品名のゴミも、一緒に保存されました。
どう直したか
Backspace を19回送りました。効きませんでした。商品名の欄は JavaScript のフレームワークが値を管理していて、キーボードの操作を無視していたからです。
効いたのはこれでした。
el.focus();
el.setSelectionRange(el.value.length - 19, el.value.length);
document.execCommand('delete');
選択範囲を作って消す。これならフレームワークにも変更が伝わります。商品名は元に戻り、公開ページのタイトルが正しいことを確認しました。
そのあと、検査が事故を1件止めた
残り4商品も同じ作業が必要でした。今度は保存の前に全部の入力欄を走査する検査を入れました。
次の商品で、検査が引っかかりました。
{"index":0,"tag":"INPUT","length":79,"strayLength":21}
商品名の欄が79文字。正しくは58文字。また21文字入っていました。画面上では何も異常が見えません。文字数を数えて初めて分かります。
検査がなければ、2件目を壊していました。消してから追記し、条件を全部満たしたことを確認してから保存しました。無傷で通りました。
| 検査を入れる前 | 3件中1件で本番を壊した |
| 検査を入れた後 | 4件中0件(うち1件は検知して未然に防いだ) |
入力欄には3種類ある
「キー入力は効かない」「ファイルは差し込めない」という一般化は、たいてい間違いです。相手が何なのかで変わります。
- 素の入力欄:キー入力も、値の直接書き換えも、ファイルの差し込みも通る
- フレームワークが値を管理している欄:値の直接書き換えは効かない(画面は変わるが保存すると元に戻る)。キー入力は途中で切れることがある。
execCommandがいちばん確実 - 保存に明示の操作が要る欄:入力しただけでは保存されない。Enter が必要なもの、ボタンが必要なもの、入力した瞬間に保存されるものがある
見分け方は簡単です。値を直接書き換えて、別の欄をクリックする。元に戻ったらフレームワーク管理です。1分で測れます。
あなたが今日やるなら
- 触る前に種類を見分ける(値を書き換えて、別の欄をクリックする)
- キー入力の前に本当にその欄にフォーカスがあるか確認する。座標クリックを信じない
- 「効かなかった」ときは開き直す前に全部の欄を走査する
- 保存ボタンの前に関門を置く。条件を全部満たしたときだけ押す
- 押したあと開き直して確認する。押せた、は保存された、ではない
この5つを実行するコードと、上の事故の全記録、7商品ぶんの実測データをまとめたキットを用意しました。依存なし、ブラウザだけで動きます。

コメント