Skip to content

Commit

Permalink
Merge pull request #196 from GSA/unit_test_updates
Browse files Browse the repository at this point in the history
Unit test updates
  • Loading branch information
collinschreyer-dev authored Jan 29, 2025
2 parents 2382b3b + d3f9812 commit dcb81bb
Show file tree
Hide file tree
Showing 11 changed files with 381 additions and 226 deletions.
16 changes: 13 additions & 3 deletions server/routes/agency.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,25 @@ module.exports = {
* @return Promise
*/
agencyList: function (req, res) {
db.sequelize.query('select distinct agency from notice order by agency', { type: db.sequelize.QueryTypes.SELECT })
console.log('AgencyList request received');

db.sequelize.query(
'select distinct agency from notice order by agency',
{
type: db.sequelize.QueryTypes.SELECT,
// Add a query timeout
timeout: 25000
}
)
.then(agencies => {
console.log(`Found ${agencies.length} agencies`);
let agencyList = []
agencies.forEach((a) => { agencyList.push(a.agency) })
return res.status(200).send(agencyList)
})
.catch(e => {
logger.log('error', 'error in: agencyList', { error:e, tag: 'agencyList' })
return res.status(500)
logger.log('error', 'error in: agencyList', { error: e, tag: 'agencyList' })
return res.status(500).send({ error: 'Internal server error' })
})
}
}
9 changes: 8 additions & 1 deletion server/routes/analytics.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,12 @@ async function computeAnalytics (params, user) {

let solStats = calcSolicitationsAddedOrUpdatedByDate(result.predictions);

logger.log('Compliance:', data.LatestComplianceSolicitation);
logger.log('Non-Compliance:', data.LatestNonComplianceSolicitation);
logger.log('Not Applicable:', data.LatestNotApplicableSolicitation);
logger.log('Cannot Evaluate:', data.LatestCannotEvaluateSolicitation);


let analytics = {
solStats: solStats,
ScannedSolicitationChart:
Expand Down Expand Up @@ -425,7 +431,8 @@ async function computeAnalytics (params, user) {
uncompliance: data.LatestNonComplianceSolicitation,
notApplicable: data.LatestNotApplicableSolicitation,
cannotEvaluate: data.LatestCannotEvaluateSolicitation
},
}
,
UndeterminedSolicitationChart:
{
presolicitation: data.LatestPresolicitation,
Expand Down
74 changes: 51 additions & 23 deletions server/routes/auth.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,14 @@ function createUser(loginGovUser) {
}

function grabAgencyFromEmail(email) {
if (!email || typeof email !== 'string' || !email.includes('@')) {
logger.log("error", "Invalid email provided", {
email,
tag: 'grabAgencyFromEmail'
});
return "No Agency Found"; // Return a default value for invalid emails
}

// Extract the full domain from the email
const fullDomain = email.split('@')[1];

Expand All @@ -175,16 +183,16 @@ function grabAgencyFromEmail(email) {
}

// If no match in the unique mapping, fall back to original functionality
let agency_abbreviance = fullDomain.split('.')[0];
const agencyAbbreviance = fullDomain.split('.')[0];
logger.log("info", "Extracting agency from email domain", {
email,
domain: agency_abbreviance,
domain: agencyAbbreviance,
tag: 'grabAgencyFromEmail'
});

let agencyName = translateCASAgencyName(agency_abbreviance);
let agencyName = translateCASAgencyName(agencyAbbreviance);
logger.log("info", "Resolved agency name", {
abbreviation: agency_abbreviance,
abbreviation: agencyAbbreviance,
resolved: agencyName,
tag: 'translateCASAgencyName'
});
Expand All @@ -197,6 +205,7 @@ function grabAgencyFromEmail(email) {
return agencyName;
}


/**
* @typedef {Object} cookie-session
* @property {function} destroy
Expand Down Expand Up @@ -615,7 +624,7 @@ module.exports = {

logger.log('info', (srt_userinfo.email || userInfo.email) + ' authenticated with LOGIN.GOV', {cas_userinfo: srt_userinfo, tag: 'Login.gov Auth Token'})

console.log("srt_userinfo: ", srt_userinfo)
logger.log("srt_userinfo: ", srt_userinfo)

let uri_components = {
token: jwt.sign({access_token: accessToken, user: srt_userinfo.user, sessionEnd: srt_userinfo.sessionEnd, token_life_in_seconds: getConfig('renewTokenLife')}, common.jwtSecret, { expiresIn: getConfig('renewTokenLife') }),
Expand All @@ -631,8 +640,6 @@ module.exports = {
}
let location = `${config['srtClientUrl']}/auth?info=${jsonToURI(uri_components)}`

//console.log("Redirecting to: ", location)

return res.redirect(302, location);
})
});
Expand Down Expand Up @@ -661,30 +668,51 @@ module.exports = {
* @param {Response} res
* @return {Promise}
*/
tokenCheck: function (req, res) {

let token = req.body.token
//console.log("token sent in tokenCheck:", token)
tokenCheck: function (req, res) {
const token = req.body.token;

try {
if ( token && jwt.verify(token, common.jwtSecret)) {
let tokenInfo = jwt.decode(token)
if (token && jwt.verify(token, common.jwtSecret)) {
const tokenInfo = jwt.decode(token);

// Additional logging for debugging
logger.log('Decoded Token Info:', tokenInfo);

/** @namespace tokenInfo.user */

//console.log('tokenInfo: ', tokenInfo)

if (tokenInfo['user'] && tokenInfo['user']['maxId']) {
return res.status(200).send(
{
isLogin: true,
isGSAAdmin: isGSAAdmin(tokenInfo.user.agency, tokenInfo.user.userRole)
})
const agency = tokenInfo.user.agency;
const userRole = tokenInfo.user.userRole;
const isAdmin = isGSAAdmin(agency, userRole);

// Logging details for debugging
logger.log('Agency:', agency);
logger.log('User Role:', userRole);
logger.log('isGSAAdmin Result:', isAdmin);

return res.status(200).send({
isLogin: true,
isGSAAdmin: isAdmin,
});
}
}
} catch (e) {
logger.log('error', 'caught error in JWT verification, failing safe and returning that the token is not valid', {error:e, tag:'tokenCheck'})
// Log error for debugging
console.error('Error during JWT verification:', e);
logger.log('error', 'Caught error in JWT verification. Failing safe and returning that the token is not valid.', {
error: e,
tag: 'tokenCheck',
});
}
return res.status(200).send({ isLogin: false, isGSAAdmin: false })

// Logging fallback response
logger.log('Token is either invalid or missing necessary information.');
return res.status(200).send({
isLogin: false,
isGSAAdmin: false,
});
},



/**
* Function called to create a JWT based on CAS info stored in the session
Expand Down
37 changes: 23 additions & 14 deletions server/tests/agency.routes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,26 @@ describe('/api/agencies', () => {
})
})

test('/api/AgencyList', async () => {
return request(appInstance)
.get('/api/AgencyList')
.set('Authorization', `Bearer ${token}`)
.send({ agency: agency, acronym: acronym })
.then((res) => {
// noinspection JSUnresolvedVariable
expect(res.statusCode).toBe(200)
expect(res.body).toBeDefined()
expect(res.body.length).toBeGreaterThan(1)
return expect(typeof (res.body[0])).toBe('string')
})
}, 10000)
})


test('/api/AgencyList', async () => {
console.log('Starting AgencyList test');
try {
const res = await request(appInstance)
.get('/api/AgencyList')
.set('Authorization', `Bearer ${token}`);

console.log('Received response:', res.statusCode);
expect(res.statusCode).toBe(200);
expect(res.body).toBeDefined();
expect(res.body.length).toBeGreaterThan(1);
expect(typeof (res.body[0])).toBe('string');
} catch (err) {
console.error('Test failed with error:', err);
throw err;
}
}, 30000); // Increased timeout to 30 seconds
});



28 changes: 19 additions & 9 deletions server/tests/analytics.routes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,25 @@ describe('Analytics routes tests', () => {
return request(appInstance)
.post('/api/analytics')
.set('Authorization', `Bearer ${adminToken}`)
.send({agency: 'Government-wide', fromPeriod: '1/1/1900', toPeriod: '12/31/2100'})
.send({ agency: 'Government-wide', fromPeriod: '1/1/1900', toPeriod: '12/31/2100' })
.then((res) => {
// noinspection JSUnresolvedVariable
expect(res.statusCode).toBe(200)
expect(res.body.PredictResultChart).toBeDefined()
expect(res.body.PredictResultChart.notApplicable).toBeDefined()
expect(res.body.PredictResultChart.notApplicable).toBeGreaterThan(2)
return expect(res.body.PredictResultChart).toBeDefined()
})
// Log the entire response body and focus on PredictResultChart
console.log('Full Response Body:', JSON.stringify(res.body, null, 2));
console.log('PredictResultChart:', res.body.PredictResultChart);
console.log('notApplicable Value:', res.body.PredictResultChart?.notApplicable);

// Assertions
expect(res.statusCode).toBe(200);
expect(res.body.PredictResultChart).toBeDefined();
expect(res.body.PredictResultChart.notApplicable).toBeDefined();

// Validate 'notApplicable' (adjust expectation if necessary)
expect(res.body.PredictResultChart.notApplicable).toBeGreaterThan(2);

return expect(res.body.PredictResultChart).toBeDefined();
});
});


})

})
18 changes: 8 additions & 10 deletions server/tests/cron.test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
// const db = require('../models/index')
// const {getConfig} = require('../config/configuration')
const {cleanAwardNotices} = require('../cron/noticeAwardCleanup')
const db = require('../models/index');
const { getConfig } = require('../config/configuration');
const { cleanAwardNotices } = require('../cron/noticeAwardCleanup');

describe('Cron tests', () => {

// Because the logger is in a different transaction space than Sequelize, I haven't figured out how to make a
// reliable unit test for this.
describe.skip('Cron tests', () => {
// Because the logger is in a different transaction space than Sequelize,
// we haven't figured out how to make a reliable unit test for this.
test('Test award notice cleanup cron', async () => {
const count_cleaned = await cleanAwardNotices();
expect (typeof(count_cleaned)).toBe('number')
}, 100000)
})
expect(typeof(count_cleaned)).toBe('number');
}, 100000);})
Loading

0 comments on commit dcb81bb

Please sign in to comment.