Tell us what’s happening:
I’m working on the issue tracker for the quality assurance certificate. The code passes all the tests when submitted to fcc except for the functional tests, and the code seems to function properly on the website.
The following functional tests are failing:
- View issues on a project with multiple filters
- Update one field on an issue
- Update an issue with an invalid _id
- Delete an issue with an invalid _id
I’ve spent a few hours trying to understand why it is not working, whether it is my tests or the routes that are the problem, and read other posts on the fcc forum to see if I could catch it, but no luck.
I’d appreciate any help!
My tests are:
const chaiHttp = require('chai-http');
const chai = require('chai');
const assert = chai.assert;
const server = require('../server');
chai.use(chaiHttp);
suite('Functional Tests', () => {
let id1;
suite('Post request to /api/issues/{project}', () => {
test('Create an issue with every field', (done) => {
chai
.request(server)
.post('/api/issues/test')
.send({
issue_title: 'Test Issue',
issue_text: 'Test Issue Text',
created_by: 'Test User',
assigned_to: 'Test Assignee',
status_text: 'Test Status'
})
.end( (err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.issue_title, 'Test Issue');
assert.equal(res.body.issue_text, 'Test Issue Text');
assert.equal(res.body.created_by, 'Test User');
assert.equal(res.body.assigned_to, 'Test Assignee');
assert.equal(res.body.status_text, 'Test Status');
assert.equal(res.body.open, true);
id1 = res.body._id;
done();
});
});
test('Create an issue with only required fields', (done) => {
chai
.request(server)
.post('/api/issues/test')
.send({
issue_title: 'Test Issue',
issue_text: 'Test Issue Text',
created_by: 'Test User'
})
.end( (err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.issue_title, 'Test Issue');
assert.equal(res.body.issue_text, 'Test Issue Text');
assert.equal(res.body.created_by, 'Test User');
assert.equal(res.body.assigned_to, '');
assert.equal(res.body.status_text, '');
assert.equal(res.body.open, true);
done();
});
});
test('Create an issue with missing required fields', (done) => {
chai
.request(server)
.post('/api/issues/test')
.send({
issue_title: 'Test Issue',
issue_text: 'Test Issue Text'
})
.end( (err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.error, 'required field(s) missing');
done();
});
});
});
suite('Get request to /api/issues/{project}', () => {
test('View issues on a project', (done) => {
chai
.request(server)
.get('/api/issues/test')
.end( (err, res) => {
assert.equal(res.status, 200);
assert.isArray(res.body);
done();
});
});
test('View issues on a project with one filter', (done) => {
chai
.request(server)
.get('/api/issues/test')
.query({
issue_title: 'Test Issue'
})
.end( (err, res) => {
assert.equal(res.status, 200);
assert.isArray(res.body);
done();
});
});
test('View issues on a project with multiple filters', (done) => {
chai
.request(server)
.get('api/issues/test')
.query({ issue_title: 'Test Issue', issue_text: 'Test Issue Text' })
.end( (err, res) => {
assert.equal(res.status, 200);
assert.isArray(res.body);
done();
});
});
});
suite('Put request to /api/issues/{project}', () => {
test('Update one field on an issue', (done) => {
chai
.request(server)
.put('api/issues/test')
.send({
_id: id1,
issue_title: 'Updated Title',
})
.end( (err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.result, 'successfully updated');
done();
});
});
test('Update multiple fields on an issue', (done) => {
chai
.request(server)
.put('/api/issues/test')
.send({
_id: id1,
issue_title: 'Second Updated Title',
issue_text: 'Updated Text'
})
.end( (err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.result, 'successfully updated');
done();
});
});
test('Update an issue with missing _id', (done) => {
chai
.request(server)
.put('/api/issues/test')
.send({
issue_title: 'Test Issue'
})
.end( (err, res) => {
assert.equal(res.status, 200);
console.log(res.body);
assert.equal(res.body.error, 'missing _id');
done();
});
});
test('Update an issue with no fields to update', (done) => {
chai
.request(server)
.put('/api/issues/test')
.send({
_id: id1
})
.end( (err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.error, 'no update field(s) sent');
done();
});
});
test('Update an issue with an invalid _id', (done) => {
chai
.request(server)
.put('/api/issues/test')
.send({
_id: 'invalid id',
issue_title: 'Test Issue'
})
.end( (err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.error, 'could not update');
done();
});
});
});
suite('Delete request to /api/issues/{project}', () => {
test('Delete an issue', (done) => {
chai
.request(server)
.delete('/api/issues/test')
.send({
_id: id1
})
.end( (err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.result, 'successfully deleted');
done();
});
});
test('Delete an issue with an invalid _id', (done) => {
chai
.request(server)
.delete('/api/issues/test')
.send({
_id: 'invalid id'
})
.end( (err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.error, 'could not delete');
done();
});
});
test('Delete an issue with missing _id', (done) => {
chai
.request(server)
.delete('/api/issues/test')
.send({
_id: ''
})
.end( (err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.error, 'missing _id');
done();
});
});
});
});
after(() => {
chai.request(server).get('/api')
});
My routes are:
'use strict';
const projectModel = require('../models').projectModel
module.exports = (app) => {
app.route('/api/issues/:project')
// getting issues of a project
.get( (req, res) => {
let project = req.params.project;
// filtering issues by query params
let iDParam = req.query._id;
let issueTitleParam = req.query.issue_title;
let issueTextParam = req.query.issue_text;
let createdByParam = req.query.created_by;
let assignedToParam = req.query.assigned_to;
let statusTextParam = req.query.status_text;
let openParam = req.query.open;
let createdOnParam = req.query.created_on;
let updatedOnParam = req.query.updated_on;
let queryObj = {
project: project
};
if (iDParam) {
queryObj._id = iDParam;
};
if (issueTitleParam) {
queryObj.issue_title = issueTitleParam;
};
if (issueTextParam) {
queryObj.issue_text = issueTextParam;
};
if (createdByParam) {
queryObj.created_by = createdByParam;
};
if (assignedToParam) {
queryObj.assigned_to = assignedToParam;
};
if (statusTextParam) {
queryObj.status_text = statusTextParam;
};
if (openParam) {
queryObj.open = openParam;
};
if (createdOnParam) {
queryObj.created_on = createdOnParam;
};
if (updatedOnParam) {
queryObj.updated_on = updatedOnParam;
};
projectModel.find(queryObj).then((data) => {
res.json(data);
return;
});
})
.post( (req, res) => {
let project = req.params.project;
if (!req.body.issue_title ||
!req.body.issue_text ||
!req.body.created_by) {
res.json({ error: 'required field(s) missing' });
return;
} else {
let newProject = new projectModel({
project: project,
issue_title: req.body.issue_title,
issue_text: req.body.issue_text,
created_by: req.body.created_by,
assigned_to: req.body.assigned_to || "",
status_text: req.body.status_text || "",
open: true,
created_on: new Date(),
updated_on: new Date()
});
newProject.save();
let resObj = {
issue_title: newProject.issue_title,
issue_text: newProject.issue_text,
created_by: newProject.created_by,
assigned_to: newProject.assigned_to,
status_text: newProject.status_text,
open: newProject.open,
created_on: newProject.created_on,
updated_on: newProject.updated_on,
_id: newProject._id
};
res.json(resObj);
return;
};
})
.put( (req, res) => {
let project = req.params.project;
if (!req.body._id) {
res.json({ error: 'missing _id' });
return;
};
if (!req.body.issue_title &&
!req.body.issue_text &&
!req.body.created_by &&
!req.body.assigned_to &&
!req.body.status_text &&
!req.body.open) {
res.json({
error: 'no update field(s) sent',
_id: req.body._id
});
return;
};
projectModel.findById(req.body._id).then((data) => {
if (!data) {
res.json({ error: 'could not update', '_id': req.body._id });
return;
} else {
let updatedObj = {
issue_title: req.body.issue_title || data.issue_title,
issue_text: req.body.issue_text || data.issue_text,
created_by: req.body.created_by || data.created_by,
assigned_to: req.body.assigned_to || data.assigned_to,
status_text: req.body.status_text || data.status_text,
open: req.body.open || data.open,
updated_on: new Date()
};
projectModel.findByIdAndUpdate(req.body._id, updatedObj,
{new: true}).then((data) => {
res.json({ result: 'successfully updated',
'_id': req.body._id });
return;
});
};
});
})
.delete( (req, res) => {
let project = req.params.project;
if (!req.body._id) {
res.json({ error: 'missing _id' });
return;
};
projectModel.findByIdAndDelete(req.body._id).then((data) => {
if (!data) {
res.json({ error: 'could not delete', '_id': req.body._id });
return;
} else {
res.json({ result: 'successfully deleted',
'_id': req.body._id });
return;
};
});
});
};
The full console output is:
> fcc-issue-tracker@1.0.0 start
> node server.js
(node:36823) [MONGODB DRIVER] Warning: useNewUrlParser is a deprecated option: useNewUrlParser has no effect since Node.js Driver version 4.0.0 and will be removed in the next major version
(Use `node --trace-warnings ...` to show where the warning was created)
(node:36823) [MONGODB DRIVER] Warning: useUnifiedTopology is a deprecated option: useUnifiedTopology has no effect since Node.js Driver version 4.0.0 and will be removed in the next major version
Your app is listening on port 3000
Running Tests...
Functional Tests
Post request to /api/issues/{project}
✓ Create an issue with every field (668ms)
✓ Create an issue with only required fields (274ms)
✓ Create an issue with missing required fields (233ms)
Get request to /api/issues/{project}
✓ View issues on a project (911ms)
✓ View issues on a project with one filter (432ms)
(node:36823) [DEP0170] DeprecationWarning: The URL http://127.0.0.1:34185api/issues/test?issue_title=Test%20Issue&issue_text=Test%20Issue%20Text is invalid. Future versions of Node.js will throw an error.
1) View issues on a project with multiple filters
Put request to /api/issues/{project}
2) Update one field on an issue
✓ Update multiple fields on an issue (458ms)
{ error: 'missing _id' }
✓ Update an issue with missing _id (244ms)
✓ Update an issue with no fields to update (427ms)
3) Update an issue with an invalid _id
Delete request to /api/issues/{project}
✓ Delete an issue (310ms)
4) Delete an issue with an invalid _id
✓ Delete an issue with missing _id (261ms)
10 passing (6s)
4 failing
1) Functional Tests
Get request to /api/issues/{project}
View issues on a project with multiple filters:
Uncaught TypeError: Cannot read properties of undefined (reading 'status')
at /home/runner/project-issuetracker/tests/2_functional-tests.js:103:26
at Request.callback (node_modules/superagent/lib/node/index.js:728:3)
at ClientRequest.<anonymous> (node_modules/superagent/lib/node/index.js:647:10)
at Object.onceWrapper (node:events:626:26)
at ClientRequest.emit (node:events:511:28)
at Socket.socketErrorListener (node:_http_client:495:9)
at Socket.emit (node:events:511:28)
at emitErrorNT (node:internal/streams/destroy:151:8)
at emitErrorCloseNT (node:internal/streams/destroy:116:3)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
2) Functional Tests
Put request to /api/issues/{project}
Update one field on an issue:
Uncaught TypeError: Cannot read properties of undefined (reading 'status')
at /home/runner/project-issuetracker/tests/2_functional-tests.js:119:26
at Request.callback (node_modules/superagent/lib/node/index.js:728:3)
at ClientRequest.<anonymous> (node_modules/superagent/lib/node/index.js:647:10)
at Object.onceWrapper (node:events:626:26)
at ClientRequest.emit (node:events:511:28)
at Socket.socketErrorListener (node:_http_client:495:9)
at Socket.emit (node:events:511:28)
at emitErrorNT (node:internal/streams/destroy:151:8)
at emitErrorCloseNT (node:internal/streams/destroy:116:3)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
3) Functional Tests
Put request to /api/issues/{project}
Update an issue with an invalid _id:
Uncaught CastError: Cast to ObjectId failed for value "invalid id" (type string) at path "_id" for model "Project"
at SchemaObjectId.cast (node_modules/mongoose/lib/schema/objectId.js:250:11)
at SchemaType.applySetters (node_modules/mongoose/lib/schemaType.js:1219:12)
at SchemaType.castForQuery (node_modules/mongoose/lib/schemaType.js:1631:15)
at cast (node_modules/mongoose/lib/cast.js:375:32)
at Query.cast (node_modules/mongoose/lib/query.js:4769:12)
at Query._castConditions (node_modules/mongoose/lib/query.js:2200:10)
at model.Query._findOne (node_modules/mongoose/lib/query.js:2485:8)
at model.Query.exec (node_modules/mongoose/lib/query.js:4291:80)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
4) Functional Tests
Delete request to /api/issues/{project}
Delete an issue with an invalid _id:
Uncaught CastError: Cast to ObjectId failed for value "invalid id" (type string) at path "_id" for model "Project"
at SchemaObjectId.cast (node_modules/mongoose/lib/schema/objectId.js:250:11)
at SchemaType.applySetters (node_modules/mongoose/lib/schemaType.js:1219:12)
at SchemaType.castForQuery (node_modules/mongoose/lib/schemaType.js:1631:15)
at cast (node_modules/mongoose/lib/cast.js:375:32)
at Query.cast (node_modules/mongoose/lib/query.js:4769:12)
at Query._castConditions (node_modules/mongoose/lib/query.js:2200:10)
at model.Query._findOneAndDelete (node_modules/mongoose/lib/query.js:3384:8)
at model.Query.exec (node_modules/mongoose/lib/query.js:4291:80)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
Your browser information:
User agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
Challenge information:
Issue tracker
Link to the challenge: