Quality Assurance Projects - Issue Tracker

Tell us what’s happening:

I have a problem with the issue tracker project. Some of the requirements are not passing and the test cases are also not passing (on the freeCodeCamp URI, but they pass on the gitpod URL).

Your project link(s)

solution: https://3000-freecodecam-boilerplate-ay7esjo30rx.ws-eu116.gitpod.io

Your browser information:

User Agent is: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36

Challenge Information:

Quality Assurance Projects - Issue Tracker

Code files

Here are my code files I edited

.env

PORT=3000
# NODE_ENV=test

routes/api.js

'use strict';

module.exports = function (app) {
  const issues = [];

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

    .get(function (req, res) {
      let project = req.params.project;
      const filters = req.query;
      let result = issues.filter(issue => issue.project === project);
      result = result.filter(issue => {
        return Object.keys(filters).every(key => issue[key] == filters[key]);
      });
      res.json(result);
    })

    .post(function (req, res) {
      let project = req.params.project;
      const { issue_title, issue_text, created_by, assigned_to, status_text } = req.body;
    
      if (!issue_title || !issue_text || !created_by) {
        return res.json({ error: 'required field(s) missing' });
      }
    
  
      const newIssue = {
        _id: issues.length + 1,
        project,
        issue_title,
        issue_text,
        created_by,
        assigned_to: assigned_to || '',
        status_text: status_text || '',
        open: true,
        created_on: new Date(),
        updated_on: new Date(),
      };
    
      issues.push(newIssue);
    
      res.json(newIssue);
    })
    

    .put(function (req, res) {
      let project = req.params.project;
      const { _id, issue_title, issue_text, created_by, assigned_to, status_text, open } = req.body;
      if (!_id) {
        return res.json({ error: 'missing _id' });
      }
      const issue = issues.find(i => i._id == _id && i.project === project);
      if (!issue) {
        return res.json({ error: 'could not update', _id });
      }
      if (!issue_title && !issue_text && !created_by && !assigned_to && !status_text && open === undefined) {
        return res.json({ error: 'no update field(s) sent', _id });
      }
      Object.assign(issue, {
        issue_title: issue_title || issue.issue_title,
        issue_text: issue_text || issue.issue_text,
        created_by: created_by || issue.created_by,
        assigned_to: assigned_to || issue.assigned_to,
        status_text: status_text || issue.status_text,
        open: open !== undefined ? open : issue.open,
        updated_on: new Date(),
      });
      res.json({ result: 'successfully updated', _id });
    })

    .delete(function (req, res) {
      let project = req.params.project;
      const { _id } = req.body;
      if (!_id) {
        return res.json({ error: 'missing _id' });
      }
      const index = issues.findIndex(i => i._id == _id && i.project === project);
      if (index === -1) {
        return res.json({ error: 'could not delete', _id });
      }
      issues.splice(index, 1);
      res.json({ result: 'successfully deleted', _id });
    });
};

tests/2_functional-tests.js

const chaiHttp = require('chai-http');
const chai = require('chai');
const assert = chai.assert;
const server = require('../server');

chai.use(chaiHttp);

suite('Functional Tests', function () {

    suite('POST /api/issues/{project}', function () {
      test('Create an issue with every field', function (done) {
        chai.request(server)
          .post('/api/issues/test')
          .send({
            issue_title: 'Test Issue',
            issue_text: 'Functional Test',
            created_by: 'Tester',
            assigned_to: 'Dev',
            status_text: 'In Progress'
          })
          .end(function (err, res) {
            assert.equal(res.status, 200);
            assert.equal(res.body.issue_title, 'Test Issue');
            done();
          });
      });
  
      test('Create an issue with only required fields', function (done) {
        chai.request(server)
          .post('/api/issues/test')
          .send({
            issue_title: 'Test Issue',
            issue_text: 'Functional Test',
            created_by: 'Tester'
          })
          .end(function (err, res) {
            assert.equal(res.status, 200);
            assert.equal(res.body.issue_title, 'Test Issue');
            done();
          });
      });
  
      test('Create an issue with missing required fields', function (done) {
        chai.request(server)
          .post('/api/issues/test')
          .send({
            issue_title: 'Test Issue'
          })
          .end(function (err, res) {
            assert.equal(res.status, 200);
            assert.equal(res.body.error, 'required field(s) missing');
            done();
          });
      });
    });
  
    suite('GET /api/issues/{project}', function () {
      test('View issues on a project', function (done) {
        chai.request(server)
          .get('/api/issues/test')
          .end(function (err, res) {
            assert.equal(res.status, 200);
            assert.isArray(res.body);
            done();
          });
      });
  
      test('View issues on a project with one filter', function (done) {
        chai.request(server)
          .get('/api/issues/test')
          .query({ created_by: 'Tester' })
          .end(function (err, res) {
            assert.equal(res.status, 200);
            assert.isArray(res.body);
            done();
          });
      });
  
      test('View issues on a project with multiple filters', function (done) {
        chai.request(server)
          .get('/api/issues/test')
          .query({ created_by: 'Tester', status_text: 'In Progress' })
          .end(function (err, res) {
            assert.equal(res.status, 200);
            assert.isArray(res.body);
            done();
          });
      });
    });
  
    suite('PUT /api/issues/{project}', function () {
      test('Update one field on an issue', function (done) {
        chai.request(server)
          .put('/api/issues/test')
          .send({ _id: 1, issue_title: 'Updated Issue' })
          .end(function (err, res) {
            assert.equal(res.status, 200);
            assert.equal(res.body.result, 'successfully updated');
            done();
          });
      });
  
      test('Update multiple fields on an issue', function (done) {
        chai.request(server)
          .put('/api/issues/test')
          .send({ _id: 1, issue_title: 'Updated Issue', assigned_to: 'Updated Dev' })
          .end(function (err, res) {
            assert.equal(res.status, 200);
            assert.equal(res.body.result, 'successfully updated');
            done();
          });
      });
  
      test('Update an issue with missing _id', function (done) {
        chai.request(server)
          .put('/api/issues/test')
          .send({ issue_title: 'Updated Issue' })
          .end(function (err, res) {
            assert.equal(res.status, 200);
            assert.equal(res.body.error, 'missing _id');
            done();
          });
      });
  
      test('Update an issue with no fields to update', function (done) {
        chai.request(server)
          .put('/api/issues/test')
          .send({ _id: 1 })
          .end(function (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', function (done) {
        chai.request(server)
          .put('/api/issues/test')
          .send({ _id: 999, issue_title: 'Updated Issue' })
          .end(function (err, res) {
            assert.equal(res.status, 200);
            assert.equal(res.body.error, 'could not update');
            done();
          });
      });
    });
  
    suite('DELETE /api/issues/{project}', function () {
      test('Delete an issue', function (done) {
        chai.request(server)
          .delete('/api/issues/test')
          .send({ _id: 1 })
          .end(function (err, res) {
            assert.equal(res.status, 200);
            assert.equal(res.body.result, 'successfully deleted');
            done();
          });
      });
  
      test('Delete an issue with an invalid _id', function (done) {
        chai.request(server)
          .delete('/api/issues/test')
          .send({ _id: 999 })
          .end(function (err, res) {
            assert.equal(res.status, 200);
            assert.equal(res.body.error, 'could not delete');
            done();
          });
      });
  
      test('Delete an issue with missing _id', function (done) {
        chai.request(server)
          .delete('/api/issues/test')
          .send({})
          .end(function (err, res) {
            assert.equal(res.status, 200);
            assert.equal(res.body.error, 'missing _id');
            done();
          });
      });
    });
  
  });
 

Traceback on freeCodeCamp UI

// running tests
3. The POST request to /api/issues/{projectname} will return the created object, and must include all of the submitted fields. Excluded optional fields will be returned as empty strings. Additionally, include created_on (date/time), updated_on (date/time), open (boolean, true for open - default value, false for closed), and _id.
7. You can send a PUT request to /api/issues/{projectname} with an _id and one or more fields to update. On success, the updated_on field should be updated, and returned should be {  result: 'successfully updated', '_id': _id }.
9. When the PUT request sent to /api/issues/{projectname} does not include update fields, the return value is { error: 'no update field(s) sent', '_id': _id }. On any other error, the return value is { error: 'could not update', '_id': _id }.
10. You can send a DELETE request to /api/issues/{projectname} with an _id to delete an issue. If no _id is sent, the return value is { error: 'missing _id' }. On success, the return value is { result: 'successfully deleted', '_id': _id }. On failure, the return value is { error: 'could not delete', '_id': _id }.
11. All 14 functional tests are complete and passing.
// tests completed
// console output
[Error: .empty was passed non-string primitive 2]
[Error: expected { Object (result, _id) } to deeply equal { Object (result, _id) }]
[Error: expected { error: 'could not update', …(1) } to deeply equal { …(2) }]
[Error: expected { Object (result, _id) } to deeply equal { Object (result, _id) }]
[Error: expected { status: 'unavailable' } to be an array]

Thank you very much for your help!

Here is what comes back for your solution link: This 3000-freecodecam-boilerplate-ay7esjo30rx.ws-eu116.gitpod.io page can’t be found. Note:According to the docs gitpod times out or closes after 30 mins.

I reinitiated it. Therefore I also shared the code. Do you have any idea what is going wrong here?

I can see your running an api with server.js why its not passing I have no Idea at this point. Your code says all passed except you still have a bunch of errors, is this correct?

Yes indeed.

The errors I am receiving are those here

// running tests
3. The POST request to /api/issues/{projectname} will return the created object, and must include all of the submitted fields. Excluded optional fields will be returned as empty strings. Additionally, include created_on (date/time), updated_on (date/time), open (boolean, true for open - default value, false for closed), and _id.
7. You can send a PUT request to /api/issues/{projectname} with an _id and one or more fields to update. On success, the updated_on field should be updated, and returned should be {  result: 'successfully updated', '_id': _id }.
9. When the PUT request sent to /api/issues/{projectname} does not include update fields, the return value is { error: 'no update field(s) sent', '_id': _id }. On any other error, the return value is { error: 'could not update', '_id': _id }.
10. You can send a DELETE request to /api/issues/{projectname} with an _id to delete an issue. If no _id is sent, the return value is { error: 'missing _id' }. On success, the return value is { result: 'successfully deleted', '_id': _id }. On failure, the return value is { error: 'could not delete', '_id': _id }.
11. All 14 functional tests are complete and passing.
// tests completed
// console output
[Error: .empty was passed non-string primitive 2]
[Error: expected { Object (result, _id) } to deeply equal { Object (result, _id) }]
[Error: expected { error: 'could not update', …(1) } to deeply equal { …(2) }]
[Error: expected { Object (result, _id) } to deeply equal { Object (result, _id) }]
[Error: expected { status: 'unavailable' } to be an array]

I am unsure where to start.

Do you have the source code for this project or the repository link?

I added the three files I edited in the first post of this issue, i.e. .env, routes/api.js and tests/2_functional-tests.js. Is there anything else you would need apart from that? If it helps, I can also make a git repo with all files.

  1. The test expects the id to be a string so it can check the length (indirectly using an empty/not empty check which relies on a length property). So it can’t be a number.

  2. Your could not update response will prevent your no update field(s) sent from running. Switch the order of the two conditions.

I entered the solution and passed like half of the test but not a source code link.

Thank you that helped sorting me out my problems! :slight_smile: I appreciate your assistance very much <3

1 Like

No problem, happy to help.

The id one had me stumped for a bit, the error isn’t super obvious. Not sure I would have found it without looking at the tests.