Skip to content
Open
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
2 changes: 1 addition & 1 deletion src/Pages/AuditLog/AuditLog.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useEffect } from 'react';
import React, { useState, useEffect } from 'react';
import { getAllLogs, createAuditLogEventSource } from '../../APIFunctions/AuditLog';
import Pagination from './Components/Pagination';
import { useSCE } from '../../Components/context/SceContext';
Expand Down
158 changes: 158 additions & 0 deletions test/api/AuditLog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
process.env.NODE_ENV = 'test';

const User = require('../../api/main_endpoints/models/User.js');
const AuditLog = require('../../api/main_endpoints/models/AuditLog.js');

const chai = require('chai');

const chaiHttp = require('chai-http');
const {
UNAUTHORIZED,
} = require('../../api/util/constants.js').STATUS_CODES;
const SceApiTester = require('../util/tools/SceApiTester.js');

let app = null;
let test = null;
const expect = chai.expect;
const tools = require('../util/tools/tools.js');
const {
setTokenStatus,
resetTokenMock,
restoreTokenMock,
initializeTokenMock
} = require('../util/mocks/TokenValidFunctions.js');
const {
setDiscordAPIStatus,
resetDiscordAPIMock,
restoreDiscordAPIMock,
initializeDiscordAPIMock
} = require('../util/mocks/DiscordApiFunction.js');
const { MEMBERSHIP_STATE } = require('../../api/util/constants.js');
const AuditLogActions = require('../../api/main_endpoints/util/auditLogActions.js');

chai.should();
chai.use(chaiHttp);

describe('AuditLog', () => {
before(done => {
initializeTokenMock();
initializeDiscordAPIMock();
app = tools.initializeServer([
__dirname + '/../../api/main_endpoints/routes/AuditLog.js'
]);
test = new SceApiTester(app);

tools.emptySchema(User);
tools.emptySchema(AuditLog);
const testUser = new User({
email: '[email protected]',
password: 'Passw0rd',
firstName: 'firstName',
lastName: 'lastName',
major: 'Software Engineering',
});
testUser.save();
const testLog = new AuditLog({
userId: testUser._id,
action: AuditLogActions.LOG_IN,
documentId: testUser._id,
details: {email: testUser.email },
});
testLog.save();
done();
});

after(done => {
resetTokenMock();
restoreDiscordAPIMock();
tools.terminateServer(done);
});

beforeEach(() => {
setTokenStatus(false);
setDiscordAPIStatus(false);
});

afterEach(async () => {
restoreTokenMock();
resetTokenMock();
restoreDiscordAPIMock();
resetDiscordAPIMock();
});

const token = '';

describe('GET /getAuditLogs', () => {
const url = '/api/AuditLog/getAuditLogs/';

it('Should return status code 401 if no token is passed through', async () => {
setTokenStatus(false);
const result = await test.sendGetRequest(url);
expect(result).to.have.status(UNAUTHORIZED);
});

it('Should return status code 401 if access level is invalid', async () => {
setTokenStatus(false, { accessLevel: MEMBERSHIP_STATE.MEMBER });
const result = await test.sendGetRequestWithToken(token, url);
expect(result).to.have.status(UNAUTHORIZED);
});

it('Should return at most 50 records when query is an empty string and access level is valid', async () => {
setTokenStatus(true, { accessLevel: MEMBERSHIP_STATE.OFFICER});

before(async () => {
const newUser = new User({
email: '[email protected]',
password: 'Passw0rd',
firstName: 'first name',
lastName: 'last name',
major: 'Software Engineering',
});
newUser.save();

for (let i = 0; i < 3; i++) {
await AuditLog.create({
userId: newUser._id,
action: AuditLogActions.RESET_PW,
documentId: newUser._id,
details: {email: newUser.email },
});
}

for (let i = 0; i < 60; i++) {
await AuditLog.create({
userId: newUser._id,
action: AuditLogActions.EMAIL_SENT,
documentId: newUser._id,
details: {email: newUser.email },
});
}
});
Copy link
Contributor

Choose a reason for hiding this comment

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

what are these loops for?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The loops create 63 records. The test checks that, when the query is empty, the route returns at most 50 records from the first page.

const result = await test.sendGetRequestWithToken(token, url);
expect(result.body.items).that.is.an('array');
expect(result.body.items.length).at.most(50);
});

it('Should return the testUser when query is "[email protected]" and access level is OFFICER', async () => {
setTokenStatus(true, { accessLevel: MEMBERSHIP_STATE.OFFICER});
const search = '[email protected]';
const fullUrl = `/api/AuditLog/getAuditLogs?search=${encodeURIComponent(search)}`;
const result = await test.sendGetRequestWithToken(token, fullUrl);
expect(result.body.items).that.is.an('array').to.have.lengthOf(1);
expect(result.body.items[0].userId.email).to.eql('[email protected]');
});

it('Should return an empty array when the query matches no record: "[email protected]" and access level is ADMIN', async () => {
setTokenStatus(true, { accessLevel: MEMBERSHIP_STATE.ADMIN});
const search = '[email protected]';
const fullUrl = `/api/AuditLog/getAuditLogs?search=${encodeURIComponent(search)}`;
const result = await test.sendGetRequestWithToken(token, fullUrl);
expect(result.body.items).that.is.an('array').that.is.empty;
});

after(async () => {
await User.deleteMany({});
await AuditLog.deleteMany({});
});
});
});
20 changes: 20 additions & 0 deletions test/frontend/Routing.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import EditUserInfo from '../../src/Pages/UserManager/EditUserInfo';
import URLShortenerPage from '../../src/Pages/URLShortener/URLShortener';
import sendUnsubscribeEmail from '../../src/Pages/Profile/admin/SendUnsubscribeEmail';
import NotFoundPage from '../../src/Pages/NotFoundPage/NotFoundPage';
import AuditLogPage from '../../src/Pages/AuditLog/AuditLog';

import { membershipState } from '../../src/Enums';
import { MemoryRouter } from 'react-router-dom';
Expand Down Expand Up @@ -59,6 +60,17 @@ function getComponentFromRoute(route, props = adminAppProps, user = mockUser) {

describe('<Routing /> with <PrivateRoute />', () => {
describe('Renders correct components for Admin user', () => {
// Prevent ReferenceError: EventSource is not defined
if (typeof global.EventSource === 'undefined') {
global.EventSource = class {
constructor() {}
close() {}
addEventListener() {}
removeEventListener() {}
onmessage() {}
onerror() {}
};
}
it('Should render a <Home /> component with the / endpoint', () => {
const wrapper = getComponentFromRoute('/');
expect(wrapper.find(Home)).to.have.lengthOf(1);
Expand Down Expand Up @@ -150,5 +162,13 @@ describe('<Routing /> with <PrivateRoute />', () => {
expect(wrapper.find(NotFoundPage)).to.have.lengthOf(1);
}
);
it(
'Should render a <AuditLogsPage /> component with with the /audit-logs ' +
'endpoint',
() => {
const wrapper = getComponentFromRoute('/audit-logs');
expect(wrapper.find(AuditLogPage)).to.have.lengthOf(1);
}
);
});
});