November 22, 2018
TestsSource
- Learning about the `new Proxy()`
- What can we do with it?
Source Code
The source code we wrote during the event.
proxies.spec.js
import assert from 'assert';
describe('Learning about the `new Proxy()`', () => {
it('Proxy without handler throws', () => {
assert.throws(() => { new Proxy({}) }, TypeError);
});
it('Proxy without a target throws', () => {
assert.throws(() => { new Proxy() }, TypeError);
});
it('Proxy a function, does not throw', () => {
assert.doesNotThrow(() => { new Proxy(function() {}, {}) });
});
it('A proxied function`s type is function', () => {
const p = new Proxy(() => {}, {});
assert.equal(typeof p, 'function');
});
it('A proxied function`s instanceof is Function', () => {
const p = new Proxy(() => {}, {});
assert(p instanceof Function);
});
it('A proxied object`s instanceof is Object', () => {
const p = new Proxy({}, {});
assert(p instanceof Object);
});
it('A proxied object`s equals the actual object', () => {
const obj = {};
const p = new Proxy(obj, {});
assert.deepEqual(obj, p);
});
});
describe('What can we do with it?', () => {
it('A proxied array that adds a prefix to every pushed element', () => {
const arr = new Proxy([], {
get: (target, property) => {
const push = (arg) => {
target.push('pre-' + arg);
return target;
};
return property === 'push' ? push : target[property];
}
});
arr.push('1');
arr.push('2');
assert.deepEqual(arr, ['pre-1', 'pre-2']);
});
it('Accessing anything on a proxied object will call handler.get', () => {
const arr = new Proxy([], {
get: () => 'something'
});
assert.equal(arr[0], 'something')
assert.equal(arr.push, 'something')
});
it('Assigning anything on a proxied object will call handler.set', () => {
const arr = new Proxy([], {
set: (target, prop) => {
target[1] = 'something';
return target;
}
});
arr[0] = 1;
assert.equal(arr[1], 'something')
});
it('A set handler must return a truthy value', () => {
const arr = new Proxy([], {
set: () => 1
});
arr[0] = 1;
assert.equal(arr[0], undefined)
});
xit('undefined is not a function', () => {
undefined = () => {};
assert.throws(() => { a() },
(e) => {
return e.message === 'undefined is not a function';
});
});
it('Proxying a class X, returns class Y', () => {
class X {};
class Y {};
const x = new Proxy(X, {
construct: () => new Y()
});
assert(new x() instanceof Y);
});
it('Proxy an Array, and provide only `push()` and access to index=0', () => {
const ProxiedArray = new Proxy(Array, {
construct: () => {
return new Proxy([], {
set: () => true,
get: (target, prop) => {
const push = (arg) => target.push(arg)
return prop === 'push' ? push : target[0];
}
});
}
});
const arr = new ProxiedArray();
arr.push(42);
arr[0] = 5;
assert.deepEqual(arr[0], 42);
assert.equal(arr.indexOf, arr[0]);
assert.equal(arr.toString, arr[0]);
});
it('Fake instanceof an object to string', () => {
const obj = new Proxy({}, {
getPrototypeOf: () => {
return String.prototype;
}
});
assert(obj instanceof String);
assert.equal(typeof obj, 'object');
assert.equal(obj.prototype, undefined);
});
});
// what we dont know:
// - how to detect a proxied object
xit('Proxying {} and have no handlers', () => {
const p = new Proxy();
assert.equal(typeof p, '???');
});
// override undefined is not a function
// proxy primitive
// proxy null