Hi everyone!
I am at the end of this X-Press Course
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
> [email protected] 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!