From b091feadb40329da70c939a4696dc4af32e9b3bf Mon Sep 17 00:00:00 2001 From: Mert Can Altin Date: Sun, 11 Aug 2024 00:37:51 +0300 Subject: [PATCH] test: add separate test files for transform mode and feature testing --- ...sform TypeScript class decorators.snapshot | 13 +++ ...d transform TypeScript namespaces.snapshot | 12 +++ ...sform-decorator-namespace.test.js.snapshot | 7 ++ .../transform-feature.test.js.snapshot | 11 +++ .../snapshots/transform-mode.test.js.snapshot | 15 +++ test/transform-decorator-namespace.test.js | 93 +++++++++++++++++++ test/transform-feature.test.js | 59 ++++++++++++ test/transform-mode.test.js | 86 +++++++++++++++++ 8 files changed, 296 insertions(+) create mode 100644 test/snapshots/should transform TypeScript class decorators.snapshot create mode 100644 test/snapshots/should transform TypeScript namespaces.snapshot create mode 100644 test/snapshots/transform-decorator-namespace.test.js.snapshot create mode 100644 test/snapshots/transform-feature.test.js.snapshot create mode 100644 test/snapshots/transform-mode.test.js.snapshot create mode 100644 test/transform-decorator-namespace.test.js create mode 100644 test/transform-feature.test.js create mode 100644 test/transform-mode.test.js diff --git a/test/snapshots/should transform TypeScript class decorators.snapshot b/test/snapshots/should transform TypeScript class decorators.snapshot new file mode 100644 index 000000000..1cf3f780f --- /dev/null +++ b/test/snapshots/should transform TypeScript class decorators.snapshot @@ -0,0 +1,13 @@ +@sealed +class BugReport { + type = "report"; + title; + constructor(t){ + this.title = t; + } +} +function sealed(constructor) { + Object.seal(constructor); + Object.seal(constructor.prototype); +} +const report = new BugReport("Test"); diff --git a/test/snapshots/should transform TypeScript namespaces.snapshot b/test/snapshots/should transform TypeScript namespaces.snapshot new file mode 100644 index 000000000..681268b23 --- /dev/null +++ b/test/snapshots/should transform TypeScript namespaces.snapshot @@ -0,0 +1,12 @@ +var Validation; +(function(Validation) { + const lettersRegexp = /^[A-Za-z]+$/; + class LettersOnlyValidator { + isAcceptable(s) { + return lettersRegexp.test(s); + } + } + Validation.LettersOnlyValidator = LettersOnlyValidator; +})(Validation || (Validation = {})); +const validator = new Validation.LettersOnlyValidator(); +const isValid = validator.isAcceptable("test"); diff --git a/test/snapshots/transform-decorator-namespace.test.js.snapshot b/test/snapshots/transform-decorator-namespace.test.js.snapshot new file mode 100644 index 000000000..5cd09cbfc --- /dev/null +++ b/test/snapshots/transform-decorator-namespace.test.js.snapshot @@ -0,0 +1,7 @@ +exports[`should transform TypeScript class decorators with multiple decorators 1`] = ` +"@sealed\\n@log\\nclass BugReport {\\n type = \\"report\\";\\n title;\\n constructor(t){\\n this.title = t;\\n }\\n}\\nfunction sealed(constructor) {\\n Object.seal(constructor);\\n Object.seal(constructor.prototype);\\n}\\nfunction log(constructor) {\\n console.log(\\"Creating instance of\\", constructor.name);\\n}\\nconst report = new BugReport(\\"Test\\");\\n" +`; + +exports[`should transform TypeScript namespaces with additional functionality 1`] = ` +"var Validation;\\n(function(Validation) {\\n const lettersRegexp = /^[A-Za-z]+$/;\\n class LettersOnlyValidator {\\n isAcceptable(s) {\\n return lettersRegexp.test(s);\\n }\\n static createValidator() {\\n return new LettersOnlyValidator();\\n }\\n }\\n Validation.LettersOnlyValidator = LettersOnlyValidator;\\n})(Validation || (Validation = {}));\\nconst validator = Validation.LettersOnlyValidator.createValidator();\\nconst isValid = validator.isAcceptable(\\"test\\");\\n" +`; diff --git a/test/snapshots/transform-feature.test.js.snapshot b/test/snapshots/transform-feature.test.js.snapshot new file mode 100644 index 000000000..284c5bc5a --- /dev/null +++ b/test/snapshots/transform-feature.test.js.snapshot @@ -0,0 +1,11 @@ +exports[`should transform TypeScript class fields 1`] = ` +"class Counter {\\n count = 0;\\n increment() {\\n this.count++;\\n }\\n}\\n" +`; + +exports[`should transform TypeScript private class fields 1`] = ` +"class Counter {\\n #count = 0;\\n increment() {\\n this.#count++;\\n }\\n getCount() {\\n return this.#count;\\n }\\n}\\n" +`; + +exports[`should transform TypeScript type annotations and type guards 1`] = ` +"function isString(value) {\\n return typeof value === 'string';\\n}\\n" +`; diff --git a/test/snapshots/transform-mode.test.js.snapshot b/test/snapshots/transform-mode.test.js.snapshot new file mode 100644 index 000000000..ee175fbc0 --- /dev/null +++ b/test/snapshots/transform-mode.test.js.snapshot @@ -0,0 +1,15 @@ +exports[`should handle TypeScript decorators 1`] = ` +"@sealed\\nclass BugReport {\\n type = \\"report\\";\\n title;\\n constructor(t){\\n this.title = t;\\n }\\n}\\nfunction sealed(constructor) {\\n Object.seal(constructor);\\n Object.seal(constructor.prototype);\\n}\\n" +`; + +exports[`should handle TypeScript enums 1`] = ` +"var Direction;\\n(function(Direction) {\\n Direction[Direction[\\"Up\\"] = 0] = \\"Up\\";\\n Direction[Direction[\\"Down\\"] = 1] = \\"Down\\";\\n Direction[Direction[\\"Left\\"] = 2] = \\"Left\\";\\n Direction[Direction[\\"Right\\"] = 3] = \\"Right\\";\\n})(Direction || (Direction = {}));\\nconst dir = 0;\\n" +`; + +exports[`should handle TypeScript namespaces 1`] = ` +"var Validation;\\n(function(Validation) {\\n const lettersRegexp = /^[A-Za-z]+$/;\\n class LettersOnlyValidator {\\n isAcceptable(s) {\\n return lettersRegexp.test(s);\\n }\\n }\\n Validation.LettersOnlyValidator = LettersOnlyValidator;\\n})(Validation || (Validation = {}));\\n" +`; + +exports[`should strip TypeScript type annotations 1`] = ` +"function greet(name) {\\n console.log(name);\\n}\\n" +`; diff --git a/test/transform-decorator-namespace.test.js b/test/transform-decorator-namespace.test.js new file mode 100644 index 000000000..6b080a021 --- /dev/null +++ b/test/transform-decorator-namespace.test.js @@ -0,0 +1,93 @@ +const { test } = require("node:test"); +const assert = require("node:assert"); +const { transformSync } = require("../dist/index.js"); +const path = require("node:path"); +const vm = require("node:vm"); + +snapshot.setResolveSnapshotPath((testPath) => { + return path.join( + __dirname, + "snapshots", + `${path.basename(testPath)}.snapshot`, + ); +}); + +test("should transform TypeScript class decorators with multiple decorators", (t) => { + const inputCode = ` + @sealed + @log + class BugReport { + type = "report"; + title: string; + constructor(t: string) { + this.title = t; + } + } + + function sealed(constructor: Function) { + Object.seal(constructor); + Object.seal(constructor.prototype); + } + + function log(constructor: Function) { + console.log("Creating instance of", constructor.name); + } + + const report = new BugReport("Test"); +`; + + const { code } = transformSync(inputCode, { + mode: "transform", + sourceMaps: true, + parserOpts: { + plugins: ["decorators-legacy"], + }, + }); + + assert.matchSnapshot(code); + + const script = new vm.Script(code); + const context = vm.createContext({}); + script.runInContext(context); + + t.ok(context.report, "Report instance should exist"); + assert.equal(context.report.type, "report", "Report type should be 'report'"); + assert.equal(context.report.title, "Test", "Report title should be 'Test'"); +}); + +test("should transform TypeScript namespaces with additional functionality", (t) => { + const inputCode = ` + namespace Validation { + export interface StringValidator { + isAcceptable(s: string): boolean; + } + const lettersRegexp = /^[A-Za-z]+$/; + export class LettersOnlyValidator implements StringValidator { + isAcceptable(s: string) { + return lettersRegexp.test(s); + } + static createValidator(): LettersOnlyValidator { + return new LettersOnlyValidator(); + } + } + } + + const validator = Validation.LettersOnlyValidator.createValidator(); + const isValid = validator.isAcceptable("test"); +`; + + const { code } = transformSync(inputCode, { + mode: "transform", + sourceMaps: true, + }); + + assert.matchSnapshot(code); + + const script = new vm.Script(code); + const context = vm.createContext({}); + script.runInContext(context); + + t.ok(context.validator, "Validator instance should exist"); + t.ok(context.isValid, "isValid should be true"); + assert.equal(context.isValid, true, "String should be valid"); +}); diff --git a/test/transform-feature.test.js b/test/transform-feature.test.js new file mode 100644 index 000000000..877ed84ee --- /dev/null +++ b/test/transform-feature.test.js @@ -0,0 +1,59 @@ +const { test, snapshot } = require("node:test"); +const { transformSync } = require("../dist/index.js"); +const path = require("node:path"); + +snapshot.setResolveSnapshotPath((testPath) => { + return path.join( + __dirname, + "snapshots", + `${path.basename(testPath)}.snapshot`, + ); +}); + +test("should transform TypeScript class fields", (t) => { + const inputCode = ` + class Counter { + count: number = 0; + increment() { + this.count++; + } + } + `; + const { code } = transformSync(inputCode, { + mode: "transform", + sourceMaps: true, + }); + t.assert.snapshot(code); +}); + +test("should transform TypeScript private class fields", (t) => { + const inputCode = ` + class Counter { + #count: number = 0; + increment() { + this.#count++; + } + getCount(): number { + return this.#count; + } + } + `; + const { code } = transformSync(inputCode, { + mode: "transform", + sourceMaps: true, + }); + t.assert.snapshot(code); +}); + +test("should transform TypeScript type annotations and type guards", (t) => { + const inputCode = ` + function isString(value: unknown): value is string { + return typeof value === 'string'; + } + `; + const { code } = transformSync(inputCode, { + mode: "transform", + sourceMaps: true, + }); + t.assert.snapshot(code); +}); diff --git a/test/transform-mode.test.js b/test/transform-mode.test.js new file mode 100644 index 000000000..034444ee5 --- /dev/null +++ b/test/transform-mode.test.js @@ -0,0 +1,86 @@ +const { test, snapshot } = require("node:test"); +const { transformSync } = require("../dist/index.js"); +const path = require("node:path"); + +// Set the path for the snapshots directory +snapshot.setResolveSnapshotPath((testPath) => { + return path.join( + __dirname, + "snapshots", + `${path.basename(testPath)}.snapshot`, + ); +}); + +test("should handle TypeScript decorators", (t) => { + const inputCode = ` + @sealed + class BugReport { + type = "report"; + title: string; + constructor(t: string) { + this.title = t; + } + } + + function sealed(constructor: Function) { + Object.seal(constructor); + Object.seal(constructor.prototype); + } + `; + const { code } = transformSync(inputCode, { + mode: "transform", + sourceMaps: true, + }); + t.assert.snapshot(code); +}); + +test("should handle TypeScript namespaces", (t) => { + const inputCode = ` + namespace Validation { + export interface StringValidator { + isAcceptable(s: string): boolean; + } + const lettersRegexp = /^[A-Za-z]+$/; + export class LettersOnlyValidator implements StringValidator { + isAcceptable(s: string) { + return lettersRegexp.test(s); + } + } + } + `; + const { code } = transformSync(inputCode, { + mode: "transform", + sourceMaps: true, + }); + t.assert.snapshot(code); +}); + +test("should strip TypeScript type annotations", (t) => { + const inputCode = ` + function greet(name: string): void { + console.log(name); + } + `; + const { code } = transformSync(inputCode, { + mode: "transform", + sourceMaps: true, + }); + t.assert.snapshot(code); +}); + +test("should handle TypeScript enums", (t) => { + const inputCode = ` + enum Direction { + Up, + Down, + Left, + Right + } + const dir = Direction.Up; + `; + const { code } = transformSync(inputCode, { + mode: "transform", + sourceMaps: true, + }); + t.assert.snapshot(code); +});