Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Jest for Basic Testing of Pure Functions #1033

Merged
merged 6 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/serve-install.yml
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the server code, we have install and test in separate workflows.
(future fix): I am fine with having this in the same workflow (at least initially), but then we should rename the file to indicate that it is also testing.

Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ jobs:
echo "ionic version"
npx ionic --version

- name: Run Jest tests
shell: bash -l {0}
run: |
npx jest

# TODO: figure out how to check that a server started correctly
# - name: Try starting it
# run: npx run serve
Expand Down
15 changes: 15 additions & 0 deletions jest.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"testPathIgnorePatterns": [
"/node_modules/",
"/platforms/",
"/plugins/",
"/lib/",
"/manual_lib/"
],
"transform": {
"^.+\\.(ts|tsx|js|jsx)$": "ts-jest"
},
"moduleNameMapper": {
"^react-native$": "react-native-web"
}
}
6 changes: 5 additions & 1 deletion package.serve.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
"devDependencies": {
"@babel/core": "^7.21.3",
Expand All @@ -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",
Expand All @@ -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",
Expand Down
65 changes: 65 additions & 0 deletions www/__tests__/diaryHelper.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
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");
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 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' });
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();
});

//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({});
})

2 changes: 1 addition & 1 deletion www/js/diary/diaryHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down
Loading