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

Creates Test Plan for Running Integration Tests on Server API Endpoints #1493

Merged
merged 31 commits into from
Nov 2, 2023
Merged
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6c8bd33
adds tests for account endpoints
agosmou Sep 19, 2023
9a38856
Merge branch 'develop' of https://github.com/hackforla/tdm-calculator…
agosmou Oct 15, 2023
a2c8ee7
pushing WIP branch - not working yet
agosmou Oct 17, 2023
66f1dc6
fixes testcontainers environment and is now functional
agosmou Oct 17, 2023
5b8efa6
creates setup configuration for test database in container
agosmou Oct 18, 2023
34538d8
adds mock for sendgrid and organizes .env
agosmou Oct 18, 2023
a9ef7b4
Merge branch 'develop' of https://github.com/hackforla/tdm-calculator…
agosmou Oct 19, 2023
9f5e596
adds api endpoint blackbox tests - logout test is not passing yet
agosmou Oct 19, 2023
e0ff2a8
fixes logout test and adds comment
agosmou Oct 19, 2023
1a3fd93
adds functionality to start and close server for each test suite
agosmou Oct 19, 2023
d0dc0b7
working test suite
agosmou Oct 19, 2023
4435b4f
adds notes to readME and comments in jest setup
agosmou Oct 21, 2023
7922153
organizes jest config in codebase
agosmou Oct 21, 2023
2cbd941
removes bloat comments in code
agosmou Oct 21, 2023
57d551f
renames jest setup directory and files
agosmou Oct 21, 2023
60b6425
refactors jest test environment setup
agosmou Oct 22, 2023
07abca5
refactors to restore original code with standard env variables
agosmou Oct 22, 2023
f74e5bf
edits the example env file
agosmou Oct 22, 2023
0b02b6b
refactors to provide server setup and teardown to use on api endpoint…
agosmou Oct 22, 2023
347f539
refactors host port on container setup to use environment variable
agosmou Oct 22, 2023
fb3fcc2
adds github action to include tests on CI pipeline
agosmou Oct 26, 2023
f751ff3
adjust test file naming conventions and minor edits to setup files
agosmou Oct 26, 2023
d4b9bef
organizes files into folders for maintainability
agosmou Oct 26, 2023
2a82ee5
refactors for maintainability and readability
agosmou Oct 26, 2023
e14cf90
refactors tests
agosmou Oct 26, 2023
3407be0
minor refactors and linting
agosmou Oct 26, 2023
9febb94
linting
agosmou Oct 26, 2023
d45e2e4
resolving merge conflict
agosmou Oct 26, 2023
d315c4e
Merge branch 'develop' of https://github.com/hackforla/tdm-calculator…
agosmou Oct 26, 2023
0b39c02
resolves merge conflict
agosmou Oct 26, 2023
0425165
fixes lerna issues on branch
agosmou Oct 26, 2023
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
Prev Previous commit
Next Next commit
adds api endpoint blackbox tests - logout test is not passing yet
agosmou committed Oct 19, 2023
commit 9f5e596e482493dda09c3c6c23e786ac5cc138a9
8 changes: 8 additions & 0 deletions server/__tests__/README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
# Testing the TDM Server API
If on windows:
You must have docker-desktop up and running. If you are using WSL2, you must have the docker daemon running in WSL2. You can test this by running `sudo docker run hello-world` from the command line. If you get an error, you need to start the docker daemon. If you get a success message, you are good to go.

## Running the tests
On Windows:

Start up your Docker Desktop to make sure your daemon is running

Comment out all variables above 'testing' in the .env file

then run from the 'server' directory `npm test`

## Troubleshooting

Test your docker daemon from linux command line:
`sudo docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=tdmTestingPassword1!" -p 1435:1435 --name sql3 --hostname sql3 -d mcr.microsoft.com/mssql/server`

# Testing Notes
These tests are manually configured to connect the docker container to port 1433 and map it to the host's port 1433.
It will create a containerized SQL Server and then a database within it. It wil run the migrations and seed the database. We will reuse this same container for all tests.


## TDM Databse Further Info
[Local Database Information](https://github.com/hackforla/tdm-calculator/wiki/Local-Database)
179 changes: 162 additions & 17 deletions server/__tests__/api_endpoint_unit_test/accounts.test.js
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ require("dotenv").config();
let originalSendgrid = sgMail.send;

beforeEach(() => {
// Mock the send function
// Mock the sendgrid mail api function
sgMail.send = jest.fn(async (msg) => {
return {statusCode: 202};
});
@@ -21,58 +21,203 @@ afterEach(() => {
describe("Account Endpoints", () => {
let userId; // id of the registered user - to be deleted by security admin
let adminToken; // jwt for security admin - for protected endpoints
let userToken; // jwt for registered user - for protected endpoints

// GET "/" Get all accounts (Security Admin only)

// PUT "/:id/roles" Update roles for an account (Security Admin only)
//////////////////////////////
// user endpoints //
//////////////////////////////

// // POST "/register" Register a new account
// POST "/register" Register a new account
it("should register a new user", async () => {
const res = await request(app)
.post("/api/accounts/register")
.send({
firstName: "Jose",
lastName: "Garcia",
email: `'[email protected]'`,
email: '[email protected]',
password: "Password1!!!"
});
// console.log(res.body);
userId = res.body.newId;
expect(res.statusCode).toEqual(200);
expect(res.body).toHaveProperty("newId");
userId = res.body.newId;
});

// POST "/resendConfirmationEmail" Resend confirmation email
it("should resend a confirmation email", async () => {
const res = await request(app)
.post("/api/accounts/resendConfirmationEmail")
.send({
email: '[email protected]',
});
// captures the token from the mocked sendgird function to be used in confirmation test below
const tokenPattern = /\/confirm\/([a-zA-Z0-9\-]+)/;
const emailContent = sgMail.send.mock.calls[0][0].html;
const match = emailContent.match(tokenPattern);
if (match && match[1]) {
capturedToken = match[1];
}
expect(res.statusCode).toEqual(200);
});

// POST "/confirmRegister" Confirm registration
it("should confirm a user's registration", async () => {
// uses the captured token from the mocked sendgrid function above
const res = await request(app)
.post("/api/accounts/confirmRegister")
.send({ token: capturedToken });
expect(res.statusCode).toEqual(200);
expect(res.body).toHaveProperty("success", true);
});

// POST "/login" Login as a user
it("should login as a user", async () => {
const res = await request(app)
.post("/api/accounts/login")
.send({
email: '[email protected]',
password: "Password1!!!"
});
expect(res.statusCode).toEqual(200);
expect(res.body).toHaveProperty("token");
userToken = res.body.token;
});

// POST "/forgotPassword" Forgot password
it("should send a forgot password email", async () => {
const res = await request(app)
.post("/api/accounts/forgotPassword")
.send({
email: '[email protected]',
});
expect(res.statusCode).toEqual(200);
});

// POST "/resetPassword" Reset password
it("should reset a password", async () => {
const res = await request(app)
.post("/api/accounts/resetPassword")
.set("Authorization", `Bearer ${userToken}`)
.send({
password: "NewPassword1!!!",
token: userToken,
});
expect(res.statusCode).toEqual(200);
});

// PUT "/:id/updateaccount" Update account
it("should update a user", async () => {
const res = await request(app)
.put(`/api/accounts/${userId}/updateaccount`)
.set("Authorization", `Bearer ${userToken}`)
.send({
firstName: "Joseph",
lastName: "Garcia",
email: '[email protected]',
});
expect(res.statusCode).toEqual(200);
});

// // GET "/logout" Logout as a user
// it("should logout the user", async () => {
// // Logout the user
// const logoutRes = await request(app).get("/api/accounts/logout");
// // Check the response of the logout route
// expect(logoutRes.statusCode).toEqual(200);
// // verify that the user token is no longer valid by calling a protected endpoint
// const updateAccRouteRes = await request(app)
// .put(`/api/accounts/${userId}/updateaccount`)
// .set("Authorization", `Bearer ${userToken}`)
// .send({
// firstName: "Yusef",
// lastName: "Garcia",
// email: '[email protected]',
// });
// expect(updateAccRouteRes.statusCode).not.toEqual(200);
// }, 10000);

// GET "/logout" Logout as a user
it("should logout the user", async () => {
const logoutRes = await request(app).get("/api/accounts/logout");
expect(logoutRes.statusCode).toEqual(200);
});

// POST "/login/:email?" Login
//////////////////////////////
// security admin endpoints //
//////////////////////////////

// POST "/login/:email?" Login as security admin
it("should login as a security admin", async () => {
const res = await request(app).post("/api/accounts/login").send({
email: process.env.SECURITY_ADMIN_EMAIL,
password: process.env.SECURITY_ADMIN_PASSWORD
});
const res = await request(app)
.post("/api/accounts/login")
.send({
email: process.env.SECURITY_ADMIN_EMAIL,
password: process.env.SECURITY_ADMIN_PASSWORD
});
expect(res.statusCode).toEqual(200);
expect(res.body).toHaveProperty("token");
adminToken = res.body.token;
// console.log(adminToken);
});

// GET "/logout" Logout
// PUT "/:id/roles" Update roles for an account to give admin priviliges (Security Admin only)
it("should update roles for an account while logged in as security admin", async () => {
const res = await request(app)
.put(`/api/accounts/${userId}/roles`)
.set("Authorization", `Bearer ${adminToken}`)
.send({
id: userId,
isAdmin: true,
isSecurityAdmin: true,
});
expect(res.statusCode).toEqual(200)
});

// PUT "/:id/roles" Update roles for an account to revoke admin priviliges (Security Admin only)
it("should update roles for an account while logged in as security admin", async () => {
const res = await request(app)
.put(`/api/accounts/${userId}/roles`)
.set("Authorization", `Bearer ${adminToken}`)
.send({
id: userId,
isAdmin: false,
isSecurityAdmin: false,
});
expect(res.statusCode).toEqual(200)
});

// PUT "/:id/updateaccount" Update account

// GET "/" Get all accounts (Security Admin only)
it("should get all accounts while logged in as security admin", async () => {
const res = await request(app)
.get("/api/accounts")
.set("Authorization", `Bearer ${adminToken}`);
expect(res.statusCode).toEqual(200);
});

// PUT "/:id/archiveaccount" Archive account (Security Admin only)
it("should archive a user", async () => {
const res = await request(app)
.put(`/api/accounts/${userId}/archiveaccount`)
.set("Authorization", `Bearer ${adminToken}`);
expect(res.statusCode).toEqual(200);
});

// PUT "/:id/unarchiveaccount" Unarchive account (Security Admin only)
it("should unarchive a user", async () => {
const res = await request(app)
.put(`/api/accounts/${userId}/unarchiveaccount`)
.set("Authorization", `Bearer ${adminToken}`);
expect(res.statusCode).toEqual(200);
});

// GET "/archivedaccounts" Get all archived accounts (Security Admin only)
it("should get all archived accounts while logged in as security admin", async () => {
const res = await request(app)
.get("/api/accounts/archivedaccounts")
.set("Authorization", `Bearer ${adminToken}`);
expect(res.statusCode).toEqual(200);
});

// DELETE "/:id/deleteaccount" Delete account (Security Admin only)
// DELETE "/:id/deleteaccount" Delete a user's account (Security Admin only)
it("should delete a user", async () => {
const res = await request(app)
.delete(`/api/accounts/${userId}/deleteaccount`)
2 changes: 1 addition & 1 deletion server/package.json
Copy link
Member Author

Choose a reason for hiding this comment

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

This adds supertest, jest, and testcontainers. These are popular libraries that are well maintained with stable dependencies.

Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
"main": "server.js",
"scripts": {
"precommit": "lint-staged",
"test": "jest --passWithNoTests --forceExit",
"test": "jest --runInBand --passWithNoTests --forceExit",
Copy link
Member Author

Choose a reason for hiding this comment

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

"--runInBand" is added to run the test files sequentially rather than in parallel because they are sharing a database instance.

"--forceExit" is a measure to force jest to exit in the case there is a server that is hanging up from being improperly closed.

"heroku-postbuild": "cd client && npm i && npm run build",
"start": "nodemon",
"release-notes": "gren release --override",