Can't pass tests on the Exercise Tracker (APIs and Microservices

Tell us what’s happening:
Hey everybody !
I’m having trouble passing tests on the exercise Tracker project. They all fail (except the “not the example URL” one), even though my own tests work fine.

I get a “cannot read property ‘log’ of undefined” in the repl.it console when I launch the FCC tests, so the app fails which is why none of the tests passes I guess, even though the new users are created just fine in my mongodb, so this test at least should be validated :-/

Anyway, my guess would be either a misnamed path/property (even though I double checked each one to make sure they were the same as the ones on the model project, might have missed one, adunno), OR my outputs are different in types or in theur keys than the ones expected by FCC.

What do you think ?

Here’s my server.js code

const express = require('express')
const app = express()
const cors = require('cors')
const bodyParser = require('body-parser');
require('dotenv').config();

const mongoose = require("mongoose");
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true });

app.use(bodyParser.urlencoded({extended: false}))
app.use(cors())
app.use(express.static('public'))

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/views/index.html')
});

let userSchema =  new mongoose.Schema({
  name: { type: String, required: true },
  count: Number,
  log: []
})

let User = mongoose.model("User", userSchema);

app.post("/api/exercise/new-user", (req, res, done) => {
  let username = req.body.username
  let user = new User({ name: username, count: 0, log: [] })

  user.save((err, data) => {
    if (err) {
      return err
    } else {
      User.findOne({name: data.name}, (err, data) => {
        if (err){ 
            err; 
        } 
        else{         
          res.json({ user: data.name, id: data._id })
        } 
      })
    }
  })
})

app.get("/api/exercise/users", (req, res) => {
  User.find({}).select({ count: 0, log: 0 }).exec((err, data) => {
    let dataObj = {};
    Object.assign(dataObj, data)
    res.json(dataObj)
  })
})

app.post("/api/exercise/add", (req, res) => {
  let exeDate;
  req.body.date ? exeDate = new Date(req.body.date).toDateString() : exeDate = new Date().toDateString()
  let logObj = { description: req.body.description, duration: req.body.duration, date: exeDate };

  User.findOne({ _id: req.body.userId }, (err, data) => {
    data.log.push(logObj);
    data.count++;
    data.save((err, data) => {
      if (err) {
        return err;
      } else {
        res.json({ id: data._id, username: data.name, date: logObj.date, duration: logObj.description, description: logObj.duration });
      } 
    })    
  })
})

app.get("/api/exercise/log", (req, res) => {
  User.findOne({ _id: req.query.userId }, (err, data) => {
    let logs = data.log;
    if(req.query.from) {
      let from = new Date(req.query.from).getTime();
      logs = logs.filter(log => new Date(log.date).getTime() >= from)
    }
    if(req.query.to) {
      let to = new Date(req.query.to).getTime();
      logs = logs.filter(log => new Date(log.date).getTime() <= to)
    }
    if (req.query.limit) {
      logs.splice(req.query.limit, logs.length - req.query.limit)
    }
    res.json({ user: data.name, id: data._id, count: data.count, log: logs })
  })
})

const listener = app.listen(process.env.PORT || 3000, () => {
  console.log('Your app is listening on port ' + listener.address().port)
})

Thanks for your help !

Your project link(s)

solution: https://boilerplate-project-exercisetracker.frtey.repl.co

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0.

Challenge: Exercise Tracker

Link to the challenge:

Welcome, frtey!

Just a small thing. I created a new user, with a new exercise:

{"id":"603fdd8edf012706701b8ebc","username":"testuser","date":"Wed Mar 03 2021","duration":"test description","description":"12"}

If you look at the last two properties, they are swapped.

EDIT: To add, duration must be a number, for the tests to pass.

I suspect this might be related… Let me know otherwise, and I will do more digging.

Hope this helps

Thanks for your reply !
You’re right on both account, and I corrected the mistakes (switched duration and description, and used parseInt() on the post body duration). Unforunately, the tests still fails

I do not think this is the issue, but thought to mention it:

  • You appear to have forgotten about error handling in this section, which could help debug:
User.findOne({ _id: req.body.userId }, (err, data) => {
    // What if `data` does not exist? Then `data.log` would
    // error as you saw...
    data.log.push(logObj);
    data.count++;
    data.save((err, data) => {
      if (err) {
        return err;

I will edit this as I go.

OK, so I wrote the error handling for this block (and all the other ones I forgot), and the error is clearer :

“Cast to ObjectId failed for value “undefined” at path “_id” for model “User””

And indeed, logging the value of req.body.userId provided by the FCC tests returns “undefined”.

The FCC test bot doesn’t send anything to the userId field it appears. Am I supposed to auto-populate the userId field with the _id of the last created db doc ? That seems weird

No.

Something else to mention:

Here are the tests: freeCodeCamp/exercise-tracker.md at main · freeCodeCamp/freeCodeCamp (github.com)

There is no case where they purposefully send a missing userId, but what else I notice, is you are not satisfying this:

You can make a GET request to api/exercise/users to get an array of all users. Each element in the array is an object containing a user’s username and _id .

Pay very close attention to the expected properties returned…

Hope this helps

Ok so it was all due to me naming the json response fields id instead of _id, and user instead of username…

Thank you very much for taking your time to respond Sky020 !

Glad you managed to get it working. Well done.

This is a major theme in programming - every little detail counts, and it pays to be thorough.