diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..33c9829 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,79 @@ +name: Step-time Biofeedback Project + +on: + push: + branches: + - feature/* + pull_request: + branches: + - feature/* + workflow_dispatch: + +env: + BUILD_TYPE: Release + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [20.x] + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + + - name: Download and cache virtual environment + run: | + pip install virtualenv + virtualenv env + source env/bin/activate + pip install -r requirements.txt + + - name: Install frontend dependencies + run: | + cd ${{github.workspace}}/frontend + npm install + npm test + + - name: Run backend tests + run: | + source env/bin/activate + cd ${{github.workspace}}/backend + pytest -s websocketUnitTest.py + + + lint: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + + - name: Download and cache virtual environment + run: | + pip install virtualenv + virtualenv env + source env/bin/activate + pip install -r requirements.txt + + - name: Lint Python Files + run: | + cd ${{github.workspace}}/backend + pylint *.py || true + + - name: Lint JavaScript files + run: | + cd ${{github.workspace}}/frontend + npm install + npm run lint \ No newline at end of file diff --git a/backend/connect_to_qtm.py b/backend/connect_to_qtm.py index 029f7b3..4130184 100644 --- a/backend/connect_to_qtm.py +++ b/backend/connect_to_qtm.py @@ -14,7 +14,7 @@ def stream_data (stream_type= 'Force', sleep_time= 0.1): return # create an inlet to read from the stream - inlet= StreamInlet(stream[0]) + inlet= StreamInlet(streams[0]) # pull and log samples try: @@ -25,6 +25,6 @@ def stream_data (stream_type= 'Force', sleep_time= 0.1): except KeyboardInterrupt: print("Streaming stopped by user.") - if __name__ == "__main__": +if __name__ == "__main__": stream_data() diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 0366338..d83c345 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -17,6 +17,7 @@ }, "devDependencies": { "@testing-library/react": "^16.0.1", + "eslint": "^8.57.1", "jest": "^27.5.1", "jest-websocket-mock": "^2.5.0", "react-test-renderer": "^18.3.1" @@ -108,9 +109,9 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.25.1", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.1.tgz", - "integrity": "sha512-Y956ghgTT4j7rKesabkh5WeqgSFZVFwaPR0IWFm7KFHFmmJ4afbG49SmfW4S+GyRPx0Dy5jxEWA5t0rpxfElWg==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.8.tgz", + "integrity": "sha512-Po3VLMN7fJtv0nsOjBDSbO1J71UhzShE9MuOSkWEV9IZQXzhZklYtzKZ8ZD/Ij3a0JBv1AG3Ny2L3jvAHQVOGg==", "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", @@ -2371,20 +2372,20 @@ } }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "deprecated": "Use @eslint/config-array instead", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", + "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" }, @@ -4208,9 +4209,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" }, "node_modules/@types/express": { "version": "4.17.21", @@ -7323,9 +7324,9 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", - "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.1.0.tgz", + "integrity": "sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -7334,12 +7335,12 @@ "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", + "globalthis": "^1.0.4", "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.3", "has-symbols": "^1.0.3", "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", + "iterator.prototype": "^1.1.3", "safe-array-concat": "^1.1.2" }, "engines": { @@ -7450,15 +7451,16 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -7549,9 +7551,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.11.0.tgz", - "integrity": "sha512-gbBE5Hitek/oG6MUVj6sFuzEjA/ClzNflVrLovHi/JgLdC7fiN5gLAY1WIPW1a0V5I999MnsrvVrCOGmmVqDBQ==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", "dependencies": { "debug": "^3.2.7" }, @@ -7590,9 +7592,9 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz", - "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==", + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.8", @@ -7602,7 +7604,7 @@ "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.9.0", + "eslint-module-utils": "^2.12.0", "hasown": "^2.0.2", "is-core-module": "^2.15.1", "is-glob": "^4.0.3", @@ -7611,13 +7613,14 @@ "object.groupby": "^1.0.3", "object.values": "^1.2.0", "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "node_modules/eslint-plugin-import/node_modules/debug": { @@ -7700,9 +7703,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.35.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.2.tgz", - "integrity": "sha512-Rbj2R9zwP2GYNcIak4xoAMV57hrBh3hTaR0k7hVjwCQgryE/pw5px4b13EYjduOI0hfXyZhwBxaGpOTbWSGzKQ==", + "version": "7.37.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.1.tgz", + "integrity": "sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==", "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", @@ -10201,15 +10204,18 @@ } }, "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", "dependencies": { "define-properties": "^1.2.1", "get-intrinsic": "^1.2.1", "has-symbols": "^1.0.3", "reflect.getprototypeof": "^1.0.4", "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/jackspeak": { @@ -18857,9 +18863,9 @@ } }, "@babel/eslint-parser": { - "version": "7.25.1", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.1.tgz", - "integrity": "sha512-Y956ghgTT4j7rKesabkh5WeqgSFZVFwaPR0IWFm7KFHFmmJ4afbG49SmfW4S+GyRPx0Dy5jxEWA5t0rpxfElWg==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.8.tgz", + "integrity": "sha512-Po3VLMN7fJtv0nsOjBDSbO1J71UhzShE9MuOSkWEV9IZQXzhZklYtzKZ8ZD/Ij3a0JBv1AG3Ny2L3jvAHQVOGg==", "requires": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", @@ -20295,16 +20301,16 @@ } }, "@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==" + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==" }, "@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "requires": { - "@humanwhocodes/object-schema": "^2.0.2", + "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" } @@ -21603,9 +21609,9 @@ } }, "@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" }, "@types/express": { "version": "4.17.21", @@ -23917,9 +23923,9 @@ } }, "es-iterator-helpers": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", - "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.1.0.tgz", + "integrity": "sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==", "requires": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -23928,12 +23934,12 @@ "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", + "globalthis": "^1.0.4", "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.3", "has-symbols": "^1.0.3", "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", + "iterator.prototype": "^1.1.3", "safe-array-concat": "^1.1.2" } }, @@ -24013,15 +24019,15 @@ } }, "eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -24208,9 +24214,9 @@ } }, "eslint-module-utils": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.11.0.tgz", - "integrity": "sha512-gbBE5Hitek/oG6MUVj6sFuzEjA/ClzNflVrLovHi/JgLdC7fiN5gLAY1WIPW1a0V5I999MnsrvVrCOGmmVqDBQ==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", "requires": { "debug": "^3.2.7" }, @@ -24235,9 +24241,9 @@ } }, "eslint-plugin-import": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz", - "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==", + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "requires": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.8", @@ -24247,7 +24253,7 @@ "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.9.0", + "eslint-module-utils": "^2.12.0", "hasown": "^2.0.2", "is-core-module": "^2.15.1", "is-glob": "^4.0.3", @@ -24256,6 +24262,7 @@ "object.groupby": "^1.0.3", "object.values": "^1.2.0", "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", "tsconfig-paths": "^3.15.0" }, "dependencies": { @@ -24314,9 +24321,9 @@ } }, "eslint-plugin-react": { - "version": "7.35.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.2.tgz", - "integrity": "sha512-Rbj2R9zwP2GYNcIak4xoAMV57hrBh3hTaR0k7hVjwCQgryE/pw5px4b13EYjduOI0hfXyZhwBxaGpOTbWSGzKQ==", + "version": "7.37.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.1.tgz", + "integrity": "sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==", "requires": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", @@ -25919,9 +25926,9 @@ } }, "iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", "requires": { "define-properties": "^1.2.1", "get-intrinsic": "^1.2.1", diff --git a/frontend/package.json b/frontend/package.json index 34d4c19..42faae5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -14,7 +14,8 @@ "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "lint": "eslint ." }, "eslintConfig": { "extends": [ @@ -36,6 +37,7 @@ }, "devDependencies": { "@testing-library/react": "^16.0.1", + "eslint": "^8.57.1", "jest": "^27.5.1", "jest-websocket-mock": "^2.5.0", "react-test-renderer": "^18.3.1" diff --git a/frontend/src/App.js b/frontend/src/App.js index fb516c0..38b8a0a 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -17,7 +17,7 @@ function App() { }; let websocket = useRef(null); - let websocketConnected = false; + // let websocketConnected = false; useEffect(() => { websocket.current = new WebSocket("ws://localhost:8000/ws"); @@ -25,7 +25,7 @@ function App() { websocket.current.onopen = () => { console.log("WebSocket Connected to React"); websocket.current.send("Websocket Connected to React") - websocketConnected = true; + // websocketConnected = true; }; websocket.current.onmessage = function(event) { @@ -34,7 +34,7 @@ function App() { websocket.current.onclose = (event) => { console.log("WebSocket connection closed: ", event); - websocketConnected = false; + // websocketConnected = false; }; return () => { diff --git a/frontend/src/App.test.js b/frontend/src/App.test.js deleted file mode 100644 index dc5925b..0000000 --- a/frontend/src/App.test.js +++ /dev/null @@ -1,77 +0,0 @@ -import { render } from '@testing-library/react'; -import { act } from 'react'; -import App from './App'; -import WS from 'jest-websocket-mock'; - -describe('WebSocket in App Component', () => { - let server; - - beforeEach(() => { - server = new WS("ws://localhost:8000/ws"); - }); - - afterEach(() => { - server.close(); - WS.clean(); - }); - - test('WebSocket connection messages', async () => { - const consoleLogSpy = jest.spyOn(console, 'log'); - - await act(async () => { - render(); - }); - - await server.connected; - - server.send("Message from backend"); - - await act(async () => { - await new Promise((resolve) => setTimeout(resolve, 100)); - }); - - expect(consoleLogSpy).toHaveBeenCalledWith("Data received from backend: ", "Message from backend"); - - consoleLogSpy.mockRestore(); - - }); - test('Message on WebSocket connection open', async () => { - await act(async () => { - render(); - }); - - // Wait for the server connection to be established - await server.connected; - - // Wait a bit to ensure the message is sent - await act(async () => { - await new Promise((resolve) => setTimeout(resolve, 100)); - }); - - // Check if the WebSocket has received the expected message - expect(server).toHaveReceivedMessages(["Websocket Connected to React"]); - - }); - - - - test("User is notified on WS Close", async () => { - const consoleLogSpy = jest.spyOn(console, 'log'); - - await act(async () => { - render(); - }); - - await server.connected; - - // Simulate WebSocket close - await act(async () => { - server.close(); - }); - - // Check if "WebSocket connection closed" is logged - expect(consoleLogSpy).toHaveBeenCalledWith("WebSocket connection closed: ", expect.any(Object)); - - consoleLogSpy.mockRestore(); - }); -}); diff --git a/frontend/src/__tests__/App.test.js b/frontend/src/__tests__/App.test.js index 45d533c..7a3921a 100644 --- a/frontend/src/__tests__/App.test.js +++ b/frontend/src/__tests__/App.test.js @@ -1,77 +1,76 @@ -import { render, screen, fireEvent } from '@testing-library/react'; -import App from '../App'; -import useStepTime from '../useStepTime'; -import { act } from 'react'; -import WS from 'jest-websocket-mock'; +import { render, screen, fireEvent } from "@testing-library/react"; +import App from "../App"; +import useStepTime from "../useStepTime"; +import WS from "jest-websocket-mock"; -jest.mock('../useStepTime'); +jest.mock("../useStepTime"); -test('Step Time Component is rendered on screen', () => { +test("Step Time Component is rendered on screen", () => { useStepTime.mockReturnValue({ left: 0, right: 0, targetZones: { left: { min: 25, max: 30 }, - right: { min: 50, max: 45 } - } + right: { min: 50, max: 45 }, + }, }); - + render(); - expect(screen.getByTestId('step-time-digits-view')).toBeInTheDocument(); + expect(screen.getByTestId("step-time-digits-view")).toBeInTheDocument(); }); -describe('Navbar Component', () => { +describe("Navbar Component", () => { beforeEach(() => { useStepTime.mockReturnValue({ left: 0, right: 0, targetZones: { left: { min: 25, max: 30 }, - right: { min: 50, max: 45 } - } + right: { min: 50, max: 45 }, + }, }); }); - test('Navbar is rendered on screen', () => { + test("Navbar is rendered on screen", () => { render(); - expect(screen.getByRole('navigation')).toBeInTheDocument(); + expect(screen.getByRole("navigation")).toBeInTheDocument(); }); - describe('View Swapping', () => { - test('Navbar swap renders StepTimeChart view', () => { + describe("View Swapping", () => { + test("Navbar swap renders StepTimeChart view", () => { render(); - fireEvent.click(screen.getByTestId('step-time-chart-nav')); - expect(screen.getByTestId('step-time-chart-view')).toBeInTheDocument(); + fireEvent.click(screen.getByTestId("step-time-chart-nav")); + expect(screen.getByTestId("step-time-chart-view")).toBeInTheDocument(); }); - - test('Navbar swap renders StepTimeGraph view', () => { + + test("Navbar swap renders StepTimeGraph view", () => { render(); - fireEvent.click(screen.getByTestId('step-time-graph-nav')); - expect(screen.getByTestId('step-time-graph-view')).toBeInTheDocument(); + fireEvent.click(screen.getByTestId("step-time-graph-nav")); + expect(screen.getByTestId("step-time-graph-view")).toBeInTheDocument(); }); - - test('Navbar swap renders StepTimeDigits view', () => { + + test("Navbar swap renders StepTimeDigits view", () => { render(); - fireEvent.click(screen.getByTestId('step-time-graph-nav')); - fireEvent.click(screen.getByTestId('step-time-digits-nav')); - expect(screen.getByTestId('step-time-digits-view')).toBeInTheDocument(); + fireEvent.click(screen.getByTestId("step-time-graph-nav")); + fireEvent.click(screen.getByTestId("step-time-digits-nav")); + expect(screen.getByTestId("step-time-digits-view")).toBeInTheDocument(); }); }); }); -describe('WebSocket in App Component', () => { +describe("WebSocket in App Component", () => { let server; beforeEach(() => { server = new WS("ws://localhost:8000/ws"); - + useStepTime.mockReturnValue({ left: 0, right: 0, targetZones: { left: { min: 25, max: 30 }, - right: { min: 50, max: 45 } - } + right: { min: 50, max: 45 }, + }, }); }); @@ -79,33 +78,48 @@ describe('WebSocket in App Component', () => { WS.clean(); }); - test('WebSocket connection messages', async () => { - const consoleLogSpy = jest.spyOn(console, 'log'); + test("WebSocket connection messages", async () => { + const consoleLogSpy = jest.spyOn(console, "log"); - await act(async () => { - render(); - }); + render(); // Removed act wrapper await server.connected; server.send("Message from backend"); - await act(async () => { - await new Promise((resolve) => setTimeout(resolve, 100)); - }); + // Await for the effects of the message + await new Promise((resolve) => setTimeout(resolve, 100)); - expect(consoleLogSpy).toHaveBeenCalledWith("Data received from backend: ", "Message from backend"); + expect(consoleLogSpy).toHaveBeenCalledWith( + "Data received from backend: ", + "Message from backend" + ); consoleLogSpy.mockRestore(); }); - test('Message on WebSocket connection open', async () => { - await act(async () => { - render(); - }); + test("Message on WebSocket connection open", async () => { + render(); // Removed act wrapper await server.connected; expect(server).toReceiveMessage("Websocket Connected to React"); }); -}); \ No newline at end of file + + test("User is notified on WS Close", async () => { + const consoleLogSpy = jest.spyOn(console, "log"); + + render(); // Removed act wrapper + + await server.connected; + + server.close(); // Removed act wrapper + + expect(consoleLogSpy).toHaveBeenCalledWith( + "WebSocket connection closed: ", + expect.any(Object) + ); + + consoleLogSpy.mockRestore(); + }); +}); diff --git a/backend/requirements.txt b/requirements.txt similarity index 72% rename from backend/requirements.txt rename to requirements.txt index a37b4cb..058bc2e 100644 --- a/backend/requirements.txt +++ b/requirements.txt @@ -12,4 +12,9 @@ pytest==8.3.3 httpcore==1.0.5 httpx==0.27.2 pytest-asyncio==0.24.0 -websockets==13.1 \ No newline at end of file +websockets==13.1 +astroid==3.3.5 +dill==0.3.9 +isort==5.13.2 +pylint==3.3.1 +tomlkit==0.13.2 \ No newline at end of file