UNPKG

@adam.biltcliffe/board-state-playground

Version:

browser-based testing tool for the board-state library

168 lines (156 loc) 4.38 kB
import React, { useCallback, useState } from "react"; import niceStringify from "json-stringify-pretty-compact"; import produce from "immer"; const PlaygroundApp = ({ gameClass, initialState, filterKeys = [] }) => { const [history, setHistory] = useState(() => [ { state: initialState, action: null, views: Object.assign( {}, ...filterKeys.map(k => ({ [k]: gameClass.filter(initialState, k) })) ), newInfos: Object.assign({}, ...filterKeys.map(k => ({ [k]: null }))) } ]); const [newAction, setNewAction] = useState(""); const [allowSubmit, setAllowSubmit] = useState(false); const [validation, setValidation] = useState("Enter action"); const [error, setError] = useState(null); const handleActionChange = useCallback(e => { setNewAction(e.target.value); validate(e.target.value); }); const validate = useCallback(actionText => { try { const actionObject = JSON.parse(actionText); try { gameClass.checkAction(history[0].state, actionObject); setAllowSubmit(true); setValidation("Ok!"); } catch (e) { setAllowSubmit(false); setValidation("Not a legal action --- " + e); } } catch (e) { setValidation("Could not parse JSON --- " + e); setAllowSubmit(false); } }); const handleSubmit = useCallback(e => { e.preventDefault(); if (!allowSubmit) { return; } try { const actionObject = JSON.parse(newAction); const { state, newInfos } = gameClass.playAction( history[0].state, actionObject ); const step = { state, action: actionObject, views: Object.assign( {}, ...filterKeys.map(k => ({ [k]: gameClass.replayAction( history[0].views[k], actionObject, newInfos[k] ) })) ), newInfos }; const newHistory = produce(history, draft => { draft.unshift(step); }); setHistory(newHistory); setNewAction(""); setError(null); } catch (e) { setError(e); } }); const actionList = gameClass.suggestActions(history[0].state).map(a => { const s = JSON.stringify(a); return <option value={s} key={s} />; }); const actionForm = ( <form onSubmit={handleSubmit}> <input type="text" list="actions" value={newAction} onChange={handleActionChange} /> <datalist id="actions">{actionList}</datalist> <button type="submit" disabled={!allowSubmit}> Apply </button> <span>{validation}</span> </form> ); let filterBlocks = null; if (filterKeys != undefined) { filterBlocks = filterKeys.map(k => ( <React.Fragment key={k}> <h4>Filter "{k}"</h4> <small> Additional info for last action:{" "} <code>{niceStringify(history[0].newInfos[k])}</code> </small> <pre> <code>{niceStringify(history[0].views[k])}</code> </pre> </React.Fragment> )); } let errorBlock = null; if (error) { const errorExtra = error.result !== undefined ? ( <> <div> Filtered result of actual action:{" "} <pre> <code>{niceStringify(error.result)}</code> </pre> </div> <div> Result of replay:{" "} <pre> <code>{niceStringify(error.replay)}</code> </pre> </div> <div> Difference: <code>{JSON.stringify(error.diff)}</code> </div> </> ) : null; errorBlock = ( <> <div> <strong>{error.name}</strong> {error.message} </div> {errorExtra} </> ); } return ( <> <h3>Full view</h3> {errorBlock} <small> Last action: <code>{niceStringify(history[0].action)}</code> </small> <pre> <code>{niceStringify(history[0].state, null, 2)}</code> </pre> {actionForm} {filterBlocks} </> ); }; export default PlaygroundApp;