<commit_before>import test from 'ava'
import mongoose, { Schema as MongooseSchema } from 'mongoose'
import Model from './Model'
import Schema, { pre } from './Schema'

// the padded-blocks rule doesn't play nice with lines containing only
// decorators calls, so we disable it!
/* eslint-disable padded-blocks */

@Schema
class PersonSchema {
  static schema = {
    name: String,
    age: Number
  };

  static randomPerson () {
    return new this({
      name: '<NAME>',
      age: Math.floor(Math.random() * 100)
    })
  }

  static get count () {
    return 10
  }

  incrementAge () {
    this.age = this.nextAge
  }

  get nextAge () {
    return this.age + 1
  }
  set nextAge (age) {
    this.age = age - 1
  }
}

let modelN = 0
function modelify (schema) {
  return mongoose.model(`Model_${modelN++}`, schema)
}

test('@Schema converts an ES2016 class to a mongoose.Schema', (t) => {
  const schema = new PersonSchema()
  t.ok(schema !== null)
  t.ok(schema instanceof MongooseSchema)
})

test('@Schema keeps instance methods', (t) => {
  const schema = new PersonSchema()
  t.is(typeof schema.methods.incrementAge, 'function')

  const Person = modelify(schema)
  const person = new Person({ name: 'Instance methods', age: 12 })
  t.is(person.age, 12)
  person.incrementAge()
  t.is(person.age, 13)
})

test('@Schema adds virtuals for instance getters and setters', (t) => {
  const schema = new PersonSchema()
  t.is(typeof schema.virtuals.nextAge, 'object')
  t.is(schema.virtuals.nextAge.getters.length, 1)
  t.is(schema.virtuals.nextAge.setters.length, 1)

  const Person = modelify(schema)
  const person = new Person({ name: 'Virtual Types', age: 19 })
  t.is(person.nextAge, 20)
  person.nextAge = 25
  t.is(person.age, 24)
})

test('@Schema keeps static methods', (t) => {
  const schema = new PersonSchema()
  t.is(typeof modelify(schema).randomPerson, 'function')
})

test('@Schema supports static property getter/setters', (t) => {
  const Person = modelify(new PersonSchema())
  t.is(Person.count, 10)
})

test('`this` in static methods passed to @Schema binds to the generated Model class', (t) => {
  const Person = modelify(new PersonSchema())
  t.ok(Person.randomPerson() instanceof Person)
})

test('Schema options can be defined as static class properties', (t) => {
  const schema = new (
    @Schema
    class {
      static typeKey = 'anotherType';
    }
  )

  t.is(schema.options.typeKey, 'anotherType')
})

test('Schema options passed to @Schema override options defined in the class body', (t) => {
  const schema = new (
    @Schema({ typeKey: 'definedInDecorator' })
    class {
      static typeKey = 'definedInClass';
      static versionKey = 'alsoDefinedInClass';
    }
  )

  t.is(schema.options.typeKey, 'definedInDecorator')
  t.is(schema.options.versionKey, 'alsoDefinedInClass')
})

test('@Model(className) registers a new model with mongoose', (t) => {
  @Model('ModelTest0')
  class Anon { // eslint-disable-line no-unused-vars
    static schema = { value: String };
  }
  t.ok(mongoose.modelNames().indexOf('ModelTest0') !== -1)
})

test('@Model and @Model() infer the model name from the decorated class', (t) => {
  @Model
  class ModelTest1 { // eslint-disable-line no-unused-vars
    static schema = { a: String };
  }
  t.ok(mongoose.modelNames().indexOf('ModelTest1') !== -1)

  @Model()
  class ModelTest2 { // eslint-disable-line no-unused-vars
    static schema = { b: String };
  }
  t.ok(mongoose.modelNames().indexOf('ModelTest2') !== -1)
})

test('@Model(options) are passed to the schema constructor', (t) => {
  @Model({ typeKey: 'tests!' })
  class ModelTestWithOptions { // eslint-disable-line no-unused-vars
    static schema = { c: String };
  }

  const retrievedOptions = mongoose.modelSchemas.ModelTestWithOptions.options
  t.is(retrievedOptions.typeKey, 'tests!')
})

test('instanceof works with @Model classes', (t) => {
  @Model<commit_msg>Add tests for attaching Models to non-default connections<commit_after>import test from 'ava'
import mongoose, { Schema as MongooseSchema } from 'mongoose'
import Model from './Model'
import Schema, { pre } from './Schema'

// the padded-blocks rule doesn't play nice with lines containing only
// decorators calls, so we disable it!
/* eslint-disable padded-blocks */

@Schema
class PersonSchema {
  static schema = {
    name: String,
    age: Number
  };

  static randomPerson () {
    return new this({
      name: '<NAME>',
      age: Math.floor(Math.random() * 100)
    })
  }

  static get count () {
    return 10
  }

  incrementAge () {
    this.age = this.nextAge
  }

  get nextAge () {
    return this.age + 1
  }
  set nextAge (age) {
    this.age = age - 1
  }
}

let modelN = 0
function modelify (schema) {
  return mongoose.model(`Model_${modelN++}`, schema)
}

test('@Schema converts an ES2016 class to a mongoose.Schema', (t) => {
  const schema = new PersonSchema()
  t.ok(schema !== null)
  t.ok(schema instanceof MongooseSchema)
})

test('@Schema keeps instance methods', (t) => {
  const schema = new PersonSchema()
  t.is(typeof schema.methods.incrementAge, 'function')

  const Person = modelify(schema)
  const person = new Person({ name: 'Instance methods', age: 12 })
  t.is(person.age, 12)
  person.incrementAge()
  t.is(person.age, 13)
})

test('@Schema adds virtuals for instance getters and setters', (t) => {
  const schema = new PersonSchema()
  t.is(typeof schema.virtuals.nextAge, 'object')
  t.is(schema.virtuals.nextAge.getters.length, 1)
  t.is(schema.virtuals.nextAge.setters.length, 1)

  const Person = modelify(schema)
  const person = new Person({ name: 'Virtual Types', age: 19 })
  t.is(person.nextAge, 20)
  person.nextAge = 25
  t.is(person.age, 24)
})

test('@Schema keeps static methods', (t) => {
  const schema = new PersonSchema()
  t.is(typeof modelify(schema).randomPerson, 'function')
})

test('@Schema supports static property getter/setters', (t) => {
  const Person = modelify(new PersonSchema())
  t.is(Person.count, 10)
})

test('`this` in static methods passed to @Schema binds to the generated Model class', (t) => {
  const Person = modelify(new PersonSchema())
  t.ok(Person.randomPerson() instanceof Person)
})

test('Schema options can be defined as static class properties', (t) => {
  const schema = new (
    @Schema
    class {
      static typeKey = 'anotherType';
    }
  )

  t.is(schema.options.typeKey, 'anotherType')
})

test('Schema options passed to @Schema override options defined in the class body', (t) => {
  const schema = new (
    @Schema({ typeKey: 'definedInDecorator' })
    class {
      static typeKey = 'definedInClass';
      static versionKey = 'alsoDefinedInClass';
    }
  )

  t.is(schema.options.typeKey, 'definedInDecorator')
  t.is(schema.options.versionKey, 'alsoDefinedInClass')
})

test('@Model(className) registers a new model with mongoose', (t) => {
  @Model('ModelTest0')
  class Anon { // eslint-disable-line no-unused-vars
    static schema = { value: String };
  }
  t.ok(mongoose.modelNames().indexOf('ModelTest0') !== -1)
})

test('@Model and @Model() infer the model name from the decorated class', (t) => {
  @Model
  class ModelTest1 { // eslint-disable-line no-unused-vars
    static schema = { a: String };
  }
  t.ok(mongoose.modelNames().indexOf('ModelTest1') !== -1)

  @Model()
  class ModelTest2 { // eslint-disable-line no-unused-vars
    static schema = { b: String };
  }
  t.ok(mongoose.modelNames().indexOf('ModelTest2') !== -1)
})

test('@Model(options) are passed to the schema constructor', (t) => {
  @Model({ typeKey: 'tests!' })
  class ModelTestWithOptions { // eslint-disable-line no-unused-vars
    static schema = { c: String };
  }

  const retrievedOptions = mongoose.modelSchemas.ModelTestWithOptions.options
  t.is(retrievedOptions.typeKey, 'tests!')
})

test('@Model({ connection }) registers the model on a non-default connection', (t) => {
  const testConnection = mongoose.createConnection()
  @Model({ connection: testConnection })
  class CustomConnection {
    static schema = { d: String };
  }

  t.is(testConnection.model('CustomConnection'), CustomConnection)
  t.not(mongoose.model('CustomConnection'), CustomConnection)
})

test('@Model uses "connection" option from static key', (t) => {
  const testConnection = mongoose.createConnection()
  @Model
  class CustomConnection {
    static connection = testConnection;
    static schema = { e: String };
  }

  t.is(testConnection.model('CustomConnection'), CustomConnection)
  t.not(mongoose.model('CustomConnection'), CustomConnection)
})

test('instanceof works with @Model classes', (t) => {
  @Model
{'fraction_non_alphanumeric': 0.14504347826086955, 'fraction_numerical': 0.009043478260869564, 'mean_word_length': 3.7815964523281598, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 31, 'https://': 0, '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': '1573892', 'n_tokens_mistral': 2868, 'n_tokens_neox': 2783, 'n_words': 755}