From fc6bbae06506068c786f66eec1f02122fa4f0690 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Sun, 26 May 2019 14:02:20 +0200 Subject: [PATCH 1/6] Added array.reduce --- src/LuaLib.ts | 1 + src/LuaTransformer.ts | 4 +- src/lualib/ArrayReduce.ts | 28 ++ test/unit/lualib/array.spec.ts | 458 ++++++++++++++++++++++++++++++++ test/unit/lualib/lualib.spec.ts | 409 ---------------------------- 5 files changed, 490 insertions(+), 410 deletions(-) create mode 100644 src/lualib/ArrayReduce.ts create mode 100644 test/unit/lualib/array.spec.ts diff --git a/src/LuaLib.ts b/src/LuaLib.ts index d339fc945..2a6c2da96 100644 --- a/src/LuaLib.ts +++ b/src/LuaLib.ts @@ -10,6 +10,7 @@ export enum LuaLibFeature { ArrayIndexOf = "ArrayIndexOf", ArrayMap = "ArrayMap", ArrayPush = "ArrayPush", + ArrayReduce = "ArrayReduce", ArrayReverse = "ArrayReverse", ArrayShift = "ArrayShift", ArrayUnshift = "ArrayUnshift", diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index d46b5d107..20bb57ae6 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -3,7 +3,7 @@ import * as ts from "typescript"; import { CompilerOptions, LuaTarget } from "./CompilerOptions"; import { DecoratorKind } from "./Decorator"; import * as tstl from "./LuaAST"; -import { LuaLibFeature } from "./LuaLib"; +import { LuaLibFeature, LuaLib } from "./LuaLib"; import { ContextType, TSHelper as tsHelper } from "./TSHelper"; import { TSTLErrors } from "./TSTLErrors"; import { luaKeywords, luaBuiltins } from "./LuaKeywords"; @@ -4607,6 +4607,8 @@ export class LuaTransformer { return this.transformLuaLibFunction(LuaLibFeature.ArrayMap, node, caller, ...params); case "filter": return this.transformLuaLibFunction(LuaLibFeature.ArrayFilter, node, caller, ...params); + case "reduce": + return this.transformLuaLibFunction(LuaLibFeature.ArrayReduce, node, caller, ...params); case "some": return this.transformLuaLibFunction(LuaLibFeature.ArraySome, node, caller, ...params); case "every": diff --git a/src/lualib/ArrayReduce.ts b/src/lualib/ArrayReduce.ts new file mode 100644 index 000000000..3bb3d2952 --- /dev/null +++ b/src/lualib/ArrayReduce.ts @@ -0,0 +1,28 @@ +// https://www.ecma-international.org/ecma-262/9.0/index.html#sec-array.prototype.reduce +function __TS__ArrayReduce( + this: void, + arr: T[], + callbackFn: (accumulator: T, currentValue: T, index: number, array: T[]) => T, + initial?: T +): T { + const len = arr.length; + + if (len === 0 && initial === undefined) { + // tslint:disable-next-line: no-string-throw + throw "Cannot reduce empty list without initial value."; + } + + let k = 0; + let accumulator = initial; + if (initial === undefined) { + accumulator = arr[0]; + k++; + } + + while (k < len) { + accumulator = callbackFn(accumulator, arr[k], k, arr); + k = k + 1; + } + + return accumulator; +} diff --git a/test/unit/lualib/array.spec.ts b/test/unit/lualib/array.spec.ts new file mode 100644 index 000000000..2786c902a --- /dev/null +++ b/test/unit/lualib/array.spec.ts @@ -0,0 +1,458 @@ +import * as util from "../../util"; + +test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])("forEach (%p)", ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let arrTest = ${JSON.stringify(inp)}; + arrTest.forEach((elem, index) => { + arrTest[index] = arrTest[index] + 1; + }) + return JSONStringify(arrTest);`, + ); + + expect(result).toBe(JSON.stringify(expected)); +}); + +test.each([ + { inp: [], searchEl: 3, expected: -1 }, + { inp: [0, 2, 4, 8], searchEl: 10, expected: -1 }, + { inp: [0, 2, 4, 8], searchEl: 8, expected: 3 }, +])("array.findIndex[value] (%p)", ({ inp, searchEl, expected }) => { + const result = util.transpileAndExecute( + `let arrTest = ${JSON.stringify(inp)}; + return JSONStringify(arrTest.findIndex((elem, index) => { + return elem === ${searchEl}; + }));`, + ); + + expect(result).toBe(expected); +}); + +test.each([ + { inp: [0, 2, 4, 8], expected: 3, value: 8 }, + { inp: [0, 2, 4, 8], expected: 1, value: 2 }, +])("array.findIndex[index] (%p)", ({ inp, expected, value }) => { + const result = util.transpileAndExecute( + `let arrTest = ${JSON.stringify(inp)}; + return JSONStringify(arrTest.findIndex((elem, index, arr) => { + return index === ${expected} && arr[${expected}] === ${value}; + }));`, + ); + + expect(result).toBe(expected); +}); + +test.each([ + { inp: [], func: "x => x" }, + { inp: [0, 1, 2, 3], func: "x => x" }, + { inp: [0, 1, 2, 3], func: "x => x*2" }, + { inp: [1, 2, 3, 4], func: "x => -x" }, + { inp: [0, 1, 2, 3], func: "x => x+2" }, + { inp: [0, 1, 2, 3], func: "x => x%2 == 0 ? x + 1 : x - 1" }, +])("array.map (%p)", ({ inp, func }) => { + const result = util.transpileAndExecute( + `return JSONStringify([${inp.toString()}].map(${func}))`, + ); + + expect(result).toBe(JSON.stringify(inp.map(eval(func)))); +}); + +test.each([ + { inp: [], func: "x => x > 1" }, + { inp: [0, 1, 2, 3], func: "x => x > 1" }, + { inp: [0, 1, 2, 3], func: "x => x < 3" }, + { inp: [0, 1, 2, 3], func: "x => x < 0" }, + { inp: [0, -1, -2, -3], func: "x => x < 0" }, + { inp: [0, 1, 2, 3], func: "() => true" }, + { inp: [0, 1, 2, 3], func: "() => false" }, +])("array.filter (%p)", ({ inp, func }) => { + const result = util.transpileAndExecute( + `return JSONStringify([${inp.toString()}].filter(${func}))`, + ); + + expect(result).toBe(JSON.stringify(inp.filter(eval(func)))); +}); + +test.each([ + { inp: [], func: "x => x > 1" }, + { inp: [0, 1, 2, 3], func: "x => x > 1" }, + { inp: [false, true, false], func: "x => x" }, + { inp: [true, true, true], func: "x => x" }, +])("array.every (%p)", ({ inp, func }) => { + const result = util.transpileAndExecute( + `return JSONStringify([${inp.toString()}].every(${func}))`, + ); + + expect(result).toBe(JSON.stringify(inp.every(eval(func)))); +}); + +test.each([ + { inp: [], func: "x => x > 1" }, + { inp: [0, 1, 2, 3], func: "x => x > 1" }, + { inp: [false, true, false], func: "x => x" }, + { inp: [true, true, true], func: "x => x" }, +])("array.some (%p)", ({ inp, func }) => { + const result = util.transpileAndExecute( + `return JSONStringify([${inp.toString()}].some(${func}))`, + ); + + expect(result).toBe(JSON.stringify(inp.some(eval(func)))); +}); + +test.each([ + { inp: [], start: 1, end: 2 }, + { inp: [0, 1, 2, 3], start: 1, end: 2 }, + { inp: [0, 1, 2, 3], start: 1, end: 1 }, + { inp: [0, 1, 2, 3], start: 1, end: -1 }, + { inp: [0, 1, 2, 3], start: -3, end: -1 }, + { inp: [0, 1, 2, 3, 4, 5], start: 1, end: 3 }, + { inp: [0, 1, 2, 3, 4, 5], start: 3 }, +])("array.slice (%p)", ({ inp, start, end }) => { + const result = util.transpileAndExecute( + `return JSONStringify([${inp.toString()}].slice(${start}, ${end}))`, + ); + + expect(result).toBe(JSON.stringify(inp.slice(start, end))); +}); + +test.each([ + { inp: [], start: 0, deleteCount: 0, newElements: [9, 10, 11] }, + { inp: [0, 1, 2, 3], start: 1, deleteCount: 0, newElements: [9, 10, 11] }, + { inp: [0, 1, 2, 3], start: 2, deleteCount: 2, newElements: [9, 10, 11] }, + { inp: [0, 1, 2, 3], start: 4, deleteCount: 1, newElements: [8, 9] }, + { inp: [0, 1, 2, 3], start: 4, deleteCount: 0, newElements: [8, 9] }, + { inp: [0, 1, 2, 3, 4, 5], start: 5, deleteCount: 9, newElements: [10, 11] }, + { inp: [0, 1, 2, 3, 4, 5], start: 3, deleteCount: 2, newElements: [3, 4, 5] }, +])("array.splice[Insert] (%p)", ({ inp, start, deleteCount, newElements }) => { + const result = util.transpileAndExecute( + `let spliceTestTable = [${inp.toString()}]; + spliceTestTable.splice(${start}, ${deleteCount}, ${newElements}); + return JSONStringify(spliceTestTable);`, + ); + + inp.splice(start, deleteCount, ...newElements); + expect(result).toBe(JSON.stringify(inp)); +}); + +test.each([ + { inp: [], start: 1, deleteCount: 1 }, + { inp: [0, 1, 2, 3], start: 1, deleteCount: 1 }, + { inp: [0, 1, 2, 3], start: 10, deleteCount: 1 }, + { inp: [0, 1, 2, 3], start: 4 }, + { inp: [0, 1, 2, 3, 4, 5], start: 3 }, + { inp: [0, 1, 2, 3, 4, 5], start: 2, deleteCount: 2 }, + { inp: [0, 1, 2, 3, 4, 5, 6, 7, 8], start: 5, deleteCount: 9, newElements: [10, 11] }, +])("array.splice[Remove] (%p)", ({ inp, start, deleteCount, newElements = [] }) => { + let result; + if (deleteCount) { + result = util.transpileAndExecute( + `let spliceTestTable = [${inp.toString()}]; + spliceTestTable.splice(${start}, ${deleteCount}, ${newElements}); + return JSONStringify(spliceTestTable);`, + ); + } else { + result = util.transpileAndExecute( + `let spliceTestTable = [${inp.toString()}]; + spliceTestTable.splice(${start}); + return JSONStringify(spliceTestTable);`, + ); + } + + if (deleteCount) { + inp.splice(start, deleteCount, ...newElements); + expect(result).toBe(JSON.stringify(inp)); + } else { + inp.splice(start); + expect(result).toBe(JSON.stringify(inp)); + } +}); + +test.each([ + { arr: [], args: [[]] }, + { arr: [1, 2, 3], args: [[]] }, + { arr: [1, 2, 3], args: [[4]] }, + { arr: [1, 2, 3], args: [[4, 5]] }, + { arr: [1, 2, 3], args: [[4, 5]] }, + { arr: [1, 2, 3], args: [4, [5]] }, + { arr: [1, 2, 3], args: [4, [5, 6]] }, + { arr: [1, 2, 3], args: [4, [5, 6], 7] }, + { arr: [1, 2, 3], args: ["test", [5, 6], 7, ["test1", "test2"]] }, + { arr: [1, 2, "test"], args: ["test", ["test1", "test2"]] }, +])("array.concat (%p)", ({ arr, args }: { arr: any[]; args: any[] }) => { + const argStr = args.map(arg => JSON.stringify(arg)).join(","); + + const result = util.transpileAndExecute( + `let concatTestTable: any[] = ${JSON.stringify(arr)}; + return JSONStringify(concatTestTable.concat(${argStr}));`, + ); + + const concatArr = arr.concat(...args); + expect(result).toBe(JSON.stringify(concatArr)); +}); + +test.each([ + { inp: [] }, + { inp: ["test1"] }, + { inp: ["test1", "test2"] }, + { inp: ["test1", "test2"], separator: ";" }, + { inp: ["test1", "test2"], separator: "" }, +])("array.join (%p)", ({ inp, separator }) => { + let separatorLua; + if (separator === "") { + separatorLua = '""'; + } else if (separator) { + separatorLua = '"' + separator + '"'; + } else { + separatorLua = ""; + } + const result = util.transpileAndExecute( + `let joinTestTable = ${JSON.stringify(inp)}; + return joinTestTable.join(${separatorLua});`, + ); + + const joinedInp = inp.join(separator); + expect(result).toBe(joinedInp); +}); + +test.each([ + { inp: [], element: "test1" }, + { inp: ["test1"], element: "test1" }, + { inp: ["test1", "test2"], element: "test2" }, + { inp: ["test1", "test2", "test3"], element: "test3", fromIndex: 1 }, + { inp: ["test1", "test2", "test3"], element: "test1", fromIndex: 2 }, + { inp: ["test1", "test2", "test3"], element: "test1", fromIndex: -2 }, + { inp: ["test1", "test2", "test3"], element: "test1", fromIndex: 12 }, +])("array.indexOf (%p)", ({ inp, element, fromIndex }) => { + let str = `return ${JSON.stringify(inp)}.indexOf("${element}");`; + if (fromIndex) { + str = `return ${JSON.stringify(inp)}.indexOf("${element}", ${fromIndex});`; + } + + const result = util.transpileAndExecute(str); + + // Account for lua indexing (-1) + expect(result).toBe(inp.indexOf(element, fromIndex)); +}); + +test.each([{ inp: [1, 2, 3], expected: 3 }, { inp: [1, 2, 3, 4, 5], expected: 3 }])( + "array.destructuring.simple (%p)", + ({ inp, expected }) => { + const result = util.transpileAndExecute( + `let [x, y, z] = ${JSON.stringify(inp)} + return z;`, + ); + + expect(result).toBe(expected); + }, +); + +test.each([{ inp: [1] }, { inp: [1, 2, 3] }])("array.push (%p)", ({ inp }) => { + const result = util.transpileAndExecute( + `let testArray = [0]; + testArray.push(${inp.join(", ")}); + return JSONStringify(testArray);`, + ); + + expect(result).toBe(JSON.stringify([0].concat(inp))); +}); + +test.each([ + { array: "[1, 2, 3]", expected: [3, 2] }, + { array: "[1, 2, 3, null]", expected: [3, 2] }, +])("array.pop (%p)", ({ array, expected }) => { + { + const result = util.transpileAndExecute( + `let testArray = ${array}; + let val = testArray.pop(); + return val`, + ); + + expect(result).toBe(expected[0]); + } + { + const result = util.transpileAndExecute( + `let testArray = ${array}; + testArray.pop(); + return testArray.length`, + ); + + expect(result).toBe(expected[1]); + } +}); + +test.each([ + { array: "[1, 2, 3]", expected: [3, 2, 1] }, + { array: "[1, 2, 3, null]", expected: [3, 2, 1] }, + { array: "[1, 2, 3, 4]", expected: [4, 3, 2, 1] }, + { array: "[1]", expected: [1] }, + { array: "[]", expected: [] }, +])("array.reverse (%p)", ({ array, expected }) => { + const result = util.transpileAndExecute( + `let testArray = ${array}; + let val = testArray.reverse(); + return JSONStringify(testArray)`, + ); + expect(result).toBe(JSON.stringify(expected)); +}); + +test.each([ + { array: "[1, 2, 3]", expectedArray: [2, 3], expectedValue: 1 }, + { array: "[1]", expectedArray: [], expectedValue: 1 }, + { array: "[]", expectedArray: [], expectedValue: undefined }, +])("array.shift (%p)", ({ array, expectedArray, expectedValue }) => { + { + // test array mutation + { + const result = util.transpileAndExecute( + `let testArray = ${array}; + let val = testArray.shift(); + return JSONStringify(testArray)`, + ); + expect(result).toBe(JSON.stringify(expectedArray)); + } + // test return value + { + const result = util.transpileAndExecute( + `let testArray = ${array}; + let val = testArray.shift(); + return val`, + ); + + expect(result).toBe(expectedValue); + } + } +}); + +test.each([ + { array: "[3, 4, 5]", toUnshift: [1, 2], expected: [1, 2, 3, 4, 5] }, + { array: "[]", toUnshift: [], expected: [] }, + { array: "[1]", toUnshift: [], expected: [1] }, + { array: "[]", toUnshift: [1], expected: [1] }, +])("array.unshift (%p)", ({ array, toUnshift, expected }) => { + const result = util.transpileAndExecute( + `let testArray = ${array}; + testArray.unshift(${toUnshift}); + return JSONStringify(testArray)`, + ); + + expect(result).toBe(JSON.stringify(expected)); +}); + +test.each([ + { array: "[4, 5, 3, 2, 1]", expected: [1, 2, 3, 4, 5] }, + { array: "[1]", expected: [1] }, + { array: "[1, null]", expected: [1] }, + { array: "[]", expected: [] }, +])("array.sort (%p)", ({ array, expected }) => { + const result = util.transpileAndExecute( + `let testArray = ${array}; + testArray.sort(); + return JSONStringify(testArray)`, + ); + + expect(result).toBe(JSON.stringify(expected)); +}); + +test.each([ + { array: [1, 2, 3, 4, 5], compareStr: "a - b", compareFn: (a: any, b: any) => a - b }, + { + array: ["4", "5", "3", "2", "1"], + compareStr: "tonumber(a) - tonumber(b)", + compareFn: (a: any, b: any) => Number(a) - Number(b), + }, + { + array: ["4", "5", "3", "2", "1"], + compareStr: "tonumber(b) - tonumber(a)", + compareFn: (a: any, b: any) => Number(b) - Number(a), + }, +])("array.sort with compare function (%p)", ({ array, compareStr, compareFn }) => { + const result = util.transpileAndExecute( + `let testArray = ${JSON.stringify(array)}; + testArray.sort((a, b) => ${compareStr}); + return JSONStringify(testArray)`, + undefined, + undefined, + `declare function tonumber(this: void, e: any): number`, + ); + + expect(result).toBe(JSON.stringify(array.sort(compareFn))); +}); + +test.each([ + { array: [1, [2, 3], 4], expected: [1, 2, 3, 4] }, + { array: [1, [2, 3], 4], depth: 0, expected: [1, [2, 3], 4] }, + { array: [1, [[2], [3]], 4], expected: [1, [2], [3], 4] }, + { array: [1, [[[2], [3]]], 4], depth: Infinity, expected: [1, 2, 3, 4] }, +])("array.flat (%p)", ({ array, depth, expected }) => { + // TODO: Remove once `Infinity` would be implemented + const luaDepth = depth === Infinity ? "1 / 0" : depth; + const result = util.transpileAndExecute(` + return JSONStringify(${JSON.stringify(array)}.flat(${luaDepth})) + `); + + expect(JSON.parse(result)).toEqual(expected); +}); + +test.each([ + { array: [1, [2, 3], [4]], map: (value: T) => value, expected: [1, 2, 3, 4] }, + { array: [1, 2, 3], map: (v: number) => v * 2, expected: [2, 4, 6] }, + { array: [1, 2, 3], map: (v: number) => [v, v * 2], expected: [1, 2, 2, 4, 3, 6] }, + { array: [1, 2, 3], map: (v: number) => [v, [v]], expected: [1, [1], 2, [2], 3, [3]] }, + { array: [1, 2, 3], map: (v: number, i: number) => [v * 2 * i], expected: [0, 4, 12] }, +])("array.flatMap (%p)", ({ array, map, expected }) => { + const result = util.transpileAndExecute(` + const array = ${JSON.stringify(array)}; + const result = array.flatMap(${map.toString()}); + return JSONStringify(result); + `); + + // TODO(node 12): array.flatMap(map) + expect(JSON.parse(result)).toEqual(expected); +}); + +test.each([ + (total: number, currentItem: number) => total + currentItem, + (total: number, currentItem: number) => total * currentItem, +])("array reduce (%p)", reducer => { + const array = [1, 3, 5, 7]; + + const result = util.transpileAndExecute(` + const myArray = ${JSON.stringify(array)}; + return myArray.reduce(${reducer.toString()}); + `); + + expect(result).toEqual(array.reduce(reducer)); +}); + +test.each([ + (total: number, currentItem: number) => total + currentItem, + (total: number, currentItem: number) => total * currentItem, +])("array reduce with initial value (%p)", reducer => { + const array = [1, 3, 5, 7]; + const initial = 10; + + const result = util.transpileAndExecute(` + const myArray = ${JSON.stringify(array)}; + return myArray.reduce(${reducer.toString()}, ${initial}); + `); + + expect(result).toEqual(array.reduce(reducer, initial)); +}); + +test("array reduce index & array arguments (%p)", () => { + const array = [1, 3, 5, 7]; + const reducer = (total: number, _: number, index: number, array: number[]) => + total + array[index]; + + const result = util.transpileAndExecute(` + const myArray = ${JSON.stringify(array)}; + return myArray.reduce(${reducer.toString()}); + `); + + expect(result).toEqual(array.reduce(reducer)); +}); + +test("array reduce index & array arguments (%p)", () => { + expect(() => { + util.transpileAndExecute("return [].reduce((a, b) => a + b);"); + }).toThrow("Cannot reduce empty list without initial value"); +}); diff --git a/test/unit/lualib/lualib.spec.ts b/test/unit/lualib/lualib.spec.ts index eaf54d1f8..148065d2f 100644 --- a/test/unit/lualib/lualib.spec.ts +++ b/test/unit/lualib/lualib.spec.ts @@ -1,414 +1,5 @@ import * as util from "../../util"; -test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])("forEach (%p)", ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let arrTest = ${JSON.stringify(inp)}; - arrTest.forEach((elem, index) => { - arrTest[index] = arrTest[index] + 1; - }) - return JSONStringify(arrTest);`, - ); - - expect(result).toBe(JSON.stringify(expected)); -}); - -test.each([ - { inp: [], searchEl: 3, expected: -1 }, - { inp: [0, 2, 4, 8], searchEl: 10, expected: -1 }, - { inp: [0, 2, 4, 8], searchEl: 8, expected: 3 }, -])("array.findIndex[value] (%p)", ({ inp, searchEl, expected }) => { - const result = util.transpileAndExecute( - `let arrTest = ${JSON.stringify(inp)}; - return JSONStringify(arrTest.findIndex((elem, index) => { - return elem === ${searchEl}; - }));`, - ); - - expect(result).toBe(expected); -}); - -test.each([ - { inp: [0, 2, 4, 8], expected: 3, value: 8 }, - { inp: [0, 2, 4, 8], expected: 1, value: 2 }, -])("array.findIndex[index] (%p)", ({ inp, expected, value }) => { - const result = util.transpileAndExecute( - `let arrTest = ${JSON.stringify(inp)}; - return JSONStringify(arrTest.findIndex((elem, index, arr) => { - return index === ${expected} && arr[${expected}] === ${value}; - }));`, - ); - - expect(result).toBe(expected); -}); - -test.each([ - { inp: [], func: "x => x" }, - { inp: [0, 1, 2, 3], func: "x => x" }, - { inp: [0, 1, 2, 3], func: "x => x*2" }, - { inp: [1, 2, 3, 4], func: "x => -x" }, - { inp: [0, 1, 2, 3], func: "x => x+2" }, - { inp: [0, 1, 2, 3], func: "x => x%2 == 0 ? x + 1 : x - 1" }, -])("array.map (%p)", ({ inp, func }) => { - const result = util.transpileAndExecute( - `return JSONStringify([${inp.toString()}].map(${func}))`, - ); - - expect(result).toBe(JSON.stringify(inp.map(eval(func)))); -}); - -test.each([ - { inp: [], func: "x => x > 1" }, - { inp: [0, 1, 2, 3], func: "x => x > 1" }, - { inp: [0, 1, 2, 3], func: "x => x < 3" }, - { inp: [0, 1, 2, 3], func: "x => x < 0" }, - { inp: [0, -1, -2, -3], func: "x => x < 0" }, - { inp: [0, 1, 2, 3], func: "() => true" }, - { inp: [0, 1, 2, 3], func: "() => false" }, -])("array.filter (%p)", ({ inp, func }) => { - const result = util.transpileAndExecute( - `return JSONStringify([${inp.toString()}].filter(${func}))`, - ); - - expect(result).toBe(JSON.stringify(inp.filter(eval(func)))); -}); - -test.each([ - { inp: [], func: "x => x > 1" }, - { inp: [0, 1, 2, 3], func: "x => x > 1" }, - { inp: [false, true, false], func: "x => x" }, - { inp: [true, true, true], func: "x => x" }, -])("array.every (%p)", ({ inp, func }) => { - const result = util.transpileAndExecute( - `return JSONStringify([${inp.toString()}].every(${func}))`, - ); - - expect(result).toBe(JSON.stringify(inp.every(eval(func)))); -}); - -test.each([ - { inp: [], func: "x => x > 1" }, - { inp: [0, 1, 2, 3], func: "x => x > 1" }, - { inp: [false, true, false], func: "x => x" }, - { inp: [true, true, true], func: "x => x" }, -])("array.some (%p)", ({ inp, func }) => { - const result = util.transpileAndExecute( - `return JSONStringify([${inp.toString()}].some(${func}))`, - ); - - expect(result).toBe(JSON.stringify(inp.some(eval(func)))); -}); - -test.each([ - { inp: [], start: 1, end: 2 }, - { inp: [0, 1, 2, 3], start: 1, end: 2 }, - { inp: [0, 1, 2, 3], start: 1, end: 1 }, - { inp: [0, 1, 2, 3], start: 1, end: -1 }, - { inp: [0, 1, 2, 3], start: -3, end: -1 }, - { inp: [0, 1, 2, 3, 4, 5], start: 1, end: 3 }, - { inp: [0, 1, 2, 3, 4, 5], start: 3 }, -])("array.slice (%p)", ({ inp, start, end }) => { - const result = util.transpileAndExecute( - `return JSONStringify([${inp.toString()}].slice(${start}, ${end}))`, - ); - - expect(result).toBe(JSON.stringify(inp.slice(start, end))); -}); - -test.each([ - { inp: [], start: 0, deleteCount: 0, newElements: [9, 10, 11] }, - { inp: [0, 1, 2, 3], start: 1, deleteCount: 0, newElements: [9, 10, 11] }, - { inp: [0, 1, 2, 3], start: 2, deleteCount: 2, newElements: [9, 10, 11] }, - { inp: [0, 1, 2, 3], start: 4, deleteCount: 1, newElements: [8, 9] }, - { inp: [0, 1, 2, 3], start: 4, deleteCount: 0, newElements: [8, 9] }, - { inp: [0, 1, 2, 3, 4, 5], start: 5, deleteCount: 9, newElements: [10, 11] }, - { inp: [0, 1, 2, 3, 4, 5], start: 3, deleteCount: 2, newElements: [3, 4, 5] }, -])("array.splice[Insert] (%p)", ({ inp, start, deleteCount, newElements }) => { - const result = util.transpileAndExecute( - `let spliceTestTable = [${inp.toString()}]; - spliceTestTable.splice(${start}, ${deleteCount}, ${newElements}); - return JSONStringify(spliceTestTable);`, - ); - - inp.splice(start, deleteCount, ...newElements); - expect(result).toBe(JSON.stringify(inp)); -}); - -test.each([ - { inp: [], start: 1, deleteCount: 1 }, - { inp: [0, 1, 2, 3], start: 1, deleteCount: 1 }, - { inp: [0, 1, 2, 3], start: 10, deleteCount: 1 }, - { inp: [0, 1, 2, 3], start: 4 }, - { inp: [0, 1, 2, 3, 4, 5], start: 3 }, - { inp: [0, 1, 2, 3, 4, 5], start: 2, deleteCount: 2 }, - { inp: [0, 1, 2, 3, 4, 5, 6, 7, 8], start: 5, deleteCount: 9, newElements: [10, 11] }, -])("array.splice[Remove] (%p)", ({ inp, start, deleteCount, newElements = [] }) => { - let result; - if (deleteCount) { - result = util.transpileAndExecute( - `let spliceTestTable = [${inp.toString()}]; - spliceTestTable.splice(${start}, ${deleteCount}, ${newElements}); - return JSONStringify(spliceTestTable);`, - ); - } else { - result = util.transpileAndExecute( - `let spliceTestTable = [${inp.toString()}]; - spliceTestTable.splice(${start}); - return JSONStringify(spliceTestTable);`, - ); - } - - if (deleteCount) { - inp.splice(start, deleteCount, ...newElements); - expect(result).toBe(JSON.stringify(inp)); - } else { - inp.splice(start); - expect(result).toBe(JSON.stringify(inp)); - } -}); - -test.each([ - { arr: [], args: [[]] }, - { arr: [1, 2, 3], args: [[]] }, - { arr: [1, 2, 3], args: [[4]] }, - { arr: [1, 2, 3], args: [[4, 5]] }, - { arr: [1, 2, 3], args: [[4, 5]] }, - { arr: [1, 2, 3], args: [4, [5]] }, - { arr: [1, 2, 3], args: [4, [5, 6]] }, - { arr: [1, 2, 3], args: [4, [5, 6], 7] }, - { arr: [1, 2, 3], args: ["test", [5, 6], 7, ["test1", "test2"]] }, - { arr: [1, 2, "test"], args: ["test", ["test1", "test2"]] }, -])("array.concat (%p)", ({ arr, args }: { arr: any[]; args: any[] }) => { - const argStr = args.map(arg => JSON.stringify(arg)).join(","); - - const result = util.transpileAndExecute( - `let concatTestTable: any[] = ${JSON.stringify(arr)}; - return JSONStringify(concatTestTable.concat(${argStr}));`, - ); - - const concatArr = arr.concat(...args); - expect(result).toBe(JSON.stringify(concatArr)); -}); - -test.each([ - { inp: [] }, - { inp: ["test1"] }, - { inp: ["test1", "test2"] }, - { inp: ["test1", "test2"], separator: ";" }, - { inp: ["test1", "test2"], separator: "" }, -])("array.join (%p)", ({ inp, separator }) => { - let separatorLua; - if (separator === "") { - separatorLua = '""'; - } else if (separator) { - separatorLua = '"' + separator + '"'; - } else { - separatorLua = ""; - } - const result = util.transpileAndExecute( - `let joinTestTable = ${JSON.stringify(inp)}; - return joinTestTable.join(${separatorLua});`, - ); - - const joinedInp = inp.join(separator); - expect(result).toBe(joinedInp); -}); - -test.each([ - { inp: [], element: "test1" }, - { inp: ["test1"], element: "test1" }, - { inp: ["test1", "test2"], element: "test2" }, - { inp: ["test1", "test2", "test3"], element: "test3", fromIndex: 1 }, - { inp: ["test1", "test2", "test3"], element: "test1", fromIndex: 2 }, - { inp: ["test1", "test2", "test3"], element: "test1", fromIndex: -2 }, - { inp: ["test1", "test2", "test3"], element: "test1", fromIndex: 12 }, -])("array.indexOf (%p)", ({ inp, element, fromIndex }) => { - let str = `return ${JSON.stringify(inp)}.indexOf("${element}");`; - if (fromIndex) { - str = `return ${JSON.stringify(inp)}.indexOf("${element}", ${fromIndex});`; - } - - const result = util.transpileAndExecute(str); - - // Account for lua indexing (-1) - expect(result).toBe(inp.indexOf(element, fromIndex)); -}); - -test.each([{ inp: [1, 2, 3], expected: 3 }, { inp: [1, 2, 3, 4, 5], expected: 3 }])( - "array.destructuring.simple (%p)", - ({ inp, expected }) => { - const result = util.transpileAndExecute( - `let [x, y, z] = ${JSON.stringify(inp)} - return z;`, - ); - - expect(result).toBe(expected); - }, -); - -test.each([{ inp: [1] }, { inp: [1, 2, 3] }])("array.push (%p)", ({ inp }) => { - const result = util.transpileAndExecute( - `let testArray = [0]; - testArray.push(${inp.join(", ")}); - return JSONStringify(testArray);`, - ); - - expect(result).toBe(JSON.stringify([0].concat(inp))); -}); - -test.each([ - { array: "[1, 2, 3]", expected: [3, 2] }, - { array: "[1, 2, 3, null]", expected: [3, 2] }, -])("array.pop (%p)", ({ array, expected }) => { - { - const result = util.transpileAndExecute( - `let testArray = ${array}; - let val = testArray.pop(); - return val`, - ); - - expect(result).toBe(expected[0]); - } - { - const result = util.transpileAndExecute( - `let testArray = ${array}; - testArray.pop(); - return testArray.length`, - ); - - expect(result).toBe(expected[1]); - } -}); - -test.each([ - { array: "[1, 2, 3]", expected: [3, 2, 1] }, - { array: "[1, 2, 3, null]", expected: [3, 2, 1] }, - { array: "[1, 2, 3, 4]", expected: [4, 3, 2, 1] }, - { array: "[1]", expected: [1] }, - { array: "[]", expected: [] }, -])("array.reverse (%p)", ({ array, expected }) => { - const result = util.transpileAndExecute( - `let testArray = ${array}; - let val = testArray.reverse(); - return JSONStringify(testArray)`, - ); - expect(result).toBe(JSON.stringify(expected)); -}); - -test.each([ - { array: "[1, 2, 3]", expectedArray: [2, 3], expectedValue: 1 }, - { array: "[1]", expectedArray: [], expectedValue: 1 }, - { array: "[]", expectedArray: [], expectedValue: undefined }, -])("array.shift (%p)", ({ array, expectedArray, expectedValue }) => { - { - // test array mutation - { - const result = util.transpileAndExecute( - `let testArray = ${array}; - let val = testArray.shift(); - return JSONStringify(testArray)`, - ); - expect(result).toBe(JSON.stringify(expectedArray)); - } - // test return value - { - const result = util.transpileAndExecute( - `let testArray = ${array}; - let val = testArray.shift(); - return val`, - ); - - expect(result).toBe(expectedValue); - } - } -}); - -test.each([ - { array: "[3, 4, 5]", toUnshift: [1, 2], expected: [1, 2, 3, 4, 5] }, - { array: "[]", toUnshift: [], expected: [] }, - { array: "[1]", toUnshift: [], expected: [1] }, - { array: "[]", toUnshift: [1], expected: [1] }, -])("array.unshift (%p)", ({ array, toUnshift, expected }) => { - const result = util.transpileAndExecute( - `let testArray = ${array}; - testArray.unshift(${toUnshift}); - return JSONStringify(testArray)`, - ); - - expect(result).toBe(JSON.stringify(expected)); -}); - -test.each([ - { array: "[4, 5, 3, 2, 1]", expected: [1, 2, 3, 4, 5] }, - { array: "[1]", expected: [1] }, - { array: "[1, null]", expected: [1] }, - { array: "[]", expected: [] }, -])("array.sort (%p)", ({ array, expected }) => { - const result = util.transpileAndExecute( - `let testArray = ${array}; - testArray.sort(); - return JSONStringify(testArray)`, - ); - - expect(result).toBe(JSON.stringify(expected)); -}); - -test.each([ - { array: [1, 2, 3, 4, 5], compareStr: "a - b", compareFn: (a: any, b: any) => a - b }, - { - array: ["4", "5", "3", "2", "1"], - compareStr: "tonumber(a) - tonumber(b)", - compareFn: (a: any, b: any) => Number(a) - Number(b), - }, - { - array: ["4", "5", "3", "2", "1"], - compareStr: "tonumber(b) - tonumber(a)", - compareFn: (a: any, b: any) => Number(b) - Number(a), - }, -])("array.sort with compare function (%p)", ({ array, compareStr, compareFn }) => { - const result = util.transpileAndExecute( - `let testArray = ${JSON.stringify(array)}; - testArray.sort((a, b) => ${compareStr}); - return JSONStringify(testArray)`, - undefined, - undefined, - `declare function tonumber(this: void, e: any): number`, - ); - - expect(result).toBe(JSON.stringify(array.sort(compareFn))); -}); - -test.each([ - { array: [1, [2, 3], 4], expected: [1, 2, 3, 4] }, - { array: [1, [2, 3], 4], depth: 0, expected: [1, [2, 3], 4] }, - { array: [1, [[2], [3]], 4], expected: [1, [2], [3], 4] }, - { array: [1, [[[2], [3]]], 4], depth: Infinity, expected: [1, 2, 3, 4] }, -])("array.flat (%p)", ({ array, depth, expected }) => { - // TODO: Remove once `Infinity` would be implemented - const luaDepth = depth === Infinity ? "1 / 0" : depth; - const result = util.transpileAndExecute(` - return JSONStringify(${JSON.stringify(array)}.flat(${luaDepth})) - `); - - expect(JSON.parse(result)).toEqual(expected); -}); - -test.each([ - { array: [1, [2, 3], [4]], map: (value: T) => value, expected: [1, 2, 3, 4] }, - { array: [1, 2, 3], map: (v: number) => v * 2, expected: [2, 4, 6] }, - { array: [1, 2, 3], map: (v: number) => [v, v * 2], expected: [1, 2, 2, 4, 3, 6] }, - { array: [1, 2, 3], map: (v: number) => [v, [v]], expected: [1, [1], 2, [2], 3, [3]] }, - { array: [1, 2, 3], map: (v: number, i: number) => [v * 2 * i], expected: [0, 4, 12] }, -])("array.flatMap (%p)", ({ array, map, expected }) => { - const result = util.transpileAndExecute(` - const array = ${JSON.stringify(array)}; - const result = array.flatMap(${map.toString()}); - return JSONStringify(result); - `); - - // TODO(node 12): array.flatMap(map) - expect(JSON.parse(result)).toEqual(expected); -}); - test.each([ { condition: "true", lhs: "4", rhs: "5", expected: 4 }, { condition: "false", lhs: "4", rhs: "5", expected: 5 }, From 41a1ef3697cd695a7b8118a222e59130bb029cc6 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Sun, 26 May 2019 14:04:35 +0200 Subject: [PATCH 2/6] Removed unused import --- src/LuaTransformer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index 20bb57ae6..9f6b0b888 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -3,7 +3,7 @@ import * as ts from "typescript"; import { CompilerOptions, LuaTarget } from "./CompilerOptions"; import { DecoratorKind } from "./Decorator"; import * as tstl from "./LuaAST"; -import { LuaLibFeature, LuaLib } from "./LuaLib"; +import { LuaLibFeature } from "./LuaLib"; import { ContextType, TSHelper as tsHelper } from "./TSHelper"; import { TSTLErrors } from "./TSTLErrors"; import { luaKeywords, luaBuiltins } from "./LuaKeywords"; From 289a24ed62a2fe237ce6404602123b234e3d854d Mon Sep 17 00:00:00 2001 From: Perry van Wesel Date: Sun, 26 May 2019 14:41:07 +0200 Subject: [PATCH 3/6] Update src/lualib/ArrayReduce.ts Co-Authored-By: ark120202 --- src/lualib/ArrayReduce.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lualib/ArrayReduce.ts b/src/lualib/ArrayReduce.ts index 3bb3d2952..9122afa68 100644 --- a/src/lualib/ArrayReduce.ts +++ b/src/lualib/ArrayReduce.ts @@ -9,7 +9,7 @@ function __TS__ArrayReduce( if (len === 0 && initial === undefined) { // tslint:disable-next-line: no-string-throw - throw "Cannot reduce empty list without initial value."; + throw "Reduce of empty array with no initial value"; } let k = 0; From 278e72d0b21e73781b68431e005a860c1b8f282d Mon Sep 17 00:00:00 2001 From: Perryvw Date: Sun, 26 May 2019 14:47:57 +0200 Subject: [PATCH 4/6] Fixed error test --- test/unit/lualib/array.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/lualib/array.spec.ts b/test/unit/lualib/array.spec.ts index 2786c902a..5ea632f94 100644 --- a/test/unit/lualib/array.spec.ts +++ b/test/unit/lualib/array.spec.ts @@ -454,5 +454,5 @@ test("array reduce index & array arguments (%p)", () => { test("array reduce index & array arguments (%p)", () => { expect(() => { util.transpileAndExecute("return [].reduce((a, b) => a + b);"); - }).toThrow("Cannot reduce empty list without initial value"); + }).toThrow("Reduce of empty array with no initial value"); }); From e84966ecf07ac876418ca0fd1262aec333f1b3f9 Mon Sep 17 00:00:00 2001 From: Perryvw Date: Mon, 27 May 2019 20:52:16 +0200 Subject: [PATCH 5/6] Updated tests --- src/lualib/ArraySlice.ts | 10 +- test/unit/lualib/array.spec.ts | 169 ++++++++++++++++----------------- 2 files changed, 90 insertions(+), 89 deletions(-) diff --git a/src/lualib/ArraySlice.ts b/src/lualib/ArraySlice.ts index 8005e9afc..d38d96006 100644 --- a/src/lualib/ArraySlice.ts +++ b/src/lualib/ArraySlice.ts @@ -1,12 +1,14 @@ -// https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf 22.1.3.23 +// https://www.ecma-international.org/ecma-262/9.0/index.html#sec-array.prototype.slice function __TS__ArraySlice(this: void, list: T[], first: number, last: number): T[] { const len = list.length; + const relativeStart = first || 0; + let k: number; - if (first < 0) { - k = Math.max(len + first, 0); + if (relativeStart < 0) { + k = Math.max(len + relativeStart, 0); } else { - k = Math.min(first, len); + k = Math.min(relativeStart, len); } let relativeEnd = last; diff --git a/test/unit/lualib/array.spec.ts b/test/unit/lualib/array.spec.ts index 5ea632f94..bd5a6800c 100644 --- a/test/unit/lualib/array.spec.ts +++ b/test/unit/lualib/array.spec.ts @@ -6,10 +6,10 @@ test.each([{ inp: [0, 1, 2, 3], expected: [1, 2, 3, 4] }])("forEach (%p)", ({ in arrTest.forEach((elem, index) => { arrTest[index] = arrTest[index] + 1; }) - return JSONStringify(arrTest);`, + return JSONStringify(arrTest);` ); - expect(result).toBe(JSON.stringify(expected)); + expect(JSON.parse(result)).toEqual(expected); }); test.each([ @@ -21,25 +21,25 @@ test.each([ `let arrTest = ${JSON.stringify(inp)}; return JSONStringify(arrTest.findIndex((elem, index) => { return elem === ${searchEl}; - }));`, + }));` ); - expect(result).toBe(expected); + expect(result).toEqual(expected); }); -test.each([ - { inp: [0, 2, 4, 8], expected: 3, value: 8 }, - { inp: [0, 2, 4, 8], expected: 1, value: 2 }, -])("array.findIndex[index] (%p)", ({ inp, expected, value }) => { - const result = util.transpileAndExecute( - `let arrTest = ${JSON.stringify(inp)}; +test.each([{ inp: [0, 2, 4, 8], expected: 3, value: 8 }, { inp: [0, 2, 4, 8], expected: 1, value: 2 }])( + "array.findIndex[index] (%p)", + ({ inp, expected, value }) => { + const result = util.transpileAndExecute( + `let arrTest = ${JSON.stringify(inp)}; return JSONStringify(arrTest.findIndex((elem, index, arr) => { return index === ${expected} && arr[${expected}] === ${value}; - }));`, - ); + }));` + ); - expect(result).toBe(expected); -}); + expect(result).toEqual(expected); + } +); test.each([ { inp: [], func: "x => x" }, @@ -49,11 +49,9 @@ test.each([ { inp: [0, 1, 2, 3], func: "x => x+2" }, { inp: [0, 1, 2, 3], func: "x => x%2 == 0 ? x + 1 : x - 1" }, ])("array.map (%p)", ({ inp, func }) => { - const result = util.transpileAndExecute( - `return JSONStringify([${inp.toString()}].map(${func}))`, - ); + const result = util.transpileAndExecute(`return JSONStringify([${inp.toString()}].map(${func}))`); - expect(result).toBe(JSON.stringify(inp.map(eval(func)))); + expect(JSON.parse(result)).toEqual(inp.map(eval(func))); }); test.each([ @@ -65,11 +63,9 @@ test.each([ { inp: [0, 1, 2, 3], func: "() => true" }, { inp: [0, 1, 2, 3], func: "() => false" }, ])("array.filter (%p)", ({ inp, func }) => { - const result = util.transpileAndExecute( - `return JSONStringify([${inp.toString()}].filter(${func}))`, - ); + const result = util.transpileAndExecute(`return JSONStringify([${inp.toString()}].filter(${func}))`); - expect(result).toBe(JSON.stringify(inp.filter(eval(func)))); + expect(JSON.parse(result)).toEqual(inp.filter(eval(func))); }); test.each([ @@ -78,11 +74,9 @@ test.each([ { inp: [false, true, false], func: "x => x" }, { inp: [true, true, true], func: "x => x" }, ])("array.every (%p)", ({ inp, func }) => { - const result = util.transpileAndExecute( - `return JSONStringify([${inp.toString()}].every(${func}))`, - ); + const result = util.transpileAndExecute(`return JSONStringify([${inp.toString()}].every(${func}))`); - expect(result).toBe(JSON.stringify(inp.every(eval(func)))); + expect(JSON.parse(result)).toEqual(inp.every(eval(func))); }); test.each([ @@ -91,11 +85,9 @@ test.each([ { inp: [false, true, false], func: "x => x" }, { inp: [true, true, true], func: "x => x" }, ])("array.some (%p)", ({ inp, func }) => { - const result = util.transpileAndExecute( - `return JSONStringify([${inp.toString()}].some(${func}))`, - ); + const result = util.transpileAndExecute(`return JSONStringify([${inp.toString()}].some(${func}))`); - expect(result).toBe(JSON.stringify(inp.some(eval(func)))); + expect(JSON.parse(result)).toEqual(inp.some(eval(func))); }); test.each([ @@ -107,11 +99,16 @@ test.each([ { inp: [0, 1, 2, 3, 4, 5], start: 1, end: 3 }, { inp: [0, 1, 2, 3, 4, 5], start: 3 }, ])("array.slice (%p)", ({ inp, start, end }) => { - const result = util.transpileAndExecute( - `return JSONStringify([${inp.toString()}].slice(${start}, ${end}))`, - ); + const result = util.transpileAndExecute(`return JSONStringify([${inp.toString()}].slice(${start}, ${end}))`); - expect(result).toBe(JSON.stringify(inp.slice(start, end))); + expect(JSON.parse(result)).toEqual(inp.slice(start, end)); +}); + +test("array.slice no argument", () => { + const input = [2, 3, 4, 5]; + const result = util.transpileAndExecute(`return JSONStringify(${JSON.stringify(input)}.slice())`); + + expect(JSON.parse(result)).toEqual(input); }); test.each([ @@ -120,17 +117,19 @@ test.each([ { inp: [0, 1, 2, 3], start: 2, deleteCount: 2, newElements: [9, 10, 11] }, { inp: [0, 1, 2, 3], start: 4, deleteCount: 1, newElements: [8, 9] }, { inp: [0, 1, 2, 3], start: 4, deleteCount: 0, newElements: [8, 9] }, + { inp: [0, 1, 2, 3], start: -2, deleteCount: 0, newElements: [8, 9] }, + { inp: [0, 1, 2, 3], start: -3, deleteCount: 0, newElements: [8, 9] }, { inp: [0, 1, 2, 3, 4, 5], start: 5, deleteCount: 9, newElements: [10, 11] }, { inp: [0, 1, 2, 3, 4, 5], start: 3, deleteCount: 2, newElements: [3, 4, 5] }, ])("array.splice[Insert] (%p)", ({ inp, start, deleteCount, newElements }) => { const result = util.transpileAndExecute( `let spliceTestTable = [${inp.toString()}]; spliceTestTable.splice(${start}, ${deleteCount}, ${newElements}); - return JSONStringify(spliceTestTable);`, + return JSONStringify(spliceTestTable);` ); inp.splice(start, deleteCount, ...newElements); - expect(result).toBe(JSON.stringify(inp)); + expect(JSON.parse(result)).toEqual(inp); }); test.each([ @@ -139,6 +138,8 @@ test.each([ { inp: [0, 1, 2, 3], start: 10, deleteCount: 1 }, { inp: [0, 1, 2, 3], start: 4 }, { inp: [0, 1, 2, 3, 4, 5], start: 3 }, + { inp: [0, 1, 2, 3, 4, 5], start: -3 }, + { inp: [0, 1, 2, 3, 4, 5], start: -2 }, { inp: [0, 1, 2, 3, 4, 5], start: 2, deleteCount: 2 }, { inp: [0, 1, 2, 3, 4, 5, 6, 7, 8], start: 5, deleteCount: 9, newElements: [10, 11] }, ])("array.splice[Remove] (%p)", ({ inp, start, deleteCount, newElements = [] }) => { @@ -147,22 +148,22 @@ test.each([ result = util.transpileAndExecute( `let spliceTestTable = [${inp.toString()}]; spliceTestTable.splice(${start}, ${deleteCount}, ${newElements}); - return JSONStringify(spliceTestTable);`, + return JSONStringify(spliceTestTable);` ); } else { result = util.transpileAndExecute( `let spliceTestTable = [${inp.toString()}]; spliceTestTable.splice(${start}); - return JSONStringify(spliceTestTable);`, + return JSONStringify(spliceTestTable);` ); } if (deleteCount) { inp.splice(start, deleteCount, ...newElements); - expect(result).toBe(JSON.stringify(inp)); + expect(JSON.parse(result)).toEqual(inp); } else { inp.splice(start); - expect(result).toBe(JSON.stringify(inp)); + expect(JSON.parse(result)).toEqual(inp); } }); @@ -182,11 +183,11 @@ test.each([ const result = util.transpileAndExecute( `let concatTestTable: any[] = ${JSON.stringify(arr)}; - return JSONStringify(concatTestTable.concat(${argStr}));`, + return JSONStringify(concatTestTable.concat(${argStr}));` ); const concatArr = arr.concat(...args); - expect(result).toBe(JSON.stringify(concatArr)); + expect(JSON.parse(result)).toEqual(concatArr); }); test.each([ @@ -206,11 +207,10 @@ test.each([ } const result = util.transpileAndExecute( `let joinTestTable = ${JSON.stringify(inp)}; - return joinTestTable.join(${separatorLua});`, + return joinTestTable.join(${separatorLua});` ); - const joinedInp = inp.join(separator); - expect(result).toBe(joinedInp); + expect(result).toEqual(inp.join(separator)); }); test.each([ @@ -230,7 +230,7 @@ test.each([ const result = util.transpileAndExecute(str); // Account for lua indexing (-1) - expect(result).toBe(inp.indexOf(element, fromIndex)); + expect(result).toEqual(inp.indexOf(element, fromIndex)); }); test.each([{ inp: [1, 2, 3], expected: 3 }, { inp: [1, 2, 3, 4, 5], expected: 3 }])( @@ -238,46 +238,46 @@ test.each([{ inp: [1, 2, 3], expected: 3 }, { inp: [1, 2, 3, 4, 5], expected: 3 ({ inp, expected }) => { const result = util.transpileAndExecute( `let [x, y, z] = ${JSON.stringify(inp)} - return z;`, + return z;` ); - expect(result).toBe(expected); - }, + expect(result).toEqual(expected); + } ); test.each([{ inp: [1] }, { inp: [1, 2, 3] }])("array.push (%p)", ({ inp }) => { const result = util.transpileAndExecute( `let testArray = [0]; testArray.push(${inp.join(", ")}); - return JSONStringify(testArray);`, + return JSONStringify(testArray);` ); - expect(result).toBe(JSON.stringify([0].concat(inp))); + expect(JSON.parse(result)).toEqual([0].concat(inp)); }); -test.each([ - { array: "[1, 2, 3]", expected: [3, 2] }, - { array: "[1, 2, 3, null]", expected: [3, 2] }, -])("array.pop (%p)", ({ array, expected }) => { - { - const result = util.transpileAndExecute( - `let testArray = ${array}; - let val = testArray.pop(); - return val`, - ); +test.each([{ array: "[1, 2, 3]", expected: [3, 2] }, { array: "[1, 2, 3, null]", expected: [3, 2] }])( + "array.pop (%p)", + ({ array, expected }) => { + { + const result = util.transpileAndExecute( + `let testArray = ${array}; + let val = testArray.pop(); + return val` + ); - expect(result).toBe(expected[0]); - } - { - const result = util.transpileAndExecute( - `let testArray = ${array}; - testArray.pop(); - return testArray.length`, - ); + expect(result).toEqual(expected[0]); + } + { + const result = util.transpileAndExecute( + `let testArray = ${array}; + testArray.pop(); + return testArray.length` + ); - expect(result).toBe(expected[1]); + expect(result).toEqual(expected[1]); + } } -}); +); test.each([ { array: "[1, 2, 3]", expected: [3, 2, 1] }, @@ -289,9 +289,9 @@ test.each([ const result = util.transpileAndExecute( `let testArray = ${array}; let val = testArray.reverse(); - return JSONStringify(testArray)`, + return JSONStringify(testArray)` ); - expect(result).toBe(JSON.stringify(expected)); + expect(JSON.parse(result)).toEqual(expected); }); test.each([ @@ -305,19 +305,19 @@ test.each([ const result = util.transpileAndExecute( `let testArray = ${array}; let val = testArray.shift(); - return JSONStringify(testArray)`, + return JSONStringify(testArray)` ); - expect(result).toBe(JSON.stringify(expectedArray)); + expect(JSON.parse(result)).toEqual(expectedArray); } // test return value { const result = util.transpileAndExecute( `let testArray = ${array}; let val = testArray.shift(); - return val`, + return val` ); - expect(result).toBe(expectedValue); + expect(result).toEqual(expectedValue); } } }); @@ -331,10 +331,10 @@ test.each([ const result = util.transpileAndExecute( `let testArray = ${array}; testArray.unshift(${toUnshift}); - return JSONStringify(testArray)`, + return JSONStringify(testArray)` ); - expect(result).toBe(JSON.stringify(expected)); + expect(JSON.parse(result)).toEqual(expected); }); test.each([ @@ -346,10 +346,10 @@ test.each([ const result = util.transpileAndExecute( `let testArray = ${array}; testArray.sort(); - return JSONStringify(testArray)`, + return JSONStringify(testArray)` ); - expect(result).toBe(JSON.stringify(expected)); + expect(JSON.parse(result)).toEqual(expected); }); test.each([ @@ -371,10 +371,10 @@ test.each([ return JSONStringify(testArray)`, undefined, undefined, - `declare function tonumber(this: void, e: any): number`, + `declare function tonumber(this: void, e: any): number` ); - expect(result).toBe(JSON.stringify(array.sort(compareFn))); + expect(JSON.parse(result)).toEqual(array.sort(compareFn)); }); test.each([ @@ -440,8 +440,7 @@ test.each([ test("array reduce index & array arguments (%p)", () => { const array = [1, 3, 5, 7]; - const reducer = (total: number, _: number, index: number, array: number[]) => - total + array[index]; + const reducer = (total: number, _: number, index: number, array: number[]) => total + array[index]; const result = util.transpileAndExecute(` const myArray = ${JSON.stringify(array)}; From a85d9a02f2bea5d4058f2b6785f78f07b587296b Mon Sep 17 00:00:00 2001 From: Perryvw Date: Mon, 27 May 2019 21:06:02 +0200 Subject: [PATCH 6/6] Added undefined deleteCount test --- test/unit/lualib/array.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/lualib/array.spec.ts b/test/unit/lualib/array.spec.ts index bd5a6800c..ad8c64db2 100644 --- a/test/unit/lualib/array.spec.ts +++ b/test/unit/lualib/array.spec.ts @@ -136,6 +136,7 @@ test.each([ { inp: [], start: 1, deleteCount: 1 }, { inp: [0, 1, 2, 3], start: 1, deleteCount: 1 }, { inp: [0, 1, 2, 3], start: 10, deleteCount: 1 }, + { inp: [0, 1, 2, 3], start: 1, deleteCount: undefined }, { inp: [0, 1, 2, 3], start: 4 }, { inp: [0, 1, 2, 3, 4, 5], start: 3 }, { inp: [0, 1, 2, 3, 4, 5], start: -3 },