diff --git a/data/db.test.js b/data/db.test.js index 9ab1039..72d46a3 100644 --- a/data/db.test.js +++ b/data/db.test.js @@ -61,17 +61,17 @@ export default function() { }); QUnit.test("cannot call constructor", function(assert) { - assert.throws(function() { - new WbDb(); - }); + assert.throws( + function() { new WbDb(); }, + new TypeError("WbDb may not be constructed externally")); - assert.throws(function() { - new WbDb(true); - }); + assert.throws( + function() { new WbDb(true); }, + new TypeError("WbDb may not be constructed externally")); - assert.throws(function() { - new WbDb(true, 1); - }); + assert.throws( + function() { new WbDb(true, 1); }, + new TypeError("WbDb may not be constructed externally")); }); QUnit.test("open db", async function(assert) { diff --git a/models/game.js b/models/game.js index 8d62dba..0e5ef0f 100644 --- a/models/game.js +++ b/models/game.js @@ -179,12 +179,12 @@ export default class Game extends EventTarget { throw new TypeError("struct must contain currentRound as object"); if (this.result.winner === null) { if (value.currentRound === null) - throw new TypeError( + throw new Error( "struct of ongoing game must contain current round"); else this.#currentRound = new Round(value.currentRound); } else if (value.currentRound !== null) - throw new TypeError( + throw new Error( "struct of finished game must not contain current round"); } } diff --git a/models/game.test.js b/models/game.test.js index 43ff67a..74a27cc 100644 --- a/models/game.test.js +++ b/models/game.test.js @@ -24,7 +24,10 @@ export default function() { }); QUnit.test("low goal", function(assert) { - assert.throws(function() { new Game(0); }, "goal must be 1 or higher"); + assert.throws( + function() { new Game(0); }, + new RangeError("goal must be at least 1"), + "goal must be 1 or higher"); }); QUnit.test("higher goal", function(assert) { @@ -265,36 +268,52 @@ export default function() { QUnit.test("fromStruct - invalid", function(assert) { let struct = {}; - function doIt(message) { - assert.throws(function() { new Game(struct); }, message); + function doIt(message, error) { + assert.throws(function() { new Game(struct); }, error, message); } - doIt("no goal"); + doIt("no goal", new TypeError("struct must contain goal as number")); struct.goal = "3"; - doIt("string goal"); + doIt("string goal", new TypeError("struct must contain goal as number")); struct.goal = Math.PI; - doIt("non-int goal"); + doIt( + "non-int goal", + new RangeError("struct must contain goal >= 1 as integer")); struct.goal = 0; - doIt("small goal"); + doIt( + "small goal", + new RangeError("struct must contain goal >= 1 as integer")); struct.goal = 3; - doIt("no rounds"); + doIt("no rounds", new TypeError("struct must contain rounds")); struct.rounds = "nope"; - doIt("rounds not array"); + doIt( + "rounds not array", + new TypeError("struct must contain rounds as array")); struct.rounds = ["nope", "again"]; - doIt("string array rounds"); + doIt( + "string array rounds", + new TypeError("unknown form of RoundResult constructor")); struct.rounds = []; - doIt("no currentRound"); + doIt( + "no currentRound", + new TypeError("struct must contain currentRound as object")); struct.currentRound = "nope"; - doIt("string currentround"); + doIt( + "string currentRound", + new TypeError("struct must contain currentRound as object")); struct.currentRound = null; - doIt("missing currentRound"); + doIt( + "missing currentRound", + new Error("struct of ongoing game must contain current round")); struct.currentRound = new Round().toStruct(); new Game(struct); struct.rounds = [ new RoundResult(3, Team.They).toStruct() ]; - doIt("unneeded currentRound"); + doIt( + "unneeded currentRound", + new Error("struct of finished game must not contain current round")); struct.currentRound = null; new Game(struct); }); diff --git a/models/round.js b/models/round.js index c3d3570..b52e324 100644 --- a/models/round.js +++ b/models/round.js @@ -56,7 +56,7 @@ export class Round extends EventTarget { } else if (typeof value === "object" && theyLimit === undefined) { this.#fromStruct(value); } else { - throw new TypeError("unknown form for Round constructor"); + throw new TypeError("unknown form of Round constructor"); } } diff --git a/models/round.test.js b/models/round.test.js index 53baabc..df791c2 100644 --- a/models/round.test.js +++ b/models/round.test.js @@ -26,9 +26,10 @@ export default function() { QUnit.test("multiple victories", function(assert) { let round = new Round(); round.winner = Team.They; - assert.throws(function() { - round.winner = Team.We; - }, "victory cannot be stolen"); + assert.throws( + function() { round.winner = Team.We; }, + new Error("decided round cannot be won again"), + "victory cannot be stolen"); }); QUnit.test("single raise", function(assert) { @@ -155,45 +156,71 @@ export default function() { QUnit.test("fromStruct - invalid", function(assert) { let struct = {}; - function doIt(message) { - assert.throws(function() { new Round(struct); }, message); + function doIt(message, error) { + assert.throws(function() { new Round(struct); }, error, message); } - doIt("no points"); + doIt("no points", new TypeError("struct must contain points as number")); struct.points = "2"; - doIt("string points"); + doIt( + "string points", + new TypeError("struct must contain points as number")); struct.points = 1.5; - doIt("non-int points"); + doIt( + "non-int points", + new RangeError("struct must contain points >= 2 as integer")); struct.points = 1; - doIt("small points"); + doIt( + "small points", + new RangeError("struct must contain points >= 2 as integer")); struct.points = 2; - doIt("no raisedLast"); + doIt("no raisedLast", new TypeError("struct must contain raisedLast")); struct.raisedLast = "we"; - doIt("string raisedLast"); + doIt( + "string raisedLast", + new TypeError("struct must contain raisedLast as Team or null")); struct.raisedLast = -1; - doIt("raisedLast not actual team"); + doIt( + "raisedLast not actual team", + new TypeError("struct must contain raisedLast as Team or null")); struct.raisedLast = null; - doIt("no winner"); + doIt("no winner", new TypeError("struct must contain winner")); struct.winner = "they"; - doIt("string winner"); + doIt( + "string winner", + new TypeError("struct must contain winner as Team or null")); struct.winner = -1; - doIt("winner not actual team"); + doIt( + "winner not actual team", + new TypeError("struct must contain winner as Team or null")); struct.winner = null; - doIt("no ourLimit"); + doIt( + "no ourLimit", + new TypeError("struct must contain ourLimit as number")); struct.ourLimit = "11"; - doIt("string ourLimit"); + doIt( + "string ourLimit", + new TypeError("struct must contain ourLimit as number")); struct.ourLimit = 1; - doIt("small ourLimit"); + doIt( + "small ourLimit", + new RangeError("struct must contain ourLimit >= 2 as integer")); struct.ourLimit = 11; - doIt("no theirLimit"); + doIt( + "no theirLimit", + new TypeError("struct must contain theirLimit as number")); struct.theirLimit = "11"; - doIt("string theirLimit"); + doIt( + "string theirLimit", + new TypeError("struct must contain theirLimit as number")); struct.theirLimit = 1; - doIt("small theirLimit"); + doIt( + "small theirLimit", + new RangeError("struct must contain theirLimit >= 2 as integer")); struct.theirLimit = 11; new Round(struct); diff --git a/models/round_result.js b/models/round_result.js index c27b280..8032e12 100644 --- a/models/round_result.js +++ b/models/round_result.js @@ -21,7 +21,7 @@ export default class RoundResult { } else if (typeof value === "object" && winner === undefined) { this.#fromStruct(value); } else { - throw new TypeError("unknown form for RoundResult constructor"); + throw new TypeError("unknown form of RoundResult constructor"); } } diff --git a/models/round_result.test.js b/models/round_result.test.js index 6e304ba..584fcc6 100644 --- a/models/round_result.test.js +++ b/models/round_result.test.js @@ -32,24 +32,33 @@ export default function() { QUnit.test("fromStruct - invalid", function(assert) { let struct = {}; - function doIt(message) { - assert.throws(function() { new Round(struct); }, message); + function doIt(message, error) { + assert.throws(function() { new RoundResult(struct); }, error, message); } - doIt("no points"); + doIt("no points", new TypeError("struct must contain points as number")); struct.points = "4"; - doIt("string points"); + doIt( + "string points", + new TypeError("struct must contain points as number")); struct.points = 4.1; - doIt("non-int points"); + doIt( + "non-int points", + new RangeError("struct must contain points >= 2 as integer")); struct.points = 1; - doIt("small points"); + doIt( + "small points", + new RangeError("struct must contain points >= 2 as integer")); struct.points = 4; - doIt("no winner"); + doIt("no winner", new TypeError("struct must contain winner")); struct.winner = "they"; - doIt("string winner"); + doIt( + "string winner", new TypeError("struct must contain winner as Team")); struct.winner = -1; - doIt("non-team winner"); + doIt( + "non-team winner", + new TypeError("struct must contain winner as Team")); struct.winner = Team.They; new RoundResult(struct); diff --git a/models/session.js b/models/session.js index b039926..7256191 100644 --- a/models/session.js +++ b/models/session.js @@ -145,7 +145,7 @@ export default class Session { } if (typeof value.goal !== "number") - throw new TypError("struct must contain goal as number"); + throw new TypeError("struct must contain goal as number"); if (!Number.isInteger(value.goal) || value.goal < 1) throw new RangeError("struct must contain goal >= 1 as integer"); this.#goal = value.goal; @@ -172,7 +172,7 @@ export default class Session { if (value.currentGame !== null) { this.#currentGame = new Game(value.currentGame); if (this.#currentGame.result.winner !== null) - throw new Error("currentGame in struct mustnot be finished"); + throw new Error("currentGame in struct must not be finished"); } } } diff --git a/models/session.test.js b/models/session.test.js index 94478b1..3f4be85 100644 --- a/models/session.test.js +++ b/models/session.test.js @@ -24,7 +24,18 @@ export default function() { assert.strictEqual(session.goal, 11, "initial goal"); session.goal = 3; assert.strictEqual(session.goal, 3, "changed goal"); - assert.throws(function() { session.goal = 0; }, "invalid goal"); + assert.throws( + function() { session.goal = "0"; }, + new TypeError("goal must be a number"), + "string goal"); + assert.throws( + function() { session.goal = 0.5; }, + new RangeError("goal must be integer >= 1"), + "float goal"); + assert.throws( + function() { session.goal = 0; }, + new RangeError("goal must be integer >= 1"), + "small goal"); }); QUnit.test("start game", function(assert) { @@ -187,8 +198,8 @@ export default function() { QUnit.test("fromStruct - invalid", function(assert) { let struct = {}; - function doIt(message) { - assert.throws(function() { new Session(struct); }, message); + function doIt(message, error) { + assert.throws(function() { new Session(struct); }, error, message); } let unfinished = new Game(3); @@ -197,39 +208,60 @@ export default function() { finished.currentRound.raise(Team.We); finished.currentRound.winner = Team.They; - doIt("no goal"); + doIt("no goal", new TypeError("struct must contain goal as number")); struct.goal = "3"; - doIt("string goal"); + doIt("string goal", new TypeError("struct must contain goal as number")); struct.goal = Math.PI; - doIt("non-int goal"); + doIt( + "non-int goal", + new RangeError("struct must contain goal >= 1 as integer")); struct.goal = 0; - doIt("small goal"); + doIt( + "small goal", + new RangeError("struct must contain goal >= 1 as integer")); struct.goal = 3; - doIt("no ourTeam"); + doIt( + "no ourTeam", new TypeError("struct must contain ourTeam as string")); struct.ourTeam = 5; - doIt("number ourTeam"); + doIt( + "number ourTeam", + new TypeError("struct must contain ourTeam as string")); struct.ourTeam = ""; - doIt("no theirTeam"); + doIt( + "no theirTeam", + new TypeError("struct must contain theirTeam as string")); struct.theirTeam = 6; - doIt("number theirTeam"); + doIt( + "number theirTeam", + new TypeError("struct must contain theirTeam as string")); struct.theirTeam = ""; - doIt("no games"); + doIt("no games", new TypeError("struct must contain games")); struct.games = "nope"; - doIt("string games"); + doIt( + "string games", new TypeError("struct must contain games as array")); struct.games = ["nope", "again"]; - doIt("string array games"); + doIt( + "string array games", + new TypeError("unknown form of Game constructor")); struct.games = [unfinished.toStruct()]; - doIt("unfinished game in games"); + doIt( + "unfinished game in games", new Error("past games must be finished")); struct.games = [finished.toStruct()]; - doIt("no currentGame"); + doIt( + "no currentGame", + new TypeError("struct must contain currentGame as object")); struct.currentGame = "nope"; - doIt("string currentGame"); + doIt( + "string currentGame", + new TypeError("struct must contain currentGame as object")); struct.currentGame = finished.toStruct(); - doIt("finished currentGame"); + doIt( + "finished currentGame", + new Error("currentGame in struct must not be finished")); struct.currentGame = unfinished.toStruct(); new Session(struct);