sequelize-fixtures

repository·master·Indexed 43 days ago

https://github.com/domasx2/sequelize-fixtures

A utility library for loading test data into databases using Sequelize. Version 1.2.0 supports JSON, YAML, and JavaScript formats, handling complex associations, duplicate detection via keys, and custom data transformations. It provides core methods such as loadFile, loadFiles, and loadFixtures, and includes a Grunt task for workflow integration.

Tokens
3.1K
Snippets
9
Records
12
Agent score
5%

What's inside sequelize-fixtures

  1. Define associations in fixtures

    master

    To handle relationships, ensure that associated objects are described in the fixture file before the objects that reference them. You can link entities using IDs or property-value maps.

    One-to-Many (belongsTo / hasMany)

    Using ID:

    [
        { "model": "Owner", "data": { "id": 11, "name": "John" } },
        { "model": "Car", "data": { "owner": 11 } }
    ]

    Using a property-value map (where clause):

    [
        { "model": "Owner", "data": { "name": "John" } },
        { "model": "Car", "data": { "owner": { "name": "John" } } }
    ]

    Many-to-Many (belongsToMany)

    Use the association's as name or the through table name. Provide an array of IDs or an array of property-value maps.

    Using IDs:

    [
        { "model": "Person", "data": { "id": 122, "name": "Jack" } },
        { "model": "Project", "data": { "people": [122] } }
    ]

    Using property-value maps:

    [
        { "model": "Person", "data": { "name": "Jack" } },
        { "model": "Project", "data": { "people": [{ "name": "Jack" }] } }
    ]

    Custom Through Model attributes: If using a custom through model, use the _through key to set additional attributes on the join table.

    [
        { "model": "Actor", "data": { "name": "Arnie", "movies": [{ "name": "Terminator", "_through": { "character": "T-80" } }] } }
    ]
  2. Configure loadFile options

    master

    When calling loadFile, you can pass an options object to customize behavior:

    • encoding: Specify file encoding (default: 'utf8').
    • log: A function to handle logging (default: console.log).
    • logger: An object containing custom log levels: { debug, info, warn, error } (useful for integration with loggers like Winston).
    • transaction: Pass a Sequelize transaction object to load fixtures within a transaction.
    • transformFixtureDataFn: A function to transform data before it is applied to the model.
    • modifyFixtureDataFn: A function to modify data during the loading process.

    Examples

    Using a custom logger:

    sequelize_fixtures.loadFile('fixtures/*.json', models, {
      logger: {
        debug: console.log,
        info: console.log,
        warn: console.log,
        error: (msg) => console.error('ERROR: ' + msg)
      }
    });

    Loading within a transaction:

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

    Transforming data:

    sequelize_fixtures.loadFile('fixtures/*.json', models, {
        transformFixtureDataFn: function (data) {
          if (data.createdAt && data.createdAt < 0) {
            data.createdAt = new Date();
          }
          return data;
        }
    });
    // Example of transformFixtureDataFn
    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(doStuffAfterLoad);
  3. Use sequelize-fixtures API

    master

    The library provides several methods to load data. It requires a models object, which is a map of [model name] : model (typically generated by your Sequelize models index file). All methods return Bluebird promises, but you can also provide a callback as the last argument.

    Core Methods

    • loadFile(path, models, [options]): Loads data from a single file or a glob pattern.
    • loadFiles(filePaths, models, [options]): Loads data from an array of file paths (supports glob syntax).
    • loadFixtures(fixturesArray, models, [options]): Loads data from a direct JavaScript array of fixture objects.
    const sequelize_fixtures = require('sequelize-fixtures');
    const models = require('./models');
    
    // Load a single file
    sequelize_fixtures.loadFile('fixtures/test_data.json', models).then(() => {
        // success
    });
    
    // Load multiple files using glob syntax
    sequelize_fixtures.loadFile('fixtures/*.json', models);
    
    // Load an array of files
    sequelize_fixtures.loadFiles(['fixtures/users.json', 'fixtures/data*.json'], models);
    
    // Load directly from a JavaScript array
    const fixtures = [
        {
            model: 'Foo',
            data: { propA: 'bar', propB: 1 }
        }
    ];
    sequelize_fixtures.loadFixtures(fixtures, models);
  4. Configure loading options

    master

    All primary API methods (loadFixture, loadFixtures, loadFile, loadFiles) accept an optional options object as the third argument.

    Currently, the supported option is:

    • encoding: The character encoding used for reading files. Defaults to 'utf8'.
    // Example using encoding option
    sequelizeFixtures.loadFile('fixtures/*.json', models, { encoding: 'utf8' });
  5. Supported fixture file formats

    master

    You can define your fixtures in JSON, YAML, or JavaScript formats. Each entry must specify a model and the data to be inserted.

    JSON

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

    YAML

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

    JavaScript

    module.exports = [
        {
            "model": "Foo",
            "data": {
                "propA": "bar",
                "propB": 1
            }
        }
    ];
  6. Advanced model configuration in fixtures

    master

    You can fine-tune how models are instantiated and saved within a fixture entry.

    Build and Save Options

    Provide buildOptions (passed to Model.build()) and saveOptions (passed to instance.save()).

    {
        "model": "Article",
        "buildOptions": { "raw": true },
        "saveOptions": { "fields": ["title"] },
        "data": { "title": "Hello" }
    }

    Duplicate Detection via Keys

    To prevent duplicates based on specific fields (instead of all fields), use the keys property. This is useful if you want to ignore entities with the same ID but different data, or vice versa.

    {
        "model": "Person",
        "keys": ["email"],
        "data": { "name": "John", "email": "john@example.com" }
    }

    Ignoring Setters

    If your Sequelize model has custom setters that cause errors during fixture loading (e.g., they access this.previous()), set ignoreSet: true. This tells the library to set the data literals directly without running the setters.

    {
        "model": "User",
        "ignoreSet": true,
        "data": { "email": "test@example.com" }
    }
  7. Use the sequelize-fixtures Grunt task

    master

    You can integrate fixture loading into your Grunt workflow. The task supports asynchronous model loading.

    grunt.initConfig({
        fixtures: {
            import_test_data: {
                src: ['fixtures/data1.json', 'fixtures/models*.json'],
                models: async function () {  
                    return await loadModels();
                },
                options: {
                    encoding: 'windows-1257'
                }
            }
        }
    });
    
    grunt.loadNpmTasks('sequelize-fixtures');
    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');
  8. Load a single fixture with loadFixture()

    master

    Use loadFixture to load a single fixture object into your Sequelize models. This function returns a Promise that resolves when the fixture is loaded. While it supports a callback as an argument, using the returned Promise is the recommended approach.

    const sequelizeFixtures = require('sequelize-fixtures');
    
    // fixtures: the fixture object
    // models: your Sequelize models object
    // options: (optional) configuration object
    sequelizeFixtures.loadFixture(fixture, models)
      .then(() => console.log('Fixture loaded!'))
      .catch(err => console.error(err));
  9. Load multiple fixtures with loadFixtures()

    master

    Use loadFixtures to load an array of fixture objects into your Sequelize models. This function returns a Promise that resolves when all fixtures in the array are loaded.

    const sequelizeFixtures = require('sequelize-fixtures');
    
    // fixtures: an array of fixture objects
    // models: your Sequelize models object
    sequelizeFixtures.loadFixtures(fixtures, models)
      .then(() => console.log('All fixtures loaded!'))
      .catch(err => console.error(err));
  10. Load fixtures from a file pattern with loadFile()

    master

    Use loadFile to load fixtures from files matching a glob pattern. The function uses a Reader to find files matching the filename pattern and then uses the Loader to inject them into your models. It returns a Promise.

    const sequelizeFixtures = require('sequelize-fixtures');
    
    // filename: a glob pattern (e.g., 'test/fixtures/*.json')
    // models: your Sequelize models object
    sequelizeFixtures.loadFile('test/fixtures/*.json', models)
      .then(() => console.log('Fixtures from files loaded!'))
      .catch(err => console.error(err));
  11. Load fixtures from specific files with loadFiles()

    master

    Use loadFiles to load fixtures from a specific list of filenames. This function returns a Promise that resolves once all specified files have been read and loaded into the models.

    const sequelizeFixtures = require('sequelize-fixtures');
    
    // filenames: an array of file paths
    // models: your Sequelize models object
    sequelizeFixtures.loadFiles(['file1.json', 'file2.json'], models)
      .then(() => console.log('Specific files loaded!'))
      .catch(err => console.error(err));