JSlang.dev

JavaScript Deep Dives with Wolfram. Since 2015
Inclusive, Test-Driven, Spec-Focused, Collaborative.

March 26, 2020
TestsSource
ES6: Reflect - (REMOTE)

Source Code

The source code we wrote during the event.

import assert from 'assert';

describe('Create an object using `Reflect`', () => {
  it('use Reflect.construct to create an object', () => {
    const constructorFunction = function() {};
    assert.equal(typeof Reflect.construct(constructorFunction, []), 'object');
  });
  it('has properties defined in the constructor function', () => {
    const constructorFunction = function() { this.a = 1; };
    const result = Reflect.construct(constructorFunction, []);
    assert.equal(result.a, 1);
    assert.equal(result['a'], 1);
  });
  it('can pass one argument to the constructor function', () => {
    const constructorFunction = function(arg1) { this.a = arg1; };
    const result = Reflect.construct(constructorFunction, [1]);
    assert.equal(result.a, 1);
  });
  it('can pass two arguments to the constructor function', () => {
    const constructorFunction = function(arg1, arg2) { this.args = [arg1, arg2]; };
    const result = Reflect.construct(constructorFunction, [1, 2]);
    assert.deepStrictEqual(result.args, [1, 2]);
  });
});

describe('Override properties using Reflect', () => {
  it('define a property and re-define it', () => {
    const a = {x: 42};
    Reflect.defineProperty(a, 'x', {value: 13});
    assert.strictEqual(a.x, 13);
  });
  it('re-defining a method on an object is possible', () => {
    const a = {method: () => 42};
    Reflect.defineProperty(a, 'method', {value: () => 13})
    assert.strictEqual(a.method(), 13);
  });
  it('make a writable property be not writable', () => {
    const a = {x: 42};
    Reflect.defineProperty(a, 'x', {value: 13, writable: false});
    assert.throws(() => { a.x = 45; }, TypeError);
  });
  it('make read-only property writable', () => {
    const a = {x: 13};
    Reflect.defineProperty(a, 'x', {writable: false});
    assert.throws(() => a.x = 45);
    assert.doesNotThrow(() => Reflect.defineProperty(a, 'x', {writable: true}));
    assert.doesNotThrow(() => a.x = 45);
  });
  it('prevent making a read-only property writable', () => {
    const a = {x: 13};
    Reflect.defineProperty(a, 'x', {configurable: false});
    assert.doesNotThrow(() => Reflect.defineProperty(a, 'x', {writable: false}));
    assert.throws(() => a.x = 42);
  });
});

describe('Object vs. Reflect', () => {
  it('changing configurable from false to true using Reflect returns false', () => {
    const a = {x: 13};
    Reflect.defineProperty(a, 'x', {configurable: false});
    const result = Reflect.defineProperty(a, 'x', {configurable: true});
    assert.strictEqual(result, false);
    assert.strictEqual(Reflect.getOwnPropertyDescriptor(a, 'x').configurable, false);
  });
  it('changing configurable from false to true using Object throws with TypeError', () => {
    const a = {x: 13};
    Object.defineProperty(a, 'x', {configurable: false});
    assert.throws(() => Object.defineProperty(a, 'x', {configurable: true}));
  });
  it('deleting an not-existing property using `delete` of an object does NOT throw', () => {
    const obj = {};
    assert.doesNotThrow(() => delete obj.y);
  });
  it('deleting a not-existing property returns true', () => {
    assert.strictEqual(Reflect.deleteProperty({}, 'y'), true);
    assert.strictEqual(Reflect.has({}, 'y'), false);
  });
  it('deleting an existing property of an object returns true', () => {
    assert.strictEqual(Reflect.deleteProperty({y: 1}, 'y'), true);
  });
});

describe('Work with a frozen object', () => {
  it('with Reflect we can NOT extend a frozen object', () => {
    const obj = Object.freeze({x: 1});
    const result = Reflect.defineProperty(obj, 'y', {value: 1});
    assert.strictEqual(result, false);
    assert.strictEqual(result.y, undefined);
    assert.strictEqual(Reflect.has(obj, 'y'), false);
    assert.strictEqual(Reflect.has(obj, 'x'), true);
    assert.strictEqual(Reflect.deleteProperty(obj, 'x'), false);
  });
  it('deleting an existing property using `delete` of a frozen object throws', () => {
    const frozenObj = Object.freeze({y: 1});
    assert.throws(() => delete frozenObj.y, TypeError);
  });
  it('deleting an existing property of a frozen object returns false', () => {
    assert.strictEqual(Reflect.deleteProperty(Object.freeze({y: 1}), 'y'), false);
  });
});