From f3bed0000049f98d9f38531cb2ee2a052f3b023c Mon Sep 17 00:00:00 2001 From: Marc Lipovsky Date: Thu, 17 Oct 2024 23:54:00 -0400 Subject: [PATCH] Rewrite tests to actually test selection of a document and then execute commands instead of executing string functions. --- content.txt | 45 +++ eslint.config.mjs | 40 +-- package-lock.json | 113 ++++-- package.json | 4 +- src/test/extension.test.ts | 691 ++++++++++++++++++++++++++++--------- 5 files changed, 669 insertions(+), 224 deletions(-) create mode 100644 content.txt diff --git a/content.txt b/content.txt new file mode 100644 index 0000000..9abcf5c --- /dev/null +++ b/content.txt @@ -0,0 +1,45 @@ +moz-transform +-moz-transform +foo Bar + foo bar +ääkkönen +foo Bar +some_class_name +MozTransform +Foo Bar + capitalize dash-CamelCase_underscore trim +Abc +Un éléphant à l'orée du bois +HELLOworld +This-is_snake case +screaming-snake case +my name is tristan +this is a test +The quick brown fox jumps over the lazy dog. +Underscored-is-like snake-case +aabbccdd +aabbccdd +aabbccddaabbccdd +aabbccdd +a1 b2 c3 4d 5e 6f 12x y23 34z45 +a1 b2 c3 4d 5e +6f 12x y23 34z45 +a-4 b-3 c-2 -1d 0e +6f 12x y23 34z45 +a1 b2 c3 4d 5e 6f 12x y23 34z45 +a1 b2 c3 4d +5e 6f 12x y23 34z45 +a-3 b-2 c-1 0d +1e 6f 12x y23 34z45 +a1 b2 c3 4d 5e 6f 12x y23 34z45 + +a1 b2 c3 4d 5e 6f 12x y23 34z45 + +a1 b2 c3 4d 5e 6f 12x y23 34z45 +a14 b2 c3 +4d 5e 6f 7x y8 9z12 +\u0061\u0062\u0063\u4e2d\u6587\ud83d\udc96 +abc中文💖 +Hello, World! +12345!@#$% +Test123! diff --git a/eslint.config.mjs b/eslint.config.mjs index d5c0b53..154c38e 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -2,27 +2,27 @@ import typescriptEslint from "@typescript-eslint/eslint-plugin"; import tsParser from "@typescript-eslint/parser"; export default [{ - files: ["**/*.ts"], + files: ["**/*.ts"], }, { - plugins: { - "@typescript-eslint": typescriptEslint, - }, + plugins: { + "@typescript-eslint": typescriptEslint, + }, - languageOptions: { - parser: tsParser, - ecmaVersion: 2022, - sourceType: "module", - }, + languageOptions: { + parser: tsParser, + ecmaVersion: 2022, + sourceType: "module", + }, - rules: { - "@typescript-eslint/naming-convention": ["warn", { - selector: "import", - format: ["camelCase", "PascalCase"], - }], + rules: { + "@typescript-eslint/naming-convention": ["warn", { + selector: "import", + format: ["camelCase", "PascalCase"], + }], - curly: "warn", - eqeqeq: "warn", - "no-throw-literal": "warn", - semi: "warn", - }, -}]; \ No newline at end of file + curly: "warn", + eqeqeq: "warn", + "no-throw-literal": "warn", + semi: "warn", + }, +}]; diff --git a/package-lock.json b/package-lock.json index 9b2c256..aff99d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@sindresorhus/slugify": "^0.3.0", "ap-style-title-case": "^1.1.2", "chicago-capitalize": "^0.1.0", + "nodemon": "^3.1.7", "underscore.string": "^3.3.5" }, "devDependencies": { @@ -1028,7 +1029,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1114,8 +1114,7 @@ "node_modules/balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "node_modules/base64-js": { "version": "1.5.1", @@ -1163,7 +1162,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, "engines": { "node": ">=8" } @@ -1209,7 +1207,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1219,7 +1216,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, "dependencies": { "fill-range": "^7.1.1" }, @@ -1478,7 +1474,6 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, "funding": [ { "type": "individual", @@ -1572,8 +1567,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "node_modules/convert-source-map": { "version": "2.0.0", @@ -1684,7 +1678,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -2090,9 +2083,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "engines": { "node": ">=6" @@ -2450,7 +2443,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2543,7 +2535,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -2664,7 +2655,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -2713,9 +2703,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "node_modules/graphemer": { @@ -2737,7 +2727,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, "engines": { "node": ">=4" } @@ -2907,6 +2896,11 @@ "node": ">= 4" } }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, "node_modules/immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", @@ -3012,7 +3006,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -3097,7 +3090,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3115,7 +3107,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -3151,7 +3142,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -3752,7 +3742,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3761,9 +3750,12 @@ } }, "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/minipass": { "version": "7.1.2", @@ -3898,8 +3890,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/mute-stream": { "version": "0.0.8", @@ -3968,6 +3959,33 @@ "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", "dev": true }, + "node_modules/nodemon": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.7.tgz", + "integrity": "sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -3999,7 +4017,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -4509,7 +4526,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -4588,6 +4604,11 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, "node_modules/pump": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", @@ -4726,7 +4747,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -4917,7 +4937,6 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -5077,6 +5096,17 @@ "simple-concat": "^1.0.0" } }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/sinon": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", @@ -5381,7 +5411,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -5481,7 +5510,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -5489,6 +5517,14 @@ "node": ">=8.0" } }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, "node_modules/traverse": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", @@ -5658,6 +5694,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, "node_modules/underscore": { "version": "1.13.7", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", diff --git a/package.json b/package.json index a3b1430..7ec770a 100644 --- a/package.json +++ b/package.json @@ -176,7 +176,7 @@ "command": "string-manipulation.duplicateAndDecrement" }, { - "title": "Sequence all numbers (starting with first number)", + "title": "Sequence all numbers from first number", "category": "String Manipulation", "command": "string-manipulation.sequence" }, @@ -338,6 +338,7 @@ "watch": "npm-run-all -p watch:*", "watch:esbuild": "node esbuild.js --watch", "watch:tsc": "tsc --noEmit --watch --project tsconfig.json", + "watch:test": "nodemon --exec 'npm run test' src/**/* content.txt", "build": "npm run check-types && npm run lint && node esbuild.js --production", "compile-tests": "tsc -p . --outDir out", "watch-tests": "tsc -p . -w --outDir out", @@ -372,6 +373,7 @@ "@sindresorhus/slugify": "^0.3.0", "ap-style-title-case": "^1.1.2", "chicago-capitalize": "^0.1.0", + "nodemon": "^3.1.7", "underscore.string": "^3.3.5" }, "__metadata": { diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index f12f114..6c2f1c9 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -1,9 +1,8 @@ import * as assert from "assert"; - -// You can import and use all API from the 'vscode' module -// as well as import your extension to test it +import { afterEach, beforeEach, suite, test } from "mocha"; +import * as path from "path"; import * as vscode from "vscode"; -import { commandNameFunctionMap, CommandFunction } from "../commands"; +import { CommandFunction, commandNameFunctionMap } from "../commands"; type StringTransformationTest = [ funcName: string, @@ -17,153 +16,506 @@ type StringTransformationTest = [ } ]; +let editor: vscode.TextEditor; +let document: vscode.TextDocument; +const originalShowInputBox = vscode.window.showInputBox; + suite("Extension Test Suite", () => { - vscode.window.showInformationMessage("Start all tests."); - const tests = [ - ["camelize", "moz-transform", "mozTransform"], - ["camelize", "-moz-transform", "MozTransform"], - ["capitalize", "foo Bar", "Foo Bar"], - ["clean", " foo bar ", "foo bar"], - ["cleanDiacritics", "ääkkönen", "aakkonen"], - ["sentence", "foo Bar", "Foo bar"], - ["classify", "some_class_name", "SomeClassName"], - ["dasherize", "MozTransform", "-moz-transform"], - ["decapitalize", "Foo Bar", "foo Bar"], - [ - "humanize", - " capitalize dash-CamelCase_underscore trim ", - "Capitalize dash camel case underscore trim", - ], - ["reverse", "Abc", "cbA"], - ["slugify", "Un éléphant à l'orée du bois", "un-elephant-a-l-oree-du-bois"], - ["swapCase", "HELLOworld", "helloWORLD"], - ["snake", "This-is_snake case", "this_is_snake_case"], - ["screamingSnake", "screaming-snake case", "SCREAMING_SNAKE_CASE"], - ["titleize", "my name is tristan", "My Name Is Tristan"], - ["titleizeApStyle", "this is a test", "This Is a Test"], - [ - "titleizeChicagoStyle", - "The quick brown fox jumps over the lazy dog.", - "The Quick Brown Fox Jumps Over the Lazy Dog.", - ], - [ - "underscored", - "Underscored-is-like snake-case", - "underscored_is_like_snake_case", - ], - ["chop", "aabbccdd", "aa,bb,cc,dd", { functionArg: 2 }], - ["truncate", "aabbccdd", "aabb...", { functionArg: 4 }], - ["prune", "aabbccddaabbccdd", "aabbc...", { functionArg: 8 }], - ["repeat", "aabbccdd", "aabbccddaabbccdd", { functionArg: 2 }], - [ - "increment", - "a1 b2 c3 4d 5e 6f 12x y23 34z45", - "a2 b3 c4 5d 6e 7f 13x y24 35z46", - ], - [ - "increment", - "a1 b2 c3 4d 5e\n6f 12x y23 34z45", - "a2 b3 c4 5d 6e\n7f 13x y24 35z46", - ], - [ - "increment", - "a-4 b-3 c-2 -1d 0e\n6f 12x y23 34z45", - "a-3 b-2 c-1 0d 1e\n7f 13x y24 35z46", - ], - [ - "decrement", - "a1 b2 c3 4d 5e 6f 12x y23 34z45", - "a0 b1 c2 3d 4e 5f 11x y22 33z44", - ], - [ - "decrement", - "a1 b2 c3 4d\n5e 6f 12x y23 34z45", - "a0 b1 c2 3d\n4e 5f 11x y22 33z44", - ], - [ - "decrement", - "a-3 b-2 c-1 0d\n1e 6f 12x y23 34z45", - "a-4 b-3 c-2 -1d\n0e 5f 11x y22 33z44", - ], - [ - "duplicateAndIncrement", - "a1 b2 c3 4d 5e 6f 12x y23 34z45\n", - "a1 b2 c3 4d 5e 6f 12x y23 34z45\na2 b3 c4 5d 6e 7f 13x y24 35z46\n", - ], - [ - "duplicateAndDecrement", - "a1 b2 c3 4d 5e 6f 12x y23 34z45\n", - "a1 b2 c3 4d 5e 6f 12x y23 34z45\na0 b1 c2 3d 4e 5f 11x y22 33z44\n", - ], - [ - "sequence", - "a1 b2 c3 4d 5e 6f 12x y23 34z45", - "a1 b2 c3 4d 5e 6f 7x y8 9z10", - ], - [ - "sequence", - "a14 b2 c3\n4d 5e 6f 7x y8 9z12", - "a14 b15 c16\n17d 18e 19f 20x y21 22z23", - ], - ["sequence", "-3 4 5 6 7", "-3 -2 -1 0 1"], - [ - "sequence", - "1 2 3 7 8 9", - "4 5 6 7 8 9", - { multiselectData: { offset: 3 } }, - ], - [ - "utf8ToChar", - "\\u0061\\u0062\\u0063\\u4e2d\\u6587\\ud83d\\udc96", - "abc中文💖", - ], - [ - "charToUtf8", - "abc中文💖", - "\\u0061\\u0062\\u0063\\u4e2d\\u6587\\ud83d\\udc96", - ], - ]; - suite("commandNameFunctionMap outputs correctly for all methods", () => { - tests.forEach((data) => { - const [ - funcName, - originalString, - expectedString, - { multiselectData, functionArg } = { - multiselectData: {}, - functionArg: null, - }, - ] = data as StringTransformationTest; - const args = `${originalString}${ - multiselectData ? `, ${JSON.stringify(multiselectData)}` : "" - }`; - test(`${funcName} returns ${expectedString} when called with ${args}`, () => { - const func = ( - functionArg - ? commandNameFunctionMap[funcName](functionArg as any) - : commandNameFunctionMap[funcName] - ) as CommandFunction; - assert.equal(func(originalString, multiselectData), expectedString); - }); + beforeEach(async () => { + // Arrange: Open a text document before each test + const uri = vscode.Uri.file(path.join(__dirname, "../../content.txt")); + document = await vscode.workspace.openTextDocument(uri); + editor = await vscode.window.showTextDocument(document); + }); + + afterEach(async () => { + await vscode.commands.executeCommand("workbench.action.closeActiveEditor"); + vscode.window.showInputBox = originalShowInputBox; + }); + + let getTextForSelectionsByCommand = async ( + commandName: string, + ranges: { + start: { line: number; character: number }; + end: { line: number; character: number }; + }[] + ): Promise => { + editor.selections = ranges.map((range) => { + const startPos = new vscode.Position( + range.start.line, + range.start.character + ); + const endPos = new vscode.Position(range.end.line, range.end.character); + return new vscode.Selection(startPos, endPos); + }); + await vscode.commands.executeCommand(commandName); + return Promise.resolve( + editor.selections.map((selection) => editor.document.getText(selection)) + ); + }; + + suite("activation events", () => { + const extension = vscode.extensions.getExtension( + "marclipovsky.string-manipulation" + )!; + + test("is not active by default", () => { + assert.equal(false, extension.isActive); + }); + + test("invoked when running one of the commands", async () => { + await vscode.commands.executeCommand("string-manipulation.titleize"); + assert.equal(true, extension.isActive); + }); + }); + + suite("commands", () => { + test("camelize", async () => { + const [output1, output2] = await getTextForSelectionsByCommand( + "string-manipulation.camelize", + [ + { start: { line: 0, character: 0 }, end: { line: 0, character: 14 } }, + { start: { line: 1, character: 0 }, end: { line: 1, character: 15 } }, + ] + ); + + assert.strictEqual(output1, "mozTransform"); + assert.strictEqual(output2, "MozTransform"); + }); + + test("capitalize", async () => { + const [output1, output2] = await getTextForSelectionsByCommand( + "string-manipulation.capitalize", + [ + { start: { line: 2, character: 0 }, end: { line: 2, character: 3 } }, + { start: { line: 2, character: 4 }, end: { line: 2, character: 8 } }, + ] + ); + + assert.strictEqual(output1, "Foo"); + assert.strictEqual(output2, "Bar"); + }); + + test("clean", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.clean", + [{ start: { line: 3, character: 0 }, end: { line: 3, character: 15 } }] + ); + + assert.strictEqual(output, "foo bar"); + }); + + test("cleanDiacritics", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.cleanDiacritics", + [{ start: { line: 4, character: 0 }, end: { line: 4, character: 8 } }] + ); + + assert.strictEqual(output, "aakkonen"); + }); + + test("sentence", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.sentence", + [{ start: { line: 5, character: 0 }, end: { line: 5, character: 7 } }] + ); + + assert.strictEqual(output, "Foo bar"); + }); + + test("classify", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.classify", + [{ start: { line: 6, character: 0 }, end: { line: 6, character: 15 } }] + ); + + assert.strictEqual(output, "SomeClassName"); + }); + + test("dasherize", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.dasherize", + [{ start: { line: 7, character: 0 }, end: { line: 7, character: 12 } }] + ); + + assert.strictEqual(output, "-moz-transform"); + }); + + test("decapitalize", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.decapitalize", + [{ start: { line: 8, character: 0 }, end: { line: 8, character: 7 } }] + ); + + assert.strictEqual(output, "foo Bar"); + }); + + test("humanize", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.humanize", + [{ start: { line: 9, character: 0 }, end: { line: 9, character: 45 } }] + ); + + assert.strictEqual(output, "Capitalize dash camel case underscore trim"); + }); + + test("reverse", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.reverse", + [{ start: { line: 10, character: 0 }, end: { line: 10, character: 3 } }] + ); + + assert.strictEqual(output, "cbA"); + }); + + test("slugify", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.slugify", + [ + { + start: { line: 11, character: 0 }, + end: { line: 11, character: 28 }, + }, + ] + ); + + assert.strictEqual(output, "un-elephant-a-l-oree-du-bois"); + }); + + test("swapCase", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.swapCase", + [ + { + start: { line: 12, character: 0 }, + end: { line: 12, character: 10 }, + }, + ] + ); + + assert.strictEqual(output, "helloWORLD"); + }); + + test("snake", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.snake", + [ + { + start: { line: 13, character: 0 }, + end: { line: 13, character: 18 }, + }, + ] + ); + + assert.strictEqual(output, "this_is_snake_case"); + }); + + test("screamingSnake", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.screamingSnake", + [ + { + start: { line: 14, character: 0 }, + end: { line: 14, character: 20 }, + }, + ] + ); + + assert.strictEqual(output, "SCREAMING_SNAKE_CASE"); + }); + + test("titleize", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.titleize", + [ + { + start: { line: 15, character: 0 }, + end: { line: 15, character: 18 }, + }, + ] + ); + + assert.strictEqual(output, "My Name Is Tristan"); + }); + + test("titleizeApStyle", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.titleizeApStyle", + [ + { + start: { line: 16, character: 0 }, + end: { line: 16, character: 14 }, + }, + ] + ); + + assert.strictEqual(output, "This Is a Test"); + }); + + test("titleizeChicagoStyle", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.titleizeChicagoStyle", + [ + { + start: { line: 17, character: 0 }, + end: { line: 17, character: 44 }, + }, + ] + ); + + assert.strictEqual( + output, + "The Quick Brown Fox Jumps Over the Lazy Dog." + ); + }); + + test("underscored", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.underscored", + [ + { + start: { line: 18, character: 0 }, + end: { line: 18, character: 31 }, + }, + ] + ); + + assert.strictEqual(output, "underscored_is_like_snake_case"); + }); + + test("chop", async () => { + vscode.window.showInputBox = async () => { + return "2"; + }; + + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.chop", + [ + { + start: { line: 19, character: 0 }, + end: { line: 19, character: 8 }, + }, + ] + ); + + assert.strictEqual(output, "aa,bb,cc,dd"); + }); + + test("truncate", async () => { + vscode.window.showInputBox = async () => { + return "4"; + }; + + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.truncate", + [ + { + start: { line: 20, character: 0 }, + end: { line: 20, character: 8 }, + }, + ] + ); + + assert.strictEqual(output, "aabb..."); + }); + + test("prune", async () => { + vscode.window.showInputBox = async () => { + return "8"; + }; + + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.prune", + [ + { + start: { line: 21, character: 0 }, + end: { line: 21, character: 16 }, + }, + ] + ); + + assert.strictEqual(output, "aabbc..."); + }); + + test("repeat", async () => { + vscode.window.showInputBox = async () => { + return "2"; + }; + + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.repeat", + [ + { + start: { line: 22, character: 0 }, + end: { line: 22, character: 8 }, + }, + ] + ); + + assert.strictEqual(output, "aabbccddaabbccdd"); + }); + + test("increment", async () => { + const [output1, output2, output3] = await getTextForSelectionsByCommand( + "string-manipulation.increment", + [ + { + start: { line: 23, character: 0 }, + end: { line: 23, character: 31 }, + }, + { + start: { line: 24, character: 0 }, + end: { line: 25, character: 16 }, + }, + { + start: { line: 26, character: 0 }, + end: { line: 27, character: 16 }, + }, + ] + ); + + assert.strictEqual(output1, "a2 b3 c4 5d 6e 7f 13x y24 35z46"); + assert.strictEqual(output2, "a2 b3 c4 5d 6e\n7f 13x y24 35z46"); + assert.strictEqual(output3, "a-3 b-2 c-1 0d 1e\n7f 13x y24 35z46"); + }); + + test("decrement", async () => { + const [output1, output2, output3] = await getTextForSelectionsByCommand( + "string-manipulation.decrement", + [ + { + start: { line: 28, character: 0 }, + end: { line: 28, character: 31 }, + }, + { + start: { line: 29, character: 0 }, + end: { line: 30, character: 19 }, + }, + { + start: { line: 31, character: 0 }, + end: { line: 32, character: 19 }, + }, + ] + ); + + assert.strictEqual(output1, "a0 b1 c2 3d 4e 5f 11x y22 33z44"); + assert.strictEqual(output2, "a0 b1 c2 3d\n4e 5f 11x y22 33z44"); + assert.strictEqual(output3, "a-4 b-3 c-2 -1d\n0e 5f 11x y22 33z44"); + }); + + test("duplicateAndIncrement", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.duplicateAndIncrement", + [ + { + start: { line: 33, character: 0 }, + end: { line: 34, character: 0 }, + }, + ] + ); + + assert.strictEqual( + output, + "a1 b2 c3 4d 5e 6f 12x y23 34z45a2 b3 c4 5d 6e 7f 13x y24 35z46\n" + ); + }); + + test("duplicateAndDecrement", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.duplicateAndDecrement", + [ + { + start: { line: 35, character: 0 }, + end: { line: 36, character: 0 }, + }, + ] + ); + + assert.strictEqual( + output, + "a1 b2 c3 4d 5e 6f 12x y23 34z45a0 b1 c2 3d 4e 5f 11x y22 33z44\n" + ); + }); + + test("sequence", async () => { + const [output1, output2] = await getTextForSelectionsByCommand( + "string-manipulation.sequence", + [ + { + start: { line: 37, character: 0 }, + end: { line: 37, character: 31 }, + }, + { + start: { line: 38, character: 0 }, + end: { line: 39, character: 20 }, + }, + ] + ); + + assert.strictEqual(output1, "a1 b2 c3 4d 5e 6f 7x y8 9z10"); + assert.strictEqual(output2, "a11 b12 c13\n14d 15e 16f 17x y18 19z20"); + }); + + test("utf8ToChar", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.utf8ToChar", + [ + { + start: { line: 40, character: 0 }, + end: { line: 40, character: 49 }, + }, + ] + ); + + assert.strictEqual(output, "abc中文💖"); + }); + + test("charToUtf8", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.charToUtf8", + [ + { + start: { line: 41, character: 0 }, + end: { line: 41, character: 49 }, + }, + ] + ); + + assert.strictEqual( + output, + "\\u0061\\u0062\\u0063\\u4e2d\\u6587\\ud83d\\udc96" + ); }); suite("randomCase", () => { const input = "Hello, World!"; - test("returns a string of the same length", () => { - const output = commandNameFunctionMap["randomCase"](input) as string; - assert.equal(output.length, input.length); - }); - - test("contains the same characters ignoring case", () => { - const output = commandNameFunctionMap["randomCase"](input) as string; - assert.equal(output.toLowerCase(), input.toLowerCase()); + test("check length and compare lower case", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.randomCase", + [ + { + start: { line: 42, character: 0 }, + end: { line: 42, character: 13 }, + }, + ] + ); + assert.equal(input.length, 13); + assert.equal(input.toLowerCase(), "hello, world!"); }); - test("changes the case of at least one character (statistically)", () => { + test("changes the case of at least one character (statistically)", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.randomCase", + [ + { + start: { line: 42, character: 0 }, + end: { line: 42, character: 13 }, + }, + ] + ); let changed = false; for (let i = 0; i < 10; i++) { - const output = commandNameFunctionMap["randomCase"](input) as string; if ( output !== input && output.toLowerCase() === input.toLowerCase() @@ -175,41 +527,46 @@ suite("Extension Test Suite", () => { assert.equal(changed, true); }); - test("handles empty strings", () => { - const output = commandNameFunctionMap.randomCase(""); + test("handles empty strings", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.randomCase", + [ + { + start: { line: 42, character: 0 }, + end: { line: 42, character: 0 }, + }, + ] + ); assert.equal(output, ""); }); - test("preserves non-alphabetic characters", () => { + test("preserves non-alphabetic characters", async () => { const specialChars = "12345!@#$%"; - const output = commandNameFunctionMap.randomCase(specialChars); + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.randomCase", + [ + { + start: { line: 43, character: 0 }, + end: { line: 43, character: 10 }, + }, + ] + ); assert.equal(output, specialChars); }); - test("handles strings with mixed content", () => { - const mixedInput = "Test123!"; - const output = commandNameFunctionMap.randomCase(mixedInput) as string; - assert.equal(output.length, mixedInput.length); + test("handles strings with mixed content", async () => { + const [output] = await getTextForSelectionsByCommand( + "string-manipulation.randomCase", + [ + { + start: { line: 44, character: 0 }, + end: { line: 44, character: 8 }, + }, + ] + ); + assert.equal(output.length, 8); assert.notEqual(output.replace(/[^a-zA-Z]/g, ""), ""); }); }); }); - - suite("activation events", () => { - const extension = vscode.extensions.getExtension( - "marclipovsky.string-manipulation" - )!; - - test("is not active by default", () => { - const extension = vscode.extensions.getExtension( - "marclipovsky.string-manipulation" - )!; - assert.equal(false, extension.isActive); - }); - - test("invoked when running one of the commands", async () => { - await vscode.commands.executeCommand("string-manipulation.titleize"); - assert.equal(true, extension.isActive); - }); - }); });