import { IInsightFacade, InsightDatasetKind, InsightError, InsightResult, NotFoundError, ResultTooLargeError, } from "../../src/controller/IInsightFacade"; import InsightFacade from "../../src/controller/InsightFacade"; import { clearDisk, getContentFromArchives, loadTestQuery } from "../TestUtil"; import { expect, use } from "chai"; import chaiAsPromised from "chai-as-promised"; use(chaiAsPromised); export interface ITestQuery { title?: string; input: unknown; errorExpected: boolean; expected: any; orderExpected: boolean; orderBy: string; } describe("InsightFacadeMartin", function () { // Declare datasets used in tests. You should add more datasets like this! let facade: IInsightFacade; let sections: string; let emptySections: string; let bSyntax: string; let coursess: string; let noResult: string; before(async function () { // This block runs once and loads the datasets. sections = await getContentFromArchives("pair.zip"); emptySections = await getContentFromArchives("empty_sections.zip"); bSyntax = await getContentFromArchives("badSyntax.zip"); coursess = await getContentFromArchives("coursess.zip"); noResult = await getContentFromArchives("no_result.zip"); // Just in case there is anything hanging around from a previous run of the test suite await clearDisk(); }); describe("AddDataset", function () { beforeEach(async function () { await clearDisk(); facade = new InsightFacade(); }); // it("should reject with an empty dataset id", async function () { // try { // await facade.addDataset("", sections, InsightDatasetKind.Sections); // expect.fail("Should have thrown!"); // } catch (err) { // expect(err).to.be.instanceOf(InsightError); // } // }); // it("should reject with an empty space dataset id", async function () { // try { // await facade.addDataset(" ", sections, InsightDatasetKind.Sections); // expect.fail("Should have thrown!"); // } catch (err) { // expect(err).to.be.instanceOf(InsightError); // } // }); // it("should add dataset", async function () { // let result = []; // try { // result = await facade.addDataset("ubc", sections, InsightDatasetKind.Sections); // expect(result.length).to.be.equal(1); // expect(result).to.have.members(["ubc"]); // } catch { // expect.fail(); // } // }); // it("should add both datasets", async function () { // let result = []; // try { // await facade.addDataset("ubc1", sections, InsightDatasetKind.Sections); // result = await facade.addDataset("ubc2", sections, InsightDatasetKind.Sections); // expect(result).to.have.members(["ubc1", "ubc2"]); // } catch { // expect.fail(); // } // }); // it("should fail add same id twice", async function () { // try { // await facade.addDataset("ubc1", sections, InsightDatasetKind.Sections); // await facade.addDataset("ubc1", sections, InsightDatasetKind.Sections); // expect.fail(); // } catch (e) { // expect(e).to.be.instanceOf(InsightError); // } // }); // it("should fail, add same id twice then fails again for same reason", async function () { // try { // await facade.addDataset("ubc1", sections, InsightDatasetKind.Sections); // await facade.addDataset("ubc1", sections, InsightDatasetKind.Sections); // expect.fail(); // } catch (e) { // expect(e).to.be.instanceOf(InsightError); // const result = await facade.listDatasets(); // expect(result.length).to.be.equal(1); // } // }); it("should reject with empty dataset", async function () { try { await facade.addDataset("ubc", emptySections, InsightDatasetKind.Sections); expect.fail(); } catch (e) { expect(e).to.be.instanceOf(InsightError); } }); it("should reject with wrong folder name", async function () { try { await facade.addDataset("ubc", coursess, InsightDatasetKind.Sections); expect.fail(); } catch (e) { expect(e).to.be.instanceOf(InsightError); } }); it("should reject with dataset bad syntax json", async function () { try { await facade.addDataset("ubc", bSyntax, InsightDatasetKind.Sections); expect.fail(); } catch (e) { expect(e).to.be.instanceOf(InsightError); } }); it("should reject with dataset has no json result", async function () { try { await facade.addDataset("ubc", noResult, InsightDatasetKind.Sections); expect.fail(); } catch (e) { expect(e).to.be.instanceOf(InsightError); } }); // it("should reject with an _ id", async function () { // try { // await facade.addDataset("_", sections, InsightDatasetKind.Sections); // expect.fail("Should have thrown!"); // } catch (err) { // expect(err).to.be.instanceOf(InsightError); // } // }); // it("should reject id contains _", async function () { // try { // await facade.addDataset("ubc_2025", sections, InsightDatasetKind.Sections); // expect.fail("Should have thrown!"); // } catch (err) { // expect(err).to.be.instanceOf(InsightError); // } // }); it("should reject id contains wrong database type", async function () { try { await facade.addDataset("ubc_2025", "hello World!", InsightDatasetKind.Sections); expect.fail("Should have thrown!"); } catch (err) { expect(err).to.be.instanceOf(InsightError); } }); }); describe("RemoveDataset", function () { beforeEach(async function () { await clearDisk(); facade = new InsightFacade(); }); it("should reject, no such dataset", async function () { try { await facade.removeDataset("ubc"); expect.fail("error not expected"); } catch (e) { expect(e).to.be.instanceOf(NotFoundError); } }); // it("should reject, wrong dataset id", async function () { // try { // await facade.addDataset("ubcc", sections, InsightDatasetKind.Sections); // await facade.removeDataset("ubc"); // expect.fail("error not expected"); // } catch (e) { // expect(e).to.be.instanceOf(NotFoundError); // } // }); // it("should reject, empty string id", async function () { // try { // await facade.removeDataset(""); // expect.fail("error not expected"); // } catch (e) { // expect(e).to.be.instanceOf(InsightError); // } // }); it("should reject empty space string id", async function () { try { await facade.removeDataset(" "); expect.fail("error not expected"); } catch (e) { expect(e).to.be.instanceOf(InsightError); } }); it("should reject _ id", async function () { try { await facade.removeDataset("_"); expect.fail("error not expected"); } catch (e) { expect(e).to.be.instanceOf(InsightError); } }); // it("should reject ubc_ id", async function () { // try { // await facade.removeDataset("ubc_"); // expect.fail("error not expected"); // } catch (e) { // expect(e).to.be.instanceOf(InsightError); // } // }); // it("should remove the dataset", async function () { // try { // await facade.addDataset("ubc", sections, InsightDatasetKind.Sections); // const result = await facade.removeDataset("ubc"); // expect(result).to.be.equal("ubc"); // const result2 = await facade.listDatasets(); // expect(result2.length).to.be.equal(0); // } catch { // expect.fail("error not expected"); // } // }); // it("should add 2 remove 1", async function () { // let result = ""; // try { // await facade.addDataset("ubc1", sections, InsightDatasetKind.Sections); // await facade.addDataset("ubc2", sections, InsightDatasetKind.Sections); // result = await facade.removeDataset("ubc1"); // expect(result).to.be.equal("ubc1"); // //const result2 = await facade.addDataset("ubc3", sections, InsightDatasetKind.Sections); // //expect(result2).to.have.members(["ubc2", "ubc3"]); // } catch { // expect.fail("error not expected"); // } // }); // it("should add 2 remove 2", async function () { // let result = ""; // try { // await facade.addDataset("ubc1", sections, InsightDatasetKind.Sections); // await facade.addDataset("ubc2", sections, InsightDatasetKind.Sections); // result = await facade.removeDataset("ubc1"); // expect(result).to.be.equal("ubc1"); // result = await facade.removeDataset("ubc2"); // expect(result).to.be.equal("ubc2"); // const result2 = await facade.listDatasets(); // expect(result2.length).to.be.equal(0); // } catch { // expect.fail("error not expected"); // } // }); }); // describe("ListDatasets", function () { // beforeEach(async function () { // await clearDisk(); // facade = new InsightFacade(); // }); // it("should produce an empty list", async function () { // let result = []; // result = await facade.listDatasets(); // expect(result.length).to.be.equal(0); // }); // it("should produce a list length 1", async function () { // try { // await facade.addDataset("ubc", sections, InsightDatasetKind.Sections); // const result = await facade.listDatasets(); // expect(result.length).to.be.equal(1); // } catch { // expect.fail(); // } // }); // it("should produce a list length 2", async function () { // try { // await facade.addDataset("ubc1", sections, InsightDatasetKind.Sections); // await facade.addDataset("ubc2", sections, InsightDatasetKind.Sections); // } catch { // expect.fail(); // } // }); // }); describe("PerformQuery", function () { /** * Loads the TestQuery specified in the test name and asserts the behaviour of performQuery. * * Note: the 'this' parameter is automatically set by Mocha and contains information about the test. */ async function checkQuery(this: Mocha.Context): Promise { if (!this.test) { throw new Error( "Invalid call to checkQuery." + "Usage: 'checkQuery' must be passed as the second parameter of Mocha's it(..) function." + "Do not invoke the function directly." ); } // Destructuring assignment to reduce property accesses const { input, expected, errorExpected, orderExpected, orderBy } = await loadTestQuery(this.test.title); let result: InsightResult[] = []; // dummy value before being reassigned try { result = await facade.performQuery(input); } catch (err) { if (!errorExpected) { expect.fail(`performQuery threw unexpected error: ${err}`); } // check what error is expected and then make sure that is the actual error received if ("InsightError" === expected) { expect(err).to.be.instanceOf(InsightError); } else { expect(err).to.be.instanceOf(ResultTooLargeError); } return; } if (errorExpected) { expect.fail(`performQuery resolved when it should have rejected with ${expected}`); } // make sure output is the expected result //expect(result).to.deep.equal(expected); expect(result).to.have.deep.members(expected); expect(result).to.have.length(expected.length); if (orderExpected) { const resultAvg = result.map((item) => orderBy.map((key) => item[key])); const expectedAvg = expected.map((item: InsightResult) => orderBy.map((key) => item[key])); expect(resultAvg).to.deep.equal(expectedAvg); } } before(async function () { facade = new InsightFacade(); // Add the datasets to InsightFacade once. // Will *fail* if there is a problem reading ANY dataset. const loadDatasetPromises: Promise[] = [ facade.addDataset("sections", sections, InsightDatasetKind.Sections), ]; try { await Promise.all(loadDatasetPromises); } catch (err) { throw new Error(`In PerformQuery Before hook, dataset(s) failed to be added. \n${err}`); } }); after(async function () { await clearDisk(); }); // Examples demonstrating how to test performQuery using the JSON Test Queries. // The relative path to the query file must be given in square brackets. it("[valid/avgmoreThan97AndStartsWithC.json] Select dept, avg WHERE avg>97 and dept c*", checkQuery); it("[valid/avgLess30.json] Select dept, avg WHERE avg < 30", checkQuery); it("[valid/notGt21.json] Select dept, avg WHERE !(avg<21)", checkQuery); it("[valid/1example.json] returns 1 example by uuid", checkQuery); it("[valid/andEmpty.json] empty and", checkQuery); it("[valid/andNonEmpty.json] not empty and", checkQuery); //it("[valid/containsAt.json] Select dept, avg WHERE dept *at*", checkQuery); //it("[valid/containsMath.json] Select dept, avg WHERE dept *math*", checkQuery); //it("[valid/deptContainsSy.json] Select dept, avg WHERE dept *sy*", checkQuery); //it("[valid/deptEndsSc.json] Select dept, avg WHERE dept *sc", checkQuery); //it("[valid/deptIsCpsc.json] Select dept, avg WHERE dept cpsc", checkQuery); //it("[valid/deptIsMath.json] Select dept, avg WHERE dept math", checkQuery); //it("[valid/deptStartsCp.json] Select dept, avg WHERE dept cp*", checkQuery); //it("[valid/endsTh.json] Select dept, avg WHERE dept *th", checkQuery); //it("[valid/startsMa.json] Select dept, avg WHERE ma*", checkQuery); //it("[valid/eq80.json] Select dept, avg WHERE avg = 80", checkQuery); //it("[valid/less68.5.json] Select dept, avg WHERE avg < 68.5", checkQuery); //it("[valid/more97OrStartsCpc.json] Select dept, avg WHERE avg > 97 or dept cps*", checkQuery); //it("[valid/usesPassOrderId.json] Select pass, id WHERE pass > 300", checkQuery); //it("[valid/usesAuditOrderTitle.json] Uses Audit and Title", checkQuery); //it("[valid/usesFailOrderInstructor.json] Uses Fail and Instructor", checkQuery); //it("[valid/4999results.json] returns with 4999 results", checkQuery); //it("[valid/5000results.json] returns with 5000 results", checkQuery); //it("[valid/usesNand.json] uses Nand", checkQuery); //it("[valid/usesNor.json] Uses nor", checkQuery); //it("[valid/usesYearOrderUuid.json] Uses year and uuid", checkQuery); //it("[valid/orWithInter.json] or with intersection", checkQuery); it("[invalid/moreThan1DS.json] Query pulls from more than 1 dataset", checkQuery); it("[invalid/tooMany.json] Query returns more than 5000 results", checkQuery); it("[invalid/empty.json] returns empty results)", checkQuery); it("[invalid/5001results.json] fails with 5001 results", checkQuery); it("[invalid/invalidColumns.json] Query mispelled columns", checkQuery); it("[invalid/invalidkey.json] invalid key", checkQuery); it("[invalid/noOptions.json] Query missing OPTIONS", checkQuery); it("[invalid/wrongType.json] s in m field", checkQuery); it("[invalid/wrongType2.json] m in s field", checkQuery); it("[invalid/badString.json] reject has bad string syntax with *", checkQuery); it("[invalid/badStringSyntax.json] extra string bad case", checkQuery); it("[invalid/doubleAsterix.json] double**", checkQuery); it("[invalid/DoubleAsterixButWorse.json] 0**0", checkQuery); it("[invalid/extraKeyInQuery.json] extra key in query", checkQuery); }); });