Hi,
I finished the project and it works as expected.
When I test my project link on the FCC project page though it fails to pass these test:
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 }.
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 }.
With the following errors:
[Error: expected undefined to be an object]
[Error: expected { error: 'could not update', …(1) } to deeply equal { …(2) }]
I’m really stuck cause I don’t understand what is happening.
Here’s the project link to test:
Emi Issue Tracker
Here’s my api.js:
"use strict";
const mongoose = require("mongoose");
// connect to DB
mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
// create project Schema
const projectSchema = new mongoose.Schema(
{
title: {
type: String,
required: true,
},
issues: Array,
},
{ versionKey: false },
); // avoid the attribute "_v" when creating doc
// create project Model
const ProjectModel = new mongoose.model("Project", projectSchema);
// create issue Schema
const issueSchema = new mongoose.Schema(
{
issue_title: {
type: String,
required: true,
},
issue_text: {
type: String,
required: true,
},
created_on: {
type: Date,
default: new Date(Date.now()).toISOString(),
},
updated_on: {
type: Date,
default: new Date(Date.now()).toISOString(),
},
created_by: {
type: String,
required: true,
},
assigned_to: {
type: String,
required: false,
default: "",
},
open: {
type: Boolean,
default: true,
},
status_text: {
type: String,
required: false,
default: "",
},
},
{ versionKey: false },
); // avoid the attribute "_v" when creating doc
// create issue Model
const IssueModel = new mongoose.model("Issue", issueSchema);
// function to set 'true'/'false' to boolean
function fixBoolean(obj) {
for (const [filter, value] of Object.entries(obj)) {
if (value === "true") {
obj[filter] = true;
} else if (value === "false") {
obj[filter] = false;
}
}
return obj;
}
module.exports = function (app) {
app
.route("/api/issues/:project")
.get(function (req, res) {
let project = req.params.project;
// if there are no filters return false else return obj with filters
let filters =
Object.keys({ ...req.query }).length === 0
? false
: fixBoolean({ ...req.query });
// number of criterias to satisfy
let criterias = Object.keys(filters).length;
ProjectModel.findOne({ title: project }).then((data) => {
// if project found
if (data) {
console.log("\nProject found!");
// if filters active
if (filters) {
console.log("Filters found! ->", filters);
// for every issue in project
let filteredArr = data.issues.filter((item, i) => {
console.log(
"\nChecking issue",
i + 1,
"of",
data.issues.length,
"\n",
);
let count = 0;
// loop through issue keys and compare it to filters key
for (const [filter, value] of Object.entries(item)) {
// if filter is matching with issue values
if (item[filter] === filters[filter]) {
count++;
console.log(
filter,
item[filter],
"correspond to",
filter,
filters[filter],
"✅",
" (",
count,
"/",
criterias,
")",
);
if (count === criterias) {
// if all the filter criterias are met add issues to the arr
console.log(
"\n✅✅✅ All filters match this issue, adding to array... ✅✅✅ ",
);
return item;
}
} else {
console.log(
filter,
item[filter],
"does not correspond to",
filter,
filters[filter],
"❌",
);
}
}
});
res.json(filteredArr);
} else {
// else return all issues
res.json(data.issues);
}
} else {
// create new project
console.log("Project not found, creating a new one...");
let new_project = new ProjectModel({
title: project,
issues: [],
});
// save project in DB
new_project.save().then((data) => {
console.log("Project added!");
// send response
res.json(data.issues);
});
}
});
})
.post(function (req, res) {
let project = req.params.project;
// find project
ProjectModel.findOne({ title: project }).then((currentProject) => {
// create new issue
let issue = new IssueModel({
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,
});
// if project found
if (currentProject) {
// save issue
issue.save().then(
(data) => {
// push new issue in project
currentProject.issues.push(data);
currentProject.save();
// return created issue
res.json(data);
},
(error) => {
res.json({ error: "required field(s) missing" });
},
);
} else {
// create new project
console.log("Project not found, creating a new one...");
let new_project = new ProjectModel({
title: project,
issues: [],
});
// save project in DB
new_project.save().then((newProject) => {
console.log("Project added!");
// save issue
issue.save().then(
(data) => {
// push new issue in project
newProject.issues.push(data);
newProject.save();
// return created issue
res.json(data);
},
(error) => {
res.json({ error: "required field(s) missing" });
},
);
});
}
});
})
.put(function (req, res) {
let project = req.params.project;
let issueId = req.body._id || false;
// find project
ProjectModel.findOne({ title: project }).then(
(currentProject) => {
// if project exists
if (currentProject) {
console.log("Project to update found! ✅");
// if issue is not an empty string
if (issueId) {
// find issue
IssueModel.findOne({ _id: issueId }).then(
(issue) => {
// if found
if (issue) {
console.log("Issue found! ✅");
// strip body of _id field
let { _id, ...bodyWithoutId } = req.body;
// check if at least one update is sent (EXCEPT _ID)
let atLeastOneUpdate =
Object.values(bodyWithoutId).filter(
(item) => item.length > 0,
).length > 0;
// if at least one update is sent
if (atLeastOneUpdate) {
console.log("At least one update sent found ✅");
// UPDATING FIELDS WITH TRUTHY VALUES ------
issue.issue_title =
req.body.issue_title || issue.issue_title;
issue.issue_text =
req.body.issue_text || issue.issue_text;
issue.created_by =
req.body.created_by || issue.created_by;
issue.assigned_to =
req.body.assigned_to || issue.assigned_to;
issue.status_text =
req.body.status_text || issue.status_text;
issue.open = req.body.open || issue.open;
issue.updated_on = new Date(Date.now()).toISOString();
// ------- UPDATING FIELDS WITH TRUTHY VALUES
// save edits
issue.save().then((data) => {
console.log("Updating issue...", issueId);
// find index of issue in project issues array
let indexOfIssue = currentProject.issues.findIndex(
(item) => item._id.toString() === issueId,
);
console.log(
"Issue",
indexOfIssue + 1,
"of",
currentProject.issues.length,
);
// replace issue in project issues array
currentProject.issues[indexOfIssue] = data;
// save edits
currentProject.save().then((data) => {
console.log("Issue saved in project array! ✅");
// return json
res.json({
result: "successfully updated",
_id: issueId,
});
});
});
} else {
console.log("No update fields sent! ❌");
res.json({ error: "no update field(s) sent", _id: issueId });
}
} else {
console.log("Issue not found! ❌");
res.json({ error: "could not update", _id: issueId });
}
},
(error) => {
res.json({ error: "could not update", _id: issueId });
},
);
} else {
console.log("Missing issue id! ❌");
res.json({ error: "missing _id" });
}
} else {
console.log("Project to update not found! ❌");
res.json({ error: "could not update", _id: issueId });
}
},
(error) => {
res.json({ error: "could not update", _id: issueId });
},
);
})
.delete(function (req, res) {
let project = req.params.project;
let issueId = req.body._id || false;
// if issue id is provided
if (issueId) {
// find project
ProjectModel.findOne({ title: project }).then(
(currentProject) => {
// if project found
if (currentProject) {
console.log("Project to delete issue within is found! ✅");
// find issue
IssueModel.findOneAndDelete({ _id: issueId }).then(
(issue) => {
// if issue found
if (issue) {
console.log("Deleting issue...", issueId);
// return currentProject without that issue
currentProject.issues = currentProject.issues.filter(
(item) => item._id.toString() != issueId,
);
// save edits
currentProject.save().then(
(data) => {
console.log(
"Issue",
issueId,
"successfully deleted from project",
project,
"✅",
);
res.json({
result: "successfully deleted",
_id: issueId,
});
},
(error) => {
res.json({ error: "could not delete", _id: issueId });
},
);
} else {
console.log("Issue to delete not found! ❌");
res.json({ error: "could not delete", _id: issueId });
}
},
(error) => {
res.json({ error: "could not delete", _id: issueId });
},
(error) => {
res.json({ error: "could not delete", _id: issueId });
},
);
} else {
console.log("Project to delete issue within is not found! ❌");
res.json({ error: "project not found", project: project });
}
},
(error) => {
res.json({ error: "could not delete", _id: issueId });
},
);
} else {
console.log("Missing issue id! ❌");
res.json({ error: "missing _id" });
}
});
};
Any hint is appreciated.
Thanks