Giter Club home page Giter Club logo

sequelize-fixtures's Introduction

Build Status

Sequelize fixtures

This is a simple lib to load data to database using sequelize.
It is intended for easily setting up test data.
Yaml and json formats are supported. Includes a grunt task.
Duplicate records are not inserted. API returns bluebird promises, but callbacks can also be used as the last argument.

Tested with latest Sequelize (5.0)

Install

npm install sequelize-fixtures

Test

npm test

Usage

    const sequelize_fixtures = require('sequelize-fixtures');

    //a map of [model name] : model
    //see offical example on how to load models
    //https://github.com/sequelize/express-example/blob/master/models/index.js
    const models = require('./models');

    //from file
    sequelize_fixtures.loadFile('fixtures/test_data.json', models).then(function(){
        doStuffAfterLoad();
    });

    //can use glob syntax to select multiple files
    sequelize_fixtures.loadFile('fixtures/*.json', models).then(function(){
        doStuffAfterLoad();
    });

    //array of files
    sequelize_fixtures.loadFiles(['fixtures/users.json', 'fixtures/data*.json'], models).then(function(){
        doStuffAfterLoad();
    });

    //specify file encoding (default utf8)
    sequelize_fixtures.loadFile('fixtures/*.json', models, { encoding: 'windows-1257'}).then(function(){
        doStuffAfterLoad();
    });

    //specify logging function (default console.log)
    function myLogging(defaultLog) {
        console.log('Fixtures: processing ...')
    }
    sequelize_fixtures.loadFile('fixtures/*.json', models, { log: myLogging}).then(function(){
        doStuffAfterLoad();
    });

    //specify separate stdout and stderr streams
    //(e.g. a winston-compatible logger)
    function errorReporter(message) {
      console.error('OH NO! ERROR: ' + message);
    }
    sequelize_fixtures.loadFile('fixtures/*.json', models, {
      logger: {
        debug: console.log,
        info: console.log,
        warn: console.log,
        error: errorReporter
      }
    }).then(function(){
        doStuffAfterLoad();
    });

    //load fixtures inside a transaction
    sequelize.transaction(function(tx) {
        sequelize_fixtures.loadFile('fixtures/*.json', models, { transaction: tx}).then(doStuffAfterLoad);
    });

    //apply transform for each model being loaded
    sequelize_fixtures.loadFile('fixtures/*.json', models, {
        transformFixtureDataFn: function (data) {
          if(data.createdAt
           && data.createdAt < 0) {
            data.createdAt = new Date((new Date()).getTime() + parseFloat(data.createdAt) * 1000 * 60);
          }
          return data;
        }
    }).then(function() {
        doStuffAfterLoad();
    });

    //modify each model being loaded
    sequelize_fixtures.loadFile('fixtures/*.json', models, {
        modifyFixtureDataFn: function (data) {
          if(!data.createdAt) {
            data.createdAt = new Date();
          }
          return data;
        }
    }).then(function() {
        doStuffAfterLoad();
    });

    //from array
    var fixtures = [
        {
            model: 'Foo',
            data: {
                propA: 'bar',
                propB: 1
            }
        },
        {
            model: 'Foo',
            data: {
                propA: 'baz',
                propB: 3
            }
        }
    ];
    sequelize_fixtures.loadFixtures(fixtures, models).then(function(){
        doStuffAfterLoad();
    });

File formats

json

    [
        {
            "model": "Foo",
            "data": {
                "propA": "bar",
                "propB": 1
            }
        },
        {
            "model": "Foo",
            "data": {
                "propA": "baz",
                "propB": 3
            }
        }
    ]

yaml

    fixtures:
        - model: Foo
          data:
            propA: bar
            propB: 1
        - model: Foo
          data:
            propA: baz
            propB: 3

javascript

    module.exports = [
        {
            "model": "Foo",
            "data": {
                "propA": "bar",
                "propB": 1
            }
        },
        {
            "model": "Foo",
            "data": {
                "propA": "baz",
                "propB": 3
            }
        }
    ];

Associations

You can specify associations by providing related object id or a where clause to select associated object with. Make sure associated objects are described before associations!

One to many

Assuming

Car.belongsTo(Owner);
Owner.hasMany(Car);

Associated entity can be mapped by providing either an id:

[
    {
        "model": "Owner",
        "data": {
            "id": 11,
            "name": "John Doe",
            "city": "Vilnius"
        }
    },
    {
        "model": "Car",
        "data": {
            "id": 203,
            "make": "Ford",
            "owner": 11
        }
    }
]

Or a property-value map (like a 'where' object) to find the entity with:

[
    {
        "model": "Owner",
        "data": {
            "name": "John Doe",
            "city": "Vilnius"
        }
    },
    {
        "model": "Car",
        "data": {
            "make": "Ford",
            "owner": {
                "name": "John Doe"
            }
        }
    }
]

Many to many

Assuming

Project.belongsToMany(Person, {through: 'peopleprojects'});
Person.belongsToMany(Project, {through: 'peopleprojects'});

Associated entities can be mapped using the association 'as' name ('people' for Project and 'projects' for People) or 'through' table name, and providing an array of ids:

[
    {
        "model":"Person",
        "data":{
            "id":122,
            "name": "Jack",
            "role": "Developer"
        }
    },
    {
        "model":"Person",
        "data":{
            "id": 123,
            "name": "John",
            "role": "Analyst"
        }
    },
    {
        "model":"Project",
        "data": {
            "id": 20,
            "name": "The Great Project",
            "people": [122, 123]
        }
    }

]

Or an array of property-value mappings to find the entities with:

[
    {
        "model":"Person",
        "data":{
            "name": "Jack",
            "role": "Developer"
        }
    },
    {
        "model":"Person",
        "data":{
            "name": "John",
            "role": "Analyst"
        }
    },
    {
        "model":"Project",
        "data": {
            "name": "The Great Project",
            "people": [
                {                        
                    "name": "Jack"
                },
                {
                    "name": "John"
                }
            ]
        }
    }

]

If you have a custom through model for a m2m relationship, you can set additional attributes using _through:

ActorsMovies = sequelize.define("ActorsMovies", {
    character: {type: DataTypes.STRING}
});
Movie.belongsToMany(Actor, {through: ActorsMovies});
Actor.belongsToMany(Movie, {through: ActorsMovies});
[
    {
        "model": "Movie",
        "data": {
            "name": "Terminator"      
        }
    },
    {
        "model": "Actor",
        "data": {
            "name": "Arnie",
            "movies": [
                {
                    "name": "Terminator",
                    "_through": {
                        "character": "T-80"
                    }
                }
            ]
        }
    }
]

Build options, save options

For each model you can provide build options that are passed to Model.build() and save options that are passed to instance.save(), example:

{
    "model": "Article",
    "buildOptions": {
        "raw": true,
        "isNewRecord": true
    },
    "saveOptions": {
        "fields": ["title", "body"]
    },
    "data": {
        "title": "Any title",
        "slug": "My Invalid Slug"
    }
}

Detect duplicates based on select fields

In case you want to detect duplicates based on specific field or fields rather than all fields (for example, don't include entities with the same id, even if other fields don't match), you can specify these fields with a 'keys' property.

{
    "model": "Person",
    "keys": ["email"],
    "data": {
        "name": "John",
        "email": "[email protected]"
    }
},
{
    "model": "Person",
    "keys": ["email"],
    "data": {
        "name": "Patrick",
        "email": "[email protected]"
    }
}

In this example only John will be loaded

Ignore setters (ignoreSet)

By default, this library attempts to run values through any defined property setters to coerce the value correctly. If you use instance methods (other than setDataValue, which a mock is created for), then this will raise an error.

For example:

const User = sequelize.define('User',
  email: {
    type: DataTypes.STRING,
    unique: true,
    validate: {
      isEmail: true,
    },
    set: function set(val) {
      if (this.previous('email')) { // <--- this line will raise an error
        // check some thing
      }
      this.setDataValue('email', val);
    }
  }
});

You can turn off this behavior by setting ignoreSet to true.

{
    "model": "User",
    "ignoreSet": true,
    "saveOptions": {
        "fields": ["title", "body"]
    },
    "data": {
        "title": "Any title",
        "slug": "My Invalid Slug"
    }
}

This ignores any defined setters for this model and instead just set the value as the same data literal specified in the fixture.

grunt task

Gruntfile.js:

    grunt.initConfig({
        fixtures: {
            import_test_data: {
                src: ['fixtures/data1.json', 'fixtures/models*.json'],
                // supports async loading models
                models: async function () {  
                    return await loadModels();
                },
                options: {
                    //specify encoding, optional default utf-8
                    encoding: 'windows-1257'
                }
            }
        }

    });

    grunt.loadNpmTasks('sequelize-fixtures');

sequelize-fixtures's People

Contributors

cachefactory avatar dennisschaaf avatar dependabot[bot] avatar dgmike avatar domasx2 avatar ekmartin avatar gwendl avatar hawkaa avatar iamblue-mtk avatar jonathanargentiero avatar jordan-burnett avatar mabeebam avatar maruware avatar matmar10 avatar nedrocks avatar nikitakrasavtsev avatar pcsanwald avatar publickeating avatar rfink avatar richayotte avatar rjz avatar samirsyed avatar samuelbolduc avatar sezanzeb avatar sylwit avatar villasv avatar vsaienko avatar witem avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

sequelize-fixtures's Issues

Why does the fixture loading change the database the foreign keys "on delete" setting?

My freshly created test database contains on delete "CASCADE" option for all the foreign keys.

As soon as I populate the database with my fixtures using sequelize-fixtures, I observe that some foreign keys change their on delete "CASCADE" to on delete "Set NULL".
It creates issues for my tests because this is not the perfect copy of my dev/staging/production database configuration.

It really occurs when I seed the fixtures. No doubt about that.
Do I have to specify options in the models?

Thanks for your help!

Importing data with nested association

I'm trying to write an import script for normalized address data with the following setup:

const Address = sequelize.define('address', { ... });
const Cities = sequelize.define('cities', { ... });
const Regions = sequelize.define('regions', { ... });

Address.belongsTo(Cities, {
    foreignKey: 'cityId'
});

Cities.belongsTo(Regions, {
    foreignKey: 'regionId'
});

And below is a sample of the data I'm trying to import:

Region import data:

ID Region
1 England

City import data:

ID City
1 London

Address import data:

ID Owner Address City Region
1 Sherlock Holmes 221B Baker Street London England

First, I import the region data, followed by the city data with a reference to the region:

// regions.json
[
    {
        "model": "Regions",
        "data": {
            "label": "England"
        }
    }
]

// cities.json
[
    {
        "model": "Cities",
        "data": {
            "label": "London",
            "region": {
                "label": "England"
            }
        }
    }
]

This works great, but is there a way to import the address data while referencing both the city and region data in order to prevent Holmes from living in London ON, CA? I've tried nesting region data inside of city:

// address.json
[
    {
        "model": "Address",
        "data": {
            "street_1": "221B Baker Street",
            "city": {
                "label": "London",
                "region": {
                    "label": "England"
                }
            }
        }
    }
]

I also tried to be clever and use Sequelize.literal which resulted in this:

[
    {
        "model": "Address",
        "data": {
            "street_1": "221B Baker Street",
            "cityId": {
                "val": "SELECT c.id FROM cities c LEFT JOIN regions r ON c.regionId = r.id WHERE c.label = \"London\" AND r.label = \"England\""
            }
        }
    }
]

Note: I've also posted this question on Stack Overflow.

Grunt files compatibility

The current version of Grunt expects filesSrc instead of files.

filesSrc: ['./db/fixtures/EventCodes.json']

I think the only changes needed are in the fixtures.js file and the docs.

if(Array.isArray(data.filesSrc)){
    loader = sf.loadFiles(data.filesSrc, models, options, callback);
} else if (data.filesSrc) {
    loader = sf.loadFile(data.filesSrc, models, options, callback);
} else {
    throw new error('missing "filesSrc" argument');
}

Fail loading JSONB with array property

var Model = sequelize.define('something', {
    jsonbField: {
        type: Sequelize.JSONB,
        allowNull: false
    }
});

sequelizeFixtures.loadFixture({
    model: 'something',
    data: {
        jsonbField: {
            prop: [111, 333]
        }
    }
}, {something: Model});

Then got

Unhandled rejection SequelizeDatabaseError: operator does not exist: text = text[]

See also sequelize/sequelize#5582

Old glob version is causing a deprecated warning

I just ran into this today so I think it just started happening. The glob version used in this project is using minimatch 0.3.0 which I guess has a huge flaw in it so they're throwing a deprecated warning to tell people to upgrade to minimatch 3.0.0 or higher.

Looks like newest glob is using the appropriate version of minimatch, so if you upgrade the glob dependency version in this project, it should fix the issue.

Proposed fix: Fix `through` associations on join tables

The current problem with adding attributes to join tables is due to the following change in sequelize:

v3:
group.addUser( alice, { role: 'member' });

v4:
group.addUser( alice, { through: { role: 'member' }});

I've forked the repo, upgraded sequelize, made the required fix. I'm happy to open a PR for this repo, if you are ok with dropping support for sequelize v3. Thoughts?

Duplicate records being inserted

Hello,

I was under the impression from the docs that duplicates would not be inserted, however, I have a database with identical records being created on each program run. Calling very simply with:

if(app.get('env') === 'development'){
    sequelize_fixtures.loadFile('fixtures/*.json', db);
  }

I'm a C/Java programmer and I'm not very familiar with Node.js or JavaScript, so maybe I am missing something? Sorry if that is the case.

Insert fails when select succeeds even with no unique constraint

I can understand if a duplicate record is not inserted when there is a unique constraint, but when I try to load fixtures with two identical records (an accident) the second is not inserted though as far as I can tell there is no reason it shouldn't be. Bug or feature?

v.0.4.0

Warning: Cannot find module

I'm trying to use grunt to import data-fixtures. However, I always got Warning: Cannot find module. Actually, I'm not quite sure what should I put in the models. Any help would be appreciated.

        fixtures: {
            data: {
                src: 'fixture/data.json',
                models: function() {
                    return require('/fixture/index.js'); // What should I put in this file?
                }
            }
        }

findById not found on model instances

Hello, great work on this lib. It's saved me a great deal of time!

Today I noticed that I was getting an error deep in loader.js. The error was:

Unhandled rejection TypeError: Object [object SequelizeModel] has no method 'findById'
    at /home/ameen/Desktop/filter/overlord/node_modules/sequelize-fixtures/lib/loader.js:127:100

My sequelize version is 2.1.3, and from isolated testing it seems that models no longer have a findById method. Unfortunately this breaks sequelize-fixtures.

Association documentation model case sensitivity issue

The documentation for association seems to be incorrect. This is what is in the readme:

[
    {
        "model": "Owner",
        "data": {
            "name": "John Doe",
            "city": "Vilnius"
        }
    },
    {
        "model": "Car",
        "data": {
            "make": "Ford",
            "owner": { //make sure it's unique across all owners
                "name": "John Doe" 
            }
        }
    }
]

owner should really be Owner to match the model name.

[
    {
        "model": "Owner",
        "data": {
            "name": "John Doe",
            "city": "Vilnius"
        }
    },
    {
        "model": "Car",
        "data": {
            "make": "Ford",
            "Owner": { //make sure it's unique across all owners
                "name": "John Doe" 
            }
        }
    }
]

sequence tables are not updated when manually setting autoincrement ids

It seems like manually setting columns which are autoincremented by db results in the db not updating any sequences it uses to track autoincrementing.

The result of this is that, if you now try to create any test data leaving 'DEFAULT' (empty) for autoincremented fields like PKs, an exception will be thrown if you manually created id 1 and db's sequence is at 0 incrementing by 1 (as it will try to insert two 1s for PK id).

You might want to do this while testing e.g. populate db in known state for all find operations - then create your own entries in the db for create, update, delete operations - leaving the db in after every test.

Please make a note of this in the README.md.

Thank you

options to fixture

I my case I want to manipulate createdAt and updatedAt values but for some reaction this is only possible when I do:

// see second argument
Call.build(data, { raw: true , isNewRecord: true })

In sequelize-fixtures the line just do an build and magically these fields are filled 😛

Maybe, if pass in .json file/array the options aka:

{ 'model':  'Call',
  'data': { 'number': '+55 11 999 878 876' },
  'options': { 'raw': true, 'isNewRecord': true }
}

belongsToMany association uses the plural form of the table on findOne

Hello, I have an issue creating a many to many association with fixtures.
In lib/loader.js#L191, assoc.target.findOne is using the plural form of the Team table and therefore the request fails because it cannot find the table.

I don't understand if my model is wrong or if it is an issue in this project.

Can you help me?

Context:

Model:

var User = sequelize.define('User', { [...] });
var Team = sequelize.define('Team', { [...] });

User.belongsToMany(Team, {
  as: 'Teams',
  foreignKey: 'userId',
  through: 'users_teams'
});
Team.belongsToMany(User, {
  as: 'members',
  foreignKey: 'teamId',
  through: 'users_teams'
});

Fixture:

[{
  "model": "User",
  "data": {
    [...],
    "Teams":[{
      [...],
      "_through":"users_teams"
    }]
  }
}]

Resulting SQL request:

SELECT [...] FROM `Teams` AS `Team` WHERE [...] LIMIT 1;

Error with belongsToMany

Hi

I'm having a problem since i updated sequelize to version 3.1.1. I also updated sequelize-fixtures to the latest version (0.4.3).

I have two tables with these associations

    user.belongsToMany(models.group, {
        through: 'user_group',
        foreignKey: 'UserId'
    });

    group.belongsToMany(models.user, {
        through: 'user_group',
        foreignKey: 'GroupId'
    });

And i have these fixtures

    [
        {
            "model": "group",
            "data": {
                "GroupId": 1,
                "Name": "grp"
            }
        },
        {
            "model": "group",
            "data": {
                "GroupId": 2,
                "Name": "grp 2"
            }
        },
        {
            "model": "user",
            "data": {
                "UserId": 1,
                "UserName":"test",
                "Name":"test",
                "Email":"[email protected]",
                "group": [1]
            }
        },
        {
            "model": "user",
            "data": {
                "UserId": 2,
                "UserName":"test2",
                "Name":"test",
                "group": [2]
            }
        },
        {
            "model": "user",
            "data": {
                "UserId": 3,
                "UserName":"test3",
                "Name":"test",
                "group": [1,2]
            }
        }
    ]

Now I'm using this with a in-memory sqlite database.

I have it set so it drops the database and recreates it before each test. The database gets created correctly and the associations are set up.

I get no errors in my log but it doesn't insert the values into the association table. I have tried to type the name of the through table as such

{
            "model": "user",
            "data": {
                "UserId": 3,
                "UserName":"test3",
                "Name":"test",
                "user_group": [1,2]
            }
        }

But in that case i get a sqlite error that says that the column group.id doesn't exist which it doesn't it's called GroupId.

Any ideas?

attribute "factory' not defined on model 'Foo'. warning, despite transformFixtureDataFn

Hey, non breaking bug here.

I'm using a dummy data value so I can know when to load in a default model. However, even if I delete the key, it's still returning the error:

attribute "factory' not defined on model 'Foo'. warning, despite using transformFixtureDataFn to remove it.

i.e.

fixtures:
  - model: Foo
    data:
      factory: foo
transformFixtureDataFn: function (data) {
  if (data.factory) {
    data = require(`${ data.factory }.js`))(data);
    delete(data.factory);
  }
  return data;
}

So, like, I don't really think it should even care about extra values.

Otherwise, it's non-breaking, but it's just a bit annoying.

Also, there's a quote '"+'" type mismatch in this console:

console.warn('attribute "' + key +"' not defined on model '" + Model.name + "'.");

Thanks

Create tables by default

Hey,
I run into Unhandled rejection SequelizeDatabaseError: relation "x" does not exist exception. The problem was that table with data wasn't created at all.

It would be nice if sequlize-fixure could check it and do something like models.sequelize.sync() when necessary.

Loader does not take any actions within `Model.set` into account

Currently I am trying to load a model which has a Sequelize.TEXT field that stores a serialized JSON blob. Doing this outside of Postgres, I need to do the serialization / parsing within the model set and get commands. Currently sequelize-fixtures loader doesn't account for these set methods which forces the system to try and sanitize an object as though it were a string, giving me this error:

Unhandled rejection TypeError: val.replace is not a function
    at Object.SqlString.escape (/Volumes/pocketship/pocketship/node_modules/sequelize/lib/sql-string.js:63:15)
    at Object.QueryGenerator.escape (/Volumes/pocketship/pocketship/node_modules/sequelize/lib/dialects/abstract/query-generator.js:977:22)
    at Object.QueryGenerator.whereItemQuery (/Volumes/pocketship/pocketship/node_modules/sequelize/lib/dialects/abstract/query-generator.js:2260:22)
    at /Volumes/pocketship/pocketship/node_modules/sequelize/lib/dialects/abstract/query-generator.js:1891:25
    at /Volumes/pocketship/pocketship/node_modules/sequelize/node_modules/lodash/lodash.js:4389:15
    at baseForOwn (/Volumes/pocketship/pocketship/node_modules/sequelize/node_modules/lodash/lodash.js:2652:24)
    at Function.forOwn (/Volumes/pocketship/pocketship/node_modules/sequelize/node_modules/lodash/lodash.js:12254:24)
    at Object.QueryGenerator.whereItemsQuery (/Volumes/pocketship/pocketship/node_modules/sequelize/lib/dialects/abstract/query-generator.js:1890:9)
    at Object.QueryGenerator.getWhereConditions (/Volumes/pocketship/pocketship/node_modules/sequelize/lib/dialects/abstract/query-generator.js:2325:19)
    at Object.QueryGenerator.selectQuery (/Volumes/pocketship/pocketship/node_modules/sequelize/lib/dialects/abstract/query-generator.js:1451:28)
    at [object Object].QueryInterface.select (/Volumes/pocketship/pocketship/node_modules/sequelize/lib/query-interface.js:669:25)
    at [object Object].<anonymous> (/Volumes/pocketship/pocketship/node_modules/sequelize/lib/model.js:1390:32)
    at [object Object].tryCatcher (/Volumes/pocketship/pocketship/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/Volumes/pocketship/pocketship/node_modules/bluebird/js/release/promise.js:504:31)
    at Promise._settlePromise (/Volumes/pocketship/pocketship/node_modules/bluebird/js/release/promise.js:561:18)
    at Promise._settlePromise0 (/Volumes/pocketship/pocketship/node_modules/bluebird/js/release/promise.js:606:10)
    at Promise._settlePromises (/Volumes/pocketship/pocketship/node_modules/bluebird/js/release/promise.js:685:18)
    at Async._drainQueue (/Volumes/pocketship/pocketship/node_modules/bluebird/js/release/async.js:138:16)
    at Async._drainQueues (/Volumes/pocketship/pocketship/node_modules/bluebird/js/release/async.js:148:10)
    at Immediate.Async.drainQueues [as _onImmediate] (/Volumes/pocketship/pocketship/node_modules/bluebird/js/release/async.js:17:14)
    at processImmediate [as _immediateCallback] (timers.js:383:17)

My model definition has been simplified to build a reproducible case:

const Role = database.define('Role', {
  permissions: {
    type: Sequelize.TEXT,
    allowNull: false,
    get(): Object {
      return JSON.parse(this.getDataValue('permissions'));
    },
    set(val: Object): void {
      this.setDataValue('permissions', JSON.stringify(val))
    },
  }
}, {
  tableName: 'roles',
  underscored: true
});

And the loaded fixture is the following:

[
  {
    "model": "Role",
    "data": {
      "permissions": {
        "*": "*"
      }
    }
  }
]

Array of files not working

I'm trying to do this
sequelize_fixtures.loadFile(['fixtures/user.json', 'fixtures/authentication.json'], models).then(() => { ... }

But it results in the following error:

Unhandled rejection TypeError: glob pattern string required
    at new Minimatch (.../node_modules/minimatch/minimatch.js:116:11)
    at setopts (.../node_modules/glob/common.js:113:20)
    at new Glob (.../node_modules/glob/glob.js:135:3)
    at glob (.../node_modules/glob/glob.js:75:10)
    at tryCatcher (.../node_modules/bluebird/js/main/util.js:26:23)
    at ret (eval at makeNodePromisifiedEval (.../node_modules/bluebird/js/main/promisify.js:163:12), <anonymous>:14:23)
    at module.exports.Reader.readFileGlob (.../node_modules/sequelize-fixtures/lib/reader.js:38:12)
    at .../node_modules/sequelize-fixtures/index.js:49:19
    at Object.loadFile (.../node_modules/sequelize-fixtures/index.js:21:23)
    at .../index.js:57:24
    at tryCatcher (.../node_modules/sequelize/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (.../node_modules/sequelize/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (.../node_modules/sequelize/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (.../node_modules/sequelize/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (.../node_modules/sequelize/node_modules/bluebird/js/release/promise.js:693:18)
    at Async._drainQueue (.../node_modules/sequelize/node_modules/bluebird/js/release/async.js:133:16)
    at Async._drainQueues (.../node_modules/sequelize/node_modules/bluebird/js/release/async.js:143:10)
    at Immediate.Async.drainQueues (.../node_modules/sequelize/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:800:20)
    at tryOnImmediate (timers.js:762:5)
    at processImmediate [as _immediateCallback] (timers.js:733:5)

I get the same error if I include only one element in the array:
sequelize_fixtures.loadFile(['fixtures/user.json'], models).then(() => { ... }

but I don't get an error I load the same file not as an array:
sequelize_fixtures.loadFile('fixtures/user.json', models).then(() => { ... }

Models not building because they are undefined

I'm trying to load a fixture into a sequelize object. It's very simple, a User model with a bunch of very basic string attributes. I'm not doing any associations or anything wacky there, simply trying to load one user at this point.

So my fixture looks like:

[{
  "model": "User",
  "data": {
    "firstname": "AJ",
    "surname": "Fisher"
  }
}]

When I go to load this fixture I'm getting a "cannot read "firstname" of Undefined" error. This is being thrown on Line 75 of loader.js which is this:

var assoc = Model.associations[key], val = data[key];

Tracing this through the debugger I can see why the error is happening which is that the Model at this point is just a function definition and is not a real "User" object, thus there's no associations and the key (firstname in this case) can't be found.

I can see that the model definition has been loaded as the function definition is correct.

I am probably missing something but I'd have thought that Model would have had to be instantiated in order to create a new object of that class before you can start manipulating the associations and then later the attributes and building it.

Nowhere in the code for loader.js can I see this happening so I'm trying to work out where this happens?

Any help would be appreciated as I'm trying to get one basic example working before then generating a decent sized fixture to load in.

jsonb datatype error

I'm not sure of the support for jsonb because it doesn't look to be mentioned or in any tests. Can anyone comment or provide an example?

I'm trying to use

  {
    model: 'Post',
    keys: [ 'content'],
    data: {
      id: 0,
      title: 'Test Title 1',
      slug: 'slug-1',
      content: [
        {
          'type': 'text',
          'body': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin vulputate ornare elit sed tristique. Cras semper ornare elit, sit amet aliquet odio viverra vel. Sed ultricies nec ante eu tempus. Quisque nec porta nisl.'
        }
      ],
      Tags: [122, 123],
      User: 2
    }
  }

I'm getting Unhandled rejection TypeError: undefined is not a function. I'm new to using sequelize and sequelize-fixtures tho.

Cannot load Fixture

I am currently trying to load a json file into my database, but get a strange error.

Fixtures: reading file ./app/tests/data/sampledata.json...
Unhandled rejection TypeError: Cannot convert undefined or null to object
    at Function.keys (native)
    at /vagrant/ase-2016/web/node_modules/sequelize-fixtures/lib/loader.js:114:16
    at Array.forEach (native)
    at Loader.prepFixtureData (/vagrant/ase-2016/web/node_modules/sequelize-fixtures/lib/loader.js:111:23)
    at Loader.loadFixture (/vagrant/ase-2016/web/node_modules/sequelize-fixtures/lib/loader.js:40:17)
    at null.<anonymous> (/vagrant/ase-2016/web/node_modules/sequelize-fixtures/lib/loader.js:12:21)
    at tryCatcher (/vagrant/ase-2016/web/node_modules/sequelize-fixtures/node_modules/bluebird/js/main/util.js:26:23)
    at ReductionPromiseArray._promiseFulfilled (/vagrant/ase-2016/web/node_modules/sequelize-fixtures/node_modules/bluebird/js/main/reduce.js:105:38)
    at ReductionPromiseArray.init (/vagrant/ase-2016/web/node_modules/sequelize-fixtures/node_modules/bluebird/js/main/promise_array.js:92:18)
    at ReductionPromiseArray.init (/vagrant/ase-2016/web/node_modules/sequelize-fixtures/node_modules/bluebird/js/main/reduce.js:42:10)
    at Async._drainQueue (/vagrant/ase-2016/web/node_modules/sequelize-fixtures/node_modules/bluebird/js/main/async.js:128:12)
    at Async._drainQueues (/vagrant/ase-2016/web/node_modules/sequelize-fixtures/node_modules/bluebird/js/main/async.js:133:10)
    at Immediate.Async.drainQueues [as _onImmediate] (/vagrant/ase-2016/web/node_modules/sequelize-fixtures/node_modules/bluebird/js/main/async.js:15:14)
    at processImmediate [as _immediateCallback] (timers.js:383:17)

seed_db.js

"use strict";
var sequelize_fixtures = require("sequelize-fixtures"),
    models = {
        User: require("./app/models/user"),
        LinkedService: require("./app/models/linkedServices"),
        Position: require("./app/models/position"),
        Position_Skill: require("./app/models/position_Skill"),
        Project: require("./app/models/project"),
        Rating: require("./app/models/rating"),
        Skill: require("./app/models/skill"),
        User_Skill: require("./app/models/user_Skill")
    };

sequelize_fixtures.loadFile("./app/tests/data/*.json", models).then(() => {

});

sampledata.json

[
    {
        "model": "User",
        "data": {
            "id": 2,
            "first_name": "first_name",
            "last_name": "last_name",
            "username": "testuser",
            "password": "password",
            "avatar": "path",
            "email": "email",
            "developer": true,
            "owner": false,
            "designer": false,
            "free_hours": 10,
            "avg_rating_owner": 0.4,
            "avg_rating_developer": 0.4,
            "avg_rating_designer": 0.4,
            "createdAt": "2004-10-19 10:23:54",
            "updatedAt": "2004-10-19 10:23:54"
        }
    },
    {
        "model": "LinkedServices",
        "data": {
            "id": 2,
            "user": 2,
            "token": "token1",
            "service": "GitHub"
        }
    },
   {
        "model": "Project",
        "data": {
            "id": 1,
            "UserId": 2,
            "name": "project1",
            "short_description": "project1",
            "private_description": "project1",
            "public_description": "project1",
            "budget": 10000,
            "status": "running"
        }
    },
    {
        "model": "Position",
        "data": {
            "id": 1,
            "hours": 2,
            "budget": 1000,
            "name": "position1",
            "type": "Developer",
            "ProjectId": 1,
            "status": "accepted"
        }
    },
    {
        "model": "Position",
        "data": {
            "id": 2,
            "hours": 2,
            "budget": 1000,
            "name": "position2",
            "type": "Designer",
            "UserId": 2,
            "ProjectId": 1,
            "status": "rejected"
        }
    },
    {
        "model": "Rating",
        "data": {
            "id": 1,
            "rating": 0.5,
            "feedback": "1000",
            "UserId": 2,
            "PositionId": 2
        }
    },
    {
        "model": "Skill",
        "data": {
            "id": 1,
            "name": "JAVA"
        }
    },
    {
        "model": "Skill",
        "data": {
            "id": 2,
            "name": "JPA",
            "parent_Skill_id": 1
        }
    },
    {
        "model": "User_Skill",
        "data": {
            "id": 1,
            "weight": 0.4,
            "SkillId": 1,
            "UserId": 2
        }
    },

    {
        "model": "Position_Skill",
        "data": {
            "id": 1,
            "weight": 0.4,
            "PositionId": 1,
            "SkillId": 1
        }
    }
]

Cant make any sense of it. Tried pinpointing the locations of the problem in the source code, but havent got a single clue what could even be causing this. any help greatly appreciated!

Fixture Many-to-many

Hi,

is possible to create a fixture for a table provided by a Many-to-many association ?

Loading fixtures with foreign keys

Hi,

I have been trying to use sequelize-fixtures to build a database that includes foreign keys, but when I do, I get the following error

[TypeError: Object # has no method 'replace'].

The main code db-create.js is

'user strict';
var Sequelize = require('sequelize');
var sequelize_fixtures = require('sequelize-fixtures');

var sf = require('./index')
sf.sequelize.sync().then(function(r) {
        var constant_models = {
                UserType: sf.UserType,
                User: sf.User
        };

        var models = {
                User: sf.User
        };

        sequelize_fixtures.loadFile('./constants.json', constant_models).then(function(r) {
                console.log("success loading!");
        }, function(err) {
                console.log("loading constants");
                console.log(err);
        });
}, function(err) {
        console.log('error syncing', err)
});

index.js is:

var Sequelize = require('sequelize');

var sequelize = new Sequelize('db', 'usr', 'pwd', {
        host: 'localhost',
        port: '5432',
        dialect: 'postgres',
        pool: false
});

exports.sequelize = sequelize
exports.all = [];
var schemaName = 'test'
exports.schemaName = schemaName
sequelize.createSchema(schemaName);


['UserType', 'User'].forEach(function(model) {
        var mod = require('./' + model)(sequelize, Sequelize, schemaName);
        module.exports[model] = mod;
        exports.all.push(mod);
});

(function(m){
        m.User.belongsTo(m.UserType, {
                foreignKey: {
                        name: 'fk_user_type',
                        allowNull: false
                }
        });
        m.UserType.hasMany(m.User, {
                foreignKey: 'fk_user_type',
                allowNull: false
        });
})(exports);

UserType.js is:

'use strict';
module.exports = function(sequelize, DataTypes, schema) {

        var UserType = sequelize.define('user_types', {
                id: {
                        type: DataTypes.INTEGER,
                        autoIncrement: true,
                        primaryKey: true,
                        allowedNull: false
                },
                userType: {
                        type: DataTypes.STRING,
                        field: 'user_type',
                        unique: true,
                        allowedNull: false
                }
        }, {
                freezeTableName: true,
                schema: schema,
                underscored: true,
                underscoredAll: true
        });

        return UserType;
};

and User.js is:

'use strict';

module.exports = function(sequelize, DataTypes, schema) {
        var User = sequelize.define('users', {
                id: {
                        type: DataTypes.INTEGER,
                        autoIncrement: true,
                        primaryKey: true,
                        allowedNull: false
                },
                firstName: {
                        type: DataTypes.STRING,
                        field: 'first_name',
                        allowNull: false,
                        unique: 'users_uq1'
                },
                lastName: {
                        type: DataTypes.STRING,
                        field: 'last_name',
                        allowNull: false,
                        unique: 'users_uq1'
                },
                email: {
                        type: DataTypes.STRING,
                        allowNull: false,
                        unique: true,
                        validate: {
                                isEmail: true
                        }
                },
                salt: {
                        type: DataTypes.STRING,
                        allowNull: false,
                        unique: true
                },
                password: {
                        type: DataTypes.STRING,
                        allowNull: false,
                        unique: true
                },
                lastLogin: {
                       type: DataTypes.DATE,
                        field: 'last_login',
                        allowNull: false,
                        validate: {
                                isDate: true,
                                isAfter: '2016-01-01'
                        }
                }
        }, {
                freezeTableName: true,
                schema: schema,
                underscored: true,
                underscoredAll: true

        });
        return User;
};

The data, constants.json, is

[{
        "model": "UserType",
        "data": {
                "userType": "Administrator"
        }
},{
        "model": "User",
        "data": {
                "firstName": "D",
                "lastName": "R",
                "email": "[email protected]",
                "lastLogin": "2016-02-01",
                "salt": "brownies",
                "password": "pass",
                "fk_user_type": {
                        "userType": "Administrator"
                }
        }
},{
        "model": "User",
        "data": {
                "firstName": "j",
                "lastName": "r",
                "email": "[email protected]",
                "lastLogin": "2016-02-01",
                "password": "password",
                "fk_user_type": {
                        "userType": "Administrator"
                }
        }
}]

Any help or suggestions would be appreciated!

Add flag to suppress usage of use of property setter methods in case they use instance methods [feedback wanted]

Proposed Feature

Adds a fixture-level flag to disable the user of setter methods. This is a necessary feature if your model's setter methods us instance methods other than simple this.setDataValue.

The new flag will be called ignoreSet or something like:

  • ignoreSetter
  • ignoreSetters
  • ignorePropertySetter
  • ignorePropertySetters
  • Something else? Thoughts on a better name?

Usage

  - model: User
    ignoreSet: true
    data:
      email: [email protected]

Other Thoughts

Considered putting this under an options object as:

  - model: User
    options:    
      ignoreSet: true
    data:
      email: [email protected]

But so far there are no other sequelize-fixtures specific options (the options are pass-through options for sequelize build / create methods only.

Background

If you use property setters, this library attempts to feed values from fixtures into them in case there is some coercion or formatting, etc.

The Problem

This library calls the setters in a simulated way, without a real object instance.

Steps to reproduce

  • Define a model with at least one set method using any instance method inside (e.g. this.previous or anything except this.setDataValue).

Example:

  const User = sequelize.define('User', {
    id: {
      autoIncrement: true,
      primaryKey: true,
      type: DataTypes.INTEGER
    },
    email: {
      type: DataTypes.STRING,
      validate: {
        isEmail: true
      },
      set: function set(val) {
        if (this.previous('email')) {
          throw new Error('Updating email is not allowed');
        }
        this.setDataValue('email', val);
      }
    }
  });

Actual behavior

[TypeError: this.previous is not a function

Expected behavior: using defined instance methods should not fail

// caused by this:
Model.rawAttributes[k].set.call(Model, data[k]);

Sequelize 4

I'm testing sequelize-fixtures with sequelize version 4

Source code

import sequelizeFixtures from 'sequelize-fixtures';

let orm = new Sequelize(this._config.database.name, ...)
let fixtures = ['./lib/resources/fixtures/user.json'];

return sequelizeFixtures.loadFiles(fixtures, orm.models);

OUTPUT

Error: models.User appears to be a function. 
Perhaps you are importing model factory function? 
You should then use sequelize.import to create your model, see https://github.com/sequelize/express-example/blob/master/models/index.js#L17

Same piece of code works like a charm with sequelize version 3

Data are not loaded

I have the same problem as described here: #16. However changing path to absolute doesn't help. My fixtures files are in test/fixtures/categories.json file. I load them:

it('returns true', () => {
  sequelizeFixtures.loadFile(__dirname + '/fixtures/categories.json', models)
    .then(() => {
      // do something
    });  
});

No errors on database, no errors in console. I get message from plugin:

Fixtures: reading file /Users/apple/Projects/my-project/test/fixtures/categories.json...

What I found is that the problem is in reader module, readFile method. fs.readFileAsync never resolve. However it also doesn't throw any errors.

dump fixtures

Hello,

Thanks for this lib, very useful. Is there any plan for a dump fixture feature ?

Disable Console.log

I am using this fixture to aid my unit testing. However, I get logs like:

Fixtures: reading file C:/Users/George/testProj/server/seeders/test.json...

Which affect my test output log, is it possible to disable this?

Data was not loaded

Hi;

My data is:

[{
    "model": "Language",
    "data": {
        "code": "en",
        "name": "English",
        "flag": "gb"
    }
}, {
    "model": "Language",
    "data": {
        "code": "tr",
        "name": "Türkçe",
        "flag": "tr"
    }
}, {
    "model": "Language",
    "data": {
        "code": "sv",
        "name": "Svenska",
        "flag": "sv"
    }
}

]

And code is:

var sequelize_fixtures = require('sequelize-fixtures'),
models = {
    Language: require('../app/models/language')
};
console.log("--------Fixtures started to load-------------");

sequelize_fixtures.loadFile('../fixtures/test_data.json', models, function() {
    console.log("Fixtures were loaded");
});

I see the fixtures loaded log, but there is no data in the db. Where am I wrong?

How to set data on a join table embodying an N:M relationship?

In sequelize it's possible to define an n:m relationship, but then define properties on that relationship with a third model seen here.

I have a setup like that; I'm using sequelize-fixtures to load data into both sides of the relationship, but I don't see in the docs how to put data on the relationship. In the sequelize example, they use this:

UserProject = sequelize.define('user_project', {
  role: Sequelize.STRING
});
User.belongsToMany(Project, { through: UserProject });
Project.belongsToMany(User, { through: UserProject });
// through is required!

user.addProject(project, { role: 'manager', transaction: t });

In JSON fixture data, what I tried (but failed at) was something like this. This was an (intuitive to me) guess at how it'd be done, but really I can't find anything in the docs on how it should be done.

{
   'model': 'User',
   'data': { 'name': 'Bob' }
},
{
  'model': 'Project',
  'data': { 
     'name': 'S00per secret',
     'data': {
         'role': 'manager'
     }
}

But no dice on that.

I've also experimented with adding entries for the join table (UserProject) but this seems not to work because of the way the models are defined. From the join table's perspective, it doesn't have relationships to lookup the right User. And if you define those relationships on the join table so they'll be there, you get a cyclical dependency error from sequelize.

The sequelize docs state that the above setup is the right way to model N:M relationships with properties on the relationship. So how can I use sequelize-fixtures to get that data in?

is it possible to make updates with fixtures?

As the title says. I'm trying to update a record, but the rule of fixture makes him fetch the data that I am wanting to update. So finding no record to make an update. How do I tell which fields it must fetch and what it should perform the update?

{
"model": "Project",
"buildOptions": {
"isNewRecord": false
},
"saveOptions": {
"fields": ["personId"]
},
"data": {
"name": "Avengers" <-- Field that i want to do the where,
"person": { <-- Field i want to update (its a personId)
"name": "Spider Man"
}
}
}

/lib/loader.js line47 has boolean problem

If my db schema has a boolean attribute and this attribute value is false, it can not pass this line.
I suggest we can change ' if (data[k]) ' to if (data.hasOwnProperty[k]) to solve this problem .

Save on Sequelize 1.7.10

I am using Sequelize 1.7.10, seems on that version if Model.build() second param is called with an Object it does an UPDATE even if there is no data on Database. I fixed changing line 17 of loader.js. Also happens with 1.7.0.

Loader.prototype.loadFixture = function(fixture, models) {
    var buildOptions = fixture.buildOptions,
        saveOptions = fixture.saveOptions || {},

Could be changed?

Create observer transformData

Like the option transformFixtureDataFn but passed as observers of sequelize-fixtures.

sequelize_fixtures = require('sequelize-fixtures');

var rnd = function (qtd) {
  return String(Math.floor(Math.random() * qtd));
};

sequelize_fixtures.addTransformData(function (data, model) {
  if (Model.tableName === 'books') {
    data.isbn = rnd(1E6);
  }
  return data;
});

sequelize_fixtures.addTransformData(function (data, model) {
  var iterator;
  for (iterator in data) {
    data[iterator] = data[iterator].replace(/#{rnd}/, rnd(1E3));
  }
  return data;
});

So, with this option it's possible to create other packages that extend this package 😄.

v4 incompatabiliy - Error: models.User appears to be a function

I have just upgraded to v4. I am now getting the issue:

Unhandled rejection Error: models.User appears to be a function. Perhaps you are importing model factory function? You should then use sequelize.import to create your model, see https://github.com/sequelize/express-example/blob/master/models/index.js#L17

Here is an example of the seed.json file I am using:

[{
        "model": "User",
        "data": {
            "email": "[email protected]",
            "password": "Password",
            "role": "Operator"
        }
}]

here is my User model:

export default function defineUser(sequelize: Sequelize.Sequelize, DataTypes) {
  var User = sequelize.define<UserInstance, UserAttributes>('User', {
    email: {
      type: Sequelize.STRING,
      unique: true,
      validate: { isEmail: true }
    },
    password: Sequelize.STRING,
    role: {
      type: DataTypes.ENUM,
      values: ['Admin', 'Operator', 'Member']
    }
  });

  User.beforeCreate(function (user: UserInstance, options) {
    return hashPassword(user.password).then(function (hashedPw) {
      user.password = hashedPw;
    });
  })
  return User;
};

I haven't got much further with my debugging, but it is definitely the test-fixture causing the issue. Aside from that, sequelize seems to be working fine with the model definition.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.