Test models using Mocha and Sequelize - javascript

I'd like to test CRUD operation on mysql database using Sequelize as ORM and Mocha/Chai for unit testing. I tested the insertion/deleting of record using http routing, but I'd test directly the models without using any http connection. I tried to do it but when I launch the test the record is not added and I don't receive any error.
app/model/article.js
module.exports = function (sequelize, DataTypes) {
var Article = sequelize.define('Article', {
title: DataTypes.STRING,
url: DataTypes.STRING,
text: DataTypes.STRING
}, {
classMethods: {
associate: function (models) {
// example on how to add relations
// Article.hasMany(models.Comments);
}
}
});
return Article;
};
app/model/index.js
var fs = require('fs'),
path = require('path'),
Sequelize = require('sequelize'),
config = require('../../config/config'),
db = {};
var sequelize = new Sequelize(config.db);
fs.readdirSync(__dirname).filter(function (file) {
return (file.indexOf('.') !== 0) && (file !== 'index.js');
}).forEach(function (file) {
var model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(function (modelName) {
if ('associate' in db[modelName]) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
test/model/article.js
'use strict';
var expect = require('chai').expect;
var db = require('../../../app/models');
var Article = db.Article;
describe('article', function () {
it('should load', function (done) {
Article.create({
title: 'Titolo',
url: 'URL',
text: 'TEXT'
});
done();
});
});

Either use async or promises to make sure the operation completed.
describe('article', function () {
it('should load', function (done) {
Article.create({
title: 'Titolo',
url: 'URL',
text: 'TEXT'
}).then( function (article) {
// do some tests on article here
done();
});
});
});

Related

Why does sequelize not recognize the Model? TypeError: Cannot read properties of undefined (reading 'findAll')

So I'm learning sequelize with MySQL and I have a few examples at my disposal on how it should be done, but this error persists as if sequelize couldn't use the functions inside the model. I just can't find why it's not working, any help?
This is the error that shows in the terminal, it points to productController line 8:
TypeError: Cannot read properties of undefined (reading 'findAll')
This is my Index.js:
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.js')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file));(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
This is the Table Model:
module.exports = (sequelize, DataTypes) => {
let alias = 'Product';
let atributes = {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
allowNull: false,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
}
let config = {
tableName: 'products',
timestamps: false
}
const Product = sequelize.define(alias, atributes, config);
return Product
}
And This productController.js:
const db = require('../../models/Index');
const sequelize = db.sequelize;
const productsController = {
'shopRender' : (req, res) => {
// res.send('hola mundo');
db.Product.findAll()
.then(function(productos) {
res.send("hola mundo");
})
}
}
module.exports = productsController;
Ive tried deconstructing db in productController into Product, using caps, non-caps, using the table name...
What does work is trying to show something inside the shopRender function, but once I try to use the model to do a query and try to access the route, the error appears.
Turns out, trying to use res.send(Object.keys(db)) to debug prints ["undefined","","sequelize","Sequelize"]
try this on a productController.js, I hope it helps.
const db = require('../../models').sequelize.models;
const productsController = {
'shopRender' : (req, res) => {
// res.send('hola mundo');
db.Product.findAll()
.then(function(productos) {
res.send("hola mundo");
})
}
}
module.exports = productsController;

getting empty response on sequelize findall from postgres

I am new to node js environment and currently I am practicing a crud applicaiton
I am using sequelize as ORM and I have used the mvc structure
npm install --save sequelize
$ npm install --save pg pg-hstore
I am using sequelize cli
npm install --save-dev sequelize-cli
npx sequelize-cli init
It is my migration
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('Books', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
firstName: {
type: Sequelize.STRING
},
lastName: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Books');
}
};
My Model:
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Books extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
};
Books.init({
firstName: DataTypes.STRING,
lastName: DataTypes.STRING,
email: DataTypes.STRING
}, {
sequelize,
modelName: 'Books',
});
return Books;
};
MY Controller:
exports.allBooks = (req,res)=>{
const bookme = Books(**how to pass sequelize**,**how to pass sequelize datatype**)
var booksJSON = bookme.findAll()
res.json(booksJSON)
console.log(JSON.stringify(booksJSON))
}
I am getting the empty response if I pass the datatypes customly by creating a connection manually to database with sequelize and passing that sequelize to the books models
I think that my mistake is in passing these parameters. What and how shoudld I pass to the Books model
I am importing the books model as follows in my controller:
const Books = require('../models/books.js');
also when i ran the bootstraping that created migrations,models,seeding folders it also created a index.js file in models folder
I have tried passing that too in the parameter to Books model but It gave error
index.js in models folder created by sequelize cli package itself
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
The error I got when I try to pass this db from index.js to Books model in my controller is:
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
^
TypeError: Class constructor model cannot be invoked without 'new'
What should I pass to the parameter and from where?
I am getting response by using aysnc and await. I used second parameter by importing directly from the package
const Sequelize = require('sequelize')
and for first parameter I used the manually created connection.
but it still doesn't clears my concern of actually what parameters were to pass

findAll() is not a function in sequelize

I am using Express.js with sequelize
I am trying to get data from table but findALL() method not working
Here , I am sharing my models & controller file
checkout_product model
module.exports = function (sequelize, DataTypes) {
var Checkout_product = sequelize.define(
"Checkout_products",
{
name: {
type: DataTypes.STRING
},
ptice: {
type: DataTypes.STRING
},
image: {
type: DataTypes.STRING
},
quantity: {
type: DataTypes.INTEGER
},
},
);
Checkout_product.associate = function (models) {
Checkout_product.hasMany(models.Product_attribute, {
foreignKey: "product_id",
sourceKey: "id"
});
};
return Checkout_product;
};
product_attribute model
module.exports = function (sequelize, DataTypes) {
var Product_attribute = sequelize.define(
"product_attributes",
{
product_id: {
type: DataTypes.INTEGER
},
attribute_name: {
type: DataTypes.STRING
},
attribute: {
type: DataTypes.STRING
},
price: {
type: DataTypes.STRING
},
},
);
Product_attribute.associate = (models) => {
Product_attribute.belongsTo(models.Checkout_product, {
foreignKey: "product_id",
sourceKey: "id"
});
};
return Product_attribute;
};
models/index.js file
"use strict";
const fs = require("fs");
const path = require("path");
const Sequelize = require("sequelize");
const config = require("./../config/development").database;
let sequelize = new Sequelize(
config.database,
config.username,
config.password,
config
);
let db = {};
fs
.readdirSync(__dirname)
.filter(function(file) {
return file.indexOf(".") !== 0 && file !== "index.js";
})
.forEach(function(file) {
let model = require(path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(function(modelName) {
if ("associate" in db[modelName]) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
Controller
const Checkout_product = require('../models');
module.exports.checkout_product_get = function (req, res) {
Checkout_product.findAll({
include: [ {
model : Product_attributes,
}]
})
.then(checkout_product => {
res.json(checkout_product)
})
}
I am stuck to get data from checkout_product & it's child model product_attribute model,
Everytime I am getting same error : TypeError: Checkout_product.findAll is not a function
const Checkout_product = require('../models').table_name;
Can you try it
You are using the deprecated - legacy way of Sequelize to initialize models. Newer ways with require and extends are available and suggested. Check the docs for more information.
Regarding your code....
You are neither initializing the db structure properly nor using it correctly later...
First your code here in index.js:
.forEach(function(file) {
let model = require(path.join(__dirname, file));
db[model.name] = model;
});
Just loads the model files in the db object. But these files are functions ment to be called with sequelize object as parameter. This is done by providing them to sequelize.import that manages the proper call of the defined model-functions to create the model instances. Check https://sequelize.org/master/manual/models-definition.html
Also after successfully initializing the db, in your controller code, the require('../models') returns the total db object. So if you want to use a specific model as Checkout_product in your case, you have to access it in the object:
const db = require('../models');
db.Checkout_product.findAll()...

"TypeError: Cannot read property 'create' of undefined"

I'm building a simple site that handles users using Passport.js. I can run my server but when a user submits their signup information it spits out "TypeError: Cannot read property 'create' of undefined".
I know what's happening, I just can't understand why. The error gets thrown in api-routes.js, specifically in the api/signup function when it attempts to create a user via db.User.create. When I console.log(db), the first thing in the db object is
undefined: 'C:\\Users\\LENOVO\\Desktop\\code\\Breel\\models\\user.js'
...so the user model is being exported, it's just not defined?
Any and all help you can lend me is greatly appreciated!
user.js, from my models directory:
var bcrypt = require("bcryptjs");
module.exports = function (sequelize, DataTypes) {
var User = sequelize.define("User", {
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isEmail: true,
},
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
});
User.prototype.validPassword = function (password) {
return bcrypt.compareSync(password, this.password);
};
User.hook("beforeCreate", function (user) {
user.password = bcrypt.hashSync(
user.password,
bcrypt.genSaltSync(10),
null
);
});
return User;
};
index.js, from models (this and user.js are the only two files in my models directory)
"use strict";
const fs = require("fs");
const path = require("path");
const Sequelize = require("sequelize");
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || "development";
const config = require(__dirname + "/../config/config.json")[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(
config.database,
config.username,
config.password,
config
);
}
fs.readdirSync(__dirname)
.filter((file) => {
return (
file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js"
);
})
.forEach((file) => {
const model = path.join(__dirname, file);
sequelize["import"];
db[model.name] = model;
});
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
api-routes.js, from my routes directory:
var db = require("../models");
var passport = require("../config/passport");
module.exports = function (app) {
app.post("/api/login", passport.authenticate("local"), function (req, res) {
res.json("/members");
});
app.post("/api/signup", function (req, res) {
console.log(req.body);
console.log(db);
db.User.create({
email: req.body.email,
password: req.body.password,
})
.then(function () {
res.redirect(307, "/api/login");
})
.catch(function (err) {
console.log(err);
res.json(err);
});
});
app.get("/logout", function (req, res) {
req.logout();
res.redirect("/");
});
app.get("/api/user_data", function (req, res) {
if (!req.user) {
res.json({});
} else {
res.json({
email: req.user.email,
id: req.user.id,
});
}
});
};
You should correct a registration process of models:
.forEach((file) => {
const modelFile = path.join(__dirname, file);
const model = sequelize['import'](modelFile)
db[model.name] = model;
})

sequelize is not defined - Sequelize and consign

I'm new in node.
I'm trying to add Sequelize in my simple application with cosign.
config/db.js
var Sequelize = require('sequelize');
var sequelize = new Sequelize('test', 'root', '', {
host: 'localhost',
dialect: 'mysql',
pool: {
max: 5,
min: 0,
idle: 10000
}
});
module.exports = function () {
return sequelize
}
model/user.js
var Sequelize = require('sequelize');
module.exports = function(application, req, res){
var User = sequelize.define('user', {
username: {
type: Sequelize.STRING,
}
}, {
freezeTableName: true // Model tableName will be the same as the model name
});
User.create({ username: 'fnord'})
.then(function() {
console.log('criado!');
})
}
config/server.js
...
consign()
.include('app/routes')
.then('config/db.js')
.then('app/models')
.then('app/controllers')
.into(app);
module.exports = app;
I'm getting the error sequelize is not definedĀ“ onvar User = sequelize.define('user', {`
What I'm doing wrong?
Create an index.js file inside your moldes folder like this:
"use strict";
var fs = require("fs");
var path = require("path");
var Sequelize = require("sequelize");
var sequelize = new Sequelize(global.config.dbConfig.name, global.config.dbConfig.user, global.config.dbConfig.password, {
host: global.config.dbConfig.host,
port: global.config.dbConfig.port,
pool: false
});
var db = {};
fs.readdirSync(__dirname)
.filter(function(file) {
return (file.indexOf(".") !== 0) && (file !== "index.js");
})
.forEach(function(file) {
var model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(function(modelName) {
if ("associate" in db[modelName]) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
module.exports = db;
and in your user.js do something like this:
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define("User", {
username: {
type: DataTypes.STRING
},
{
freezeTableName: true // Model tableName will be the same as the model name
}
});
return User;
}
http://docs.sequelizejs.com/en/1.7.0/articles/express/
You should require sequelize instance into user model
config/db.js
module.exports = sequelize;
model/user.js
var Sequelize = require('sequelize');
var sequelize = require('../config/db.js'); //sequelize instance
module.exports = function(application, req, res){
var User = sequelize.define('user', {
...
The Sequelize-CLI is a very useful tool for projects that use Sequelize. When you download it
npm install -g sequelize-cli
You can then run
sequelize init
The above command will go and write out a few folders for you including a models folder that has the index file that Ricardo created above. This gives some really cool environment configuration as well. Within the new models folder, you can create a new file with your object with the syntax...
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define("User", {
username: {
type: DataTypes.STRING
},
{
freezeTableName: true // Model tableName will be the same as the model name
}
});
return User;
}
While I do like this as a tool. It is key here to notice that Sequelize will go and look for the first argument to the define() method. So we could just write
module.exports = function(sequelize, DataType){
return sequelize.define("User", {
username: {
type: DataTypes.STRING
},
{
freezeTableName: true // Model tableName will be the same as the model name
}
});

Categories