typicode / json-server

Get a full fake REST API with zero coding in less than 30 seconds (seriously)
Other
72.56k stars 7k forks source link

Reset the db on command #872

Open hoefling opened 5 years ago

hoefling commented 5 years ago

Basically, I'm looking for a pendant to Angular in-memory-web-api's resetdb command that recreates the data in its original state. I can create an in-memory db with JSON server, but it persists its state through the whole test session and I want to reset it after each test. What would be the proper way of doing that?

hoefling commented 5 years ago

Ok, think I found it, need a confirmation of whether it's the correct way. Snippet:

const reloadDB = (req, res, next) => {
  if (req.method === 'POST' && req.url.endsWith('/reloadDB/')) {
    const db = JSON.parse(fs.readFileSync(path.join(__dirname, 'mocks', 'db.json'), 'utf8'));
    router.db.setState(db);
    res.sendStatus(201);
  } else {
    next();
  }
};

const server = jsonServer.create();
server.use(reloadDB);
const router = jsonServer.router(db);
server.use(router);

Now, a POST on /reloadDB/ triggers the data reload, for example

$ curl -i http://localhost:3000/api/v2/reloadDB/ -X POST
tillg commented 5 years ago

Sounds good. But does it work more than once? I.e. can u reload the dB multiple times?

hoefling commented 5 years ago

@tillg it works reliable for the suite of 30+ tests I wrote so far, placed the reset request in a global afterEach and get a clean db state in each test. I'm rather concerned about router.db.setState(db) - not that I'm messing with the library internals that may cause unexpected side effects somewhere else.

ltakato commented 5 years ago

@hoefling I liked your suggestion! I'm using on my project! I adapted your approach using "initial database" file, with code below:

server.use((req, res, next) => {
  if (req.method === 'POST' && req.path === '/api/reloadDB') {
    const initialData = fs.readFileSync(path.join(__dirname, 'initialData.json'), 'utf8');
    // to update (sync) current database (db.json) file
    fs.writeFileSync(path.join(__dirname, 'db.json'), initialData);
    router.db.setState(JSON.parse(initialData));
    res.sendStatus(200);
  } else {
    next();
  }
});
WellerQu commented 4 years ago

Ok, think I found it, need a confirmation of whether it's the correct way. Snippet:

const reloadDB = (req, res, next) => { if (req.method === 'POST' && req.url.endsWith('/reloadDB/')) { const db = JSON.parse(fs.readFileSync(path.join(__dirname, 'mocks', 'db.json'), 'utf8')); router.db.setState(db); res.sendStatus(201); } else { next(); } };

const server = jsonServer.create(); server.use(reloadDB); const router = jsonServer.router(db); server.use(router); Now, a POST on /reloadDB/ triggers the data reload, for example

$ curl -i http://localhost:3000/api/v2/reloadDB/ -X POST

I also have an idea

I use jest to run my test cases, so I add a afterEach to the describe like this:

describe('a name', () => {
  if (process.env.CI !== 'Github') {
    afterEach(() => {
      // the server/db.json is the file that json-server needs
      exec('git checkout server/db.json', function (err: Error) {
        if (err != null) {
          return console.error(err) // eslint-disable-line no-console
        }
      })
    })
  }
})

then every case is completed, the json-server will be reset

PLQin commented 4 years ago

use nodemon 👍

start.js :

// github.com/remy/nodemon
var nodemon = require('nodemon');
nodemon({
  script: 'index.js',
  ext: 'js json' // watching extensions
});

nodemon.on('start', function () {
  console.log('App has started');
}).on('quit', function () {
  console.log('App has quit');
  process.exit();
}).on('restart', function (files) {
  console.log('App restarted due to: ', files);
});

index.js :

const jsonServer = require('json-server')

const data = require('./api/db.js')
const routes = require('./api/routes.json')

const server = jsonServer.create()
const router = jsonServer.router(data)
const middlewares = jsonServer.defaults()

// github.com/typicode/json-server/issues/690#issuecomment-348616467
// json-server options.bodyParser defalut is true
// server.use(jsonServer.bodyParser);

server.use(middlewares)
server.use(jsonServer.rewriter(routes))
server.use(router)

// Avoid CORS issue
// json-server options.noCors defalut is false
// server.use( (req, res, next) => {
//   res.header("Access-Control-Allow-Origin", "*");
//   // res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
//   next();
// });

server.listen(9538, () => {
  console.log('JSON Server is running, see http://localhost:9538')
})

All you need to do is exec the command node start.js to listen to all files