<commit_before>import {test} from 'tap'
import {createFormBuilderState} from '../src/state/FormBuilderState'
import {compileSchema} from '../src'

import schema from './fixtures/schema'

const compiledSchema = compileSchema(schema)

const rawValue = {
  $type: 'simple',
  someString: 'foo',
  home: {
    $type: 'homeAddress',
    zip: '2012',
    location: {
      $type: 'latlon',
      lat: 231,
      lon: 31
    }
  },
  someLatLon: {
    $type: 'latlon',
    lat: 10,
    lon: 10
  }
}

test('create from raw value', t => {
  const state = createFormBuilderState(rawValue, {type: compiledSchema.types.simple, schema: schema})
  t.same(state.unwrap(), rawValue)
  t.end()
})

test('create from empty', t => {
  const state = createFormBuilderState(void 0, {type: compiledSchema.types.simple, schema: schema})
  t.same(state.unwrap(), void 0)
  t.end()
})

test('create empty, and patch with simple value', t => {
  const state = createFormBuilderState(void 0, {type: compiledSchema.types.simple, schema: schema})
  const newState = state.patch({
    someString: {$set: 'foobar'}
  })

  t.same(newState.unwrap(), {
    $type: 'simple',
    someString: 'foobar'
  })

  t.end()
})


test('apply a patch setting a simple value', t => {
  const state = createFormBuilderState(rawValue, {type: compiledSchema.types.simple, schema: schema})
  const newState = state.patch({someString: {$set: 'bar'}})
  t.same(newState.unwrap(), {
    $type: 'simple',
    someString: 'bar',
    home: {
      $type: 'homeAddress',
      zip: '2012',
      location: {
        $type: 'latlon',
        lat: 231,
        lon: 31
      }
    },
    someLatLon: {
      $type: 'latlon',
      lat: 10,
      lon: 10
    }
  })
  t.end()
})

test('apply a patch by replacing a tree', t => {
  const state = createFormBuilderState(rawValue, {type: compiledSchema.types.simple, schema: schema})

  const newState = state.patch({
    home: {
      location: {
        lat: {$set: 666},
        lon: {$set: 444}
      }
    }
  })

  t.same(newState.unwrap(), {
    $type: 'simple',
    someString: 'foo',
    home: {
      $type: 'homeAddress',
      zip: '2012',
      location: {
        $type: 'latlon',
        lat: 666,
        lon: 444
      }
    },
    someLatLon: {
      $type: 'latlon',
      lat: 10,
      lon: 10
    }
  })
  t.end()
})


test('custom container', t => {

  class NumberContainer {
    constructor(value, context) {
      this.stringValue = String(value)
      this.context = context
    }

    patch(patch) {
      if (patch.hasOwnProperty('$set')) {
        this.stringValue = patch.$set
        return this
      }
      throw new Error(`Only $set is supported by NumberContainer, got: ${JSON.stringify(patch)}`)
    }

    unwrap() {
      return Number(this.stringValue)
    }
  }

  function resolveContainer(field, schemaType) {
    if (field.type === 'number' || schemaType.type === 'number') {
      return NumberContainer
    }
  }

  const state = createFormBuilderState(rawValue, {
    type: compiledSchema.types.simple,
    schema: schema,
    resolveContainer: resolveContainer
  })
<commit_msg>Fix failing tests<commit_after>import {test} from 'tap'
import {createFormBuilderState} from '../src/state/FormBuilderState'
import ObjectContainer from '../src/state/ObjectContainer'
import ArrayContainer from '../src/state/ArrayContainer'
import {compileSchema} from '../src'

import schema from './fixtures/schema'

const compiledSchema = compileSchema(schema)

const rawValue = {
  $type: 'simple',
  someString: 'foo',
  home: {
    $type: 'homeAddress',
    zip: '2012',
    location: {
      $type: 'latlon',
      lat: 231,
      lon: 31
    }
  },
  someLatLon: {
    $type: 'latlon',
    lat: 10,
    lon: 10
  }
}

function defaultResolveContainer(field, type) {
  switch (field.type) {
    case 'object':
      return ObjectContainer
    case 'array':
      return ArrayContainer
  }
  switch (type.type) {
    case 'object':
      return ObjectContainer
    case 'array':
      return ArrayContainer
  }
}

const defaultContext = {
  type: compiledSchema.types.simple,
  schema: schema,
  resolveContainer: defaultResolveContainer
}

test('create from raw value', t => {
  const state = createFormBuilderState(rawValue, defaultContext)
  t.same(state.unwrap(), rawValue)
  t.end()
})

test('create from empty', t => {
  const state = createFormBuilderState(void 0, defaultContext)
  t.same(state.unwrap(), void 0)
  t.end()
})

test('create empty, and patch with simple value', t => {
  const state = createFormBuilderState(void 0, defaultContext)
  const newState = state.patch({
    someString: {$set: 'foobar'}
  })

  t.same(newState.unwrap(), {
    $type: 'simple',
    someString: 'foobar'
  })

  t.end()
})


test('apply a patch setting a simple value', t => {
  const state = createFormBuilderState(rawValue, defaultContext)
  const newState = state.patch({someString: {$set: 'bar'}})
  t.same(newState.unwrap(), {
    $type: 'simple',
    someString: 'bar',
    home: {
      $type: 'homeAddress',
      zip: '2012',
      location: {
        $type: 'latlon',
        lat: 231,
        lon: 31
      }
    },
    someLatLon: {
      $type: 'latlon',
      lat: 10,
      lon: 10
    }
  })
  t.end()
})

test('apply a patch by replacing a tree', t => {
  const state = createFormBuilderState(rawValue, defaultContext)

  const newState = state.patch({
    home: {
      location: {
        lat: {$set: 666},
        lon: {$set: 444}
      }
    }
  })

  t.same(newState.unwrap(), {
    $type: 'simple',
    someString: 'foo',
    home: {
      $type: 'homeAddress',
      zip: '2012',
      location: {
        $type: 'latlon',
        lat: 666,
        lon: 444
      }
    },
    someLatLon: {
      $type: 'latlon',
      lat: 10,
      lon: 10
    }
  })
  t.end()
})


test('custom container', t => {

  class NumberContainer {
    constructor(value, context) {
      this.value = value
      this.context = context
    }

    patch(patch) {
      if (patch.hasOwnProperty('$set')) {
        this.value = patch.$set
        return new NumberContainer(patch.$set, this.context)
      }
      throw new Error(`Only $set is supported by NumberContainer, got: ${JSON.stringify(patch)}`)
    }

    unwrap() {
      return this.value.trim() ? Number(this.value) : void 0
    }
  }

  NumberContainer.wrap = function wrap(val) {
    return new NumberContainer(String(val))
  }

  function resolveContainer(field, schemaType) {
    if (field.type === 'number' || schemaType.type === 'number') {
      return NumberContainer
    }
    return defaultResolveContainer(field, schemaType)
  }

  const state = createFormBuilderState(rawValue, {
    type: compiledSchema.types.simple,
    schema,
    resolveContainer
  })

{'fraction_non_alphanumeric': 0.14581791265729088, 'fraction_numerical': 0.014655810510732791, 'mean_word_length': 2.701917808219178, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 15, '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': '5291630', 'n_tokens_mistral': 2291, 'n_tokens_neox': 2183, 'n_words': 536}