Exercise Tracker Project: save() and findById() question

Hello there

Hope you guys doing well.

So, I’m having trouble with the third unit test in the ‘Exercise Tracker’ project of the APIs and Microservices course:

Blockquote You can POST to /api/users/:_id/exercises with form data description , duration , and optionally date . If no date is supplied, the current date will be used. The response returned will be the user object with the exercise fields added.

Here is my code:

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

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

//--- Database modelling

// creating docuemnt and model
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true });

const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
  console.log('Successfully connected to Mongo db')
});

let UserSchema = new mongoose.Schema({
  username: String,
  description: String,
  duration: Number,
  date: Date
});

let User = mongoose.model('User', UserSchema);

//---

//--- Other functions

function isValidDate(d) {
  return d instanceof Date && !isNaN(d);
}

//---


//--- DB access methods

const createUser = (usernameSubmited, done) => {
  
  User.findOne({'username': usernameSubmited}, (err, data) => {
    if (!data) {
      data = new User({username: usernameSubmited});
      data.save(function(err) {
          if (err) done(err);
          done(null, data);
      });
    } else if (err) {
      done(err);
    } else {
      done(null, 'Username already taken')
    }
  });

};

const findUserAndAddExercise = (submitedUID, exercise, done) => {

  User.findById(submitedUID, function (err, data) {

      console.log('FindById: below is the user data');
      console.log(data);

      if (!data) {
        done(null, 'User Id is not found')
      } else if (exercise.description == '') {
        done(null, 'Exercise description is required')
      } else if (exercise.duration == '') {
        done(null, 'Exercise duration is required')
      } else if (isNaN(exercise.duration)) {
        done(null, 'Exercise duration should be a numerical value')
      } else if (!isValidDate(exercise.date)) {
        done(null, 'Entered date is not valid')
      } else if (err) {
        done(err);
      } else {

        console.log('New exercise was added to the DB\n');

        data.description = exercise.description;
        data.duration = exercise.duration;
        data.date = exercise.date.toDateString();

        data.save(function (err, data) {
          if (err) return console.error(err);
          done(null,data);
        });
      }
  });
};


//---

//--- Routes

// body parser middleware
app.use('/', (req, res, next) => {
  console.log(req.method + ' ' + req.path + ' - ' + req.ip);
  next();
}, bodyParser.urlencoded({extended: false}) );

// get vector of all users
app.get('/api/users',function(req,res)
{
  User.find(function (err, data) {
      if (err) return console.error(err);
      res.json(data);
  });
});


// submit a new username
app.post('/api/users', (req, res) =>
{
  createUser(req.body.username, (err, data) =>
  {
    if(err) {
      console.log('Error occured: ' + err + '\n')
      res.send(err);
    } else if (data == 'Username already taken') {
      console.log('Error occured: ' + data + '\n')
      res.send(data);
    } else {
      console.log('\nNEWLY-CREATED USER ID: ' + data._id)
      res.json({'username': data.username, '_id': data._id});
    }
  });

});

// submit new exercise data
app.post('/api/users/:_id/exercises', (req, res) =>
{
  let dateToSet = new Date();
  if (req.body.date != ''){
    dateToSet = new Date(req.body.date); 
  }

  // initialize data to save in DB
  uid = req.body[':_id'];
  exerciseToAdd = {
    description: req.body.description,
    duration: parseInt(req.body.duration),
    date: dateToSet
  } 

  // set Id route parameter
  req.params._id = uid;

  findUserAndAddExercise(uid, exerciseToAdd, (err, data) => {
    if(err) {
      console.log('Error occured: ' + err + '\n');
      res.send(err);
    } else if (data == 'User Id is not found'
              || data == 'Exercise description is required'
              || data == 'Exercise duration is required'
              || data == 'Exercise duration should be a numerical value'
              || data == 'Entered date is not valid') {
      console.log('Error occured: ' + data + '\n');
      res.send(data);
    } else {
      res.json({'_id': data._id, 'username': data.username, 'date': new Date(data.date).toDateString(), 'duration': data.duration, 'description': data.description});
    }
  });

});


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

So, let’s created a new user and add a few exercise activities for this new user. I am doing it manually, and the console output is as follows:

NEWLY-CREATED USER ID: 60d794b4a93fa505205341b3
POST /api/users/60d794b4a93fa505205341b3/exercises - ::ffff:172.18.0.1
FindById: below is the user data
{ _id: 60d794b4a93fa505205341b3, username: 'Eliz', __v: 0 }
New exercise was added to the DB

POST /api/users/60d794b4a93fa505205341b3/exercises - ::ffff:172.18.0.1
FindById: below is the user data
{
  _id: 60d794b4a93fa505205341b3,
  username: 'Eliz',
  __v: 0,
  date: 2021-06-26T00:00:00.000Z,
  description: 'Running',
  duration: 15
}
New exercise was added to the DB

OK, that seems fine.

Now, when I fire the fcc unit tests, the console output is as follows:

NEWLY-CREATED USER ID: 60d79121a10ad00469ea8f4b
POST /api/users/60d79121a10ad00469ea8f4b/exercises - ::ffff:172.18.0.1
FindById: below is the user data
null
Error occured: User Id is not found

Here, we can see that the new user was created and should have been added to the DB. But then, when we try to find this user (using findById), there is no data (- null).

I’m kinda stuck for few days on this one. I think I have some sort of asynchronous bug in my code.

I’ll appreciate any advice you can give me on this issue or my code in general. Thank you!


I’m using replit (I’m unsure if you can access my project by this link): https://replit.com/@andreyxdd/boilerplate-project-exercisetracker#README.md
System details: Google Chrome Version 91.0.4472.114 (Official Build) (64-bit), Windows 10.

I should’ve used:

let uid = req.params._id;

instead of:

uid = req.body[':_id'];

in the app.post('/api/users/:_id/exercises'

Hope it’d help somebody one day

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.