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<void> {
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<string[]>[] = [
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);
});
});