summaryrefslogtreecommitdiff
path: root/javascript/videojs/test/unit/utils/obj.test.js
blob: f8aa1c6e0f05c07df1943ecc566f7a47e6b25007 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/* eslint-env qunit */
import sinon from 'sinon';
import * as Obj from '../../../src/js/utils/obj';

class Foo {
  constructor() {}
  toString() {
    return 'I am a Foo!';
  }
}

const passFail = (assert, fn, descriptor, passes, failures) => {
  Object.keys(passes).forEach(key => {
    assert.ok(fn(passes[key]), `${key} IS ${descriptor}`);
  });

  Object.keys(failures).forEach(key => {
    assert.notOk(fn(failures[key]), `${key} IS NOT ${descriptor}`);
  });
};

QUnit.module('utils/obj', function() {

  QUnit.test('each', function(assert) {
    const spy = sinon.spy();

    Obj.each({
      a: 1,
      b: 'foo',
      c: null
    }, spy);

    assert.strictEqual(spy.callCount, 3);
    assert.ok(spy.calledWith(1, 'a'));
    assert.ok(spy.calledWith('foo', 'b'));
    assert.ok(spy.calledWith(null, 'c'));

    Obj.each({}, spy);
    assert.strictEqual(spy.callCount, 3, 'an empty object was not iterated over');
  });

  QUnit.test('reduce', function(assert) {
    const first = Obj.reduce({
      a: 1,
      b: 2,
      c: 3,
      d: 4
    }, (accum, value) => accum + value);

    assert.strictEqual(first, 10);

    const second = Obj.reduce({
      a: 1,
      b: 2,
      c: 3,
      d: 4
    }, (accum, value) => accum + value, 10);

    assert.strictEqual(second, 20);

    const third = Obj.reduce({
      a: 1,
      b: 2,
      c: 3,
      d: 4
    }, (accum, value, key) => {
      accum[key] = 0 - value;
      return accum;
    }, {});

    assert.strictEqual(third.a, -1);
    assert.strictEqual(third.b, -2);
    assert.strictEqual(third.c, -3);
    assert.strictEqual(third.d, -4);
  });

  QUnit.test('isObject', function(assert) {
    passFail(assert, Obj.isObject, 'an object', {
      'plain object': {},
      'constructed object': new Foo(),
      'array': [],
      'regex': new RegExp('.'),
      'date': new Date()
    }, {
      null: null,
      function() {},
      boolean: true,
      number: 1,
      string: 'xyz'
    });
  });

  QUnit.test('isPlain', function(assert) {
    passFail(assert, Obj.isPlain, 'a plain object', {
      'plain object': {}
    }, {
      'constructed object': new Foo(),
      'null': null,
      'array': [],
      'function'() {},
      'regex': new RegExp('.'),
      'date': new Date(),
      'boolean': true,
      'number': 1,
      'string': 'xyz'
    });
  });

  QUnit.module('merge');

  QUnit.test('should merge objects', function(assert) {
    const ob1 = {
      a: true,
      b: { b1: true, b2: true, b3: true },
      c: true
    };

    const ob2 = {
      // override value
      a: false,
      // merge sub-option values
      b: { b1: true, b2: false, b4: true },
      // add new option
      d: true
    };

    const ob3 = Obj.merge(ob1, ob2);

    assert.deepEqual(ob3, {
      a: false,
      b: { b1: true, b2: false, b3: true, b4: true },
      c: true,
      d: true
    }, 'options objects merged correctly');
  });

  QUnit.test('should ignore non-objects', function(assert) {
    const obj = { a: 1 };

    assert.deepEqual(Obj.merge(obj, true), obj, 'ignored non-object input');
  });

  QUnit.module('defineLazyProperty');

  QUnit.test('should define a "lazy" property', function(assert) {
    assert.expect(12);

    const obj = {a: 1};
    const getValue = sinon.spy(() => {
      return 2;
    });

    Obj.defineLazyProperty(obj, 'b', getValue);

    let descriptor = Object.getOwnPropertyDescriptor(obj, 'b');

    assert.ok(getValue.notCalled, 'getValue function was not called');
    assert.strictEqual(typeof descriptor.get, 'function', 'descriptor has a getter');
    assert.strictEqual(typeof descriptor.set, 'function', 'descriptor has a setter');
    assert.strictEqual(typeof descriptor.value, 'undefined', 'descriptor has no value');

    let b = obj.b;

    descriptor = Object.getOwnPropertyDescriptor(obj, 'b');

    assert.ok(getValue.calledOnce, 'getValue function was not called');
    assert.strictEqual(b, 2, 'the value was retrieved correctly');
    assert.strictEqual(typeof descriptor.get, 'undefined', 'descriptor has no getter');
    assert.strictEqual(typeof descriptor.set, 'undefined', 'descriptor has no setter');
    assert.strictEqual(descriptor.value, 2, 'descriptor has a value');

    b = obj.b;
    descriptor = Object.getOwnPropertyDescriptor(obj, 'b');

    assert.ok(getValue.calledOnce, 'getValue function was still only called once');
    assert.strictEqual(b, 2, 'the value was retrieved correctly');
    assert.strictEqual(descriptor.value, 2, 'descriptor has a value');
  });

  QUnit.module('values', () => {
    QUnit.test('returns an array of values for a given object', (assert) => {
      const source = { a: 1, b: 2, c: 3 };
      const expectedResult = [1, 2, 3];

      assert.deepEqual(Obj.values(source), expectedResult, 'All values are extracted correctly');
    });

    QUnit.test('returns an empty array for an empty object', (assert) => {
      const source = {};
      const expectedResult = [];

      assert.deepEqual(Obj.values(source), expectedResult, 'Empty array is returned for an empty object');
    });

    QUnit.test('ignores prototype properties', (assert) => {
      const source = Object.create({ a: 1 });

      source.b = 2;

      const expectedResult = [2];

      assert.deepEqual(Obj.values(source), expectedResult, 'Only own properties are included in the result');
    });
  });
});