249 lines
5.6 KiB
JavaScript
249 lines
5.6 KiB
JavaScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @format
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const Enum = require('../index');
|
|
|
|
describe('Enum', () => {
|
|
const E = Enum({A: 1, B: 2});
|
|
|
|
test('access members', () => {
|
|
expect(E.A).toBe(1);
|
|
expect(E.B).toBe(2);
|
|
});
|
|
|
|
test('only two own properties', () => {
|
|
expect(Object.getOwnPropertyNames(E).length).toBe(2);
|
|
});
|
|
|
|
test('no enumerable properties', () => {
|
|
let count = 0;
|
|
for (const _ in E) {
|
|
count++;
|
|
}
|
|
expect(count).toBe(0);
|
|
});
|
|
|
|
test('not extensible', () => {
|
|
expect(Object.isExtensible(E)).toBe(false);
|
|
expect(() => {
|
|
E.C = 3;
|
|
}).toThrow();
|
|
expect(E.C).toBe(undefined);
|
|
expect(Object.getOwnPropertyNames(E).length).toBe(2);
|
|
});
|
|
|
|
test('not writable', () => {
|
|
expect(() => {
|
|
E.A = 66;
|
|
}).toThrow();
|
|
expect(() => {
|
|
E.B = 66;
|
|
}).toThrow();
|
|
expect(E.A).toBe(1);
|
|
expect(E.B).toBe(2);
|
|
});
|
|
|
|
test('not deletable', () => {
|
|
expect(() => {
|
|
delete E.A;
|
|
}).toThrow();
|
|
expect(() => {
|
|
delete E.B;
|
|
}).toThrow();
|
|
expect(E.A).toBe(1);
|
|
expect(E.B).toBe(2);
|
|
});
|
|
|
|
test('not configurable', () => {
|
|
expect(() => {
|
|
Object.defineProperty(E, 'A', {
|
|
value: 66,
|
|
writable: true,
|
|
enumerable: true,
|
|
configurable: true,
|
|
});
|
|
}).toThrow('Cannot redefine property: A');
|
|
});
|
|
|
|
test('not castable to primitive', () => {
|
|
expect(() => {
|
|
'' + E;
|
|
}).toThrow('Cannot convert object to primitive value');
|
|
});
|
|
|
|
test('prototype frozen', () => {
|
|
const F = Enum({A: 1});
|
|
expect(() => {
|
|
Object.getPrototypeOf(F).isValid = () => true;
|
|
}).toThrow();
|
|
expect(F.isValid(1)).toBe(true);
|
|
});
|
|
|
|
describe('prototype methods', () => {
|
|
test('isValid', () => {
|
|
expect(E.isValid(1)).toBe(true);
|
|
expect(E.isValid(2)).toBe(true);
|
|
expect(E.isValid(3)).toBe(false);
|
|
expect(E.isValid(null)).toBe(false);
|
|
expect(E.isValid(undefined)).toBe(false);
|
|
});
|
|
|
|
test('cast', () => {
|
|
expect(E.cast(1)).toBe(E.A);
|
|
expect(E.cast(2)).toBe(E.B);
|
|
expect(E.cast(3)).toBe(undefined);
|
|
});
|
|
|
|
test('members iterable', () => {
|
|
expect(Array.from(E.members())).toEqual([1, 2]);
|
|
let i = 1;
|
|
for (const x of E.members()) {
|
|
expect(x).toEqual(i);
|
|
i++;
|
|
}
|
|
});
|
|
|
|
test('members iterator', () => {
|
|
const iter = E.members();
|
|
expect(iter.next()).toEqual({value: 1, done: false});
|
|
expect(iter.next()).toEqual({value: 2, done: false});
|
|
expect(iter.next()).toEqual({value: undefined, done: true});
|
|
});
|
|
|
|
test('getName', () => {
|
|
expect(E.getName(E.A)).toBe('A');
|
|
expect(E.getName(E.B)).toBe('B');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Enum.Mirrored', () => {
|
|
const E = Enum.Mirrored(['A', 'B']);
|
|
|
|
test('access members', () => {
|
|
expect(E.A).toBe('A');
|
|
expect(E.B).toBe('B');
|
|
});
|
|
|
|
test('only two own properties', () => {
|
|
expect(Object.getOwnPropertyNames(E).length).toBe(2);
|
|
});
|
|
|
|
test('no enumerable properties', () => {
|
|
let count = 0;
|
|
for (const _ in E) {
|
|
count++;
|
|
}
|
|
expect(count).toBe(0);
|
|
});
|
|
|
|
test('not extensible', () => {
|
|
expect(Object.isExtensible(E)).toBe(false);
|
|
expect(() => {
|
|
E.C = 'C';
|
|
}).toThrow();
|
|
expect(E.C).toBe(undefined);
|
|
expect(Object.getOwnPropertyNames(E).length).toBe(2);
|
|
});
|
|
|
|
test('not writable', () => {
|
|
expect(() => {
|
|
E.A = 'foo';
|
|
}).toThrow();
|
|
expect(() => {
|
|
E.B = 'bar';
|
|
}).toThrow();
|
|
expect(E.A).toBe('A');
|
|
expect(E.B).toBe('B');
|
|
});
|
|
|
|
test('not deletable', () => {
|
|
expect(() => {
|
|
delete E.A;
|
|
}).toThrow();
|
|
expect(() => {
|
|
delete E.B;
|
|
}).toThrow();
|
|
expect(E.A).toBe('A');
|
|
expect(E.B).toBe('B');
|
|
});
|
|
|
|
test('not configurable', () => {
|
|
expect(() => {
|
|
Object.defineProperty(E, 'A', {
|
|
value: 'x',
|
|
writable: true,
|
|
enumerable: true,
|
|
configurable: true,
|
|
});
|
|
}).toThrow('Cannot redefine property: A');
|
|
});
|
|
|
|
test('not castable to primitive', () => {
|
|
expect(() => {
|
|
'' + E;
|
|
}).toThrow('Cannot convert object to primitive value');
|
|
});
|
|
|
|
test('prototype frozen', () => {
|
|
const F = Enum.Mirrored(['A']);
|
|
expect(() => {
|
|
Object.getPrototypeOf(F).isValid = () => true;
|
|
}).toThrow();
|
|
expect(F.isValid('A')).toBe(true);
|
|
});
|
|
|
|
describe('prototype methods', () => {
|
|
test('isValid', () => {
|
|
expect(E.isValid('A')).toBe(true);
|
|
expect(E.isValid('B')).toBe(true);
|
|
expect(E.isValid('C')).toBe(false);
|
|
expect(E.isValid(null)).toBe(false);
|
|
expect(E.isValid(undefined)).toBe(false);
|
|
|
|
const s = {
|
|
toString() {
|
|
return 'A';
|
|
},
|
|
};
|
|
expect(E.isValid(s)).toBe(false);
|
|
});
|
|
|
|
test('cast', () => {
|
|
expect(E.cast('A')).toBe(E.A);
|
|
expect(E.cast('B')).toBe(E.B);
|
|
expect(E.cast('C')).toBe(undefined);
|
|
});
|
|
|
|
test('members iterable', () => {
|
|
const expected = ['A', 'B'];
|
|
expect(Array.from(E.members())).toEqual(expected);
|
|
let i = 0;
|
|
for (const x of E.members()) {
|
|
expect(x).toEqual(expected[i]);
|
|
i++;
|
|
}
|
|
});
|
|
|
|
test('members iterator', () => {
|
|
const iter = E.members();
|
|
expect(iter.next()).toEqual({value: 'A', done: false});
|
|
expect(iter.next()).toEqual({value: 'B', done: false});
|
|
expect(iter.next()).toEqual({value: undefined, done: true});
|
|
});
|
|
|
|
test('getName', () => {
|
|
expect(E.getName(E.A)).toBe('A');
|
|
expect(E.getName(E.B)).toBe('B');
|
|
});
|
|
});
|
|
});
|