X-Press 68 pass 2 Fail PUT / DELETE Errors

Hi everyone!

I am at the end of this X-Press Course

X-Press

I have run my tests and 68 out of 70 tests passed except 2 —

Here is the Terminal Results of (npm test)

DBP Post@DESKTOP-BP7QPD2 MINGW64 /z/Coding/X-Press/capstone-project-1-x-press-publishing
$ npm test

> x-press-publishing@1.0.0 test Z:\Coding\X-Press\capstone-project-1-x-press-publishing
> mocha



Listening on PORT: 8081
  Artist Table
    √ should exist
    √ should have name, date_of_birth, biography, and is_currently_employed columns with appropriate data types
    √ should have a required name column
    √ should have a required date_of_birth column
    √ should have a required biography column
    √ is_currently_employed should default to 1

  Series Table
    √ should exist
    √ should have id, name, and description columns with appropriate data types
    √ should have a required name column
    √ should have a required description column

  Issue Table
    √ should exist
    √ should have id, name, issue_number, publication_date, artist_id, and series_id columns with appropriate data types
    √ should have a required name column
    √ should have a required name column
    √ should have a required issue_number column
    √ should have a required publication_date column
    √ should have a required artist_id column
    √ should have a required series_id column

  GET /api/artists
GET /api/artists 200 2.375 ms - 242
    √ should return all currently-employed artists
GET /api/artists 200 0.508 ms - 242
    √ should return a status code of 200

  GET /api/artists/:id
GET /api/artists/2 200 0.734 ms - 127
    √ should return the artist with the given ID
GET /api/artists/2 200 0.413 ms - 127
    √ should return a 200 status code for valid IDs
GET /api/artists/999 404 0.320 ms - 9
    √ should return a 404 status code for invalid IDs

  POST /api/artists
POST /api/artists/ 201 4.044 ms - 127
    √ should create a valid artist
POST /api/artists/ 201 3.389 ms - 127
    √ should return a 201 status code after artist creation
POST /api/artists/ 201 2.835 ms - 127
    √ should return the newly-created artist after artist creation
POST /api/artists/ 201 2.906 ms - 127
    √ should set new artists as currently-employed by default
POST /api/artists/ 400 0.146 ms - 11
    √ should return a 400 status code for invalid artists

  PUT /api/artists/:id
PUT /api/artists/1 200 2.930 ms - 135
    √ should update the artist with the given ID
PUT /api/artists/1 200 3.542 ms - 135
    √ should return a 200 status code after artist update
PUT /api/artists/1 200 3.197 ms - 135
    √ should return the updated artist after artist update
PUT /api/artists/1 400 0.405 ms - 11
    √ should return a 400 status code for invalid artist updates

  DELETE /api/artists/:id
DELETE /api/artists/1 200 2.930 ms - 122
    √ should set the artist with the given ID as not currently-employed
DELETE /api/artists/1 200 2.823 ms - 122
    √ should return a 200 status code after artist delete
DELETE /api/artists/1 200 2.751 ms - 122
    √ should return the deleted artist after artist delete

  GET /api/series
GET /api/series 200 0.477 ms - 192
    √ should return all series
GET /api/series 200 0.422 ms - 192
    √ should return a status code of 200

  GET /api/series/:id
GET /api/series/2 200 0.530 ms - 70
    √ should return the series with the given ID
GET /api/series/2 200 0.315 ms - 70
    √ should return a 200 status code for valid IDs
GET /api/series/999 404 0.293 ms - 9
    √ should return a 404 status code for invalid IDs

  POST /api/series
POST /api/series/ 201 2.838 ms - 71
    √ should create a valid series
POST /api/series/ 201 2.679 ms - 71
    √ should return a 201 status code after series creation
POST /api/series/ 201 3.008 ms - 71
    √ should return the newly-created series after series creation
POST /api/series/ 400 0.138 ms - 11
    √ should return a 400 status code for invalid series

  PUT /api/series/:id
PUT /api/series/1 200 3.269 ms - 79
    √ should update the series with the given ID
PUT /api/series/1 200 2.901 ms - 79
    √ should return a 200 status code after series update
PUT /api/series/1 200 3.062 ms - 79
    √ should return the updated series after series update
PUT /api/series/1 400 0.406 ms - 11
    √ should return a 400 status code for invalid series updates

  DELETE /api/series/:id
DELETE /api/series/1 204 2.926 ms - -
    √ should remove the series with the specified ID from the database if that series has no related issues
DELETE /api/series/1 204 2.833 ms - -
    √ should return a 204 status code after series delete
DELETE /api/series/2 400 0.609 ms - 11
    √ should not delete series with existing related issues
DELETE /api/series/2 400 0.572 ms - 11
    √ should return a 400 status code if deleted series has existing related issues

  GET /api/series/:seriesId/issues
GET /api/series/2/issues 200 0.781 ms - 246
    √ should return all issues of an existing series
GET /api/series/1/issues 200 0.426 ms - 13
    √ should return an empty array for existing series with no issues
GET /api/series/2/issues 200 0.397 ms - 246
    √ should return a status code of 200 for valid series
GET /api/series/999/issues 404 0.220 ms - 9
    √ should return a status code of 404 for invalid series

  POST /api/series/:seriesId/issues
POST /api/series/2/issues 201 3.047 ms - 119
    √ should create a valid issue
POST /api/series/2/issues 201 4.048 ms - 119
    √ should return a 201 status code after issue creation
POST /api/series/2/issues 201 3.142 ms - 119
    √ should return the newly-created issue after issue creation
POST /api/series/2/issues 400 0.704 ms - 11
    √ should return a 400 status code for invalid issues
POST /api/series/2/issues 400 1.267 ms - 11
    √ should return a 400 status code if an artist with the issue's artist ID doesn't exist

  PUT /api/series/:seriesId/issues/:issueId
PUT /api/series/2/issues/1 200 3.413 ms - 123
    √ should update the issue with the given ID
PUT /api/series/2/issues/1 200 3.244 ms - 123
    √ should return a 200 status code after issue update
PUT /api/series/2/issues/1 200 3.266 ms - 123
    √ should return the updated issue after issue update
PUT /api/series/2/issues/999 400 0.652 ms - 11
    1) should return a 404 status code for invalid issue IDs
PUT /api/series/2/issues/1 400 0.590 ms - 11
    √ should return a 400 status code for invalid issue updates
PUT /api/series/2/issues/1 400 0.651 ms - 11
    √ should return a 400 status code if an artist with the updated artist ID doesn't exist

  DELETE /api/series/:seriesId/issues/:issueId
DELETE /api/series/2/issues/1 204 3.337 ms - -
    √ should remove the issue with the specified ID from the database
DELETE /api/series/2/issues/1 204 2.943 ms - -
    √ should return a 204 status code after issue delete
DELETE /api/series/2/issues/999 204 0.676 ms - -
    2) should return a 404 status code for invalid issue IDs


  68 passing (859ms)
  2 failing

  1) PUT /api/series/:seriesId/issues/:issueId should return a 404 status code for invalid issue IDs:
     Error: expected 404 "Not Found", got 400 "Bad Request"
      at Test._assertStatus (node_modules\supertest\lib\test.js:268:12)
      at Test._assertFunction (node_modules\supertest\lib\test.js:283:11)
      at Test.assert (node_modules\supertest\lib\test.js:173:18)
      at Server.localAssert (node_modules\supertest\lib\test.js:131:12)
      at emitCloseNT (net.js:1659:8)
      at processTicksAndRejections (internal/process/task_queues.js:79:21)

  2) DELETE /api/series/:seriesId/issues/:issueId should return a 404 status code for invalid issue IDs:
     Error: expected 404 "Not Found", got 204 "No Content"
      at Test._assertStatus (node_modules\supertest\lib\test.js:268:12)
      at Test._assertFunction (node_modules\supertest\lib\test.js:283:11)
      at Test.assert (node_modules\supertest\lib\test.js:173:18)
      at Server.localAssert (node_modules\supertest\lib\test.js:131:12)
      at emitCloseNT (net.js:1659:8)
      at processTicksAndRejections (internal/process/task_queues.js:79:21)



npm ERR! Test failed.  See above for more details.

Here is my code below:

server.js

const bodyParser = require('body-parser');
const cors = require('cors');
const errorhandler = require('errorhandler');
const express = require('express');
const morgan = require('morgan');
const apiRouter = require('./api/api');

const app = express();
const PORT = process.env.PORT || 4000;

app.use(bodyParser.json());
app.use(cors());
app.use(morgan('dev'));

app.use('/api', apiRouter);

app.use(errorhandler());

app.listen(PORT, () => {
    console.log(`Listening on PORT: ${PORT}`);
});

module.exports = app;

api.js

const express = require('express');
const apiRouter = express.Router();
const artistsRouter = require('./artists.js');
const seriesRouter = require('./series.js');

apiRouter.use('/artists', artistsRouter);
apiRouter.use('/series', seriesRouter);

module.exports = apiRouter;

migration.js

const sqlite3 = require('sqlite3');
const db = new sqlite3.Database('./database.sqlite');
//Create Artist Table
 db.serialize(function() {
     db.run('CREATE TABLE IF NOT EXISTS `Artist` ( ' + 
        '`id` INTEGER NOT NULL, ' +
        '`name` TEXT NOT NULL, ' +
        '`date_of_birth` TEXT NOT NULL, ' +
        '`biography` TEXT NOT NULL, ' +
        '`is_currently_employed` INTEGER NOT NULL DEFAULT 1, ' +
        'PRIMARY KEY(`id`) )' );

//Create Series Table
        db.run('CREATE TABLE IF NOT EXISTS `Series` ( ' +
        '`id` INTEGER NOT NULL, ' +
        '`name` TEXT NOT NULL, ' +
        '`description` TEXT NOT NULL, ' +
        'PRIMARY KEY(`id`) )');

//Create Issue's Table 45
        db.run('CREATE TABLE IF NOT EXISTS `Issue` ( ' +
        '`id` INTEGER NOT NULL,' +
        '`name` TEXT NOT NULL, ' +
        '`issue_number` INTEGER NOT NULL,' +
        '`publication_date` TEXT NOT NULL,' +
        '`artist_id` INTEGER NOT NULL,' +
        '`series_id` INTEGER NOT NULL,' +
        'PRIMARY KEY(`id`), ' +
        'FOREIGN KEY(`artist_id`) REFERENCES `Artist`(`id`), ' +
        'FOREIGN KEY(`series_id`) REFERENCES `Series`(`id`) )');
 });

artists.js

const express = require('express');
const artistsRouter = express.Router();

const sqlite3 = require('sqlite3');
const db = new sqlite3.Database(process.env.TEST_DATABASE || './database.sqlite');

// app.param()
artistsRouter.param('artistId', (req, res, next, artistId) => {
    const sql = 'SELECT * FROM Artist WHERE Artist.id = $artistId';
    const values = {$artistId: artistId};
    db.get(sql, values, (error, artist) => {
        if (error) {
            next(error);
        } else if (artist) {
            req.artist = artist;
            next();
        } else {
            res.sendStatus(404);
        }
    });
})


// artists currently employed?
artistsRouter.get('/', (req, res, next) => {
    db.all('SELECT * FROM Artist WHERE Artist.is_currently_employed = 1', (err, artists) => {
        if (err) {
            next(err);
          } else {
            res.status(200).json({artists: artists});
          }
    });
});
// GET -- this reads the relevant path and displays it
artistsRouter.get('/:artistId', (req, res, next) => {
    res.status(200).json({artist: req.artist});
})
// POST -- Creating a new field for the Artist table status (201)(created)
artistsRouter.post('/', (req, res, next) => {
    const name = req.body.artist.name;
    const dateOfBirth = req.body.artist.dateOfBirth;
    const biography = req.body.artist.biography;
    const isCurrentlyEmployed = req.body.artist.isCurrentlyEmployed === 0 ? 0 : 1;
    if (!name || !dateOfBirth || !biography) {
        return res.sendStatus(400);
    }

    const sql = 'INSERT INTO Artist (name, date_of_birth, biography, is_currently_employed) VALUES ($name, $dateOfBirth, $biography, $isCurrentlyEmployed)';
    const values = {
        $name: name,
        $dateOfBirth: dateOfBirth,
        $biography: biography,
        $isCurrentlyEmployed: isCurrentlyEmployed
    };

    db.run(sql, values, function(error) {
        if (error) {
            next(error);
        } else {
            db.get(`SELECT * FROM Artist WHERE Artist.id = ${this.lastID}`,
            (error, artist) => {
                res.status(201).json({artist: artist});
            });
        }
    })
});
// PUT -- Update/Replace artist table by artistId -- updates the relavant artists fields -- after if ! (not) required fields send back status of (400) NOT FOUND - This way we know the selected artist has been removed??
artistsRouter.put('/:artistId', (req, res, next) => {
    const name = req.body.artist.name;
    const dateOfBirth = req.body.artist.dateOfBirth;
    const biography = req.body.artist.biography;
    const isCurrentlyEmployed = req.body.artist.isCurrentlyEmployed === 0 ? 0 : 1;
    if (!name || !dateOfBirth || !biography) {
        return res.sendStatus(400);
    }
const sql = 'UPDATE Artist SET name = $name, date_of_birth = $dateOfBirth, biography = $biography, is_currently_employed = $isCurrentlyEmployed WHERE Artist.id = $artistId';
const values = {
    $name: name,
    $dateOfBirth: dateOfBirth,
    $biography: biography,
    $isCurrentlyEmployed: isCurrentlyEmployed,
    $artistId: req.params.artistId
};
 
db.run(sql, values, (error) => {
    if (error) {
        next(error);
    }else {
        db.get(`SELECT * FROM Artist WHERE Artist.id = ${req.params.artistId}`,
        
        (error, artist) => {
            res.status(200).json({artist: artist});
        });
    }
  }); 
});
// delete artist by id logic
artistsRouter.delete('/:artistId', (req, res, next) => {
    const sql = 'UPDATE Artist SET is_currently_employed = 0 WHERE Artist.id = $artistId';
    const values = {$artistId: req.params.artistId};
//db.run() sql, values & error // if/else --- error / else -- grabs and deletes artist by id requested with req.params.artistId -- sends back a status of (200).json for artist requested..
    db.run(sql, values, (error) => {
        if (error) {
            next(error);
        } else {
            db.get(`SELECT * FROM Artist WHERE Artist.id = ${req.params.artistId}`,
            (error, artist) => {
                res.status(200).json({artist: artist});
            });
        }
    });
});

module.exports = artistsRouter;

issues.js

const express = require('express');
const issuesRouter = express.Router({mergeParams: true});

const sqlite3 = require('sqlite3');
const db = new sqlite3.Database(process.env.TEST_DATABASE || './database.sqlite');

issuesRouter.param('issuesId', (req, res, next, userId) => {
  const sql = 'SELECT* FROM Issue WHERE Issue.id = $issueId';
  const values = {$issueId: issueId};
  db.get(sql, values, (error, issue) => {
    if (error) {
      next(error);
    } else if (issue) {
      next();
    } else {
      res.sendStatus(404);
    }
  })
})

issuesRouter.get('/', (req, res, next) => {
    const sql = 'SELECT * FROM Issue WHERE Issue.series_id = $seriesId';
    const values = { $seriesId: req.params.seriesId};
    db.all(sql, values, (error, issues) => {
      if (error) {
        next(error);
      } else {
        res.status(200).json({issues: issues});
      }
    });
  });
//49
  issuesRouter.post('/', (req, res, next) => {
    const name = req.body.issue.name,
          issueNumber = req.body.issue.issueNumber,
          publicationDate = req.body.issue.publicationDate,
          artistId = req.body.issue.artistId;
    const artistSql = 'SELECT * FROM Artist WHERE Artist.id = $artistId';
    const artistValues = {$artistId: artistId};
    db.get(artistSql, artistValues, (error, artist) => {
      if (error) {
        next(error);
      } else {
        if (!name || !issueNumber || !publicationDate || !artist) {
          return res.sendStatus(400);
        }
  
        const sql = 'INSERT INTO Issue (name, issue_number, publication_date, artist_id, series_id)' +
            'VALUES ($name, $issueNumber, $publicationDate, $artistId, $seriesId)';
        const values = {
          $name: name,
          $issueNumber: issueNumber,
          $publicationDate: publicationDate,
          $artistId: artistId,
          $seriesId: req.params.seriesId
        };
  
        db.run(sql, values, function(error) {
          if (error) {
            next(error);
          } else {
            db.get(`SELECT * FROM Issue WHERE Issue.id = ${this.lastID}`,
              (error, issue) => {
                res.status(201).json({issue: issue});
              });
          }
        });
      }
    });
  });

  issuesRouter.put('/:issueId', (req, res, next) => {
    const name = req.body.issue.name,
          issueNumber = req.body.issue.issueNumber,
          publicationDate = req.body.issue.publicationDate,
          artistId = req.body.issue.artistId;
    const artistSql = 'SELECT * FROM Artist WHERE Artist.id = $artistId';
    const artistValues = {$artistId: artistId};
    db.get(artistSql, artistValues, (error, artist) => {
      if (error) {
        next(error);
      } else {
        if (!name || !issueNumber || !publicationDate || !artist) {
          return res.sendStatus(400);
        }
  
        const sql = 'UPDATE Issue SET name = $name, issue_number = $issueNumber, ' +
            'publication_date = $publicationDate, artist_id = $artistId ' +
            'WHERE Issue.id = $issueId';
        const values = {
          $name: name,
          $issueNumber: issueNumber,
          $publicationDate: publicationDate,
          $artistId: artistId,
          $issueId: req.params.issueId
        };
  
        db.run(sql, values, function(error) {
          if (error) {
            next(error);
          } else {
            db.get(`SELECT * FROM Issue WHERE Issue.id = ${req.params.issueId}`,
              (error, issue) => {
                res.status(200).json({issue: issue});
              });
          }
        });
      }
    });
  });

  //52: Delete Request

  issuesRouter.delete('/:issueId', (req, res, next) => {
  const sql = 'DELETE FROM Issue WHERE Issue.id = $issueId';
  const values = {$issueId: req.params.issueId};

  db.run(sql, values, (error) => {
    if (error) {
      next(error);
    } else {
      res.sendStatus(204);
    }
  });
});


module.exports = issuesRouter;

series.js

const express = require('express');
const seriesRouter = express.Router();

const sqlite3 = require('sqlite3');
const db = new sqlite3.Database(process.env.TEST_DATABASE || './database.sqlite');

const issuesRouter = require('./issues.js');

// Step 41
seriesRouter.param('seriesId', (req, res, next, seriesId) => {
    const sql = 'SELECT * FROM Series WHERE Series.id = $seriesId';
    const values = {$seriesId: seriesId};
    db.get(sql, values, (error, series) => {
        if (error) {
            next(error);
        } else if (series) {
            req.series = series;
            next();
        } else {
            res.sendStatus(404);
        }
    });
});

seriesRouter.use('/:seriesId/issues', issuesRouter);

seriesRouter.get('/', (req, res, next) => {
    db.all('SELECT * FROM Series', (err, series) => {
      if (err) {
        next(err);
      } else {
        res.status(200).json({series: series});
      }
    });
  });
// 42
seriesRouter.get('/:seriesId', (req, res, next) => {
    res.status(200).json({series: req.series});
});
//43
seriesRouter.post('/', (req, res, next) => {
    const name = req.body.series.name,
    description = req.body.series.description;
    if (!name || !description) {
        return res.sendStatus(400);
    }
const sql = 'INSERT INTO Series (name, description) VALUES ($name, $description)';
const values = {
    $name: name,
    $description: description
    };
db.run(sql, values, function(error) {
    if (error) {
        next(error);
    } else {
        db.get(`SELECT * FROM Series WHERE Series.id = ${this.lastID}`,
        (error, series) => {
            res.status(201).json({series: series});
            });
        }
    });
});

// 44

seriesRouter.put('/:seriesId', (req, res, next) => {
    const name = req.body.series.name,
          description = req.body.series.description;
    if (!name || !description) {
      return res.sendStatus(400);
    }
  
    const sql = 'UPDATE Series SET name = $name, description = $description ' +
        'WHERE Series.id = $seriesId';
    const values = {
      $name: name,
      $description: description,
      $seriesId: req.params.seriesId
    };
  
    db.run(sql, values, (error) => {
      if (error) {
        next(error);
      } else {
        db.get(`SELECT * FROM Series WHERE Series.id = ${req.params.seriesId}`,
          (error, series) => {
            res.status(200).json({series: series});
          });
      }
    });
  });


seriesRouter.post('/', (req, res, next) => {
    const name = req.body.series.name,
    description = req.body.series.description;
    if (!name || !description) {
        return res.sendStatus(400);
    }
    const sql = 'INSERT INTO Series (name, description) VALUES ($name, $description)';
    const values = {
        $name: name,
        $description: description
    };

    db.run(sql, values, function(error) {
        if (error) {
            next(error);
        } else {
            db.get(`SELECT * FROM Series WHERE Series.id = ${this.lastID}`,
            (error, series) => {
                res.status(201).json({series: series});
            });
        }
    });
});


seriesRouter.delete('/:seriesId', (req, res, next) => {
    const issueSql = 'SELECT * FROM Issue WHERE Issue.series_id = $seriesId';
    const issueValues = {$seriesId: req.params.seriesId};
    db.get(issueSql, issueValues, (error, issue) => {
      if (error) {
        next(error);
      } else if (issue) {
        res.sendStatus(400);
      } else {
        const deleteSql = 'DELETE FROM Series WHERE Series.id = $seriesId';
        const deleteValues = {$seriesId: req.params.seriesId};
  
        db.run(deleteSql, deleteValues, (error) => {
          if (error) {
            next(error);
          } else {
            res.sendStatus(204);
          }
        });
      }
    });
  });

module.exports = seriesRouter;

I have decided to move on with the course in the mean time as I cant waste any more time on this right now! I hope some one can help me with this problem!

Thanks in advance and happy coding!