Exercise tracker - 'The date property of any object in the log array that is returned from GET /api/users/:id/logs should be a string'

I’m stuck on this acceptance criterion. I am not able to create a situation where the logs do not return a string, yet it fails. And, I am logging all of FCC’s attempts to the console, and nothing is coming up wrong, as far as I can tell. Any help would be appreciated.



Here is the code for the app. Never was perfect, but was nicer looking before I started trying to make this one work.


////////////////////////////////////////////////////////////////////
//additional packages
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
//servce static assets
app.use('/public', express.static(__dirname + '/public'));

//mongoose and db items
var mongoose = require('mongoose');
mongoose.connect(process.env.URI, { useNewUrlParser: true, useUnifiedTopology: true });
const { Schema } = mongoose;
  //User
const userSchema = new Schema({
  username: {type: String, required: true},
  description: {type: String},
  duration: {type: Number},
  date: {type: String},
  count: {type: Number},
  log: [{
    description: String,
    duration: Number,
    date: {type: String, required: false},
    _id: false
  }]
})
const User = mongoose.model('User', userSchema);






var resObj = {};

const defDate = new Date().toDateString();
var dateCheck = (input) => {
  if (!input || isNaN(Date.parse(input))) {
    return defDate;
  } else {
    return new Date(input).toDateString();
  }
}

console.log(dateCheck('1111-01-01'));
//console.log(Date.parse('1111-01-01'))


app.post('/api/users', (req,res) => {
  let inUser = new User({username: req.body.username});
  inUser.save((err, data) => {
    if (!err) {
      resObj.username = data.username;
      resObj._id = data.id;
      res.send(resObj)
    }
  })
})

app.get('/api/users', (req,res) => {
  User.find({}).then((users) => {
    res.send(users)
  });
});



app.post('/api/users/:_id/exercises', (req,res) => {
  var filter = {_id: req.params._id};
  var update = {
    description: req.body.description,
    duration: parseInt(req.body.duration),
    date: dateCheck(req.body.date)
  };
  var options = {new: true};
  
  
  User.findOneAndUpdate (filter, update, options, (err,data) => {
    if (!err) {
      //push to log array
      data.log.push(update);
      console.log('saving the date ' + typeof(update.date) + ' to the db')
      data.save();
      //response object with correct parameters
      resObj.username = data.username;
      resObj.description = data.description;
      resObj.duration = data.duration;
      resObj.date = data.date;
      resObj._id = data.id;
      res.json(resObj);
    } else {
      res.json({
        error: err
      })
    }
  })
})

app.get('/api/users/:_id/logs', (req,res) => {
  var id = req.params._id;
  var limit = req.query.limit;
  var from = req.query.from;
  var to = req.query.to;

  if (limit) {
    User.findById(id, {log: {$slice: -limit}}, (err,data) => {
      res.json({
        _id: id,
        username: data.username,
        count: data.log.length,
        log: data.log
      })
    })
  } else if (to) {
    User.findById(id, (err,data) => {
      res.json({
        _id: id,
        username: data.username,
        to: to,
        count: data.log.length,
        log: data.log.filter(a => a.date < to)
      })
    })
  } else if (from) {
    User.findById(id, (err,data) => {
      res.json({
        _id: id,
        username: data.username,
        from: from,
        count: data.log.length,
        log: data.log.filter(a => a.date > from)
      })
    })
  } else {
    User.findById(id, (err,data) => {
      if (!err) {
          res.json({
            username: data.username,
            count: data.log.length,
            _id: id,
            log: data.log.map(a => ({description: a.description, duration: a.duration, date: a.date}))
          })        
      }
    })    
  }    
})






///////function ends here//////////

Update: I logged in today, did not touch the code base at all, but ran it again. And the acceptance criterion passed. No idea why.

OK, yet another update. I spent some time on the last criterion - ’ You can add from , to and limit parameters to a GET /api/users/:_id/logs request to retrieve part of the log of any user. from and to are dates in yyyy-mm-dd format. limit is an integer of how many logs to send back.’

After some work, I am passing all of the query paramters as they should - from, to, and limit. The criterion gives me a check mark…however, the previous test is no longer giving me a checkmark. This time, I am using a .map() function to log every instance of the FCC’s testing to the console. Everything date has a typeof string. I even took extra steps to be sure, as you will see in my updated code. What is going on here? First it didn’t work, then it did, and now it doesn’t. Getting super frustrated about this. I hope I’m missing something easy. Thanks all.

Code:

const express = require('express')
const app = express()
const cors = require('cors')
require('dotenv').config()

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


////////////////////////////////////////////////////////////////////
//additional packages
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
//servce static assets
app.use('/public', express.static(__dirname + '/public'));

//mongoose and db items
var mongoose = require('mongoose');
mongoose.connect(process.env.URI, { useNewUrlParser: true, useUnifiedTopology: true });
const { Schema } = mongoose;
  //User
const userSchema = new Schema({
  username: {type: String, required: true},
  description: {type: String},
  duration: {type: Number},
  date: {type: String},
  count: {type: Number},
  log: [{
    description: String,
    duration: Number,
    date: {type: String, required: false},
    _id: false
  }]
})
const User = mongoose.model('User', userSchema);


var resObj = {};

const defDate = new Date().toDateString();
//console.log(new Date("Wed Jan 04 1111").toISOString().slice(0, 10));
var dateCheck = (input) => {
  if (!input || isNaN(Date.parse(input))) {
    return defDate;
  } else {
    return new Date(input).toDateString();
  }
}
var dateCon = (input) => {return new Date(input).toISOString().slice(0,10)}
//console.log(dateCon("Wed Jan 04 1111"))

app.post('/api/users', (req,res) => {
  let inUser = new User({username: req.body.username});
  inUser.save((err, data) => {
    if (!err) {
      resObj.username = data.username;
      resObj._id = data.id;
      res.send(resObj)
    }
  })
})

app.get('/api/users', (req,res) => {
  User.find({}).then((users) => {
    res.send(users)
  });
});



app.post('/api/users/:_id/exercises', (req,res) => {
  var filter = {_id: req.params._id};
  var update = {
    description: req.body.description,
    duration: parseInt(req.body.duration),
    date: dateCheck(req.body.date)
  };
  var options = {new: true};
  
  
  User.findOneAndUpdate (filter, update, options, (err,data) => {
    if (!err) {
      //push to log array
      data.log.push(update);
      console.log('saving the date ' + typeof(update.date) + ' to the db')
      data.save();
      //response object with correct parameters
      resObj.username = data.username;
      resObj.description = data.description;
      resObj.duration = data.duration;
      resObj.date = data.date;
      resObj._id = data.id;
      res.json(resObj);
    } else {
      res.json({
        error: err
      })
    }
  })
})

app.get('/api/users/:_id/logs', (req,res) => {
  var id = req.params._id;
  var limit = req.query.limit;
  var from = req.query.from;
  var to = req.query.to
  if (limit) {
    User.findById(id, {log: {$slice: -limit}}, (err,data) => {
      res.json({
        _id: id,
        username: data.username,
        count: data.log.length,
        log: data.log
      })
    })
  } else if (to) {
    User.findById(id, (err,data) => {
      res.json({
        _id: id,
        username: data.username,
        count: data.log.length,
        log: data.log.filter(a => dateCon(a.date) < to).map(a => ({description:a.description, duration: a.duration, date:new Date (a.date).toDateString()}))
      })
      data.log.map(a => console.log(typeof(a.date)))
    })
  } else if (from) {
    User.findById(id, (err,data) => {
      res.json({
        _id: id,
        username: data.username,
        from: from,
        count: data.log.length,
        log: data.log.filter(a => dateCon(a.date) > from).map(a => ({description:a.description, duration: a.duration, date: new Date (a.date).toDateString()}))
      });
      data.log.map(a => console.log(typeof(a.date)))
    })
  } else {
    User.findById(id, (err,data) => {
      if (!err) {
          res.json({
            username: data.username,
            count: data.log.length,
            _id: id,
            log: data.log.map(a => ({description: a.description, duration: a.duration, date: new Date (a.date).toDateString()}))
          });
          data.log.filter(a => console.log(typeof(a.date)))
      }
    })    
  }    
})


///////function ends here//////////

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

Console after pushing FCC’s tests through:

saving the date string to the db
saving the date string to the db
saving the date string to the db
string
saving the date string to the db
string
saving the date string to the db
string
saving the date string to the db
string
saving the date string to the db
string
saving the date string to the db
string
saving the date string to the db
string
saving the date string to the db
saving the date string to the db
string
string

Since it’s passing intermittently, check if its the often mentioned timezone offset problem.

1 Like

Thank you!

As soon as I DL’d a Chrome extension to switch to UTC, it worked. I was not aware of that issue until I googled it and found your other thread. I wasted a few hours of my life on this issue, and my code has lots of convoluted parts now, trying to make this pass. You get what you pay for.