From 76a26a17596ffa55e714d0b858938a926cdac6c2 Mon Sep 17 00:00:00 2001 From: ananyaspatil Date: Fri, 4 Oct 2024 06:39:32 -0400 Subject: [PATCH] create unit test subdirectory --- .github/workflows/test.yaml | 28 ++++++++- package.json | 4 +- tests/database/search.test.seq.ts | 2 + tests/general/notifyer.test.ts | 73 +++++++++++++++++++---- tests/unit/services/searcher.test.unit.ts | 70 ++++++++++++++++++++++ tests/unit/services/updater.test.unit.ts | 0 6 files changed, 165 insertions(+), 12 deletions(-) create mode 100644 tests/unit/services/searcher.test.unit.ts create mode 100644 tests/unit/services/updater.test.unit.ts diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 4253ff97..16a51dde 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -6,6 +6,32 @@ on: branches: - master jobs: + units: + name: Unit Tests + runs-on: ubuntu-latest + timeout-minutes: 10 + services: + env: + TWILIO_ACCOUNT_SID: AC_dummy_value_so_tests_dont_error_out + TWILIO_AUTH_TOKEN: 123 + elasticURL: "http://localhost:9200" + NODE_COVERALLS_DEBUG: 1 + steps: + - uses: actions/checkout@v2 + - name: install node + uses: actions/setup-node@v2 + with: + node-version: "16" + - uses: bahmutov/npm-install@v1 + + - run: yarn unittest --coverage + - name: Coveralls + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + flag-name: Unit tests + parallel: true + tests: name: Tests runs-on: ubuntu-latest @@ -153,7 +179,7 @@ jobs: # - run: 'curl ''http://localhost:4000'' -X POST -H ''content-type: application/json'' --data ''{ "query": "query { search(termId: \"202250\", query: \"fundies\") { nodes { ... on ClassOccurrence { name subject classId } } } }" }''' coverage: - needs: [end_to_end, tests] + needs: [end_to_end, tests, unit] name: Sends Coveralls coverage runs-on: ubuntu-latest env: diff --git a/package.json b/package.json index fc8e4051..a10e957a 100644 --- a/package.json +++ b/package.json @@ -38,9 +38,11 @@ "about:tsc": "//// Runs TSC (because of our config, this will NOT compile the files, just typecheck them)", "tsc": "tsc", "about:test": "//// Runs a basic suite of unit and integration tests", - "test": "yarn jest --verbose --testPathIgnorePatterns='(seq|reg|git).[jt]s'", + "test": "yarn jest --verbose --testPathIgnorePatterns='(seq|reg|git|unit).[jt]s'", "about:dbtest": "//// Runs tests interacting with our database. Must have the Docker containers running. This won't touch live data - it will create and teardown a temporary database.", "dbtest": "jest -i --projects tests/database --verbose", + "about:unittest": "//// Runs unit tests. Does not need db, elasticsearch, spun up. Does not need the Docker containers to be running.", + "unittest": "jest -i --projects tests/unit --verbose", "about:build_backend": "//// Compiles this project", "build_backend": "rm -rf dist && mkdir -p dist && babel --extensions '.js,.ts' . -d dist/ --copy-files --ignore node_modules --ignore .git --include-dotfiles && rm -rf dist/.git", "about:build": "//// Compiles this project, surpressing output", diff --git a/tests/database/search.test.seq.ts b/tests/database/search.test.seq.ts index c3a3d3f7..97ea8ea7 100644 --- a/tests/database/search.test.seq.ts +++ b/tests/database/search.test.seq.ts @@ -23,6 +23,7 @@ describe("searcher", () => { }); }); + /* //Unit tests for the parseQuery function describe("parseQuery", () => { it("query with no phrases", () => { @@ -84,6 +85,7 @@ describe("searcher", () => { }); }); }); + */ // TODO: create an association between cols in elasticCourseSerializer and here describe("generateQuery", () => { it("generates match_all when no query", () => { diff --git a/tests/general/notifyer.test.ts b/tests/general/notifyer.test.ts index d4d34a91..9153ba89 100644 --- a/tests/general/notifyer.test.ts +++ b/tests/general/notifyer.test.ts @@ -60,7 +60,7 @@ async function createSection( } const mockSendNotificationText = jest.fn(() => { - console.log("I SHOULD BE CALLED"); + //console.log("I SHOULD BE CALLED"); return Promise.resolve(); }); @@ -328,7 +328,7 @@ describe("Notifyer", () => { }); it("sends a properly formatted message when a new section is added to a course", async () => { - console.log("INSIDE TEST 2"); + //console.log("INSIDE TEST 2"); notificationInfo = { updatedCourses: [ { @@ -360,7 +360,7 @@ describe("Notifyer", () => { }); it("sends a properly formatted message when multiple sections are added to a course", async () => { - console.log("INSIDE TEST 3"); + //console.log("INSIDE TEST 3"); notificationInfo = { updatedCourses: [ { @@ -392,7 +392,7 @@ describe("Notifyer", () => { }); it("sends a properly formatted message when seats open up in a section", async () => { - console.log("INSIDE TEST 4"); + //console.log("INSIDE TEST 4"); notificationInfo = { updatedCourses: [], updatedSections: [ @@ -427,7 +427,7 @@ describe("Notifyer", () => { }); it("sends a properly formatted message when waitlist seats open up in a section", async () => { - console.log("INSIDE TEST 5"); + //console.log("INSIDE TEST 5"); notificationInfo = { updatedCourses: [], updatedSections: [ @@ -462,7 +462,7 @@ describe("Notifyer", () => { }); it("does not send any notifications for each course and section when each subscribed section and class has notifCount>=3", async () => { - console.log("TEST 6"); + //console.log("TEST 6"); notificationInfo = { updatedCourses: [ @@ -541,12 +541,17 @@ describe("Notifyer", () => { ], }); + /* const sectionHashToUsers: Record = await new Updater( [] ).modelToUser("section"); const courseHashToUsers: Record = await new Updater( [] ).modelToUser("course"); + */ + + courseHashToUsers = {}; + sectionHashToUsers = {}; await sendNotifications( notificationInfo, @@ -557,7 +562,7 @@ describe("Notifyer", () => { }); it("deletes subscriptions for each course and section when their notifCount>=3", async () => { - console.log("TEST 7"); + //console.log("TEST 7"); notificationInfo = { updatedCourses: [ @@ -637,12 +642,17 @@ describe("Notifyer", () => { ], }); + /* const sectionHashToUsers: Record = await new Updater( [] ).modelToUser("section"); const courseHashToUsers: Record = await new Updater( [] ).modelToUser("course"); + */ + + courseHashToUsers = {}; + sectionHashToUsers = {}; const initialCourseNotifs = await prisma.followedCourse.count(); expect(initialCourseNotifs).toEqual(3); @@ -662,7 +672,7 @@ describe("Notifyer", () => { }); it("sends notifications for each course and section when each subscribed section and class has notifCount<3", async () => { - console.log("TEST 8"); + //console.log("TEST 8"); notificationInfo = { updatedCourses: [ @@ -742,12 +752,28 @@ describe("Notifyer", () => { ], }); + /* const sectionHashToUsers: Record = await new Updater( [] ).modelToUser("section"); const courseHashToUsers: Record = await new Updater( [] ).modelToUser("course"); + */ + + courseHashToUsers = { + "neu.edu/202210/ARTF/1122": [ + { id: 1, phoneNumber: "+11231231234" }, + { id: 2, phoneNumber: "+19879879876" }, + ], + "neu.edu/202210/CS/2500": [{ id: 1, phoneNumber: "+11231231234" }], + }; + sectionHashToUsers = { + "neu.edu/202210/CS/2500/11920": [ + { id: 1, phoneNumber: "+11231231234" }, + { id: 2, phoneNumber: "+19879879876" }, + ], + }; await sendNotifications( notificationInfo, @@ -758,7 +784,7 @@ describe("Notifyer", () => { }); it("maintains subscriptions for each course and section when their notifCount<3", async () => { - console.log("TEST 9"); + //console.log("TEST 9"); notificationInfo = { updatedCourses: [ @@ -838,12 +864,28 @@ describe("Notifyer", () => { ], }); + /* const sectionHashToUsers: Record = await new Updater( [] ).modelToUser("section"); const courseHashToUsers: Record = await new Updater( [] ).modelToUser("course"); + */ + + courseHashToUsers = { + "neu.edu/202210/ARTF/1122": [ + { id: 1, phoneNumber: "+11231231234" }, + { id: 2, phoneNumber: "+19879879876" }, + ], + "neu.edu/202210/CS/2500": [{ id: 1, phoneNumber: "+11231231234" }], + }; + sectionHashToUsers = { + "neu.edu/202210/CS/2500/11920": [ + { id: 1, phoneNumber: "+11231231234" }, + { id: 2, phoneNumber: "+19879879876" }, + ], + }; const initialCourseNotifs = await prisma.followedCourse.count(); expect(initialCourseNotifs).toEqual(3); @@ -863,7 +905,7 @@ describe("Notifyer", () => { }); it("increases notifCount for each course and section after notif is sent", async () => { - console.log("TEST 7"); + //console.log("TEST 7"); notificationInfo = { updatedCourses: [ @@ -915,12 +957,23 @@ describe("Notifyer", () => { }, }); + /* const sectionHashToUsers: Record = await new Updater( [] ).modelToUser("section"); const courseHashToUsers: Record = await new Updater( [] ).modelToUser("course"); + */ + + courseHashToUsers = { + "neu.edu/202210/CS/2500": [{ id: 1, phoneNumber: "+11231231234" }], + }; + sectionHashToUsers = { + "neu.edu/202210/CS/2500/11920": [ + { id: 1, phoneNumber: "+11231231234" }, + ], + }; const initialCourseNotifCount: { notifCount: number }[] = await prisma.followedCourse.findMany({ diff --git a/tests/unit/services/searcher.test.unit.ts b/tests/unit/services/searcher.test.unit.ts new file mode 100644 index 00000000..082ef4eb --- /dev/null +++ b/tests/unit/services/searcher.test.unit.ts @@ -0,0 +1,70 @@ +import searcher from "../../../services/searcher"; +import { LeafQuery, ParsedQuery } from "../../../types/searchTypes"; + +beforeAll(async () => { + searcher.subjects = {}; +}); + +describe("searcher unit tests", () => { + //Unit tests for the parseQuery function + describe("parseQuery", () => { + it("query with no phrases", () => { + const retQueries: ParsedQuery = searcher.parseQuery( + "this is a query with no phrases" + ); + expect(retQueries.phraseQ.length).toEqual(0); //no phrase queries + expect(retQueries.fieldQ).not.toEqual(null); + const fieldQuery: LeafQuery = retQueries.fieldQ; + + expect(fieldQuery).toEqual({ + multi_match: { + query: "this is a query with no phrases", + type: "most_fields", + fields: searcher.getFields(), + }, + }); + }); + + it("query with just a phrase", () => { + const retQueries: ParsedQuery = searcher.parseQuery('"this is a phrase"'); + + expect(retQueries.phraseQ.length).toEqual(1); + expect(retQueries.fieldQ).toEqual(null); + + const phraseQuery: LeafQuery = retQueries.phraseQ[0]; + + expect(phraseQuery).toEqual({ + multi_match: { + query: "this is a phrase", + type: "phrase", + fields: searcher.getFields(), + }, + }); + }); + + it("query with a phrase and other text", () => { + const retQueries: ParsedQuery = searcher.parseQuery('text "phrase" text'); + expect(retQueries.phraseQ.length).toEqual(1); + expect(retQueries.fieldQ).not.toEqual(null); + + const phraseQuery: LeafQuery = retQueries.phraseQ[0]; + const fieldQuery: LeafQuery = retQueries.fieldQ; + + expect(phraseQuery).toEqual({ + multi_match: { + query: "phrase", + type: "phrase", + fields: searcher.getFields(), + }, + }); + + expect(fieldQuery).toEqual({ + multi_match: { + query: "text text", + type: "most_fields", + fields: searcher.getFields(), + }, + }); + }); + }); +}); diff --git a/tests/unit/services/updater.test.unit.ts b/tests/unit/services/updater.test.unit.ts new file mode 100644 index 00000000..e69de29b