From 856b2d684cf16f689899bb1de670205c652113cb Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Mon, 18 Sep 2023 15:46:11 -0400 Subject: [PATCH 1/6] add jest for basic testing of pure functions --- jest.config.json | 8 ++++++++ package.serve.json | 6 +++++- www/__tests__/diaryHelper.test.ts | 5 +++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 jest.config.json create mode 100644 www/__tests__/diaryHelper.test.ts diff --git a/jest.config.json b/jest.config.json new file mode 100644 index 000000000..d9655cbf8 --- /dev/null +++ b/jest.config.json @@ -0,0 +1,8 @@ +{ + "transform": { + "^.+\\.(ts|tsx|js|jsx)$": "ts-jest" + }, + "moduleNameMapper": { + "^react-native$": "react-native-web" + } +} diff --git a/package.serve.json b/package.serve.json index da3b60b89..7eb50a4a1 100644 --- a/package.serve.json +++ b/package.serve.json @@ -10,7 +10,8 @@ "scripts": { "setup-serve": "./bin/download_settings_controls.js && ./bin/setup_autodeploy.js", "serve": "webpack --config webpack.dev.js && concurrently -k \"phonegap --verbose serve\" \"webpack --config webpack.dev.js --watch\"", - "serve-only": "phonegap --verbose serve" + "serve-only": "phonegap --verbose serve", + "test": "npx jest www/__tests__" }, "devDependencies": { "@babel/core": "^7.21.3", @@ -30,11 +31,13 @@ "exports-loader": "^4.0.0", "expose-loader": "^4.1.0", "file-loader": "^6.2.0", + "jest": "^29.7.0", "phonegap": "9.0.0+cordova.9.0.0", "process": "^0.11.10", "sass": "^1.62.1", "sass-loader": "^13.3.1", "style-loader": "^3.3.3", + "ts-jest": "^29.1.1", "ts-loader": "^9.4.2", "typescript": "^5.0.3", "url-loader": "^4.1.1", @@ -45,6 +48,7 @@ "@react-navigation/native": "^6.1.7", "@react-navigation/stack": "^6.3.17", "@shopify/flash-list": "^1.3.1", + "@types/jest": "^29.5.5", "angular": "1.6.7", "angular-animate": "1.6.7", "angular-local-storage": "^0.7.1", diff --git a/www/__tests__/diaryHelper.test.ts b/www/__tests__/diaryHelper.test.ts new file mode 100644 index 000000000..3aab018e1 --- /dev/null +++ b/www/__tests__/diaryHelper.test.ts @@ -0,0 +1,5 @@ +import { getFormattedDate } from "../js/diary/diaryHelper"; + +it('returns a formatted date', () => { + expect(getFormattedDate("2023-09-18T00:00:00-07:00")).toBe("Mon September 18, 2023"); +}); From 4604405116916ab323bb17e19fc3b4fb7d66668c Mon Sep 17 00:00:00 2001 From: Abby Wheelis Date: Tue, 19 Sep 2023 16:28:33 -0600 Subject: [PATCH 2/6] add some DiaryHelper tests testing the testing framework :) my goal is to test the normal cases and the edge cases ex: isMultiDay - test one expecting true, one expecting false, and one with invalid input (so false) --- www/__tests__/diaryHelper.test.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/www/__tests__/diaryHelper.test.ts b/www/__tests__/diaryHelper.test.ts index 3aab018e1..fa2ae800e 100644 --- a/www/__tests__/diaryHelper.test.ts +++ b/www/__tests__/diaryHelper.test.ts @@ -1,5 +1,19 @@ -import { getFormattedDate } from "../js/diary/diaryHelper"; +import { getFormattedDate, motionTypeOf, isMultiDay } from "../js/diary/diaryHelper"; it('returns a formatted date', () => { expect(getFormattedDate("2023-09-18T00:00:00-07:00")).toBe("Mon September 18, 2023"); + expect(getFormattedDate("")).toBeUndefined(); + expect(getFormattedDate("2023-09-18T00:00:00-07:00", "2023-09-21T00:00:00-07:00")).toBe("Mon September 18, 2023 - Thu September 21, 2023"); }); + +it("returns a MotionType object", () => { + expect(motionTypeOf("WALKING")).toEqual({ name: "WALKING", icon: "walk", color: '#0068a5' }); + // expect(motionTypeOf("MotionTypes.WALKING")).toEqual({ name: "WALKING", icon: "walk", color: '#0068a5' }); //failing but I don't know why + expect(motionTypeOf("I made this type up")).toEqual({ name: "UNKNOWN", icon: "help", color: '#484848'}); +}); + +it('returns true/false is multi day', () => { + expect(isMultiDay("2023-09-18T00:00:00-07:00", "2023-09-19T00:00:00-07:00")).toBeTruthy(); + expect(isMultiDay("2023-09-18T00:00:00-07:00", "2023-09-18T00:00:00-09:00")).toBeFalsy(); + expect(isMultiDay("", "2023-09-18T00:00:00-09:00")).toBeFalsy(); +}); \ No newline at end of file From 1b49b89b3c9359b3d022d1ea08e4ad8151a0109d Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Wed, 20 Sep 2023 10:40:06 -0400 Subject: [PATCH 3/6] fix motionTypeOf function; re-enable test As discovered in https://github.com/e-mission/e-mission-phone/pull/1033#issuecomment-1727858083, this function was not working as expected - it formats a key for lookup, and then didn't actually use the key. With this fix, the test runs correctly! --- www/__tests__/diaryHelper.test.ts | 4 ++-- www/js/diary/diaryHelper.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/www/__tests__/diaryHelper.test.ts b/www/__tests__/diaryHelper.test.ts index fa2ae800e..687173cf4 100644 --- a/www/__tests__/diaryHelper.test.ts +++ b/www/__tests__/diaryHelper.test.ts @@ -8,7 +8,7 @@ it('returns a formatted date', () => { it("returns a MotionType object", () => { expect(motionTypeOf("WALKING")).toEqual({ name: "WALKING", icon: "walk", color: '#0068a5' }); - // expect(motionTypeOf("MotionTypes.WALKING")).toEqual({ name: "WALKING", icon: "walk", color: '#0068a5' }); //failing but I don't know why + expect(motionTypeOf("MotionTypes.WALKING")).toEqual({ name: "WALKING", icon: "walk", color: '#0068a5' }); expect(motionTypeOf("I made this type up")).toEqual({ name: "UNKNOWN", icon: "help", color: '#484848'}); }); @@ -16,4 +16,4 @@ it('returns true/false is multi day', () => { expect(isMultiDay("2023-09-18T00:00:00-07:00", "2023-09-19T00:00:00-07:00")).toBeTruthy(); expect(isMultiDay("2023-09-18T00:00:00-07:00", "2023-09-18T00:00:00-09:00")).toBeFalsy(); expect(isMultiDay("", "2023-09-18T00:00:00-09:00")).toBeFalsy(); -}); \ No newline at end of file +}); diff --git a/www/js/diary/diaryHelper.ts b/www/js/diary/diaryHelper.ts index 88dd9baa5..942268ec7 100644 --- a/www/js/diary/diaryHelper.ts +++ b/www/js/diary/diaryHelper.ts @@ -48,7 +48,7 @@ type MotionTypeKey = keyof typeof MotionTypes; export function motionTypeOf(motionName: MotionTypeKey | `MotionTypes.${MotionTypeKey}`) { let key = ('' + motionName).toUpperCase(); key = key.split(".").pop(); // if "MotionTypes.WALKING", then just take "WALKING" - return MotionTypes[motionName] || MotionTypes.UNKNOWN; + return MotionTypes[key] || MotionTypes.UNKNOWN; } /** From df60ea4b25ac6965149fd5cb400094e2eaa15be1 Mon Sep 17 00:00:00 2001 From: Abby Wheelis Date: Wed, 20 Sep 2023 10:43:37 -0600 Subject: [PATCH 4/6] more diaryHelper tests continuing to improve testing coverage for diaryHelper by adding tests for more functions For some of the functions related to a trip, I found it easiest to look at a trip in the logs, create a test trip object with the relevant parts, and then also mock the results --- www/__tests__/diaryHelper.test.ts | 48 ++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/www/__tests__/diaryHelper.test.ts b/www/__tests__/diaryHelper.test.ts index 687173cf4..429fbd08e 100644 --- a/www/__tests__/diaryHelper.test.ts +++ b/www/__tests__/diaryHelper.test.ts @@ -1,4 +1,5 @@ -import { getFormattedDate, motionTypeOf, isMultiDay } from "../js/diary/diaryHelper"; +import { getFormattedSectionProperties, getFormattedDate, motionTypeOf, isMultiDay, getFormattedDateAbbr, getFormattedTimeRange, getPercentages } from "../js/diary/diaryHelper"; +import { useImperialConfig } from "../js/config/useImperialConfig"; it('returns a formatted date', () => { expect(getFormattedDate("2023-09-18T00:00:00-07:00")).toBe("Mon September 18, 2023"); @@ -6,6 +7,18 @@ it('returns a formatted date', () => { expect(getFormattedDate("2023-09-18T00:00:00-07:00", "2023-09-21T00:00:00-07:00")).toBe("Mon September 18, 2023 - Thu September 21, 2023"); }); +it('returns an abbreviated formatted date', () => { + expect(getFormattedDateAbbr("2023-09-18T00:00:00-07:00")).toBe("Mon, Sep 18"); + expect(getFormattedDateAbbr("")).toBeUndefined(); + expect(getFormattedDateAbbr("2023-09-18T00:00:00-07:00", "2023-09-21T00:00:00-07:00")).toBe("Mon, Sep 18 - Thu, Sep 21"); +}); + +it('returns a human readable time range', () => { + expect(getFormattedTimeRange("2023-09-18T00:00:00-07:00", "2023-09-18T00:00:00-09:20")).toBe("2 hours"); + expect(getFormattedTimeRange("2023-09-18T00:00:00-07:00", "2023-09-18T00:00:00-09:30")).toBe("3 hours"); + expect(getFormattedTimeRange("", "2023-09-18T00:00:00-09:30")).toBeFalsy(); +}); + it("returns a MotionType object", () => { expect(motionTypeOf("WALKING")).toEqual({ name: "WALKING", icon: "walk", color: '#0068a5' }); expect(motionTypeOf("MotionTypes.WALKING")).toEqual({ name: "WALKING", icon: "walk", color: '#0068a5' }); @@ -17,3 +30,36 @@ it('returns true/false is multi day', () => { expect(isMultiDay("2023-09-18T00:00:00-07:00", "2023-09-18T00:00:00-09:00")).toBeFalsy(); expect(isMultiDay("", "2023-09-18T00:00:00-09:00")).toBeFalsy(); }); + +//created a fake trip with relevant sections by examining log statements +let myFakeTrip = {sections: [ + { "sensed_mode_str": "BICYCLING", "distance": 6013.73657416706 }, + { "sensed_mode_str": "WALKING", "distance": 715.3078629361006 } +]}; +let myFakeTrip2 = {sections: [ + { "sensed_mode_str": "BICYCLING", "distance": 6013.73657416706 }, + { "sensed_mode_str": "BICYCLING", "distance": 715.3078629361006 } +]}; + +let myFakePcts = [ + { mode: "BICYCLING", + icon: "bike", + color: '#007e46', + pct: 89 }, + { mode: "WALKING", + icon: "walk", + color: '#0068a5', + pct: 11 }]; + +let myFakePcts2 = [ + { mode: "BICYCLING", + icon: "bike", + color: '#007e46', + pct: 100 }]; + +it('returns the percetnages by mode for a trip', () => { + expect(getPercentages(myFakeTrip)).toEqual(myFakePcts); + expect(getPercentages(myFakeTrip2)).toEqual(myFakePcts2); + expect(getPercentages({})).toEqual({}); +}) + From f24ce9db6f7e121e44d8b0705af95e0c3a76dd97 Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Wed, 20 Sep 2023 16:25:05 -0400 Subject: [PATCH 5/6] add step in serve-install for jest tests --- .github/workflows/serve-install.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/serve-install.yml b/.github/workflows/serve-install.yml index 288c1c8cb..04b3c8b2f 100644 --- a/.github/workflows/serve-install.yml +++ b/.github/workflows/serve-install.yml @@ -56,6 +56,11 @@ jobs: echo "ionic version" npx ionic --version + - name: Run Jest tests + shell: bash -l {0} + run: | + npx jest www/__tests__ + # TODO: figure out how to check that a server started correctly # - name: Try starting it # run: npx run serve From 1d0ddca5ed41bb8336cec4a75fa378bca1070082 Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Wed, 20 Sep 2023 16:39:45 -0400 Subject: [PATCH 6/6] jest: ignore these directories when discover tests We should only look for tests in our `www/__tests__` directory, not any other `__tests__` directories that may exist in dependencies or anywhere in the project directory tree. Further, by explicitly ignoring these directories, we don't have to specify `npx jest www/__tests__`, and can simply run `npx jest`. --- .github/workflows/serve-install.yml | 2 +- jest.config.json | 7 +++++++ package.serve.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/serve-install.yml b/.github/workflows/serve-install.yml index 04b3c8b2f..a5e634821 100644 --- a/.github/workflows/serve-install.yml +++ b/.github/workflows/serve-install.yml @@ -59,7 +59,7 @@ jobs: - name: Run Jest tests shell: bash -l {0} run: | - npx jest www/__tests__ + npx jest # TODO: figure out how to check that a server started correctly # - name: Try starting it diff --git a/jest.config.json b/jest.config.json index d9655cbf8..78dc839b4 100644 --- a/jest.config.json +++ b/jest.config.json @@ -1,4 +1,11 @@ { + "testPathIgnorePatterns": [ + "/node_modules/", + "/platforms/", + "/plugins/", + "/lib/", + "/manual_lib/" + ], "transform": { "^.+\\.(ts|tsx|js|jsx)$": "ts-jest" }, diff --git a/package.serve.json b/package.serve.json index 7eb50a4a1..a342a73de 100644 --- a/package.serve.json +++ b/package.serve.json @@ -11,7 +11,7 @@ "setup-serve": "./bin/download_settings_controls.js && ./bin/setup_autodeploy.js", "serve": "webpack --config webpack.dev.js && concurrently -k \"phonegap --verbose serve\" \"webpack --config webpack.dev.js --watch\"", "serve-only": "phonegap --verbose serve", - "test": "npx jest www/__tests__" + "test": "npx jest" }, "devDependencies": { "@babel/core": "^7.21.3",