エラー処理_単項目チェック  例_01 とても質素な場合

# 概要

・エラー処理の単項目チェックについてです。
  内容はCodepenで動く実物と設計書（もどき）です。

# 目的
・ブラウザのみで動作できるようにする。
　プログラマ以外の端末でも動作環境を確保できるようにしたい。
　極力docker,node.jsなどを動作環境に含めたくない。
 　（テストコードの動作環境はdocker有り）
 
・設計書を書く練習するため。ソースコードは手抜く感じにします。
・設計から実装、単体テストまで一貫して考える習慣をつけるため。

# 単項目チェックとは？

```
エラーチェックの一種
入力値の型、桁数、書式、必須、文字コードなどが規則どおりかを確認します。
ウェブシステムの場合はフロントエンド側で実施する
```
図解でなっとく！トラブル知らずのシステム設計　エラー制御・排他制御編　p25 単項目チェックより

# 成果物
## codepen
数値に対して単項目チェックを行う
１以上１００未満以外の値はエラーになるよう判定します。


<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="xbKVERy" data-pen-title="singleItemCheck" data-user="rya234" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/rya234/pen/xbKVERy">
  singleItemCheck</a> by RYA234 (<a href="https://codepen.io/rya234">@rya234</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>




## プロダクトコード

動作環境

名称|version|説明
---|--------|---
GoogleChrome|131.0.6778.86|ウェブブラウザ


```html
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>単項目チェック_01</title>
</head>
<body>
    <h1>単項目チェック_01</h1>
    <div>
        <label for="number">数値 :</label>
        <input type="number" id="number" name="number" size="10" />
    </div>
    <div>
        <button id="checkbutton">単項目チェック</button>
    </div>
    <div id="result">結果：</div>
<script>
　　// エラーメッセージ設計

    // event 系
window.onload = (event) => {
    // dom要素取得
    const button = document.getElementById('checkbutton');
    const number = document.getElementById('number');
    const result = document.getElementById('result');
    
    // ボタンクリック時の処理
    button.addEventListener('click', event => {

        result.innerHTML　= "結果：";
        let isNumber =  numberSingleItemCheck(parseInt(number.value));
        if(isNumber != true){
            console.error(isNumber);
            result.innerHTML += isNumber
            return;
        }
        result.innerHTML += "問題無し。"
    });
};

function numberSingleItemCheck(number){
    try{
        let numberMessage = "";

        // 整数以外の数字
        console.log(typeof(number));
        console.log(number);
        if( !Number.isInteger(number)){
            throw new TypeError("エラー：空欄か文字が入力されています。");
        }
        console.log(number);
        if( number < 0 || number >= 100){
            throw new RangeError("エラー：数値は0以上100未満です。");
        }
        return true;
    }catch (e) {
         return e.message;

        } finally {
    	 //必ず実行される処理
    }
}
</script>
</body>
</html>

```


## テストコード

開発環境
名称|version|説明
---|--------|---
Javascript|-|プログラミング言語
HTML|HTML Living Standard|GUI
Nodejs|22.9.0|単体テスト実行で使う
Jest|29.70|テストフレームワーク
jsdom|25.01|DOM操作のライブラリ　テストで使う
Github Codespaces|-|クラウドIDE


```js
import { beforeEach, expect, test } from '@jest/globals';
import fs from "fs/promises";
import { JSDOM } from "jsdom";
// 実行コマンド
// docker-compose exec -it webserver bash -c  "npm test simple_error_01.test.js"
// 参考にしたやつ
// https://symfoware.blog.fc2.com/blog-entry-2685.html

;
describe('test11', () => {

  let html="";
  let dom = ""
  beforeEach(async() => {
    html = await fs.readFile("system_design_error/01_simple_error/simple_error.html")
    dom =  new JSDOM(html,{runScripts: "dangerously"});
    dom.window.onload();

  })


  test.each([
    ["","空欄、数値以外が入力されています。"],
    ["kk","空欄、数値以外が入力されています。"],
    ["ああ","空欄、数値以外が入力されています。"],
    ["111","数値は0以上100未満です。"],
    ["100","数値は0以上100未満です。"],
    ["10","問題無し。"],  
    ["0","問題無し。"],
    ["99","問題無し。"],  
  ])('数字単項目テスト"', async(actualNumber,expected) => {
        // テキスト入力欄を取得し値を設定
        const number = dom.window.document.getElementById('number');
        number.value =  actualNumber;
        // ボタン取得とクリック
        const button = dom.window.document.getElementById('checkbutton');
        await button.click();
        // 結果の取得
        const result = dom.window.document.getElementById('result');

        expect(result.innerHTML).toContain(expected);
  });
});

```



# ドキュメント

## ユースケース記述
項目名|説明
--|---
ユースケース|単項目チェック
主アクター|ユーザ
事前条件|無し
主シナリオ|・ユーザーが数値を入力する<br>・ボタンを押す<br>・入力値がビジネスルールを満たしているか判定する
成功時保証|無し
ビジネスルール|数値入力規則



## ビジネスルール
項目名|説明
--|---
ビジネスルール名|数値　入力規則
内容|１以上１００未満


## 画面項目

項目名|表示名|I/O|プロパティ(物理名)|種類|備考
-----|-----|---|--------|---|---
タイトル|単項目チェックサンプル|O|title|ラベル| _|
数値|--|I|number|テキストボックス| _|
実行|単項目チェック|I|checkButton|ボタン| clickイベント有り|
結果|結果：XXX|O|result|ラベル|clickイベント実行後に値が変化する|




## イベント処理

### ボタン　onClickイベント
　入力項目に対して、入力規則を満たしているか確認する。
　頻繁に使うので、クライアントで実行

```plantuml
@startuml
title button click event
autonumber
actor user

box HTML
participant text as "textbox"
participant Button as "button"
participant output as "result"

endBOX
box javascript
 participant event
 participant value_check as "singleItemCheck"

 activate event
 user --> text:input text
 user --> Button:pressButton
 Button --> event:call event handler
 event-->value_check : Value Check
alt#Gold #LightBlue Successful case
    value_check -> event: Check is OK
    event --> output :  display[問題無し] by DOM
else #Pink Failure
    value_check -> event: Check is NG
    event-->output : display [error_message]  by DOM
end
 deactivate event
endbox
@enduml


```




ライフライン名|分類|説明
------------|----|---
textbox|HTML|id=numberに該当
button|HTML|id=checkbuttonが該当
message|HTML|id= resultに相当
event|JS| Clickイベントハンドラー
singleItemCheck|JS| ビジネスルール　数値入力規則


## 単体テスト仕様書

|テスト観点|確認内容|テスト条件|テスト手順|期待値|備考|
|--------|--------|---------|--------|------|----|
入力|数値の入力欄がエラーになる場合。</br> 未入力 数値以外の値|-|数値の入力欄に値（空欄, ”あああ”,"kk"）を入力する。</br>|以下のように表示</br>結果：空欄、数値以外が入力されています。|テストコード作成
入力|数値の入力欄に期待する値が場合。</br> 正常値の値|-|数値の入力欄に値（と）を入力する。</br>|以下のように表示</br>結果：問題なし。|テストコード作成
画面|初期表示|-|ページを表示する|仕様書どおりになっていること|目視で確認




# 課題点
try catchの実装で手間取りました。
→多分エラー設計の経験が足りないからです。
　try catch exceptionとか深く考えたことない。

あとドキュメントが全体的にガバですね。数こなして改善していきます

# ノートに書いた下書き

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/c47e391f-f8ea-5f72-c908-da0795ef3fb2.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/a30e368e-c464-7461-8c22-8bd4651e8d62.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/0de1abe2-e032-eaae-ed6a-df2b2ca60205.png)





# 参考

github 差分
https://github.com/RYA234/routine_tool/commit/2e2ae590ecbe4208dd5a9a6bb882698b938c1985


テストコード


テスト観点

https://qiita.com/nittannittan/items/2d8a342a8d77db53b70a

「図解でなっとく！トラブル知らずのシステム設計　エラー制御・排他制御編」　p25 単項目チェック
「はじめての設計をやり抜くための本　第２版」　p95 ユースケース分析

qiitaにCodepenを埋め込む
https://qiita.com/Qiita/items/edae7417214c8e957f54