<commit_before>/* global, describe, it */

var chai = require('chai'),
    sinon = require('sinon'),
    sinonChai = require('sinon-chai'),
    expect = chai.expect,
    React = require('react'),
    Backbone = require('backbone'),
    _ = require('underscore'),
    $ = {
        options: [],
        ajax: function(options) {
          this.options.push(options);
        },
        success: function(data) {
          var options = this.options.pop();
          options.success && options.success(data);
        },
        error: function(error) {
          var options = this.options.pop();
          options.error && options.error(error);
        }
      };
chai.use(sinonChai);
Backbone.$ = $;

// intitialize dependencies
require('react-mixin-manager')(React);
require('backbone-async-event')(Backbone);
require('react-events')(React);
// add react-backbone mixins
require('../index')(React, Backbone);

function newComponent(attributes, mixins) {

  if (mixins) {
    mixins = React.mixins.get(mixins);
  } else {
    mixins = [];
  }

  var obj = {
    setState: sinon.spy(),
    setProps: function(props) {
      this.props = this.props || {};
      _.extend(this.props, props);
    },
    mount: function() {
      this._mounted = true;
      this.trigger('componentWillMount');
      this.trigger('componentDidMount');
    },
    unmount: function() {
      this._mounted = false;
      this.trigger('componentWillUnmount');
      this.trigger('componentDidUnmount');
    },

    isMounted: function() { return this._mounted; },
    trigger: function(method) {
      var rtn = [];
      for (var i=0; i<mixins.length; i++) {
        var func = mixins[i][method];
        if (func) {
          rtn.push(func.apply(this, Array.prototype.slice.call(arguments, 1)));
        }
      }
      return rtn;
    }
  };
  if (attributes) {
    for (var name in attributes) {
      obj[name] = attributes[name];
    }
  }

  var state, aggregateState;

  for (var i=0; i<mixins.length; i++) {
    var mixin = mixins[i];
    _.defaults(obj, mixin);
    state = mixin.getInitialState && mixin.getInitialState.call(obj);
    if (state) {
      if (!aggregateState) {
        aggregateState = {};
      }
      _.defaults(aggregateState, state);
    }
  }
  obj.state = aggregateState;
  return obj;
}

var Model = Backbone.Model.extend({
  url: 'foo'
});

describe('modelAware', function() {

  it('should get and set the model', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelAware']);
    expect(obj.getModel()).to.eql(model);

    var model2 = new Backbone.Model();
    obj.setModel(model2);
    expect(obj.getModel()).to.eql(model2);    
  });
});

describe('modelPopulate', function() {

  it('should iterate components and call getUIValue to set attributes', function() {
    var obj = newComponent({}, ['modelPopulate']);
    var components = [
      {
        props: {
          ref: 'foo'
        },
        getUIValue: function() {
          return 'bar';
        }
      }
    ];
    var attributes = obj.modelPopulate(components);
    expect(attributes).to.eql({foo: 'bar'});
  });

  it('should iterate components and call getModelValue to set attributes using refs', function() {
    var obj = newComponent({}, ['modelPopulate']);
    var component = {
      props: {
        ref: 'foo'
      },
      getUIValue: function() {
        return 'bar';
      }
    };
    obj.refs = {
      foo: component
    };
    var attributes = obj.modelPopulate();
    expect(attributes).to.eql({foo: 'bar'});
  });

  it('should set values on model if a callback is provided', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelAware', 'modelPopulate']);
    var component = {
      props: {
        ref: 'foo'
      },
      getUIValue: function() {
        return 'bar';
      }
    };
    obj.refs = {
      foo: component
    };
    var spy = sinon.spy(),
        attributes = obj.modelPopulate(spy);
    expect(spy).to.have.been.called;
    expect(attributes).to.eql({foo: 'bar'});
  });

  it('should not execute the callback if the validation fails', function() {
    var Model = Backbone.Model.extend({
      validate: sinon.spy(function() {
        // just return something so it looks like validation failed
        return 'fail';
      })
    })
    var model = new Model(),
        obj = newComponent({props: {model: model}}, ['modelAware', 'modelPopulate']);
    var component = {
      props: {
        ref: 'foo'
      },
      getUIValue: function() {
        return 'bar';
      }
    };
    obj.refs = {
      foo: component
    };
    var spy = sinon.spy(),
        attributes = obj.modelPopulate(spy);
    expect(spy).to.not.have.been.called;
    expect(attributes).to.eql({foo: 'bar'});
    expect(Model.prototype.validate).to.have.been.calledWith({foo: 'bar'});
  });
});

describe('modelValueAware', function() {

  it('should get and set the model value using "key"', function() {
    var model = new Backbone.Model({foo: 'bar'}),
        obj = newComponent({props: {model: model, key: 'foo'}}, ['modelValueAware']);
    expect(obj.getModelValue()).to.eql('bar');
    obj.setModelValue('baz');
    expect(model.get('foo')).to.eql('baz');
  });

  it('should get and set the model value using "ref"', function() {
    var model = new Backbone.Model({foo: 'bar'}),
        obj = newComponent({props: {model: model, ref: 'foo'}}, ['modelValueAware']);
    expect(obj.getModelValue()).to.eql('bar');
    obj.setModelValue('baz');
    expect(model.get('foo')).to.eql('baz');
  });
});

describe('modelValidator', function() {
  var Model = Backbone.Model.extend({
    validate: function(attributes, options) {
      return options && options.rtn;
    }
  })

  it('should return undefined if no model exists or the model does not implement "validate"', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelValidator']);
    expect(obj.modelValidate()).to.eql(undefined);
  });
  it('should return false if "validate" returns a falsy value', function() {
    var model = new Model(),
        obj = newComponent({props: {model: model}}, ['modelValidator']);
    expect(obj.modelValidate()).to.eql(false);
  });
  it('should return the same value if "validate" returns a truthy value', function() {
    var model = new Model(),
        obj = newComponent({props: {model: model}}, ['modelValidator']);
    expect(obj.modelValidate(undefined, {rtn: 'foo'})).to.eql('foo');
  });
});

describe('modelEventAware', function() {

  it('should not do event binding until node is mounted', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelEventAware']),
        spy = sinon.spy();
    obj.modelOn('foo', spy);
    model.trigger('foo');
    // we shouldn't bind yet because we aren't mounted
    expect(spy.callCount).to.eql(0);

    obj.mount();
    model.trigger('foo');
    expect(spy.callCount).to.eql(1);

    // we shouldn't bind now because we will be unmounted
    obj.unmount();
    model.trigger('foo');
    expect(spy.callCount).to.eql(1);

    // mount again and ensure that we rebind
    obj.mount();
    model.trigger('foo');
    expect(spy.callCount).to.eql(2);
    obj.unmount();
    model.trigger('foo');
    expect(spy.callCount).to.eql(2);
  });

  it('should bind if model does not exist when registered', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelEventAware']),
        spy = sinon.spy();

    // setting model before mounting
    obj.modelOn('foo', spy);
    obj.setModel(model);
    // we shouldn't bind yet because we are not mounted
    model.trigger('foo');
    expect(spy.callCount).to.eql(0);

    obj.mount();
    model.trigger('foo');
    expect(spy.callCount).to.eql(1);
  });

  it('should bind if component has already been mounted when setting model', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelEventAware']),
        spy = sinon.spy();

    obj.modelOn('foo', spy);
    obj.mount();
    obj.setModel(model);
    model.trigger('foo');
    expect(spy.callCount).to.eql(1);
  });

  it('should unbind a previous model and rebind to a new model', function() {
    var model1 = new Backbone.Model(),
        model2 = new Backbone.Model(),
        obj = newComponent({props: {model: model1}}, ['modelEventAware']),
        spy = sinon.spy();

    obj.modelOn('foo', spy);
    obj.mount();
    model1.trigger('foo');
    expect(spy.callCount).to.eql(1);

    // set another model and ensure the first was unbound
    obj.setModel(model2);
    model1.trigger('foo');
    expect(spy.callCount).to.eql(1); // ensure the previous trigger *did not* call the handler
    model2.trigger('foo');
    expect(spy.callCount).to.eql(2);
  });
});

describe('modelChangeAware', function() {
  var clock;
  beforeEach(function() {
    clock = sinon.useFakeTimers();
  });
  afterEach(function() {
    clock.restore();
  });

  it('should listen to all events and force an update', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelChangeAware']),
        spy = sinon.spy();
    obj.forceUpdate = spy;
    
    obj.mount();
    expect(spy.callCount).to.eql(0);
    model.trigger('change');
    clock.tick(1);
    expect(spy.callCount).to.eql(1);
    model.trigger('reset');
    clock.tick(1);
    expect(spy.callCount).to.eql(2);
    model.trigger('add');
    clock.tick(1);
    expect(spy.callCount).to.eql(3);
    model.trigger('remove');
    clock.tick(1);
    expect(spy.callCount).to.eql(4);
    model.trigger('sort');
    clock.tick(1);
    expect(spy.callCount).to.eql(5);
  });
});

describe('modelUpdateOn', function() {
  var clock;
  beforeEach(function() {
    clock = sinon.useFakeTimers();
  });
  afterEach(function() {
    clock.restore();
  });

  it('should listen to provided events and force an update', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model, updateOn: 'foo'}}, ['modelUpdateOn']),
        spy = sinon.spy();
    obj.forceUpdate = spy;
    
    obj.mount();
    expect(spy.callCount).to.eql(0);
    model.trigger('foo');
    clock.tick(1);
    expect(spy.callCount).to.eql(1);
  });

  it('should listen to provided events (as array) and force an update', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model, updateOn: ['foo', 'bar']}}, ['modelUpdateOn']),
        spy = sinon.spy();
    obj.forceUpdate = spy;
    
    obj.mount();
    expect(spy.callCount).to.eql(0);
    model.trigger('foo');
    clock.tick(1);
    expect(spy.callCount).to.eql(1);
    model.trigger('bar');
    clock.tick(1);
    expect(spy.callCount).to.eql(2);
  });

  it('should listen to declaring component provided events and force an update', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelUpdateOn("foo", "bar")']),
        spy = sinon.spy();
    obj.forceUpdate = spy;
    
    obj.mount();
    expect(spy.callCount).to.eql(0);
    model.trigger('foo');
    clock.tick(1);
    expect(spy.callCount).to.eql(1);
    model.trigger('bar');
    clock.tick(1);
    expect(spy.callCount).to.eql(2);
  });
});


// THE FOLLING TESTS ASSUME THE INCLUSION OF [backbone-async-event](https://github.com/jhudson8/backbone-async-event)

describe('modelLoadOn', function() {

  it('should set loading state when an async event is triggered (success condition)', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model, loadOn: 'foo'}}, ['modelLoadOn']),
        spy = sinon.spy();
    obj.setState = spy;
    obj.mount();

    Backbone.sync('foo', model, {url: 'foo'});
    expect(spy).to.have.been.calledWith({loading: true});
    $.success();
    expect(spy).to.have.been.calledWith({loading: false});
    expect(spy.callCount).to.eql(2);
  });

  it('should set loading state when an async event is triggered (error condition)', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model, loadOn: 'foo'}}, ['modelLoadOn']),
        spy = sinon.spy();
    obj.setState = spy;
    obj.mount();

    obj.mount();

    Backbone.sync('foo', model, {url: 'foo'});<commit_msg>clean up unit tests<commit_after>/* global, describe, it, beforeEach, afterEach, React, Backbone, _ */

var chai = require('chai'),
    sinon = require('sinon'),
    sinonChai = require('sinon-chai'),
    expect = chai.expect,
    React = require('react'),
    Backbone = require('backbone'),
    _ = require('underscore'),
    $ = {
        options: [],
        ajax: function(options) {
          this.options.push(options);
        },
        success: function(data) {
          var options = this.options.pop();
          options.success && options.success(data);
        },
        error: function(error) {
          var options = this.options.pop();
          options.error && options.error(error);
        }
      };
chai.use(sinonChai);
Backbone.$ = $;

// intitialize dependencies
require('react-mixin-manager')(React);
require('backbone-async-event')(Backbone);
require('react-events')(React);
// add react-backbone mixins
require('../index')(React, Backbone);

function newComponent(attributes, mixins) {

  if (mixins) {
    mixins = React.mixins.get(mixins);
  } else {
    mixins = [];
  }

  var obj = {
    setState: sinon.spy(),
    setProps: function(props) {
      this.props = this.props || {};
      _.extend(this.props, props);
    },
    mount: function() {
      this._mounted = true;
      this.trigger('componentWillMount');
      this.trigger('componentDidMount');
    },
    unmount: function() {
      this._mounted = false;
      this.trigger('componentWillUnmount');
      this.trigger('componentDidUnmount');
    },

    isMounted: function() { return this._mounted; },
    trigger: function(method) {
      var rtn = [];
      for (var i=0; i<mixins.length; i++) {
        var func = mixins[i][method];
        if (func) {
          rtn.push(func.apply(this, Array.prototype.slice.call(arguments, 1)));
        }
      }
      return rtn;
    }
  };
  if (attributes) {
    for (var name in attributes) {
      obj[name] = attributes[name];
    }
  }

  var state, aggregateState;

  for (var i=0; i<mixins.length; i++) {
    var mixin = mixins[i];
    _.defaults(obj, mixin);
    state = mixin.getInitialState && mixin.getInitialState.call(obj);
    if (state) {
      if (!aggregateState) {
        aggregateState = {};
      }
      _.defaults(aggregateState, state);
    }
  }
  obj.state = aggregateState;
  return obj;
}

var Model = Backbone.Model.extend({
  url: 'foo'
});

describe('modelAware', function() {

  it('should get and set the model', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelAware']);
    expect(obj.getModel()).to.eql(model);

    var model2 = new Backbone.Model();
    obj.setModel(model2);
    expect(obj.getModel()).to.eql(model2);    
  });
});

describe('modelPopulate', function() {

  it('should iterate components and call getUIValue to set attributes', function() {
    var obj = newComponent({}, ['modelPopulate']);
    var components = [
      {
        props: {
          ref: 'foo'
        },
        getUIValue: function() {
          return 'bar';
        }
      }
    ];
    var attributes = obj.modelPopulate(components);
    expect(attributes).to.eql({foo: 'bar'});
  });

  it('should iterate components and call getModelValue to set attributes using refs', function() {
    var obj = newComponent({}, ['modelPopulate']);
    var component = {
      props: {
        ref: 'foo'
      },
      getUIValue: function() {
        return 'bar';
      }
    };
    obj.refs = {
      foo: component
    };
    var attributes = obj.modelPopulate();
    expect(attributes).to.eql({foo: 'bar'});
  });

  it('should set values on model if a callback is provided', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelAware', 'modelPopulate']);
    var component = {
      props: {
        ref: 'foo'
      },
      getUIValue: function() {
        return 'bar';
      }
    };
    obj.refs = {
      foo: component
    };
    var spy = sinon.spy(),
        attributes = obj.modelPopulate(spy);
    expect(spy).to.have.been.called;
    expect(attributes).to.eql({foo: 'bar'});
  });

  it('should not execute the callback if the validation fails', function() {
    var Model = Backbone.Model.extend({
      validate: sinon.spy(function() {
        // just return something so it looks like validation failed
        return 'fail';
      })
    })
    var model = new Model(),
        obj = newComponent({props: {model: model}}, ['modelAware', 'modelPopulate']);
    var component = {
      props: {
        ref: 'foo'
      },
      getUIValue: function() {
        return 'bar';
      }
    };
    obj.refs = {
      foo: component
    };
    var spy = sinon.spy(),
        attributes = obj.modelPopulate(spy);
    expect(spy).to.not.have.been.called;
    expect(attributes).to.eql({foo: 'bar'});
    expect(Model.prototype.validate).to.have.been.calledWith({foo: 'bar'});
  });
});

describe('modelValueAware', function() {

  it('should get and set the model value using "key"', function() {
    var model = new Backbone.Model({foo: 'bar'}),
        obj = newComponent({props: {model: model, key: 'foo'}}, ['modelValueAware']);
    expect(obj.getModelValue()).to.eql('bar');
    obj.setModelValue('baz');
    expect(model.get('foo')).to.eql('baz');
  });

  it('should get and set the model value using "ref"', function() {
    var model = new Backbone.Model({foo: 'bar'}),
        obj = newComponent({props: {model: model, ref: 'foo'}}, ['modelValueAware']);
    expect(obj.getModelValue()).to.eql('bar');
    obj.setModelValue('baz');
    expect(model.get('foo')).to.eql('baz');
  });
});

describe('modelValidator', function() {
  var Model = Backbone.Model.extend({
    validate: function(attributes, options) {
      return options && options.rtn;
    }
  })

  it('should return undefined if no model exists or the model does not implement "validate"', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelValidator']);
    expect(obj.modelValidate()).to.eql(undefined);
  });
  it('should return false if "validate" returns a falsy value', function() {
    var model = new Model(),
        obj = newComponent({props: {model: model}}, ['modelValidator']);
    expect(obj.modelValidate()).to.eql(false);
  });
  it('should return the same value if "validate" returns a truthy value', function() {
    var model = new Model(),
        obj = newComponent({props: {model: model}}, ['modelValidator']);
    expect(obj.modelValidate(undefined, {rtn: 'foo'})).to.eql('foo');
  });
});

describe('modelEventAware', function() {

  it('should not do event binding until node is mounted', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelEventAware']),
        spy = sinon.spy();
    obj.modelOn('foo', spy);
    model.trigger('foo');
    // we shouldn't bind yet because we aren't mounted
    expect(spy.callCount).to.eql(0);

    obj.mount();
    model.trigger('foo');
    expect(spy.callCount).to.eql(1);

    // we shouldn't bind now because we will be unmounted
    obj.unmount();
    model.trigger('foo');
    expect(spy.callCount).to.eql(1);

    // mount again and ensure that we rebind
    obj.mount();
    model.trigger('foo');
    expect(spy.callCount).to.eql(2);
    obj.unmount();
    model.trigger('foo');
    expect(spy.callCount).to.eql(2);
  });

  it('should bind if model does not exist when registered', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelEventAware']),
        spy = sinon.spy();

    // setting model before mounting
    obj.modelOn('foo', spy);
    obj.setModel(model);
    // we shouldn't bind yet because we are not mounted
    model.trigger('foo');
    expect(spy.callCount).to.eql(0);

    obj.mount();
    model.trigger('foo');
    expect(spy.callCount).to.eql(1);
  });

  it('should bind if component has already been mounted when setting model', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelEventAware']),
        spy = sinon.spy();

    obj.modelOn('foo', spy);
    obj.mount();
    obj.setModel(model);
    model.trigger('foo');
    expect(spy.callCount).to.eql(1);
  });

  it('should unbind a previous model and rebind to a new model', function() {
    var model1 = new Backbone.Model(),
        model2 = new Backbone.Model(),
        obj = newComponent({props: {model: model1}}, ['modelEventAware']),
        spy = sinon.spy();

    obj.modelOn('foo', spy);
    obj.mount();
    model1.trigger('foo');
    expect(spy.callCount).to.eql(1);

    // set another model and ensure the first was unbound
    obj.setModel(model2);
    model1.trigger('foo');
    expect(spy.callCount).to.eql(1); // ensure the previous trigger *did not* call the handler
    model2.trigger('foo');
    expect(spy.callCount).to.eql(2);
  });
});

describe('modelChangeAware', function() {
  var clock;
  beforeEach(function() {
    clock = sinon.useFakeTimers();
  });
  afterEach(function() {
    clock.restore();
  });

  it('should listen to all events and force an update', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelChangeAware']),
        spy = sinon.spy();
    obj.forceUpdate = spy;
    
    obj.mount();
    expect(spy.callCount).to.eql(0);
    model.trigger('change');
    clock.tick(1);
    expect(spy.callCount).to.eql(1);
    model.trigger('reset');
    clock.tick(1);
    expect(spy.callCount).to.eql(2);
    model.trigger('add');
    clock.tick(1);
    expect(spy.callCount).to.eql(3);
    model.trigger('remove');
    clock.tick(1);
    expect(spy.callCount).to.eql(4);
    model.trigger('sort');
    clock.tick(1);
    expect(spy.callCount).to.eql(5);
  });
});

describe('modelUpdateOn', function() {
  var clock;
  beforeEach(function() {
    clock = sinon.useFakeTimers();
  });
  afterEach(function() {
    clock.restore();
  });

  it('should listen to provided events and force an update', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model, updateOn: 'foo'}}, ['modelUpdateOn']),
        spy = sinon.spy();
    obj.forceUpdate = spy;
    
    obj.mount();
    expect(spy.callCount).to.eql(0);
    model.trigger('foo');
    clock.tick(1);
    expect(spy.callCount).to.eql(1);
  });

  it('should listen to provided events (as array) and force an update', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model, updateOn: ['foo', 'bar']}}, ['modelUpdateOn']),
        spy = sinon.spy();
    obj.forceUpdate = spy;
    
    obj.mount();
    expect(spy.callCount).to.eql(0);
    model.trigger('foo');
    clock.tick(1);
    expect(spy.callCount).to.eql(1);
    model.trigger('bar');
    clock.tick(1);
    expect(spy.callCount).to.eql(2);
  });

  it('should listen to declaring component provided events and force an update', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model}}, ['modelUpdateOn("foo", "bar")']),
        spy = sinon.spy();
    obj.forceUpdate = spy;
    
    obj.mount();
    expect(spy.callCount).to.eql(0);
    model.trigger('foo');
    clock.tick(1);
    expect(spy.callCount).to.eql(1);
    model.trigger('bar');
    clock.tick(1);
    expect(spy.callCount).to.eql(2);
  });
});


// THE FOLLING TESTS ASSUME THE INCLUSION OF [backbone-async-event](https://github.com/jhudson8/backbone-async-event)

describe('modelLoadOn', function() {

  it('should set loading state when an async event is triggered (success condition)', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model, loadOn: 'foo'}}, ['modelLoadOn']),
        spy = sinon.spy();
    obj.setState = spy;
    obj.mount();

    Backbone.sync('foo', model, {url: 'foo'});
    expect(spy).to.have.been.calledWith({loading: true});
    $.success();
    expect(spy).to.have.been.calledWith({loading: false});
    expect(spy.callCount).to.eql(2);
  });

  it('should set loading state when an async event is triggered (error condition)', function() {
    var model = new Backbone.Model(),
        obj = newComponent({props: {model: model, loadOn: 'foo'}}, ['modelLoadOn']),
        spy = sinon.spy();
    obj.setState = spy;
    obj.mount();

    Backbone.sync('foo', model, {url: 'foo'});
{'fraction_non_alphanumeric': 0.1727203556125105, 'fraction_numerical': 0.004004645388650835, 'mean_word_length': 2.940044177974124, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7267411', 'n_tokens_mistral': 8096, 'n_tokens_neox': 7986, 'n_words': 1787}