diff --git a/7-quality-assurance/4-sudoku-solver/controllers/puzzle-strings.js b/7-quality-assurance/4-sudoku-solver/controllers/puzzle-strings.js index c58405c..9d5e49c 100644 --- a/7-quality-assurance/4-sudoku-solver/controllers/puzzle-strings.js +++ b/7-quality-assurance/4-sudoku-solver/controllers/puzzle-strings.js @@ -1,22 +1,41 @@ export const puzzlesAndSolutions = [ [ - '1.5..2.84..63.12.7.2..5.....9..1....8.2.3674.3.7.2..9.47...8..1..16....926914.37.', - '135762984946381257728459613694517832812936745357824196473298561581673429269145378' + "1.5..2.84..63.12.7.2..5.....9..1....8.2.3674.3.7.2..9.47...8..1..16....926914.37.", + "135762984946381257728459613694517832812936745357824196473298561581673429269145378", ], [ - '5..91372.3...8.5.9.9.25..8.68.47.23...95..46.7.4.....5.2.......4..8916..85.72...3', - '568913724342687519197254386685479231219538467734162895926345178473891652851726943' + "5..91372.3...8.5.9.9.25..8.68.47.23...95..46.7.4.....5.2.......4..8916..85.72...3", + "568913724342687519197254386685479231219538467734162895926345178473891652851726943", ], [ - '..839.7.575.....964..1.......16.29846.9.312.7..754.....62..5.78.8...3.2...492...1', - '218396745753284196496157832531672984649831257827549613962415378185763429374928561' + "..839.7.575.....964..1.......16.29846.9.312.7..754.....62..5.78.8...3.2...492...1", + "218396745753284196496157832531672984649831257827549613962415378185763429374928561", ], [ - '.7.89.....5....3.4.2..4..1.5689..472...6.....1.7.5.63873.1.2.8.6..47.1..2.9.387.6', - '473891265851726394926345817568913472342687951197254638734162589685479123219538746' + ".7.89.....5....3.4.2..4..1.5689..472...6.....1.7.5.63873.1.2.8.6..47.1..2.9.387.6", + "473891265851726394926345817568913472342687951197254638734162589685479123219538746", ], [ - '82..4..6...16..89...98315.749.157.............53..4...96.415..81..7632..3...28.51', - '827549163531672894649831527496157382218396475753284916962415738185763249374928651' - ] + "82..4..6...16..89...98315.749.157.............53..4...96.415..81..7632..3...28.51", + "827549163531672894649831527496157382218396475753284916962415738185763249374928651", + ], +]; + +export const invalidStrings = [ + "135762984946-8125772845961369451783281293674535B82419647329856158167342926:145378", + '56891372434268751"%=7254386685479231219538467734162895926345178473891652851726943', + "/////////////////////////////////////////////////////////////////////////////////", + "NyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyan.", +]; + +export const unsolvableStrings = [ + "115..2.84..63.12.7.2..5.....9..1....8.2.3674.3.7.2..9.420..8..1..16....926969.37.", + "4206942069.......................................................................", + "111111111111111111111111111111111111111111111111111111111111111111111111111111111", +]; + +export const wrongLengthStrings = [ + "123456", + "9999999.9999992", + "1.5..2.84..63.12.7.2..5.....9..1....8.2.3674.3.7.2..9.47...8..1..16....926914.37.5..91372.3...8.5.9.9.25..8.68.47.23...95..46.7.4.....5.2.......4..8916..85.72...3", ]; diff --git a/7-quality-assurance/4-sudoku-solver/controllers/sudoku-solver.js b/7-quality-assurance/4-sudoku-solver/controllers/sudoku-solver.js index 69d3d35..b1fc386 100644 --- a/7-quality-assurance/4-sudoku-solver/controllers/sudoku-solver.js +++ b/7-quality-assurance/4-sudoku-solver/controllers/sudoku-solver.js @@ -41,7 +41,7 @@ class SudokuSolver { checkRegionPlacement(puzzleString, row, column, value) {} solve(puzzleString) { - return false; + return { error: "test" }; } } diff --git a/7-quality-assurance/4-sudoku-solver/tests/1_unit-tests.js b/7-quality-assurance/4-sudoku-solver/tests/1_unit-tests.js index d5f11ee..3aab681 100644 --- a/7-quality-assurance/4-sudoku-solver/tests/1_unit-tests.js +++ b/7-quality-assurance/4-sudoku-solver/tests/1_unit-tests.js @@ -1,19 +1,11 @@ const chai = require("chai"); const assert = chai.assert; -import { puzzlesAndSolutions } from "../controllers/puzzle-strings"; - -const invalidStrings = [ - "135762984946-8125772845961369451783281293674535B82419647329856158167342926:145378", - '56891372434268751"%=7254386685479231219538467734162895926345178473891652851726943', - "/////////////////////////////////////////////////////////////////////////////////", - "NyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyan.", -]; - -const unsolvableStrings = [ - "115..2.84..63.12.7.2..5.....9..1....8.2.3674.3.7.2..9.420..8..1..16....926969.37.", - "4206942069.......................................................................", - "111111111111111111111111111111111111111111111111111111111111111111111111111111111", -]; +import { + puzzlesAndSolutions, + invalidStrings, + unsolvableStrings, + wrongLengthStrings, +} from "../controllers/puzzle-strings"; const Solver = require("../controllers/sudoku-solver.js"); let solver = new Solver(); @@ -35,10 +27,12 @@ suite("Unit Tests", () => { } }); test("Logic handles a puzzle string that is not 81 characters in length", () => { - assert.equal( - solver.validate("135762984946145378").error, - "Expected puzzle to be 81 characters long" - ); + for (let i in wrongLengthStrings) { + assert.equal( + solver.validate(wrongLengthStrings[i]).error, + "Expected puzzle to be 81 characters long" + ); + } }); }); suite("Placement Checks", () => { @@ -106,7 +100,6 @@ suite("Unit Tests", () => { suite("Solver", () => { test("Valid puzzle strings pass the solver", () => { for (let i in puzzlesAndSolutions) { - console.log(i); assert.equal( solver.solve(puzzlesAndSolutions[i][1]), puzzlesAndSolutions[i][1] @@ -116,21 +109,9 @@ suite("Unit Tests", () => { test("Invalid puzzle strings fail the solver", () => { for (let i in invalidStrings) { assert.equal( - solver.solve(invalidStrings[i].error), - "Invalid characters in puzzle", - "invalid characters" + invalidStrings[i] - ); - } - assert.equal( - solver.solve("135762984946145378").error, - "Expected puzzle to be 81 characters long", - "wrong length" - ); - for (let i in unsolvableStrings) { - assert.equal( - solver.solve().error, - "Puzzle cannot be solved", - "not solvable" + unsolvableStrings[i] + solver.solve(invalidStrings[i]), + { error: "Invalid characters in puzzle" }, + "invalid characters" ); } }); @@ -145,12 +126,3 @@ suite("Unit Tests", () => { }); }); }); - -/* -TODO: - - - - - Valid puzzle strings pass the solver - */ diff --git a/7-quality-assurance/4-sudoku-solver/tests/2_functional-tests.js b/7-quality-assurance/4-sudoku-solver/tests/2_functional-tests.js index 39ec9b3..f63e914 100644 --- a/7-quality-assurance/4-sudoku-solver/tests/2_functional-tests.js +++ b/7-quality-assurance/4-sudoku-solver/tests/2_functional-tests.js @@ -2,27 +2,197 @@ const chai = require("chai"); const chaiHttp = require("chai-http"); const assert = chai.assert; const server = require("../server"); +import { + puzzlesAndSolutions, + invalidStrings, + unsolvableStrings, + wrongLengthStrings, +} from "../controllers/puzzle-strings"; chai.use(chaiHttp); -suite("Functional Tests", () => {}); - -/* -TODO: - - Solve a puzzle with valid puzzle string: POST request to /api/solve - Solve a puzzle with missing puzzle string: POST request to /api/solve - Solve a puzzle with invalid characters: POST request to /api/solve - Solve a puzzle with incorrect length: POST request to /api/solve - Solve a puzzle that cannot be solved: POST request to /api/solve - Check a puzzle placement with all fields: POST request to /api/check - Check a puzzle placement with single placement conflict: POST request to /api/check - Check a puzzle placement with multiple placement conflicts: POST request to /api/check - Check a puzzle placement with all placement conflicts: POST request to /api/check - Check a puzzle placement with missing required fields: POST request to /api/check - Check a puzzle placement with invalid characters: POST request to /api/check - Check a puzzle placement with incorrect length: POST request to /api/check - Check a puzzle placement with invalid placement coordinate: POST request to /api/check - Check a puzzle placement with invalid placement value: POST request to /api/check - - */ +suite("Functional Tests", () => { + suite("Solving puzzles", () => { + test("Solve a puzzle with valid puzzle string: POST request to /api/solve", (done) => { + for (let i in puzzlesAndSolutions) { + chai + .request(server) + .post("/api/solve") + .send({ puzzle: puzzlesAndSolutions[i][0] }) + .end((err, res) => { + assert.equal(res.status, 200); + assert.equal(res.body.solution, puzzlesAndSolutions[i][1]); + done(); + }); + } + }); + test("Solve a puzzle with missing puzzle string: POST request to /api/solve", (done) => { + for (let i in puzzlesAndSolutions) { + chai + .request(server) + .post("/api/solve") + .send({}) + .end((err, res) => { + assert.equal(res.status, 200); + assert.equal(res.body.error, "Required field missing"); + done(); + }); + } + }); + test("Solve a puzzle with invalid characters: POST request to /api/solve", (done) => { + for (let i in invalidStrings) { + chai + .request(server) + .post("/api/solve") + .send({ puzzle: invalidStrings[i] }) + .end((err, res) => { + assert.equal(res.status, 200); + assert.equal(res.body.error, "Invalid characters in puzzle"); + done(); + }); + } + }); + test("Solve a puzzle with incorrect length: POST request to /api/solve", (done) => { + for (let i in wrongLengthStrings) { + chai + .request(server) + .post("/api/solve") + .send({ puzzle: wrongLengthStrings[i] }) + .end((err, res) => { + assert.equal(res.status, 200); + assert.equal( + res.body.error, + "Expected puzzle to be 81 charcters long" + ); + done(); + }); + } + }); + test("Solve a puzzle that cannot be solved: POST request to /api/solve", (done) => { + for (let i in unsolvableStrings) { + chai + .request(server) + .post("/api/solve") + .send({ puzzle: unsolvableStrings[i] }) + .end((err, res) => { + assert.equal(res.status, 200); + assert.equal(res.body.error, "Puzzle cannot be solved"); + done(); + }); + } + }); + }); + suite("Placement Checks", () => { + test("Check a puzzle placement with all fields: POST request to /api/check", (done) => { + chai + .request(server) + .post("/api/check") + .send({ puzzle: puzzlesAndSolutions[0][0], coordinate: "A2", value: 3 }) + .end((err, res) => { + assert.equal(res.status, 200); + assert.equal(res.body.valid, true); + done(); + }); + }); + test("Check a puzzle placement with single placement conflict: POST request to /api/check", (done) => { + chai + .request(server) + .post("/api/check") + .send({ puzzle: puzzlesAndSolutions[0][0], coordinate: "A2", value: 4 }) + .end((err, res) => { + assert.equal(res.status, 200); + assert.equal(res.body.valid, false); + assert.include(res.body.conflict, "row"); + assert.notInclude(res.body.conflict, "region"); + assert.notInclude(res.body.conflict, "column"); + done(); + }); + }); + test("Check a puzzle placement with multiple placement conflicts: POST request to /api/check", (done) => { + chai + .request(server) + .post("/api/check") + .send({ puzzle: puzzlesAndSolutions[0][0], coordinate: "A2", value: 1 }) + .end((err, res) => { + assert.equal(res.status, 200); + assert.equal(res.body.valid, false); + assert.include(res.body.conflict, "row"); + assert.include(res.body.conflict, "region"); + assert.notInclude(res.body.conflict, "column"); + done(); + }); + }); + test("Check a puzzle placement with all placement conflicts: POST request to /api/check", (done) => { + chai + .request(server) + .post("/api/check") + .send({ puzzle: puzzlesAndSolutions[0][0], coordinate: "A2", value: 2 }) + .end((err, res) => { + assert.equal(res.status, 200); + assert.equal(res.body.valid, false); + assert.include(res.body.conflict, "row"); + assert.include(res.body.conflict, "region"); + assert.include(res.body.conflict, "column"); + done(); + }); + }); + test("Check a puzzle placement with missing required fields: POST request to /api/check", (done) => { + chai + .request(server) + .post("/api/check") + .send({ puzzle: puzzlesAndSolutions[0][0], coordinate: "A2" }) + .end((err, res) => { + assert.equal(res.status, 200); + assert.equal(res.body.error, "Required field(s) missing"); + done(); + }); + }); + test("Check a puzzle placement with invalid characters: POST request to /api/check", (done) => { + chai + .request(server) + .post("/api/check") + .send({ puzzle: invalidStrings[0], coordinate: "A2", value: "3" }) + .end((err, res) => { + assert.equal(res.status, 200); + assert.equal(res.body.error, "Invalid characters in puzzle"); + done(); + }); + }); + test("Check a puzzle placement with incorrect length: POST request to /api/check", (done) => { + chai + .request(server) + .post("/api/check") + .send({ puzzle: wrongLengthStrings[0], coordinate: "A2", value: "3" }) + .end((err, res) => { + assert.equal(res.status, 200); + assert.equal( + res.body.error, + "Expected puzzle to be 81 characters long" + ); + done(); + }); + }); + test("Check a puzzle placement with invalid placement coordinate: POST request to /api/check", (done) => { + chai + .request(server) + .post("/api/check") + .send({ puzzle: puzzlesAndSolutions[0], coordinate: "Z11", value: "3" }) + .end((err, res) => { + assert.equal(res.status, 200); + assert.equal(res.body.error, "Invalid coordinate"); + done(); + }); + }); + test("Check a puzzle placement with invalid placement value: POST request to /api/check", (done) => { + chai + .request(server) + .post("/api/check") + .send({ puzzle: puzzlesAndSolutions[0], coordinate: "A2", value: "22" }) + .end((err, res) => { + assert.equal(res.status, 200); + assert.equal(res.body.error, "Invalid value"); + done(); + }); + }); + }); +});