Issue Tracker - Res is undefined in route tests

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:

  1. View issues on a project with multiple filters
  2. Update one field on an issue
  3. Update an issue with an invalid _id
  4. 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:

1 Like

use .get('/api/issues/test') .

1 Like

the same , you are mising /

1 Like

Thank you @zaklina! Sometimes it just takes a fresh set of eyes!

As for the second error I was having with:

  1. Update an issue with an invalid _id
  2. Delete an issue with an invalid _id

The error was:

 Uncaught CastError: Cast to ObjectId failed for value "" (type string) at path "" for model ""

(everything in the “” are custom names that would vary by your code).

I went with the solution from here: mongodb - What's Mongoose error Cast to ObjectId failed for value XXX at path "_id"? - Stack Overflow

With MongoDB, object Id seems to need to be 12 bites or 24 characters in hex representation, so when I was passing an ID string that was not that length, it was throwing an error.

The solution was to wrap an if/else statement around my findById and findByIdAndDelete calls requiring an ID that was 24 hex characters:

// check that id matches ObjectId format
      if (req.body._id.match(/^[0-9a-fA-F]{24}$/)) {

        // find issue in db by id and delete
        projectModel
        .findByIdAndDelete(req.body._id)
        .then((data) => {

          // return response for id not found
          if (!data) {
            res.json({ 
              error: 'could not delete', 
              _id: req.body._id 
            });
            return;
            
          } else {
            // return response found and deleted
            res.json({ 
              result: 'successfully deleted', 
              _id: req.body._id 
            });
            return;
          };
          
        });
        
      } else {
        // return response if id was not ObjectId format
        res.json({ 
          error: 'could not delete', 
          _id: req.body._id 
        });
        return;
      };

I would like to find a way to handle the case where I don’t repeat the “could not delete” return response, but I’m calling it good enough.

1 Like

So first two errors solved by adding ‘/’ to ‘/api/issues/test’ in the functional tests:

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) => {
        console.log(res.body._id);
        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')
});

And second two errors solved by adding wrapped function around variations of findbyid in the routes to check that id’s were 24 hex characters long:

'use strict';

const projectModel = require('../models').projectModel

module.exports = (app) => {

  app.route('/api/issues/:project')

    // get issues of a project
    .get( (req, res) => {
      let project = req.params.project;

      // get 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 };

      // add query params to query object
      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
      };

      // filter issues by project and query params
      projectModel.find(queryObj).then((data) => {
        res.json(data);
        return;
      });
      
    })

    // create a new issue
    .post( (req, res) => {
      let project = req.params.project;

      // return response for missing required fields
      if (!req.body.issue_title || 
          !req.body.issue_text || 
          !req.body.created_by) {
        res.json({ 
          error: 'required field(s) missing' 
        });
        return;
        
      } else {
        // create issue and send to db
        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();

        // respond with issue, minus project title
        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;
        
      };
     
    })

    // update an issue
    .put( (req, res) => {
      
      // return response for missing _id
      if (!req.body._id) {
        res.json({ 
          error: 'missing _id' 
        });
        return;
      };

      // return response for no fields to update
      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;
      };

      // check that id matches ObjectId format
      if (req.body._id.match(/^[0-9a-fA-F]{24}$/)) {

        // find issue in db by id
        projectModel.findById(req.body._id).then((data) => {

          // return response for id not found
          if (!data) {
            res.json({ 
              error: 'could not update', 
              _id: req.body._id 
            });
            return;
            
          } else {
            // create updated issue object and replace in db
            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(() => {
              res.json({ 
                result: 'successfully updated', 
                _id: req.body._id 
              });
              return;
            });
            
          };
        });
        
      } else {
        // return response if id was not ObjectId format
        res.json({ 
          error: 'could not update', 
          _id: req.body._id 
        });
        return;
      };
    })

    // removing an issue
    .delete( (req, res) => { 
      
      // return response for missing _id
      if (!req.body._id) {
        res.json({ 
          error: 'missing _id' 
        });
        return;
      };

      // check that id matches ObjectId format
      if (req.body._id.match(/^[0-9a-fA-F]{24}$/)) {

        // find issue in db by id and delete
        projectModel
        .findByIdAndDelete(req.body._id)
        .then((data) => {

          // return response for id not found
          if (!data) {
            res.json({ 
              error: 'could not delete', 
              _id: req.body._id 
            });
            return;
            
          } else {
            // return response found and deleted
            res.json({ 
              result: 'successfully deleted', 
              _id: req.body._id 
            });
            return;
          };
          
        });
        
      } else {
        // return response if id was not ObjectId format
        res.json({ 
          error: 'could not delete', 
          _id: req.body._id 
        });
        return;
      };
      
    });
};

That’s all!

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.