"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

require("../injector");

var _create = require("./create");

var _AccountId = _interopRequireDefault(require("../primitive/Generic/AccountId"));

var _Text = _interopRequireDefault(require("../primitive/Text"));

var _U = _interopRequireDefault(require("../primitive/U32"));

var _Struct = _interopRequireDefault(require("./Struct"));

var _Vec = _interopRequireDefault(require("./Vec"));

// Copyright 2017-2019 @polkadot/types authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
describe('Struct', () => {
  describe('decoding', () => {
    const testDecode = (type, input) => it("can decode from ".concat(type), () => {
      const s = new _Struct.default({
        foo: _Text.default,
        bar: _U.default
      }, input);
      expect([...s.keys()]).toEqual(['foo', 'bar']);
      expect([...s.values()].map(v => v.toString())).toEqual(['bazzing', '69']);
    });

    testDecode('array', ['bazzing', 69]);
    testDecode('hex', '0x1c62617a7a696e6745000000');
    testDecode('object', {
      foo: 'bazzing',
      bar: 69
    });
    testDecode('Uint8Array', Uint8Array.from([28, 98, 97, 122, 122, 105, 110, 103, 69, 0, 0, 0]));
  });
  describe('encoding', () => {
    const testEncode = (to, expected) => it("can encode ".concat(to), () => {
      const s = new _Struct.default({
        foo: _Text.default,
        bar: _U.default
      }, {
        foo: 'bazzing',
        bar: 69
      });
      expect(s[to]()).toEqual(expected);
    });

    testEncode('toHex', '0x1c62617a7a696e6745000000');
    testEncode('toJSON', {
      foo: 'bazzing',
      bar: 69
    });
    testEncode('toU8a', Uint8Array.from([28, 98, 97, 122, 122, 105, 110, 103, 69, 0, 0, 0]));
    testEncode('toString', '{"foo":"bazzing","bar":69}');
  });
  it('decodes null', () => {
    expect(new (_Struct.default.with({
      txt: _Text.default,
      u32: _U.default
    }))(null).toString()).toEqual('{}');
  });
  it('decodes a more complicated type', () => {
    const s = new _Struct.default({
      foo: _Vec.default.with(_Struct.default.with({
        bar: _Text.default
      }))
    }, {
      foo: [{
        bar: 1
      }, {
        bar: 2
      }]
    });
    expect(s.toString()).toBe('{"foo":[{"bar":"1"},{"bar":"2"}]}');
  });
  it('decodes from a Map input', () => {
    const input = new _Struct.default({
      a: _U.default,
      txt: _Text.default
    }, {
      a: 42,
      txt: 'fubar'
    });
    const s = new _Struct.default({
      txt: _Text.default,
      foo: _U.default,
      bar: _U.default
    }, input);
    expect(s.toString()).toEqual('{"txt":"fubar","foo":0,"bar":0}');
  });
  it('throws when it cannot decode', () => {
    expect(() => new (_Struct.default.with({
      txt: _Text.default,
      u32: _U.default
    }))('ABC')).toThrowError(/Struct: cannot decode type/);
  });
  it('provides a clean toString()', () => {
    expect(new (_Struct.default.with({
      txt: _Text.default,
      u32: _U.default
    }))({
      txt: 'foo',
      u32: 0x123456
    }).toString()).toEqual('{"txt":"foo","u32":1193046}');
  });
  it('provides a clean toString() (string types)', () => {
    expect(new (_Struct.default.with({
      txt: 'Text',
      num: 'u32',
      cls: _U.default
    }))({
      txt: 'foo',
      num: 0x123456,
      cls: 123
    }).toString()).toEqual('{"txt":"foo","num":1193046,"cls":123}');
  });
  it('exposes the properties on the object', () => {
    const struct = new (_Struct.default.with({
      txt: _Text.default,
      u32: _U.default
    }))({
      txt: 'foo',
      u32: 0x123456
    });
    expect(struct.txt.toString()).toEqual('foo');
    expect(struct.u32.toNumber()).toEqual(0x123456);
  });
  it('correctly encodes length', () => {
    expect(new (_Struct.default.with({
      txt: _Text.default,
      u32: _U.default
    }))({
      foo: 'bazzing',
      bar: 69
    }).encodedLength).toEqual(5);
  });
  it('exposes the types', () => {
    expect(new _Struct.default({
      foo: _Text.default,
      bar: _Text.default,
      baz: _U.default
    }, {
      foo: 'foo',
      bar: 'bar',
      baz: 3
    }).Type).toEqual({
      foo: 'Text',
      bar: 'Text',
      baz: 'u32'
    });
  });
  it('gets the value at a particular index', () => {
    expect(new (_Struct.default.with({
      txt: _Text.default,
      u32: _U.default
    }))({
      txt: 'foo',
      u32: 1234
    }).getAtIndex(1).toString()).toEqual('1234');
  });
  describe('utils', () => {
    it('compares against other objects', () => {
      const test = {
        foo: 'foo',
        bar: 'bar',
        baz: 3
      };
      expect(new _Struct.default({
        foo: _Text.default,
        bar: _Text.default,
        baz: _U.default
      }, test).eq(test)).toBe(true);
    });
  });
  it('allows toString with large numbers', () => {
    // replicate https://github.com/polkadot-js/api/issues/640
    expect(new _Struct.default({
      blockNumber: (0, _create.ClassOf)('Option<BlockNumber>')
    }, {
      blockNumber: '0x0000000010abcdef'
    }).toString()).toEqual('{"blockNumber":279694831}');
  });
  it('generates sane toRawType', () => {
    expect(new _Struct.default({
      accountId: _AccountId.default,
      balanceCompact: (0, _create.ClassOf)('Compact<Balance>'),
      blockNumber: (0, _create.ClassOf)('BlockNumber'),
      compactNumber: (0, _create.ClassOf)('Compact<BlockNumber>'),
      optionNumber: (0, _create.ClassOf)('Option<BlockNumber>'),
      counter: _U.default,
      vector: _Vec.default.with(_AccountId.default)
    }).toRawType()).toEqual(JSON.stringify({
      accountId: 'AccountId',
      balanceCompact: 'Compact<Balance>',
      // Override in Uint
      blockNumber: 'u32',
      compactNumber: 'Compact<u32>',
      optionNumber: 'Option<u32>',
      counter: 'u32',
      vector: 'Vec<AccountId>'
    }));
  });
  it('generates sane toRawType (via with)', () => {
    const Type = _Struct.default.with({
      accountId: _AccountId.default,
      balance: (0, _create.ClassOf)('Balance')
    });

    expect(new Type().toRawType()).toEqual(JSON.stringify({
      accountId: 'AccountId',
      balance: 'Balance' // Override in Uint

    }));
  });
});