Sudoku Solver: Add functional tests and fix Unit Tests
This commit is contained in:
parent
70cee77a95
commit
0d2e39e7ba
4 changed files with 237 additions and 76 deletions
|
@ -1,22 +1,41 @@
|
||||||
export const puzzlesAndSolutions = [
|
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.',
|
"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'
|
"135762984946381257728459613694517832812936745357824196473298561581673429269145378",
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'5..91372.3...8.5.9.9.25..8.68.47.23...95..46.7.4.....5.2.......4..8916..85.72...3',
|
"5..91372.3...8.5.9.9.25..8.68.47.23...95..46.7.4.....5.2.......4..8916..85.72...3",
|
||||||
'568913724342687519197254386685479231219538467734162895926345178473891652851726943'
|
"568913724342687519197254386685479231219538467734162895926345178473891652851726943",
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'..839.7.575.....964..1.......16.29846.9.312.7..754.....62..5.78.8...3.2...492...1',
|
"..839.7.575.....964..1.......16.29846.9.312.7..754.....62..5.78.8...3.2...492...1",
|
||||||
'218396745753284196496157832531672984649831257827549613962415378185763429374928561'
|
"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',
|
".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'
|
"473891265851726394926345817568913472342687951197254638734162589685479123219538746",
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'82..4..6...16..89...98315.749.157.............53..4...96.415..81..7632..3...28.51',
|
"82..4..6...16..89...98315.749.157.............53..4...96.415..81..7632..3...28.51",
|
||||||
'827549163531672894649831527496157382218396475753284916962415738185763249374928651'
|
"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",
|
||||||
];
|
];
|
||||||
|
|
|
@ -41,7 +41,7 @@ class SudokuSolver {
|
||||||
checkRegionPlacement(puzzleString, row, column, value) {}
|
checkRegionPlacement(puzzleString, row, column, value) {}
|
||||||
|
|
||||||
solve(puzzleString) {
|
solve(puzzleString) {
|
||||||
return false;
|
return { error: "test" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,11 @@
|
||||||
const chai = require("chai");
|
const chai = require("chai");
|
||||||
const assert = chai.assert;
|
const assert = chai.assert;
|
||||||
import { puzzlesAndSolutions } from "../controllers/puzzle-strings";
|
import {
|
||||||
|
puzzlesAndSolutions,
|
||||||
const invalidStrings = [
|
invalidStrings,
|
||||||
"135762984946-8125772845961369451783281293674535B82419647329856158167342926:145378",
|
unsolvableStrings,
|
||||||
'56891372434268751"%=7254386685479231219538467734162895926345178473891652851726943',
|
wrongLengthStrings,
|
||||||
"/////////////////////////////////////////////////////////////////////////////////",
|
} from "../controllers/puzzle-strings";
|
||||||
"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",
|
|
||||||
];
|
|
||||||
|
|
||||||
const Solver = require("../controllers/sudoku-solver.js");
|
const Solver = require("../controllers/sudoku-solver.js");
|
||||||
let solver = new Solver();
|
let solver = new Solver();
|
||||||
|
@ -35,10 +27,12 @@ suite("Unit Tests", () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
test("Logic handles a puzzle string that is not 81 characters in length", () => {
|
test("Logic handles a puzzle string that is not 81 characters in length", () => {
|
||||||
assert.equal(
|
for (let i in wrongLengthStrings) {
|
||||||
solver.validate("135762984946145378").error,
|
assert.equal(
|
||||||
"Expected puzzle to be 81 characters long"
|
solver.validate(wrongLengthStrings[i]).error,
|
||||||
);
|
"Expected puzzle to be 81 characters long"
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
suite("Placement Checks", () => {
|
suite("Placement Checks", () => {
|
||||||
|
@ -106,7 +100,6 @@ suite("Unit Tests", () => {
|
||||||
suite("Solver", () => {
|
suite("Solver", () => {
|
||||||
test("Valid puzzle strings pass the solver", () => {
|
test("Valid puzzle strings pass the solver", () => {
|
||||||
for (let i in puzzlesAndSolutions) {
|
for (let i in puzzlesAndSolutions) {
|
||||||
console.log(i);
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
solver.solve(puzzlesAndSolutions[i][1]),
|
solver.solve(puzzlesAndSolutions[i][1]),
|
||||||
puzzlesAndSolutions[i][1]
|
puzzlesAndSolutions[i][1]
|
||||||
|
@ -116,21 +109,9 @@ suite("Unit Tests", () => {
|
||||||
test("Invalid puzzle strings fail the solver", () => {
|
test("Invalid puzzle strings fail the solver", () => {
|
||||||
for (let i in invalidStrings) {
|
for (let i in invalidStrings) {
|
||||||
assert.equal(
|
assert.equal(
|
||||||
solver.solve(invalidStrings[i].error),
|
solver.solve(invalidStrings[i]),
|
||||||
"Invalid characters in puzzle",
|
{ error: "Invalid characters in puzzle" },
|
||||||
"invalid characters" + invalidStrings[i]
|
"invalid characters"
|
||||||
);
|
|
||||||
}
|
|
||||||
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]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -145,12 +126,3 @@ suite("Unit Tests", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
TODO:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Valid puzzle strings pass the solver
|
|
||||||
*/
|
|
||||||
|
|
|
@ -2,27 +2,197 @@ const chai = require("chai");
|
||||||
const chaiHttp = require("chai-http");
|
const chaiHttp = require("chai-http");
|
||||||
const assert = chai.assert;
|
const assert = chai.assert;
|
||||||
const server = require("../server");
|
const server = require("../server");
|
||||||
|
import {
|
||||||
|
puzzlesAndSolutions,
|
||||||
|
invalidStrings,
|
||||||
|
unsolvableStrings,
|
||||||
|
wrongLengthStrings,
|
||||||
|
} from "../controllers/puzzle-strings";
|
||||||
|
|
||||||
chai.use(chaiHttp);
|
chai.use(chaiHttp);
|
||||||
|
|
||||||
suite("Functional Tests", () => {});
|
suite("Functional Tests", () => {
|
||||||
|
suite("Solving puzzles", () => {
|
||||||
/*
|
test("Solve a puzzle with valid puzzle string: POST request to /api/solve", (done) => {
|
||||||
TODO:
|
for (let i in puzzlesAndSolutions) {
|
||||||
|
chai
|
||||||
Solve a puzzle with valid puzzle string: POST request to /api/solve
|
.request(server)
|
||||||
Solve a puzzle with missing puzzle string: POST request to /api/solve
|
.post("/api/solve")
|
||||||
Solve a puzzle with invalid characters: POST request to /api/solve
|
.send({ puzzle: puzzlesAndSolutions[i][0] })
|
||||||
Solve a puzzle with incorrect length: POST request to /api/solve
|
.end((err, res) => {
|
||||||
Solve a puzzle that cannot be solved: POST request to /api/solve
|
assert.equal(res.status, 200);
|
||||||
Check a puzzle placement with all fields: POST request to /api/check
|
assert.equal(res.body.solution, puzzlesAndSolutions[i][1]);
|
||||||
Check a puzzle placement with single placement conflict: POST request to /api/check
|
done();
|
||||||
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
|
test("Solve a puzzle with missing puzzle string: POST request to /api/solve", (done) => {
|
||||||
Check a puzzle placement with incorrect length: POST request to /api/check
|
for (let i in puzzlesAndSolutions) {
|
||||||
Check a puzzle placement with invalid placement coordinate: POST request to /api/check
|
chai
|
||||||
Check a puzzle placement with invalid placement value: POST request to /api/check
|
.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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Reference in a new issue