diff --git a/test/with.test.js b/test/with.test.js new file mode 100644 index 00000000..525fdc57 --- /dev/null +++ b/test/with.test.js @@ -0,0 +1,142 @@ +/* -------------------- + * livepack module + * Tests for `with` + * ------------------*/ + +/* eslint-disable strict, no-with */ + +// Imports + +const support = require('./support/index.js'), + itSerializes = support.itSerializes.withOptions({strictEnv: false}), + {transpiledFiles} = support; + +// Tests +describe('with statements', () => { + describe('outside serialized function', () => { + itSerializes('provides scope to function when no outer binding', { + in() { + with ({x: 123}) { + return () => x; // eslint-disable-line no-undef + } + }, + out: '(a=>{with(a)return()=>x})({x:123})', + validate(fn) { + expect(fn).toBeFunction(); + expect(fn()).toBe(123); + } + }); + + itSerializes('provides scope to function when outer binding', { + in() { + const x = 456; + with ({x: 123}) { + return () => x; + } + }, + out: '(x=>a=>{with(a)return()=>x})(456)({x:123})', + validate(fn) { + expect(fn).toBeFunction(); + expect(fn()).toBe(123); + } + }); + + itSerializes('allows access to outer binding', { + in() { + const x = 456; + with ({}) { + return () => x; + } + }, + out: '(x=>a=>{with(a)return()=>x})(456)({})', + validate(fn) { + expect(fn).toBeFunction(); + expect(fn()).toBe(456); + } + }); + + itSerializes('allows access to global', { + in() { + with ({}) { + return () => console; + } + }, + out: '(a=>{with(a)return()=>console})({})', + validate(fn) { + expect(fn).toBeFunction(); + expect(fn()).toBe(console); + } + }); + + itSerializes('Alters scope when `with` object property changed', { + in() { + const obj = {x: 123}, + x = 456; + let fn; + with (obj) { + fn = (0, () => x); + } + return [fn, obj]; + }, + out: `(()=>{ + const a={x:123}; + return[ + (x=>a=>{with(a)return()=>x})(456)(a), + a + ] + })()`, + validate([fn, obj]) { + expect(fn).toBeFunction(); + expect(fn()).toBe(123); + obj.x = 789; + expect(fn()).toBe(789); + } + }); + + itSerializes('Alters scope when `with` object property deleted', { + in() { + const obj = {x: 123}, + x = 456; + let fn; + with (obj) { + fn = (0, () => x); + } + return [fn, obj]; + }, + out: `(()=>{ + const a={x:123}; + return[ + (x=>a=>{with(a)return()=>x})(456)(a), + a + ] + })()`, + validate([fn, obj]) { + expect(fn).toBeFunction(); + expect(fn()).toBe(123); + delete obj.x; + expect(fn()).toBe(456); + } + }); + + itSerializes("does not disrupt instrumentation's internal functions", { + in() { + const x = 123; + with ({livepack_tracker: 1, livepack_getScopeId: 2}) { + const y = 456; + return () => [x, y]; + } + }, + out: '(x=>b=>{with(b)return a=>()=>[x,a]})(123)({livepack_tracker:1,livepack_getScopeId:2})(456)', + validate(fn) { + expect(fn).toBeFunction(); + expect(fn()).toEqual([123, 456]); + + // Check internal functions match the ones being tested for + expect(transpiledFiles[__filename]).toInclude( + // eslint-disable-next-line no-useless-concat + 'const [livepack_tracker, livepack_getScopeId] = ' + 'require(' + ); + } + }); + }); +});