├── .editorconfig ├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── .vscode ├── extensions.json └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── RELEASE.md ├── TODO.md ├── _svelte.config.cjs ├── e2e ├── README.md ├── init-svelte-4.sh ├── init-svelte.sh ├── svelte-3 │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.png │ │ ├── global.css │ │ └── index.html │ ├── rollup.config.js │ ├── scripts │ │ └── setupTypeScript.js │ ├── src │ │ ├── App.svelte │ │ ├── Comp.svelte │ │ ├── main.js │ │ └── test │ │ │ └── Comp.spec.js │ └── svelte.config.js ├── svelte-4 │ ├── .gitignore │ ├── .npmrc │ ├── .vscode │ │ └── extensions.json │ ├── README.md │ ├── index.html │ ├── jsconfig.json │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── vite.svg │ ├── src │ │ ├── App.svelte │ │ ├── app.css │ │ ├── assets │ │ │ └── svelte.svg │ │ ├── lib │ │ │ └── Counter.svelte │ │ ├── main.js │ │ ├── test │ │ │ └── Comp.spec.js │ │ └── vite-env.d.ts │ ├── svelte.config.js │ └── vite.config.js ├── svelte-5 │ ├── .npmrc │ ├── package.json │ ├── src │ │ ├── legacy.svelte │ │ ├── legacy.test.js │ │ ├── modern.svelte │ │ ├── modern.test.js │ │ ├── module.svelte.js │ │ └── module.test.js │ └── svelte.config.js └── sveltekit │ ├── .babelrc │ ├── .gitignore │ ├── .npmrc │ ├── README.md │ ├── jest.config.json │ ├── package.json │ ├── src │ ├── app.d.ts │ ├── app.html │ ├── lib │ │ └── images │ │ │ ├── github.svg │ │ │ ├── svelte-logo.svg │ │ │ ├── svelte-welcome.png │ │ │ └── svelte-welcome.webp │ └── routes │ │ ├── +layout.svelte │ │ ├── +page.svelte │ │ ├── +page.ts │ │ ├── Counter.svelte │ │ ├── Header.svelte │ │ ├── about │ │ ├── +page.svelte │ │ └── +page.ts │ │ ├── index-dom.spec.ts │ │ ├── styles.css │ │ └── sverdle │ │ ├── +page.server.ts │ │ ├── +page.svelte │ │ ├── game.ts │ │ ├── how-to-play │ │ ├── +page.svelte │ │ └── +page.ts │ │ ├── reduced-motion.ts │ │ └── words.server.ts │ ├── static │ ├── favicon.png │ └── robots.txt │ ├── svelte.config.js │ ├── tsconfig.json │ ├── tsconfig.spec.json │ └── vite.config.ts ├── jest.config.js ├── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── rollup.config.cjs ├── src ├── __tests__ │ ├── fixtures │ │ ├── BasicComp.svelte │ │ ├── SassComp.svelte │ │ ├── TypescriptComp.svelte │ │ ├── svelte.config.cjs │ │ └── sveltekit.config.js │ ├── transformer.test.cjs │ └── transformer.test.js ├── preprocess.js ├── svelteconfig.js ├── transformer.js └── utils.js └── svelte.config.cjs /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.md] 11 | max_line_length = off 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.{js,ts} text eol=lf 3 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "npm" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | Tests: 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | matrix: 14 | node-version: [18, 20, 22] 15 | os: [ubuntu-latest, windows-latest, macOS-latest] 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: pnpm/action-setup@v4 20 | - uses: actions/setup-node@v4 21 | with: 22 | node-version: ${{ matrix.node-version }} 23 | cache: pnpm 24 | 25 | - run: pnpm install 26 | 27 | - run: pnpm test 28 | env: 29 | CI: true 30 | 31 | - run: pnpm run e2e 32 | env: 33 | CI: true 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | dist 4 | .opt-in 5 | .opt-out 6 | .DS_Store 7 | .eslintcache 8 | .idea 9 | yarn-error.log 10 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "editorconfig.editorconfig", 4 | "standard.vscode-standard", 5 | "svelte.svelte-vscode" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "standard.autoFixOnSave": true, 3 | 4 | // SVELTE 5 | "[svelte]": { 6 | "editor.defaultFormatter": "svelte.svelte-vscode" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ## [5.0.0](https://github.com/svelteness/svelte-jester/compare/v5.1.0...v5.0.0) (2024-06-14) 6 | 7 | ## [5.1.0](https://github.com/svelteness/svelte-jester/compare/v3.0.0...v5.1.0) (2024-06-14) 8 | 9 | 10 | ### Features 11 | 12 | * add $state rune to globals ([586a6d8](https://github.com/svelteness/svelte-jester/commit/586a6d84948cfb43ffd76264bcb4310a580f7d6f)) 13 | * add coverage ([e6679d0](https://github.com/svelteness/svelte-jester/commit/e6679d0931fe7102a4f9f8c5a8917bdae27e7dcc)) 14 | * add e2e test for svelte 4 ([80941b6](https://github.com/svelteness/svelte-jester/commit/80941b64e4a3ac9dfb6d49612e879660936929fe)) 15 | * add jest-dom ([5f1d5f5](https://github.com/svelteness/svelte-jester/commit/5f1d5f53eb2a34ae21d8f3a367ae0973568f9d48)) 16 | * add RELEASE documentation ([c69d0e9](https://github.com/svelteness/svelte-jester/commit/c69d0e9dc3c7069005c539892ccd2f9e4abed049)) 17 | * add svelte4 test project ([d9f4f2c](https://github.com/svelteness/svelte-jester/commit/d9f4f2cc0977f893d0ec0775b6628158c48325a6)) 18 | * add test case ([109a0b4](https://github.com/svelteness/svelte-jester/commit/109a0b414cdefa642be89db3ea111ef58fc695fc)) 19 | * add test dependencies ([08f2821](https://github.com/svelteness/svelte-jester/commit/08f282150c654cc4f099f421cf161e4fbd4245ce)) 20 | * add test dependencies, setup and scripts ([71076e5](https://github.com/svelteness/svelte-jester/commit/71076e559d18e5ee2a8fd1c7e55cf263d4cea06d)) 21 | * enable import ([f9a947d](https://github.com/svelteness/svelte-jester/commit/f9a947d18255ef4cbe36239e936f705908d32cc2)) 22 | * lock version to 3 ([c9839cd](https://github.com/svelteness/svelte-jester/commit/c9839cde1572480385026b975564a0fc137c1d0b)) 23 | * rename svelte test folder to svelte-3 ([25709ca](https://github.com/svelteness/svelte-jester/commit/25709ca9553b6ef61e3bd4457d5c1772ca0bf2ad)) 24 | * replace cross-env with pnpm shell emulation ([25afa84](https://github.com/svelteness/svelte-jester/commit/25afa847d1d9fb1dd8554fde64a1196f099db634)) 25 | * run e2e tests during validation ([9a1cb23](https://github.com/svelteness/svelte-jester/commit/9a1cb2366211e3f8a006029dcf1aa5cb95c133ca)) 26 | * set version to 5.0.0 ([44d54c0](https://github.com/svelteness/svelte-jester/commit/44d54c07985ab7707e7d4528ad83694e44757732)) 27 | * **svelte5:** add support for Svelte 5 modules ([ed57c66](https://github.com/svelteness/svelte-jester/commit/ed57c66bb5d7cdeff838ef08a91c730b528e7dfd)) 28 | * test only supported engines ([3f77257](https://github.com/svelteness/svelte-jester/commit/3f77257ccd4fcc73aa6c760d66f38a6bbbe825f8)) 29 | 30 | 31 | ### Bug Fixes 32 | 33 | * add npmrc with shell emulation for all e2e folders ([fc3f525](https://github.com/svelteness/svelte-jester/commit/fc3f525768d92b1e8d13b0182ed90bccdf91d35b)) 34 | * add option no-cache ([1248b36](https://github.com/svelteness/svelte-jester/commit/1248b3678118251ff03f46331bc994162d2e3966)) 35 | * bring back cross-env ([759d4cb](https://github.com/svelteness/svelte-jester/commit/759d4cb888edf958dc7be7603ed6700cd891898e)) 36 | * enable tests ([8356e0f](https://github.com/svelteness/svelte-jester/commit/8356e0fe6b254919e52c287ecb7d8900f89d11fb)) 37 | * fix merge lockfile ([17caa9a](https://github.com/svelteness/svelte-jester/commit/17caa9a6bff3d2ea8034facf435fa8c483bc9d50)) 38 | * formatting ([d28dfb8](https://github.com/svelteness/svelte-jester/commit/d28dfb881cb29d8591c748be85a4fdacb8adf152)) 39 | * let tests complete on node 16 - 22 ([a9b21e1](https://github.com/svelteness/svelte-jester/commit/a9b21e12d97e5a11d0c0085d82345a9cb8e7b6ef)) 40 | * pass linter ([2f89077](https://github.com/svelteness/svelte-jester/commit/2f89077f2748a499714f01e2d797df17b4f6419e)) 41 | * pnpm handles argument passing ([0b2dd99](https://github.com/svelteness/svelte-jester/commit/0b2dd99b82bf5cebd58b1da2054d6734568083a3)) 42 | * reduce visibility of const ([250441a](https://github.com/svelteness/svelte-jester/commit/250441a429a2feb13f339a55394263e1542a889a)) 43 | * remove missing vite logo ([b7a54cb](https://github.com/svelteness/svelte-jester/commit/b7a54cbc4b467982ddc0633b893c790ee6be70c6)) 44 | * remove obsolete step ([01c82c7](https://github.com/svelteness/svelte-jester/commit/01c82c712ba44e9180a159d5b6a444a4bb248894)) 45 | * remove unused npmrc ([cea907d](https://github.com/svelteness/svelte-jester/commit/cea907d016f2662d7b54a1956c882d0b90d77a28)) 46 | * rewrite url as suggested by npm ([ec050b6](https://github.com/svelteness/svelte-jester/commit/ec050b65fd23f89323703b5660c99854cabfc34a)) 47 | * use different matcher to pass linter ([df6d2a3](https://github.com/svelteness/svelte-jester/commit/df6d2a3515ef5d9595eeab04ffd6a49c42234f62)) 48 | 49 | ## [3.0.0](https://github.com/svelteness/svelte-jester/compare/v2.3.1...v3.0.0) (2023-07-24) 50 | 51 | 52 | ### Features 53 | 54 | * add jest globals to standard ([be8c23d](https://github.com/svelteness/svelte-jester/commit/be8c23dcc8466c07dfcc2c82f568169fca13c819)) 55 | * allow svelteVersion to be injected for tests ([5b12cc0](https://github.com/svelteness/svelte-jester/commit/5b12cc0d12d8758e4c49050510c26e7e27ca4852)) 56 | * disallow calling ESM mode from processSync ([d6a381e](https://github.com/svelteness/svelte-jester/commit/d6a381e512415540c5ebd3df7c392a881603dbdd)) 57 | * document option svelteVersion ([210591a](https://github.com/svelteness/svelte-jester/commit/210591a4a3c7aa6a4a2f2a108199359ab608c7ae)) 58 | * extract functions into utils ([ea8b0c3](https://github.com/svelteness/svelte-jester/commit/ea8b0c32757f6b9710535c188bb32752abb45490)) 59 | * remove * import for treeshaking ([d079756](https://github.com/svelteness/svelte-jester/commit/d079756fa8259837d380755628739c63965c2f6d)) 60 | * remove globals ([15c5f5c](https://github.com/svelteness/svelte-jester/commit/15c5f5c06a9bc4113731670542a18cfaac677d34)) 61 | * remove restriction on Svelte3 ([3051249](https://github.com/svelteness/svelte-jester/commit/3051249d16d6ad56f3483ee9ec9a852567348096)) 62 | * run dependabot only on root package.json ([6abfb88](https://github.com/svelteness/svelte-jester/commit/6abfb88bef3945078b5819ed55f624a839e2f8ae)) 63 | * split release script into pre phase ([96edf43](https://github.com/svelteness/svelte-jester/commit/96edf4319b5f74ca3f1222cde67c9b9741a10bdd)) 64 | * split test call to not use NODE_OPTIONS for CJS ([7493725](https://github.com/svelteness/svelte-jester/commit/749372558562f3ad7f9599889deca0868f5f9dd2)) 65 | * upgrade e2e packages ([1372d0f](https://github.com/svelteness/svelte-jester/commit/1372d0f8033114187987f9a1242561902b64a754)) 66 | * upgrade e2e packages ([5d4d08c](https://github.com/svelteness/svelte-jester/commit/5d4d08c5371463acaa836bbe1761809c66143a53)) 67 | * upgrade svelte to v4 ([227785e](https://github.com/svelteness/svelte-jester/commit/227785e113a96f7da8a1ef47c56c603eb51b814b)) 68 | 69 | 70 | ### Bug Fixes 71 | 72 | * add jest globals ([a047c45](https://github.com/svelteness/svelte-jester/commit/a047c451dcc2262077cfab4b3cd162f4ee7bdce2)) 73 | * add missing jest import ([c88841d](https://github.com/svelteness/svelte-jester/commit/c88841d0ef019faf756e9b84966fcba19761de34)) 74 | * add missing jest-environment ([66bad7b](https://github.com/svelteness/svelte-jester/commit/66bad7b505787c6affee13de88a78b763ac1db50)) 75 | * add missing words to comment ([801162e](https://github.com/svelteness/svelte-jester/commit/801162e36537d9f132cccc33b182d0ff3fe0cac8)) 76 | * enable validation for standardjs ([a028920](https://github.com/svelteness/svelte-jester/commit/a0289205b1a5e32aacc60f64c38461d7837cf7f7)) 77 | * migrate deprecated tsconfig object ([875f27f](https://github.com/svelteness/svelte-jester/commit/875f27f9a033d1db9d8b488e9b36087e79bf1fb9)) 78 | * remove duplicate line ([5cf2ca6](https://github.com/svelteness/svelte-jester/commit/5cf2ca695aa13302022063caa8dc408c54717dc6)) 79 | * rename constant ([9243034](https://github.com/svelteness/svelte-jester/commit/92430340e32c1095ab2bf77f697f0bfe753e7732)) 80 | * revert change from last PR breaking windows ([a4f1341](https://github.com/svelteness/svelte-jester/commit/a4f13418820b7b129c3905937728f1e4fce197f2)) 81 | * use real svelte version as default ([847933e](https://github.com/svelteness/svelte-jester/commit/847933eecca579147b4972b517ad926d2d913715)) 82 | * use same relative path ([6004a96](https://github.com/svelteness/svelte-jester/commit/6004a968087565979ad73eadf85d6b56dc9a30bf)) 83 | 84 | ### [2.3.2](https://github.com/mihar-22/svelte-jester/compare/v2.3.1...v2.3.2) (2022-02-16) 85 | 86 | ### [2.3.1](https://github.com/mihar-22/svelte-jester/compare/v2.3.0...v2.3.1) (2022-02-01) 87 | 88 | 89 | ### Bug Fixes 90 | 91 | * drop min node version to `14` for `node-sass` ([aa4508d](https://github.com/mihar-22/svelte-jester/commit/aa4508dd9dcfb68c99c492239c6400bcbab69e5e)) 92 | 93 | ## [2.3.0](https://github.com/mihar-22/svelte-jester/compare/v2.2.0...v2.3.0) (2022-02-01) 94 | 95 | 96 | ### Features 97 | 98 | * bump min node version to `16` ([9172250](https://github.com/mihar-22/svelte-jester/commit/917225044ffe0d534da6c60b4650df3b50163ced)) 99 | 100 | ## [2.2.0](https://github.com/mihar-22/svelte-jester/compare/v2.1.5...v2.2.0) (2022-02-01) 101 | 102 | 103 | ### Features 104 | 105 | * bump min node version to `14` ([526d3ed](https://github.com/mihar-22/svelte-jester/commit/526d3edffd1a55f66faf21a7b7f3f31426ba195d)) 106 | 107 | 108 | ### Bug Fixes 109 | 110 | * [ERR_INVALID_ARG_TYPE]: The "id" argument must be of type string. Received an instance of URL ([1384839](https://github.com/mihar-22/svelte-jester/commit/1384839dac8bb87d2a62ef903b4a7587683ef35e)) 111 | 112 | ### [2.1.5](https://github.com/mihar-22/svelte-jester/compare/v2.1.4...v2.1.5) (2021-09-22) 113 | 114 | 115 | ### Bug Fixes 116 | 117 | * add preprocess to published files array ([#84](https://github.com/mihar-22/svelte-jester/issues/84)) ([4a10e92](https://github.com/mihar-22/svelte-jester/commit/4a10e923e688727b3a415daa8595e7a03b8f681b)) 118 | * allow installation on Node 12 ([7093aee](https://github.com/mihar-22/svelte-jester/commit/7093aeed66dc36d6d61cd15b50a49ee54b6ffcc8)) 119 | 120 | ### [2.1.4](https://github.com/mihar-22/svelte-jester/compare/v2.1.3...v2.1.4) (2021-09-21) 121 | 122 | 123 | ### Bug Fixes 124 | 125 | * add back Node 12 support ([#83](https://github.com/mihar-22/svelte-jester/issues/83)) ([e5de1c6](https://github.com/mihar-22/svelte-jester/commit/e5de1c6c6c2e82b0dffb3fc1892abdaa3dc7d414)) 126 | * unpin svelte-preprocess ([#82](https://github.com/mihar-22/svelte-jester/issues/82)) ([a48d909](https://github.com/mihar-22/svelte-jester/commit/a48d90913993eb271ac40ee009110d48e39255ba)) 127 | 128 | ### [2.1.3](https://github.com/mihar-22/svelte-jester/compare/v2.1.2...v2.1.3) (2021-09-19) 129 | 130 | 131 | ### Bug Fixes 132 | 133 | * invalid transformer export ([#75](https://github.com/mihar-22/svelte-jester/issues/75)) ([4729f0b](https://github.com/mihar-22/svelte-jester/commit/4729f0b65cd0f6d3140551a969a564913ffb9972)) 134 | * surface frame on failed Svelte compilation ([a747d96](https://github.com/mihar-22/svelte-jester/commit/a747d9665e180f4365bead8a93b9596d217692e1)) 135 | 136 | ### [2.1.2](https://github.com/mihar-22/svelte-jester/compare/v2.1.1...v2.1.2) (2021-09-12) 137 | 138 | 139 | ### Bug Fixes 140 | 141 | * add back process method for CJS support ([#71](https://github.com/mihar-22/svelte-jester/issues/71)) ([6ee7c5c](https://github.com/mihar-22/svelte-jester/commit/6ee7c5c6c15c5f92cf59ee1acaacbf94a3450a05)) 142 | 143 | ### [2.1.1](https://github.com/mihar-22/svelte-jester/compare/v2.1.0...v2.1.1) (2021-08-31) 144 | 145 | 146 | ### Bug Fixes 147 | 148 | * file paths in `package.json` pointing to `src` instead of `dist` ([#69](https://github.com/mihar-22/svelte-jester/issues/69)) ([b6f2cbb](https://github.com/mihar-22/svelte-jester/commit/b6f2cbb77e2c1f9976045d841cca2781795b9117)) 149 | 150 | ## [2.1.0](https://github.com/mihar-22/svelte-jester/compare/v2.0.1...v2.1.0) (2021-08-27) 151 | 152 | 153 | ### Features 154 | 155 | * build CJS and ESM versions of the library ([#68](https://github.com/mihar-22/svelte-jester/issues/68)) ([d93f2dc](https://github.com/mihar-22/svelte-jester/commit/d93f2dc155820ff0b2843143037d23c2934fc55d)) 156 | 157 | ### [2.0.1](https://github.com/mihar-22/svelte-jester/compare/v2.0.0...v2.0.1) (2021-08-05) 158 | 159 | 160 | ### Bug Fixes 161 | 162 | * module not found error ([#60](https://github.com/mihar-22/svelte-jester/issues/60)) ([3748f49](https://github.com/mihar-22/svelte-jester/commit/3748f49949fd8bdf8edf25bb7d7d0a72a27f2950)), closes [#59](https://github.com/mihar-22/svelte-jester/issues/59) 163 | 164 | ## [2.0.0](https://github.com/mihar-22/svelte-jester/compare/v1.8.2...v2.0.0) (2021-08-04) 165 | 166 | 167 | ### ⚠ BREAKING CHANGES 168 | 169 | * async transformers are only supported in Jest `>=27`. 170 | 171 | ### Features 172 | 173 | * avoid creating new node processes by leveraging processAsync ([#57](https://github.com/mihar-22/svelte-jester/issues/57)) ([92760dd](https://github.com/mihar-22/svelte-jester/commit/92760dd821e7685d67ed3d0f0ebff84484db4361)) 174 | 175 | ### [1.8.2](https://github.com/mihar-22/svelte-jester/compare/v1.8.1...v1.8.2) (2021-08-04) 176 | 177 | 178 | ### Bug Fixes 179 | 180 | * actually revert async changes -_- ([64c3d4d](https://github.com/mihar-22/svelte-jester/commit/64c3d4dc5a0a9f1f18868ef139686cf10bf70022)) 181 | 182 | ### [1.8.1](https://github.com/mihar-22/svelte-jester/compare/v1.8.0...v1.8.1) (2021-08-04) 183 | 184 | 185 | ### Bug Fixes 186 | 187 | * revert "Avoid creating new node processes by leveraging processAsync ([#57](https://github.com/mihar-22/svelte-jester/issues/57))" ([#58](https://github.com/mihar-22/svelte-jester/issues/58)) ([3a3e500](https://github.com/mihar-22/svelte-jester/commit/3a3e500a4815264c8cb6b8c1a4d7415fa2f0fe4a)) 188 | 189 | ## [1.8.0](https://github.com/mihar-22/svelte-jester/compare/v1.7.0...v1.8.0) (2021-08-04) 190 | 191 | 192 | ### Features 193 | 194 | * avoid creating new node processes by leveraging processAsync ([#57](https://github.com/mihar-22/svelte-jester/issues/57)) ([d5be238](https://github.com/mihar-22/svelte-jester/commit/d5be238e2ecbaca615947859339a7e5f76eb5abc)) 195 | * provide option to show console.logs from preprocessors ([#53](https://github.com/mihar-22/svelte-jester/issues/53)) ([173620a](https://github.com/mihar-22/svelte-jester/commit/173620a7312af994a626d62597ae3971c978bd4f)) 196 | 197 | ## [1.7.0](https://github.com/mihar-22/svelte-jester/compare/v1.6.0...v1.7.0) (2021-06-01) 198 | 199 | 200 | ### Features 201 | 202 | * hide console log in preprocess ([#50](https://github.com/mihar-22/svelte-jester/issues/50)) ([91d3cc6](https://github.com/mihar-22/svelte-jester/commit/91d3cc6ab6c44771117513175a6c24eb22470a83)) 203 | * support Windows ([#49](https://github.com/mihar-22/svelte-jester/issues/49)) ([48a7506](https://github.com/mihar-22/svelte-jester/commit/48a75061f7ebcaae1d30c514f8775725047d82a8)) 204 | 205 | ## [1.6.0](https://github.com/mihar-22/svelte-jester/compare/v1.5.0...v1.6.0) (2021-05-25) 206 | 207 | 208 | ### Features 209 | 210 | * initial SvelteKit support ([#46](https://github.com/mihar-22/svelte-jester/issues/46)) ([0c008d7](https://github.com/mihar-22/svelte-jester/commit/0c008d7e56e03da7d402406655a9edd80dc719cb)) 211 | 212 | ## [1.5.0](https://github.com/mihar-22/svelte-jester/compare/v1.4.0...v1.5.0) (2021-04-22) 213 | 214 | 215 | ### Features 216 | 217 | * all process env variables are passed down to child transform process ([#40](https://github.com/mihar-22/svelte-jester/issues/40)) ([beecf48](https://github.com/mihar-22/svelte-jester/commit/beecf48f2677d5a294f851841896dd0e5779d078)) 218 | 219 | ## [1.4.0](https://github.com/mihar-22/svelte-jester/compare/v1.3.2...v1.4.0) (2021-04-12) 220 | 221 | 222 | ### Features 223 | 224 | * allow svelte.config.cjs ([#37](https://github.com/mihar-22/svelte-jester/issues/37)) ([9e259c4](https://github.com/mihar-22/svelte-jester/commit/9e259c4b4d254ee163c67995cacf224e64c229d3)), closes [#35](https://github.com/mihar-22/svelte-jester/issues/35) 225 | 226 | ### [1.3.2](https://github.com/mihar-22/svelte-jester/compare/v1.3.1...v1.3.2) (2021-03-24) 227 | 228 | 229 | ### Bug Fixes 230 | 231 | * use RawSourceMap for sourcemap ([b056107](https://github.com/mihar-22/svelte-jester/commit/b05610769b575c236e66c26e9f480cbb6e2c3ee8)) 232 | 233 | ### [1.3.1](https://github.com/mihar-22/svelte-jester/compare/v1.3.0...v1.3.1) (2021-03-19) 234 | 235 | 236 | ### Bug Fixes 237 | 238 | * incorrect coverage lines ([fd629b7](https://github.com/mihar-22/svelte-jester/commit/fd629b73b667f0926873a27b1be59151b4a784e0)), closes [#28](https://github.com/mihar-22/svelte-jester/issues/28) 239 | 240 | ## [1.3.0](https://github.com/mihar-22/svelte-jester/compare/v1.2.0...v1.3.0) (2020-12-10) 241 | 242 | 243 | ### Features 244 | 245 | * allow user to specify `svelte.config` path ([540e986](https://github.com/mihar-22/svelte-jester/commit/540e986bf5bb0bf40eea72056cc5aea62e09f233)) 246 | 247 | ## [1.2.0](https://github.com/mihar-22/svelte-jester/compare/v1.1.5...v1.2.0) (2020-12-09) 248 | 249 | 250 | ### Features 251 | 252 | * adds maxBuffer option that sets buffer limit for preprocess ([bd80185](https://github.com/mihar-22/svelte-jester/commit/bd80185d90d09b80989fb6e9af421754c0da938f)), closes [#20](https://github.com/mihar-22/svelte-jester/issues/20) 253 | 254 | ### [1.1.5](https://github.com/mihar-22/svelte-jester/compare/v1.1.4...v1.1.5) (2020-09-02) 255 | 256 | 257 | ### Bug Fixes 258 | 259 | * svelte.config.js should not be required unless preprocessing ([6b3e567](https://github.com/mihar-22/svelte-jester/commit/6b3e56788010d3d00e1fce045470e7e270dad9eb)) 260 | 261 | ### [1.1.4](https://github.com/mihar-22/svelte-jester/compare/v1.1.3...v1.1.4) (2020-09-02) 262 | 263 | 264 | ### Bug Fixes 265 | 266 | * use double quotes for windows ([e45313d](https://github.com/mihar-22/svelte-jester/commit/e45313d9680ac9ac14044f9f6d8c8babb49471d2)) 267 | 268 | ### [1.1.3](https://github.com/mihar-22/svelte-jester/compare/v1.1.2...v1.1.3) (2020-08-31) 269 | 270 | 271 | ### Bug Fixes 272 | 273 | * error when path to preprocessor contains some characters like '&' ([00e61d8](https://github.com/mihar-22/svelte-jester/commit/00e61d86aaaa764454d8774f9ec63fce01e93869)) 274 | 275 | ### [1.1.2](https://github.com/mihar-22/svelte-jester/compare/v1.1.1...v1.1.2) (2020-08-16) 276 | 277 | ### [1.1.1](https://github.com/mihar-22/svelte-jester/compare/v1.1.0...v1.1.1) (2020-08-15) 278 | 279 | 280 | ### Bug Fixes 281 | 282 | * add svelteconfig.js to files pattern ([a0f57b3](https://github.com/mihar-22/svelte-jester/commit/a0f57b30362dbe53fa5480020cd17e14dcd6011a)) 283 | 284 | ## [1.1.0](https://github.com/mihar-22/svelte-jester/compare/v1.0.6...v1.1.0) (2020-08-15) 285 | 286 | 287 | ### Features 288 | 289 | * rootMode option ([531e7d7](https://github.com/mihar-22/svelte-jester/commit/531e7d7ca40a27e82a5bd66f3a8256d3a4325fae)) 290 | 291 | ### [1.0.6](https://github.com/mihar-22/svelte-jester/compare/v1.0.5...v1.0.6) (2020-05-18) 292 | 293 | 294 | ### Bug Fixes 295 | 296 | * raise unhandled rejection on child process as uncaught exception ([ae64409](https://github.com/mihar-22/svelte-jester/commit/ae644094bcee93e17ecf3e02f38f29f485ea78c1)), closes [#5](https://github.com/mihar-22/svelte-jester/issues/5) 297 | 298 | ### [1.0.5](https://github.com/mihar-22/svelte-jester/compare/v1.0.4...v1.0.5) (2020-03-05) 299 | 300 | ### [1.0.4](https://github.com/mihar-22/svelte-jester/compare/v1.0.3...v1.0.4) (2020-02-14) 301 | 302 | 303 | ### Bug Fixes 304 | 305 | * replace sync-rpc due to leaving open handles in jest@25 ([9024ca9](https://github.com/mihar-22/svelte-jester/commit/9024ca93d639c3d7fff863af88d60f2cc8b0b5a4)) 306 | 307 | ### [1.0.3](https://github.com/mihar-22/svelte-jester/compare/v1.0.2...v1.0.3) (2019-12-05) 308 | 309 | 310 | ### Bug Fixes 311 | 312 | * cosmiconfig was loading config from pkg if svelte key was defined ([8783131](https://github.com/mihar-22/svelte-jester/commit/8783131a538b6c5263f2069b00d252f44d7acc0e)) 313 | 314 | ### [1.0.2](https://github.com/mihar-22/svelte-jester/compare/v1.0.1...v1.0.2) (2019-12-05) 315 | 316 | ### 1.0.1 (2019-12-05) 317 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Rahim Alwer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

svelte-jester

3 | 4 |

5 | Simply precompiles Svelte components before importing them into Jest tests. 6 |

7 | 8 |

9 | This version requires Jest >= 27 and defaults to ESM, which is required with Svelte 4+. If you're using Svelte 3 and want to use CJS, you need to specify the full path for the jest transformer in your jest config. 10 |

11 | 12 | [![version][version-badge]][package] 13 | [![MIT License][license-badge]][license] 14 | 15 |
16 | 17 |
18 | 19 | ## Table of Contents 20 | 21 | 22 | 23 | 24 | - [Why not just use x?](#why-not-just-use-x) 25 | - [Installation](#installation) 26 | - [Manual installation](#manual-installation) 27 | - [ESM version](#esm-version) 28 | - [CJS (CommonJS) version](#cjs-commonjs-version) 29 | - [Babel (only for CJS)](#babel-only-for-cjs) 30 | - [TypeScript](#typescript) 31 | - [ESM version](#esm-version-1) 32 | - [CJS version](#cjs-version) 33 | - [Preprocess](#preprocess) 34 | - [Options](#options) 35 | - [CJS mode options](#cjs-mode-options) 36 | - [Testing Library](#testing-library) 37 | - [Credits](#credits) 38 | - [LICENSE](#license) 39 | 40 | 41 | 42 | ## Why not just use x? 43 | 44 | Seems like other libraries won't be working with preprocessors, won't be maintained actively or didn't 45 | have proper licensing. 46 | 47 | ## Installation 48 | 49 | If you're using SvelteKit, you can set it up and install it with [svelte-add-jest](https://github.com/rossyman/svelte-add-jest) by running: 50 | 51 | ``` 52 | npx apply rossyman/svelte-add-jest 53 | ``` 54 | 55 | ### Manual installation 56 | 57 | This library has `peerDependencies` listings for `svelte >= 3` and `jest >= 27`. 58 | 59 | `npm install svelte-jester -D` 60 | 61 | #### ESM version 62 | 63 | Add the following to your Jest config: 64 | 65 | ```json 66 | { 67 | "transform": { 68 | "^.+\\.svelte$": "svelte-jester" 69 | }, 70 | "moduleFileExtensions": ["js", "svelte"], 71 | "extensionsToTreatAsEsm": [".svelte"] 72 | } 73 | ``` 74 | 75 | Run your tests with `NODE_OPTIONS=--experimental-vm-modules`. For Windows you need to add `cross-env` as well. 76 | 77 | ```json 78 | "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest src", 79 | ``` 80 | 81 | #### CJS (CommonJS) version 82 | 83 | Add the following to your Jest config: 84 | 85 | ```json 86 | { 87 | "transform": { 88 | "^.+\\.svelte$": "./node_modules/svelte-jester/dist/transformer.cjs" 89 | }, 90 | "moduleFileExtensions": ["js", "svelte"] 91 | } 92 | ``` 93 | 94 | ### Babel (only for CJS) 95 | 96 | `npm install @babel/core @babel/preset-env babel-jest -D` 97 | 98 | Add the following to your Jest config 99 | 100 | ```json 101 | "transform": { 102 | "^.+\\.js$": "babel-jest", 103 | "^.+\\.svelte$": "svelte-jester" 104 | } 105 | ``` 106 | 107 | Create a `.babelrc` and add the following 108 | 109 | ```json 110 | { 111 | "presets": [["@babel/preset-env", { "targets": { "node": "current" } }]] 112 | } 113 | ``` 114 | 115 | ### TypeScript 116 | 117 | To enable TypeScript support you'll need to setup [`svelte-preprocess`](https://github.com/sveltejs/svelte-preprocess) and [`ts-jest`](https://github.com/kulshekhar/ts-jest). 118 | 119 | 1. Install `typescript`, `svelte-preprocess`, and `ts-jest`: 120 | 121 | ```shell 122 | npm install typescript svelte-preprocess ts-jest -D 123 | ``` 124 | 125 | #### ESM version 126 | 127 | 1. Create a `svelte.config.js` at the root of your project: 128 | 129 | ```js 130 | import preprocess from 'svelte-preprocess' 131 | 132 | /** @type {import('@sveltejs/kit').Config} */ 133 | export default config = { 134 | preprocess: preprocess(), 135 | // ... 136 | }; 137 | ``` 138 | 139 | To learn what options you can pass to `sveltePreprocess`, please refer to the [documentation](https://github.com/sveltejs/svelte-preprocess/blob/main/docs/preprocessing.md#typescript). 140 | 141 | 1. In your Jest config, enable preprocessing for `svelte-jester`, and add `ts-jest` as a transform: 142 | 143 | ```json 144 | "transform": { 145 | "^.+\\.svelte$": [ 146 | "svelte-jester", 147 | { 148 | "preprocess": true 149 | } 150 | ], 151 | "^.+\\.ts$": [ 152 | "ts-jest", 153 | { 154 | "useESM": true 155 | // optional: seperate tsconfig for tests 156 | //"tsconfig": "tsconfig.spec.json", 157 | } 158 | ], 159 | }, 160 | "moduleFileExtensions": [ 161 | "js", 162 | "ts", 163 | "svelte" 164 | ], 165 | "extensionsToTreatAsEsm": [ 166 | ".svelte", 167 | ".ts" 168 | ], 169 | ``` 170 | 171 | However if you do not want to create a `svelte.config.js` at the root of your 172 | project or you wish to use a custom config just for tests, you may pass the 173 | path to the config file to the `preprocess` option thus: 174 | 175 | ```json 176 | "transform": { 177 | "^.+\\.svelte$": [ 178 | "svelte-jester", 179 | { 180 | "preprocess": "/some/path/to/svelte.config.js" 181 | } 182 | ], 183 | "^.+\\.ts$": [ 184 | "ts-jest", 185 | { 186 | "useESM": true 187 | // optional: seperate tsconfig for tests 188 | //"tsconfig": "tsconfig.spec.json", 189 | } 190 | ], 191 | }, 192 | "moduleFileExtensions": [ 193 | "js", 194 | "ts", 195 | "svelte" 196 | ], 197 | "extensionsToTreatAsEsm": [ 198 | ".svelte", 199 | ".ts" 200 | ], 201 | ``` 202 | 203 | #### CJS version 204 | 205 | 1. Create a `svelte.config.js` at the root of your project: 206 | 207 | ```js 208 | const sveltePreprocess = require("svelte-preprocess"); 209 | 210 | module.exports = { 211 | preprocess: sveltePreprocess({ 212 | // ... 213 | }), 214 | }; 215 | ``` 216 | 217 | To learn what options you can pass to `sveltePreprocess`, please refer to the [documentation](https://github.com/sveltejs/svelte-preprocess/blob/main/docs/preprocessing.md#typescript). 218 | 219 | 1. In your Jest config, enable preprocessing for `svelte-jester`, and add `ts-jest` as a transform: 220 | 221 | ```json 222 | "transform": { 223 | "^.+\\.svelte$": [ 224 | "./node_modules/svelte-jester/dist/transformer.cjs", 225 | { 226 | "preprocess": true 227 | } 228 | ], 229 | "^.+\\.ts$": "ts-jest" 230 | }, 231 | "moduleFileExtensions": [ 232 | "js", 233 | "ts", 234 | "svelte" 235 | ] 236 | ``` 237 | 238 | However if you do not want to create a `svelte.config.js` at the root of your 239 | project or you wish to use a custom config just for tests, you may pass the 240 | path to the config file to the `preprocess` option thus: 241 | 242 | ```json 243 | "transform": { 244 | "^.+\\.svelte$": [ 245 | "./node_modules/svelte-jester/dist/transformer.cjs", 246 | { 247 | "preprocess": "/some/path/to/svelte.config.js" 248 | } 249 | ], 250 | "^.+\\.ts$": "ts-jest" 251 | }, 252 | "moduleFileExtensions": [ 253 | "js", 254 | "ts", 255 | "svelte" 256 | ] 257 | ``` 258 | 259 | Note that TypeScript supports ES modules, so if you were previously using babel-jest just for ES module transpilation, you can remove babel-jest, babel, and any associated presets and config. 260 | 261 | By default, ts-jest will only transpile .ts files though, so if you want to continue using ES modules in .js files, you'll need to configure ts-jest to process .js files as well. 262 | To do this, update the file glob above, and follow the instructions in the [ts-jest docs](https://kulshekhar.github.io/ts-jest/). 263 | 264 | ### Preprocess 265 | 266 | Preprocessors are loaded from `svelte.config.js` or `svelte.config.cjs`. 267 | 268 | Add the following to your Jest config: 269 | 270 | ```json 271 | "transform": { 272 | "^.+\\.svelte$": ["svelte-jester", { "preprocess": true }] 273 | } 274 | ``` 275 | 276 | For CJS, replace `"svelte-jester"` with `"./node_modules/svelte-jester/dist/transformer.cjs"`. 277 | 278 | Create a `svelte.config.js` file and configure it, see 279 | [svelte-preprocess](https://github.com/kaisermann/svelte-preprocess) for more information. 280 | 281 | In CJS mode, `svelte-jester` must start a new a process for each file needing to be preprocessed, which adds a performance overhead. 282 | 283 | In ESM mode, this isn't necessary. You can set `NODE_OPTIONS=--experimental-vm-modules` and `"extensionsToTreatAsEsm": [".svelte"]` to run in ESM mode. However, be aware that ESM support in Jest is still experimental as according to their [docs](https://jestjs.io/docs/ecmascript-modules). Follow the development along at https://github.com/facebook/jest/issues/9430. 284 | 285 | ## Options 286 | 287 | `preprocess` (default: false): Pass in `true` if you are using Svelte preprocessors. 288 | They are loaded from `svelte.config.js` or `svelte.config.cjs`. 289 | 290 | `debug` (default: false): If you'd like to see the output of the compiled code then pass in `true`. 291 | 292 | `svelteVersion` (default: actual Version from Svelte package): If you'd like to override the svelteVersion for some reason. 293 | 294 | `compilerOptions` (default: {}): Use this to pass in 295 | [Svelte compiler options](https://svelte.dev/docs#svelte_compile). 296 | 297 | `rootMode` (default: ""): Pass in `upward` to walk up from the transforming file's directory and use the first `svelte.config.js` or `svelte.config.cjs` found, or throw an error if no config file is discovered. This is particularly useful in a monorepo as it allows you to: 298 | 299 | - Run tests from the worktree root using Jest projects where you only want to put `svelte.config.js` in workspace folders, and not in the root. 300 | - Run tests from the worktree root using Jest projects, but have different `svelte.config.js` configurations for individual workspaces. 301 | - Have one common `svelte.config.js` in your worktree root (or any directory above the file being transformed) without needing individual `svelte.config.js` files in each workspace. _Note - this root config file can be overriden if necessary by putting another config file into a workspace folder_ 302 | 303 | The default mode is to load `svelte.config.js` or `svelte.config.cjs` from the current project root to avoid the risk of accidentally loading a config file from outside the current project folder. 304 | 305 | When `upward` is set it will stop at the first config file it finds above the file being transformed, but will walk up the directory structure all the way to the filesystem root if it cannot find any config file. This means that if there is no `svelte.config.js` or `svelte.config.cjs` file in the project above the file being transformed, it is always possible that someone will have a forgotten config file in their home directory which could cause unexpected errors in your builds. 306 | 307 | ### CJS mode options 308 | 309 | `showConsoleLog` (default: false): If you'd like to see console.logs of the preprocessors then pass in `true`. Otherwise these will be surpressed, because the compiler could complain about unexpected tokens. 310 | 311 | `maxBuffer` (default: 10485760): Sets limit for buffer when `preprocess` is true. It defines the largest amount of data in bytes allowed on stdout or stderr for [child_process.spawnSync](https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options). If exceeded, the child process is terminated and any output is truncated. The default value of 10Mb overrides Node's default value of 1Mb. 312 | 313 | ```json 314 | "transform": { 315 | "^.+\\.js$": "babel-jest", 316 | "^.+\\.svelte$": ["./node_modules/svelte-jester/dist/transformer.cjs", { 317 | "preprocess": false, 318 | "debug": false, 319 | "compilerOptions": {}, 320 | "rootMode": "", 321 | "maxBuffer": 15000000 322 | }] 323 | } 324 | ``` 325 | 326 | ## Testing Library 327 | 328 | This package is required when using Svelte with the [Testing Library](https://testing-library.com/). 329 | If you'd like to avoid including implementation details in your tests, and making them more 330 | maintainble in the long run, then consider checking out 331 | [@testing-library/svelte](https://github.com/testing-library/svelte-testing-library). 332 | 333 | ## Credits 334 | 335 | Thanks to all contributors, inspired by: 336 | 337 | - https://github.com/pngwn/svelte-test 338 | - https://github.com/WeAreGenki/minna-ui 339 | - https://github.com/rspieker/jest-transform-svelte 340 | 341 | ## LICENSE 342 | 343 | [MIT](LICENSE) 344 | 345 | 346 | [package]: https://www.npmjs.com/package/svelte-jester 347 | [version-badge]: https://img.shields.io/npm/v/svelte-jester 348 | [license]: https://github.com/svelteness/svelte-jester/blob/main/LICENSE 349 | [license-badge]: https://img.shields.io/github/license/svelteness/svelte-jester?color=b 350 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # Release a new version 2 | 3 | 1. `pnpm run lint` 4 | 1. `pnpm run toc` 5 | 1. `pnpm run setup` 6 | 1. Raise Version 7 | 1. `pnpm run build` 8 | 1. `npx standard-version --release-as 5.0.0` or with automatic version increments `pnpm run release` 9 | 1. Login to NPM via `npm adduser` and `npm publish` 10 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | - upgrade to Svelte@4 3 | - migrate e2e/svelte to Vite (see e2e/svelte/README.md) 4 | - cleanup README 5 | - add eslint with plugins (svelte, import, promise) 6 | - add code coverage https://itnext.io/github-actions-code-coverage-without-third-parties-f1299747064d 7 | 8 | # Done 9 | - ~README~ 10 | - ~add section about CJS/ESM~ 11 | - ~v1.x~ 12 | - ~manual override~ 13 | - ~update packages~ 14 | - ~update e2e skeletons~ 15 | - ~add jest test for choosing of module system~ 16 | 17 | # Considerations 18 | - use different config loader https://github.com/unjs/c12 19 | - use different build tool https://github.com/unjs/unbuild 20 | - add https://github.com/TrySound/rollup-plugin-terser 21 | -------------------------------------------------------------------------------- /_svelte.config.cjs: -------------------------------------------------------------------------------- 1 | const { replace } = require('svelte-preprocess') 2 | 3 | module.exports = { 4 | preprocess: [ 5 | // strip style tag 6 | replace([[/|([^]*?)<\/style>|\/>)/gi, '']]) 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /e2e/README.md: -------------------------------------------------------------------------------- 1 | # End-to-End test for Svelte/SvelteKit using svelte-jester 2 | 3 | ## Svelte (CJS) 4 | 5 | ### Bootstrapping the project 6 | 7 | The following steps were executed to create the source for this test. 8 | 9 | (mostly from https://svelte.dev/blog/the-easiest-way-to-get-started and https://testing-library.com/docs/svelte-testing-library/setup) 10 | 11 | ``` 12 | ./init-svelte.sh 13 | 14 | # add the following config to your package.json (mostly from https://testing-library.com/docs/svelte-testing-library/setup but with our own transformer) 15 | "jest": { 16 | "transform": { 17 | "^.+\\.js$": "babel-jest", 18 | "^.+\\.svelte$": [ 19 | "../../dist/transformer.cjs", 20 | { 21 | "preprocess": true 22 | } 23 | ] 24 | }, 25 | "moduleFileExtensions": ["js", "svelte"], 26 | "setupFilesAfterEnv": ["@testing-library/jest-dom/extend-expect"], 27 | "testEnvironment": "jsdom" 28 | }, 29 | "babel": { 30 | "presets": [["@babel/preset-env", {"targets": {"node": "current"}}]] 31 | } 32 | 33 | # remove `type: "module",` from `package.json` 34 | 35 | # add basic component from https://testing-library.com/docs/svelte-testing-library/example/#component under __src/__ 36 | # add basic sample from https://testing-library.com/docs/svelte-testing-library/example#test under __src/test/__ 37 | # add svelte.config.js (CJS-style) from https://github.com/sveltejs/language-tools/blob/master/docs/preprocessors/in-general.md#generic-setup 38 | ``` 39 | 40 | ### Run the tests 41 | 42 | Start the tests with `npm run e2e:svelte` 43 | 44 | ## SvelteKit (ESM) 45 | 46 | ### Bootstrapping the project 47 | 48 | The following steps were executed to create the source for this test. 49 | 50 | (mostly from https://github.com/rossyman/svelte-add-jest) 51 | 52 | ``` 53 | mkdir sveltekit 54 | cd sveltekit 55 | npm init svelte 56 | # choose Demo App, typescript, no linter, no formatter, no Playwright, no Vitest 57 | npm install 58 | 59 | # remove comments from `tsconfig.json` or svelte-add-jest will fail with `SyntaxError: Unexpected token / in JSON at position 271` 60 | # add Jest 61 | npx apply rossyman/svelte-add-jest 62 | # choose Jest DOM, typescript, sample file, jsdom by default 63 | 64 | # downgrade some versions 65 | npm install --save-dev typescript@4 svelte@3 66 | # change path for svelte-jester in `jest.config.json` to `[ 67 | "../../dist/transformer.mjs", 68 | { 69 | "preprocess": true 70 | } 71 | ]` 72 | 73 | # edit `src/routes/index-dom.spec.ts`` 74 | # add `import { jest } from '@jest/globals'` 75 | # replace component `import Index from './Counter.svelte';` 76 | # change test, because of failing $app/stores mock 77 | test('should show the proper label', () => { 78 | expect(renderedComponent.getByLabelText(/Decrease the counter by one/)).toBeInTheDocument(); 79 | }); 80 | # check that the tests are passing 81 | npm run test 82 | ``` 83 | 84 | ## Svelte 5 (ESM) 85 | 86 | A minimal Svelte 5 test to ensure Svelte 5 components and `.svelte.js` modules work with Jest. No special steps were taken to create this suite. It only contains a few components and their associated tests. 87 | 88 | ### Run the Svelte 5 tests 89 | 90 | ```shell 91 | pnpm build 92 | pnpm e2e:svelte-5 93 | ``` 94 | -------------------------------------------------------------------------------- /e2e/init-svelte-4.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | npm init vite 4 | # select svelte, js and name "svelte-4" 5 | cd svelte-4 6 | 7 | pnpm install 8 | 9 | # install test dependencies 10 | pnpm install --save-dev svelte-preprocess jest jest-environment-jsdom svelte-jester@workspace @testing-library/svelte@4 @testing-library/jest-dom 11 | # apply all steps from https://github.com/rossyman/svelte-add-jest/blob/main/preset.ts 12 | 13 | # add svg transformer 14 | pnpm i -D jest-svg-transformer@https://github.com/Em-Ant/jest-transformer-svg 15 | # add transform config to package.json `"^.+\\.svg$": "jest-svg-transformer"` 16 | 17 | cd .. 18 | -------------------------------------------------------------------------------- /e2e/init-svelte.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | mkdir svelte 4 | cd svelte 5 | npx degit sveltejs/template . --force 6 | 7 | npm install 8 | npm install --save-dev svelte-preprocess jest jest-environment-jsdom svelte-jester @babel/preset-env babel-jest @testing-library/svelte@3 @testing-library/jest-dom 9 | 10 | cd .. 11 | -------------------------------------------------------------------------------- /e2e/svelte-3/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /public/build/ 3 | 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /e2e/svelte-3/README.md: -------------------------------------------------------------------------------- 1 | # This repo is no longer maintained. Consider using `npm init vite` and selecting the `svelte` option or — if you want a full-fledged app framework — use [SvelteKit](https://kit.svelte.dev), the official application framework for Svelte. 2 | 3 | --- 4 | 5 | # svelte app 6 | 7 | This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template. 8 | 9 | To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit): 10 | 11 | ```bash 12 | npx degit sveltejs/template svelte-app 13 | cd svelte-app 14 | ``` 15 | 16 | *Note that you will need to have [Node.js](https://nodejs.org) installed.* 17 | 18 | 19 | ## Get started 20 | 21 | Install the dependencies... 22 | 23 | ```bash 24 | cd svelte-app 25 | npm install 26 | ``` 27 | 28 | ...then start [Rollup](https://rollupjs.org): 29 | 30 | ```bash 31 | npm run dev 32 | ``` 33 | 34 | Navigate to [localhost:8080](http://localhost:8080). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes. 35 | 36 | By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`. 37 | 38 | If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense. 39 | 40 | ## Building and running in production mode 41 | 42 | To create an optimised version of the app: 43 | 44 | ```bash 45 | npm run build 46 | ``` 47 | 48 | You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com). 49 | 50 | 51 | ## Single-page app mode 52 | 53 | By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere. 54 | 55 | If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json: 56 | 57 | ```js 58 | "start": "sirv public --single" 59 | ``` 60 | 61 | ## Using TypeScript 62 | 63 | This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with: 64 | 65 | ```bash 66 | node scripts/setupTypeScript.js 67 | ``` 68 | 69 | Or remove the script via: 70 | 71 | ```bash 72 | rm scripts/setupTypeScript.js 73 | ``` 74 | 75 | If you want to use `baseUrl` or `path` aliases within your `tsconfig`, you need to set up `@rollup/plugin-alias` to tell Rollup to resolve the aliases. For more info, see [this StackOverflow question](https://stackoverflow.com/questions/63427935/setup-tsconfig-path-in-svelte). 76 | 77 | ## Deploying to the web 78 | 79 | ### With [Vercel](https://vercel.com) 80 | 81 | Install `vercel` if you haven't already: 82 | 83 | ```bash 84 | npm install -g vercel 85 | ``` 86 | 87 | Then, from within your project folder: 88 | 89 | ```bash 90 | cd public 91 | vercel deploy --name my-project 92 | ``` 93 | 94 | ### With [surge](https://surge.sh/) 95 | 96 | Install `surge` if you haven't already: 97 | 98 | ```bash 99 | npm install -g surge 100 | ``` 101 | 102 | Then, from within your project folder: 103 | 104 | ```bash 105 | npm run build 106 | surge public my-project.surge.sh 107 | ``` 108 | -------------------------------------------------------------------------------- /e2e/svelte-3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-app", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "build": "rollup -c", 7 | "dev": "rollup -c -w", 8 | "start": "sirv public --no-clear", 9 | "test": "jest src --no-cache --coverage", 10 | "test:watch": "pnpm run test --watch" 11 | }, 12 | "devDependencies": { 13 | "@babel/preset-env": "^7.22.9", 14 | "@rollup/plugin-commonjs": "^25.0.3", 15 | "@rollup/plugin-node-resolve": "^15.1.0", 16 | "@rollup/plugin-terser": "^0.4.3", 17 | "@testing-library/jest-dom": "^5.17.0", 18 | "@testing-library/svelte": "^3.2.2", 19 | "babel-jest": "^29.6.1", 20 | "jest": "^29.6.1", 21 | "jest-environment-jsdom": "^29.6.1", 22 | "rollup": "^3.26.3", 23 | "rollup-plugin-css-only": "^4.3.0", 24 | "rollup-plugin-livereload": "^2.0.5", 25 | "rollup-plugin-svelte": "^7.1.6", 26 | "svelte": "<4", 27 | "svelte-jester": "workspace:^", 28 | "svelte-preprocess": "^5.0.4" 29 | }, 30 | "dependencies": { 31 | "sirv-cli": "^2.0.2" 32 | }, 33 | "jest": { 34 | "transform": { 35 | "^.+\\.js$": "babel-jest", 36 | "^.+\\.svelte$": [ 37 | "../../dist/transformer.cjs", 38 | { 39 | "preprocess": true 40 | } 41 | ] 42 | }, 43 | "moduleFileExtensions": [ 44 | "js", 45 | "svelte" 46 | ], 47 | "setupFilesAfterEnv": [ 48 | "@testing-library/jest-dom/extend-expect" 49 | ], 50 | "testEnvironment": "jsdom" 51 | }, 52 | "babel": { 53 | "presets": [ 54 | [ 55 | "@babel/preset-env", 56 | { 57 | "targets": { 58 | "node": "current" 59 | } 60 | } 61 | ] 62 | ] 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /e2e/svelte-3/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/svelteness/svelte-jester/161609a4bb3e67f9b55e5ace0dc3f9844b3178db/e2e/svelte-3/public/favicon.png -------------------------------------------------------------------------------- /e2e/svelte-3/public/global.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | } 6 | 7 | body { 8 | color: #333; 9 | margin: 0; 10 | padding: 8px; 11 | box-sizing: border-box; 12 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; 13 | } 14 | 15 | a { 16 | color: rgb(0,100,200); 17 | text-decoration: none; 18 | } 19 | 20 | a:hover { 21 | text-decoration: underline; 22 | } 23 | 24 | a:visited { 25 | color: rgb(0,80,160); 26 | } 27 | 28 | label { 29 | display: block; 30 | } 31 | 32 | input, button, select, textarea { 33 | font-family: inherit; 34 | font-size: inherit; 35 | -webkit-padding: 0.4em 0; 36 | padding: 0.4em; 37 | margin: 0 0 0.5em 0; 38 | box-sizing: border-box; 39 | border: 1px solid #ccc; 40 | border-radius: 2px; 41 | } 42 | 43 | input:disabled { 44 | color: #ccc; 45 | } 46 | 47 | button { 48 | color: #333; 49 | background-color: #f4f4f4; 50 | outline: none; 51 | } 52 | 53 | button:disabled { 54 | color: #999; 55 | } 56 | 57 | button:not(:disabled):active { 58 | background-color: #ddd; 59 | } 60 | 61 | button:focus { 62 | border-color: #666; 63 | } 64 | -------------------------------------------------------------------------------- /e2e/svelte-3/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Svelte app 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /e2e/svelte-3/rollup.config.js: -------------------------------------------------------------------------------- 1 | import { spawn } from 'child_process' 2 | import svelte from 'rollup-plugin-svelte' 3 | import commonjs from '@rollup/plugin-commonjs' 4 | import terser from '@rollup/plugin-terser' 5 | import resolve from '@rollup/plugin-node-resolve' 6 | import livereload from 'rollup-plugin-livereload' 7 | import css from 'rollup-plugin-css-only' 8 | 9 | const production = !process.env.ROLLUP_WATCH 10 | 11 | function serve () { 12 | let server 13 | 14 | function toExit () { 15 | if (server) server.kill(0) 16 | } 17 | 18 | return { 19 | writeBundle () { 20 | if (server) return 21 | server = spawn('npm', ['run', 'start', '--', '--dev'], { 22 | stdio: ['ignore', 'inherit', 'inherit'], 23 | shell: true 24 | }) 25 | 26 | process.on('SIGTERM', toExit) 27 | process.on('exit', toExit) 28 | } 29 | } 30 | } 31 | 32 | export default { 33 | input: 'src/main.js', 34 | output: { 35 | sourcemap: true, 36 | format: 'iife', 37 | name: 'app', 38 | file: 'public/build/bundle.js' 39 | }, 40 | plugins: [ 41 | svelte({ 42 | compilerOptions: { 43 | // enable run-time checks when not in production 44 | dev: !production 45 | } 46 | }), 47 | // we'll extract any component CSS out into 48 | // a separate file - better for performance 49 | css({ output: 'bundle.css' }), 50 | 51 | // If you have external dependencies installed from 52 | // npm, you'll most likely need these plugins. In 53 | // some cases you'll need additional configuration - 54 | // consult the documentation for details: 55 | // https://github.com/rollup/plugins/tree/master/packages/commonjs 56 | resolve({ 57 | browser: true, 58 | dedupe: ['svelte'], 59 | exportConditions: ['svelte'] 60 | }), 61 | commonjs(), 62 | 63 | // In dev mode, call `npm run start` once 64 | // the bundle has been generated 65 | !production && serve(), 66 | 67 | // Watch the `public` directory and refresh the 68 | // browser on changes when not in production 69 | !production && livereload('public'), 70 | 71 | // If we're building for production (npm run build 72 | // instead of npm run dev), minify 73 | production && terser() 74 | ], 75 | watch: { 76 | clearScreen: false 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /e2e/svelte-3/scripts/setupTypeScript.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | /** This script modifies the project to support TS code in .svelte files like: 4 | 5 | 8 | 9 | As well as validating the code for CI. 10 | */ 11 | 12 | /** To work on this script: 13 | rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template 14 | */ 15 | 16 | import fs from 'fs' 17 | import path from 'path' 18 | import { argv } from 'process' 19 | import url from 'url' 20 | 21 | const __filename = url.fileURLToPath(import.meta.url) 22 | const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) 23 | const projectRoot = argv[2] || path.join(__dirname, '..') 24 | 25 | // Add deps to pkg.json 26 | const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf8')) 27 | packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { 28 | 'svelte-check': '^3.0.0', 29 | 'svelte-preprocess': '^5.0.0', 30 | '@rollup/plugin-typescript': '^11.0.0', 31 | typescript: '^4.9.0', 32 | tslib: '^2.5.0', 33 | '@tsconfig/svelte': '^3.0.0' 34 | }) 35 | 36 | // Add script for checking 37 | packageJSON.scripts = Object.assign(packageJSON.scripts, { 38 | check: 'svelte-check' 39 | }) 40 | 41 | // Write the package JSON 42 | fs.writeFileSync(path.join(projectRoot, 'package.json'), JSON.stringify(packageJSON, null, ' ')) 43 | 44 | // mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too 45 | const beforeMainJSPath = path.join(projectRoot, 'src', 'main.js') 46 | const afterMainTSPath = path.join(projectRoot, 'src', 'main.ts') 47 | fs.renameSync(beforeMainJSPath, afterMainTSPath) 48 | 49 | // Switch the app.svelte file to use TS 50 | const appSveltePath = path.join(projectRoot, 'src', 'App.svelte') 51 | let appFile = fs.readFileSync(appSveltePath, 'utf8') 52 | appFile = appFile.replace(' 4 | 5 |
6 |

Hello {name}!

7 |

Visit the Svelte tutorial to learn how to build Svelte apps.

8 |
9 | 10 | -------------------------------------------------------------------------------- /e2e/svelte-3/src/Comp.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |

Hello {name}!

12 | 13 | 14 | -------------------------------------------------------------------------------- /e2e/svelte-3/src/main.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte' 2 | 3 | const app = new App({ 4 | target: document.body, 5 | props: { 6 | name: 'world' 7 | } 8 | }) 9 | 10 | export default app 11 | -------------------------------------------------------------------------------- /e2e/svelte-3/src/test/Comp.spec.js: -------------------------------------------------------------------------------- 1 | // NOTE: jest-dom adds handy assertions to Jest and it is recommended, but not required. 2 | import '@testing-library/jest-dom' 3 | 4 | import { render, fireEvent, screen } from '@testing-library/svelte' 5 | 6 | import Comp from '../Comp' 7 | 8 | test('shows proper heading when rendered', () => { 9 | render(Comp, { name: 'World' }) 10 | const heading = screen.getByText('Hello World!') 11 | expect(heading).toBeInTheDocument() 12 | }) 13 | 14 | // Note: This is as an async test as we are using `fireEvent` 15 | test('changes button text on click', async () => { 16 | render(Comp, { name: 'World' }) 17 | const button = screen.getByRole('button') 18 | 19 | // Using await when firing events is unique to the svelte testing library because 20 | // we have to wait for the next `tick` so that Svelte flushes all pending state changes. 21 | await fireEvent.click(button) 22 | 23 | expect(button).toHaveTextContent('Button Clicked') 24 | }) 25 | -------------------------------------------------------------------------------- /e2e/svelte-3/svelte.config.js: -------------------------------------------------------------------------------- 1 | const sveltePreprocess = require('svelte-preprocess') 2 | 3 | module.exports = { 4 | preprocess: sveltePreprocess() 5 | } 6 | -------------------------------------------------------------------------------- /e2e/svelte-4/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /e2e/svelte-4/.npmrc: -------------------------------------------------------------------------------- 1 | shell-emulator=true 2 | -------------------------------------------------------------------------------- /e2e/svelte-4/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["svelte.svelte-vscode"] 3 | } 4 | -------------------------------------------------------------------------------- /e2e/svelte-4/README.md: -------------------------------------------------------------------------------- 1 | # Svelte + Vite 2 | 3 | This template should help get you started developing with Svelte in Vite. 4 | 5 | ## Recommended IDE Setup 6 | 7 | [VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). 8 | 9 | ## Need an official Svelte framework? 10 | 11 | Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more. 12 | 13 | ## Technical considerations 14 | 15 | **Why use this over SvelteKit?** 16 | 17 | - It brings its own routing solution which might not be preferable for some users. 18 | - It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app. 19 | 20 | This template contains as little as possible to get started with Vite + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project. 21 | 22 | Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate. 23 | 24 | **Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?** 25 | 26 | Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information. 27 | 28 | **Why include `.vscode/extensions.json`?** 29 | 30 | Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project. 31 | 32 | **Why enable `checkJs` in the JS template?** 33 | 34 | It is likely that most cases of changing variable types in runtime are likely to be accidental, rather than deliberate. This provides advanced typechecking out of the box. Should you like to take advantage of the dynamically-typed nature of JavaScript, it is trivial to change the configuration. 35 | 36 | **Why is HMR not preserving my local component state?** 37 | 38 | HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/sveltejs/svelte-hmr/tree/master/packages/svelte-hmr#preservation-of-local-state). 39 | 40 | If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR. 41 | 42 | ```js 43 | // store.js 44 | // An extremely simple external store 45 | import { writable } from 'svelte/store' 46 | export default writable(0) 47 | ``` 48 | -------------------------------------------------------------------------------- /e2e/svelte-4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + Svelte 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /e2e/svelte-4/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "bundler", 4 | "target": "ESNext", 5 | "module": "ESNext", 6 | /** 7 | * svelte-preprocess cannot figure out whether you have 8 | * a value or a type, so tell TypeScript to enforce using 9 | * `import type` instead of `import` for Types. 10 | */ 11 | "verbatimModuleSyntax": true, 12 | "isolatedModules": true, 13 | "resolveJsonModule": true, 14 | /** 15 | * To have warnings / errors of the Svelte compiler at the 16 | * correct position, enable source maps by default. 17 | */ 18 | "sourceMap": true, 19 | "esModuleInterop": true, 20 | "skipLibCheck": true, 21 | /** 22 | * Typecheck JS in `.svelte` and `.js` files by default. 23 | * Disable this if you'd like to use dynamic types. 24 | */ 25 | "checkJs": true 26 | }, 27 | /** 28 | * Use global.d.ts instead of compilerOptions.types 29 | * to avoid limiting type declarations. 30 | */ 31 | "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"] 32 | } 33 | -------------------------------------------------------------------------------- /e2e/svelte-4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-4", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview", 10 | "test": "pnpm install && NODE_OPTIONS=\"--experimental-vm-modules --no-warnings\" jest --coverage --no-cache", 11 | "test:watch": "pnpm run test --watch" 12 | }, 13 | "devDependencies": { 14 | "@sveltejs/vite-plugin-svelte": "^3.0.2", 15 | "@testing-library/jest-dom": "^6.4.6", 16 | "@testing-library/svelte": "^4.2.3", 17 | "jest": "^29.7.0", 18 | "jest-environment-jsdom": "^29.7.0", 19 | "jest-svg-transformer": "https://github.com/Em-Ant/jest-transformer-svg", 20 | "svelte": "<5", 21 | "svelte-jester": "workspace:^", 22 | "vite": "^5.2.0" 23 | }, 24 | "jest": { 25 | "transform": { 26 | "^.+\\.svelte$": [ 27 | "svelte-jester" 28 | ], 29 | "^.+\\.svg$": "jest-svg-transformer" 30 | }, 31 | "moduleFileExtensions": [ 32 | "js", 33 | "svelte" 34 | ], 35 | "extensionsToTreatAsEsm": [ 36 | ".svelte" 37 | ], 38 | "setupFilesAfterEnv": [ 39 | "@testing-library/jest-dom" 40 | ], 41 | "testEnvironment": "jsdom" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /e2e/svelte-4/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /e2e/svelte-4/src/App.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 |
8 | 9 | 10 | 11 |
12 |

Vite + Svelte

13 | 14 |
15 | 16 |
17 | 18 |

19 | Check out SvelteKit, the official Svelte app framework powered by Vite! 20 |

21 | 22 |

23 | Click on the Vite and Svelte logos to learn more 24 |

25 |
26 | 27 | 44 | -------------------------------------------------------------------------------- /e2e/svelte-4/src/app.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; 3 | line-height: 1.5; 4 | font-weight: 400; 5 | 6 | color-scheme: light dark; 7 | color: rgba(255, 255, 255, 0.87); 8 | background-color: #242424; 9 | 10 | font-synthesis: none; 11 | text-rendering: optimizeLegibility; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | } 15 | 16 | a { 17 | font-weight: 500; 18 | color: #646cff; 19 | text-decoration: inherit; 20 | } 21 | a:hover { 22 | color: #535bf2; 23 | } 24 | 25 | body { 26 | margin: 0; 27 | display: flex; 28 | place-items: center; 29 | min-width: 320px; 30 | min-height: 100vh; 31 | } 32 | 33 | h1 { 34 | font-size: 3.2em; 35 | line-height: 1.1; 36 | } 37 | 38 | .card { 39 | padding: 2em; 40 | } 41 | 42 | #app { 43 | max-width: 1280px; 44 | margin: 0 auto; 45 | padding: 2rem; 46 | text-align: center; 47 | } 48 | 49 | button { 50 | border-radius: 8px; 51 | border: 1px solid transparent; 52 | padding: 0.6em 1.2em; 53 | font-size: 1em; 54 | font-weight: 500; 55 | font-family: inherit; 56 | background-color: #1a1a1a; 57 | cursor: pointer; 58 | transition: border-color 0.25s; 59 | } 60 | button:hover { 61 | border-color: #646cff; 62 | } 63 | button:focus, 64 | button:focus-visible { 65 | outline: 4px auto -webkit-focus-ring-color; 66 | } 67 | 68 | @media (prefers-color-scheme: light) { 69 | :root { 70 | color: #213547; 71 | background-color: #ffffff; 72 | } 73 | a:hover { 74 | color: #747bff; 75 | } 76 | button { 77 | background-color: #f9f9f9; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /e2e/svelte-4/src/assets/svelte.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /e2e/svelte-4/src/lib/Counter.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /e2e/svelte-4/src/main.js: -------------------------------------------------------------------------------- 1 | import './app.css' 2 | import App from './App.svelte' 3 | 4 | const app = new App({ 5 | target: document.getElementById('app') 6 | }) 7 | 8 | export default app 9 | -------------------------------------------------------------------------------- /e2e/svelte-4/src/test/Comp.spec.js: -------------------------------------------------------------------------------- 1 | // NOTE: jest-dom adds handy assertions to Jest and it is recommended, but not required. 2 | import '@testing-library/jest-dom' 3 | 4 | import { render, fireEvent, screen } from '@testing-library/svelte' 5 | 6 | import App from '../App.svelte' 7 | 8 | test('shows proper heading when rendered', () => { 9 | render(App) 10 | const heading = screen.getByText('Vite + Svelte') 11 | expect(heading).toBeInTheDocument() 12 | }) 13 | 14 | // Note: This is as an async test as we are using `fireEvent` 15 | test('changes button text on click', async () => { 16 | render(App) 17 | const button = screen.getByRole('button') 18 | 19 | // Using await when firing events is unique to the svelte testing library because 20 | // we have to wait for the next `tick` so that Svelte flushes all pending state changes. 21 | await fireEvent.click(button) 22 | 23 | expect(button).toHaveTextContent('count is 1') 24 | }) 25 | -------------------------------------------------------------------------------- /e2e/svelte-4/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /e2e/svelte-4/svelte.config.js: -------------------------------------------------------------------------------- 1 | import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' 2 | 3 | export default { 4 | // Consult https://svelte.dev/docs#compile-time-svelte-preprocess 5 | // for more information about preprocessors 6 | preprocess: vitePreprocess() 7 | } 8 | -------------------------------------------------------------------------------- /e2e/svelte-4/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import { svelte } from '@sveltejs/vite-plugin-svelte' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [svelte()] 7 | }) 8 | -------------------------------------------------------------------------------- /e2e/svelte-5/.npmrc: -------------------------------------------------------------------------------- 1 | shell-emulator=true 2 | -------------------------------------------------------------------------------- /e2e/svelte-5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@svelte-jester-e2e/svelte-5", 3 | "version": "1.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "test": "pnpm install && NODE_OPTIONS=\"--experimental-vm-modules --no-warnings\" jest --coverage --no-cache", 8 | "test:watch": "pnpm run test --watch" 9 | }, 10 | "devDependencies": { 11 | "@testing-library/jest-dom": "^6.6.3", 12 | "jest": "^29.7.0", 13 | "jest-environment-jsdom": "^29.7.0", 14 | "svelte": "^5.19.9", 15 | "svelte-jester": "workspace:*" 16 | }, 17 | "dependenciesMeta": { 18 | "svelte-jester": { 19 | "injected": true 20 | } 21 | }, 22 | "jest": { 23 | "transform": { 24 | "^.+\\.svelte(?:\\.js)?$": [ 25 | "svelte-jester" 26 | ] 27 | }, 28 | "moduleFileExtensions": [ 29 | "js", 30 | "svelte" 31 | ], 32 | "extensionsToTreatAsEsm": [ 33 | ".svelte" 34 | ], 35 | "setupFilesAfterEnv": [ 36 | "@testing-library/jest-dom" 37 | ], 38 | "testEnvironment": "jsdom" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /e2e/svelte-5/src/legacy.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | {#if showGreeting} 10 |

hello {name}

11 | {/if} 12 | -------------------------------------------------------------------------------- /e2e/svelte-5/src/legacy.test.js: -------------------------------------------------------------------------------- 1 | import { mount, unmount, tick } from 'svelte' 2 | 3 | import Subject from './legacy.svelte' 4 | 5 | let component 6 | 7 | afterEach(() => { 8 | unmount(component) 9 | component = undefined 10 | }) 11 | 12 | test('render', () => { 13 | component = mount(Subject, { 14 | target: document.body, 15 | props: { name: 'alice' } 16 | }) 17 | 18 | const button = document.querySelector('button') 19 | 20 | expect(button).toHaveRole('button') 21 | }) 22 | 23 | test('interaction', async () => { 24 | component = mount(Subject, { 25 | target: document.body, 26 | props: { name: 'alice' } 27 | }) 28 | 29 | const button = document.querySelector('button') 30 | 31 | button.click() 32 | await tick() 33 | 34 | const message = document.querySelector('p') 35 | 36 | expect(message.textContent).toMatch(/hello alice/iu) 37 | }) 38 | -------------------------------------------------------------------------------- /e2e/svelte-5/src/modern.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | {#if showGreeting} 10 |

hello {name}

11 | {/if} 12 | -------------------------------------------------------------------------------- /e2e/svelte-5/src/modern.test.js: -------------------------------------------------------------------------------- 1 | import { mount, unmount, tick } from 'svelte' 2 | 3 | import Subject from './modern.svelte' 4 | 5 | let component 6 | 7 | afterEach(() => { 8 | unmount(component) 9 | component = undefined 10 | }) 11 | 12 | test('render', () => { 13 | component = mount(Subject, { 14 | target: document.body, 15 | props: { name: 'alice' } 16 | }) 17 | 18 | const button = document.querySelector('button') 19 | 20 | expect(button).toHaveRole('button') 21 | }) 22 | 23 | test('interaction', async () => { 24 | component = mount(Subject, { 25 | target: document.body, 26 | props: { name: 'alice' } 27 | }) 28 | 29 | const button = document.querySelector('button') 30 | 31 | button.click() 32 | await tick() 33 | 34 | const message = document.querySelector('p') 35 | 36 | expect(message.textContent).toMatch(/hello alice/iu) 37 | }) 38 | -------------------------------------------------------------------------------- /e2e/svelte-5/src/module.svelte.js: -------------------------------------------------------------------------------- 1 | export const createCounter = () => { 2 | let count = $state(0) 3 | 4 | return { 5 | get count () { 6 | return count 7 | }, 8 | 9 | increment () { 10 | count = count + 1 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /e2e/svelte-5/src/module.test.js: -------------------------------------------------------------------------------- 1 | import { test } from '@jest/globals' 2 | 3 | import * as Subject from './module.svelte.js' 4 | 5 | test('get current count', () => { 6 | const subject = Subject.createCounter() 7 | const result = subject.count 8 | 9 | expect(result).toBe(0) 10 | }) 11 | 12 | test('increment', () => { 13 | const subject = Subject.createCounter() 14 | 15 | subject.increment() 16 | const result = subject.count 17 | 18 | expect(result).toBe(1) 19 | }) 20 | -------------------------------------------------------------------------------- /e2e/svelte-5/svelte.config.js: -------------------------------------------------------------------------------- 1 | export default {} 2 | -------------------------------------------------------------------------------- /e2e/sveltekit/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "node": "current" 8 | } 9 | } 10 | ] 11 | ] 12 | } -------------------------------------------------------------------------------- /e2e/sveltekit/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | .vercel 10 | .output 11 | vite.config.js.timestamp-* 12 | vite.config.ts.timestamp-* 13 | -------------------------------------------------------------------------------- /e2e/sveltekit/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | resolution-mode=highest 3 | shell-emulator=true 4 | -------------------------------------------------------------------------------- /e2e/sveltekit/README.md: -------------------------------------------------------------------------------- 1 | # create-svelte 2 | 3 | Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte). 4 | 5 | ## Creating a project 6 | 7 | If you're seeing this, you've probably already done this step. Congrats! 8 | 9 | ```bash 10 | # create a new project in the current directory 11 | npm create svelte@latest 12 | 13 | # create a new project in my-app 14 | npm create svelte@latest my-app 15 | ``` 16 | 17 | ## Developing 18 | 19 | Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: 20 | 21 | ```bash 22 | npm run dev 23 | 24 | # or start the server and open the app in a new browser tab 25 | npm run dev -- --open 26 | ``` 27 | 28 | ## Building 29 | 30 | To create a production version of your app: 31 | 32 | ```bash 33 | npm run build 34 | ``` 35 | 36 | You can preview the production build with `npm run preview`. 37 | 38 | > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. 39 | -------------------------------------------------------------------------------- /e2e/sveltekit/jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "transform": { 3 | "^.+\\.js$": "babel-jest", 4 | "^.+\\.svelte$": [ 5 | "svelte-jester", 6 | { 7 | "preprocess": true 8 | } 9 | ], 10 | "^.+\\.ts$": ["ts-jest", { 11 | "tsconfig": "tsconfig.spec.json", 12 | "useESM": true 13 | }] 14 | }, 15 | "moduleNameMapper": { 16 | "^\\$lib(.*)$": "/src/lib$1", 17 | "^\\$app(.*)$": [ 18 | "/.svelte-kit/dev/runtime/app$1", 19 | "/.svelte-kit/build/runtime/app$1" 20 | ] 21 | }, 22 | "extensionsToTreatAsEsm": [ 23 | ".svelte", 24 | ".ts" 25 | ], 26 | "moduleFileExtensions": [ 27 | "js", 28 | "svelte", 29 | "ts" 30 | ], 31 | "setupFilesAfterEnv": [ 32 | "@testing-library/jest-dom/extend-expect" 33 | ], 34 | "testEnvironment": "jsdom" 35 | } 36 | -------------------------------------------------------------------------------- /e2e/sveltekit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sveltekit", 3 | "version": "0.0.1", 4 | "type": "module", 5 | "scripts": { 6 | "dev": "vite dev", 7 | "build": "vite build", 8 | "preview": "vite preview", 9 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 10 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 11 | "test": "svelte-kit sync && cross-env NODE_OPTIONS=--experimental-vm-modules jest src --config jest.config.json --no-cache", 12 | "test:watch": "pnpm run test -- --watch" 13 | }, 14 | "devDependencies": { 15 | "@babel/core": "^7.22.9", 16 | "@babel/preset-env": "^7.22.9", 17 | "@fontsource/fira-mono": "^5.0.5", 18 | "@neoconfetti/svelte": "^2.0.0", 19 | "@sveltejs/adapter-auto": "^3.0.1", 20 | "@sveltejs/kit": "^1.22.3", 21 | "@testing-library/jest-dom": "^5.17.0", 22 | "@testing-library/svelte": "^4.0.3", 23 | "@types/cookie": "^0.6.0", 24 | "@types/jest": "^29.5.3", 25 | "@types/testing-library__jest-dom": "^5.14.8", 26 | "babel-jest": "^29.6.1", 27 | "cross-env": "^7.0.3", 28 | "jest": "^29.6.1", 29 | "jest-environment-jsdom": "^29.6.1", 30 | "svelte": "^4.1.1", 31 | "svelte-check": "^3.4.6", 32 | "svelte-jester": "workspace:^", 33 | "ts-jest": "^29.1.1", 34 | "tslib": "^2.6.0", 35 | "typescript": "^5.1.6", 36 | "vite": "^5.0.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | declare global { 4 | namespace App { 5 | // interface Error {} 6 | // interface Locals {} 7 | // interface PageData {} 8 | // interface Platform {} 9 | } 10 | } 11 | 12 | export {}; 13 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/lib/images/github.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 16 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/lib/images/svelte-logo.svg: -------------------------------------------------------------------------------- 1 | svelte-logo -------------------------------------------------------------------------------- /e2e/sveltekit/src/lib/images/svelte-welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/svelteness/svelte-jester/161609a4bb3e67f9b55e5ace0dc3f9844b3178db/e2e/sveltekit/src/lib/images/svelte-welcome.png -------------------------------------------------------------------------------- /e2e/sveltekit/src/lib/images/svelte-welcome.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/svelteness/svelte-jester/161609a4bb3e67f9b55e5ace0dc3f9844b3178db/e2e/sveltekit/src/lib/images/svelte-welcome.webp -------------------------------------------------------------------------------- /e2e/sveltekit/src/routes/+layout.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 |
8 | 9 |
10 | 11 |
12 | 13 | 16 |
17 | 18 | 54 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | Home 9 | 10 | 11 | 12 |
13 |

14 | 15 | 16 | 17 | Welcome 18 | 19 | 20 | 21 | to your new
SvelteKit app 22 |

23 | 24 |

25 | try editing src/routes/+page.svelte 26 |

27 | 28 | 29 |
30 | 31 | 60 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/routes/+page.ts: -------------------------------------------------------------------------------- 1 | // since there's no dynamic data here, we can prerender 2 | // it so that it gets served as a static asset in production 3 | export const prerender = true; 4 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/routes/Counter.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 |
17 | 22 | 23 |
24 |
25 | 26 | {Math.floor($displayed_count)} 27 |
28 |
29 | 30 | 35 |
36 | 37 | 103 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/routes/Header.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
8 |
9 | 10 | SvelteKit 11 | 12 |
13 | 14 | 33 | 34 |
35 | 36 | GitHub 37 | 38 |
39 |
40 | 41 | 130 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/routes/about/+page.svelte: -------------------------------------------------------------------------------- 1 | 2 | About 3 | 4 | 5 | 6 |
7 |

About this app

8 | 9 |

10 | This is a SvelteKit app. You can make your own by typing the 11 | following into your command line and following the prompts: 12 |

13 | 14 |
npm create svelte@latest
15 | 16 |

17 | The page you're looking at is purely static HTML, with no client-side interactivity needed. 18 | Because of that, we don't need to load any JavaScript. Try viewing the page's source, or opening 19 | the devtools network panel and reloading. 20 |

21 | 22 |

23 | The Sverdle page illustrates SvelteKit's data loading and form handling. Try 24 | using it with JavaScript disabled! 25 |

26 |
27 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/routes/about/+page.ts: -------------------------------------------------------------------------------- 1 | import { dev } from '$app/environment'; 2 | 3 | // we don't need any JS on this page, though we'll load 4 | // it in dev so that we get hot module replacement 5 | export const csr = dev; 6 | 7 | // since there's no dynamic data here, we can prerender 8 | // it so that it gets served as a static asset in production 9 | export const prerender = true; 10 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/routes/index-dom.spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @jest-environment jsdom 3 | */ 4 | 5 | import { render } from '@testing-library/svelte'; 6 | import Counter from './Counter.svelte'; 7 | 8 | /** 9 | * @see https://jestjs.io/docs/getting-started 10 | * @see https://github.com/testing-library/jest-dom 11 | */ 12 | 13 | describe('Index', () => { 14 | 15 | describe('once the component has been rendered', () => { 16 | 17 | test('should show the proper label', () => { 18 | expect(render(Counter).getByLabelText(/Decrease the counter by one/)).toBeInTheDocument(); 19 | }); 20 | 21 | }); 22 | 23 | }); 24 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/routes/styles.css: -------------------------------------------------------------------------------- 1 | @import '@fontsource/fira-mono'; 2 | 3 | :root { 4 | --font-body: Arial, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 5 | Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 6 | --font-mono: 'Fira Mono', monospace; 7 | --color-bg-0: rgb(202, 216, 228); 8 | --color-bg-1: hsl(209, 36%, 86%); 9 | --color-bg-2: hsl(224, 44%, 95%); 10 | --color-theme-1: #ff3e00; 11 | --color-theme-2: #4075a6; 12 | --color-text: rgba(0, 0, 0, 0.7); 13 | --column-width: 42rem; 14 | --column-margin-top: 4rem; 15 | font-family: var(--font-body); 16 | color: var(--color-text); 17 | } 18 | 19 | body { 20 | min-height: 100vh; 21 | margin: 0; 22 | background-attachment: fixed; 23 | background-color: var(--color-bg-1); 24 | background-size: 100vw 100vh; 25 | background-image: radial-gradient( 26 | 50% 50% at 50% 50%, 27 | rgba(255, 255, 255, 0.75) 0%, 28 | rgba(255, 255, 255, 0) 100% 29 | ), 30 | linear-gradient(180deg, var(--color-bg-0) 0%, var(--color-bg-1) 15%, var(--color-bg-2) 50%); 31 | } 32 | 33 | h1, 34 | h2, 35 | p { 36 | font-weight: 400; 37 | } 38 | 39 | p { 40 | line-height: 1.5; 41 | } 42 | 43 | a { 44 | color: var(--color-theme-1); 45 | text-decoration: none; 46 | } 47 | 48 | a:hover { 49 | text-decoration: underline; 50 | } 51 | 52 | h1 { 53 | font-size: 2rem; 54 | text-align: center; 55 | } 56 | 57 | h2 { 58 | font-size: 1rem; 59 | } 60 | 61 | pre { 62 | font-size: 16px; 63 | font-family: var(--font-mono); 64 | background-color: rgba(255, 255, 255, 0.45); 65 | border-radius: 3px; 66 | box-shadow: 2px 2px 6px rgb(255 255 255 / 25%); 67 | padding: 0.5em; 68 | overflow-x: auto; 69 | color: var(--color-text); 70 | } 71 | 72 | .text-column { 73 | display: flex; 74 | max-width: 48rem; 75 | flex: 0.6; 76 | flex-direction: column; 77 | justify-content: center; 78 | margin: 0 auto; 79 | } 80 | 81 | input, 82 | button { 83 | font-size: inherit; 84 | font-family: inherit; 85 | } 86 | 87 | button:focus:not(:focus-visible) { 88 | outline: none; 89 | } 90 | 91 | @media (min-width: 720px) { 92 | h1 { 93 | font-size: 2.4rem; 94 | } 95 | } 96 | 97 | .visually-hidden { 98 | border: 0; 99 | clip: rect(0 0 0 0); 100 | height: auto; 101 | margin: 0; 102 | overflow: hidden; 103 | padding: 0; 104 | position: absolute; 105 | width: 1px; 106 | white-space: nowrap; 107 | } 108 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/routes/sverdle/+page.server.ts: -------------------------------------------------------------------------------- 1 | import { fail } from '@sveltejs/kit'; 2 | import { Game } from './game'; 3 | import type { PageServerLoad, Actions } from './$types'; 4 | 5 | export const load = (({ cookies }) => { 6 | const game = new Game(cookies.get('sverdle')); 7 | 8 | return { 9 | /** 10 | * The player's guessed words so far 11 | */ 12 | guesses: game.guesses, 13 | 14 | /** 15 | * An array of strings like '__x_c' corresponding to the guesses, where 'x' means 16 | * an exact match, and 'c' means a close match (right letter, wrong place) 17 | */ 18 | answers: game.answers, 19 | 20 | /** 21 | * The correct answer, revealed if the game is over 22 | */ 23 | answer: game.answers.length >= 6 ? game.answer : null 24 | }; 25 | }) satisfies PageServerLoad; 26 | 27 | export const actions = { 28 | /** 29 | * Modify game state in reaction to a keypress. If client-side JavaScript 30 | * is available, this will happen in the browser instead of here 31 | */ 32 | update: async ({ request, cookies }) => { 33 | const game = new Game(cookies.get('sverdle')); 34 | 35 | const data = await request.formData(); 36 | const key = data.get('key'); 37 | 38 | const i = game.answers.length; 39 | 40 | if (key === 'backspace') { 41 | game.guesses[i] = game.guesses[i].slice(0, -1); 42 | } else { 43 | game.guesses[i] += key; 44 | } 45 | 46 | cookies.set('sverdle', game.toString()); 47 | }, 48 | 49 | /** 50 | * Modify game state in reaction to a guessed word. This logic always runs on 51 | * the server, so that people can't cheat by peeking at the JavaScript 52 | */ 53 | enter: async ({ request, cookies }) => { 54 | const game = new Game(cookies.get('sverdle')); 55 | 56 | const data = await request.formData(); 57 | const guess = data.getAll('guess') as string[]; 58 | 59 | if (!game.enter(guess)) { 60 | return fail(400, { badGuess: true }); 61 | } 62 | 63 | cookies.set('sverdle', game.toString()); 64 | }, 65 | 66 | restart: async ({ cookies }) => { 67 | cookies.delete('sverdle'); 68 | } 69 | } satisfies Actions; 70 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/routes/sverdle/+page.svelte: -------------------------------------------------------------------------------- 1 | 83 | 84 | 85 | 86 | 87 | Sverdle 88 | 89 | 90 | 91 |

Sverdle

92 | 93 |
{ 97 | // prevent default callback from resetting the form 98 | return ({ update }) => { 99 | update({ reset: false }); 100 | }; 101 | }} 102 | > 103 | How to play 104 | 105 |
106 | {#each Array.from(Array(6).keys()) as row (row)} 107 | {@const current = row === i} 108 |

Row {row + 1}

109 |
110 | {#each Array.from(Array(5).keys()) as column (column)} 111 | {@const answer = data.answers[row]?.[column]} 112 | {@const value = data.guesses[row]?.[column] ?? ''} 113 | {@const selected = current && column === data.guesses[row].length} 114 | {@const exact = answer === 'x'} 115 | {@const close = answer === 'c'} 116 | {@const missing = answer === '_'} 117 |
118 | {value} 119 | 120 | {#if exact} 121 | (correct) 122 | {:else if close} 123 | (present) 124 | {:else if missing} 125 | (absent) 126 | {:else} 127 | empty 128 | {/if} 129 | 130 | 131 |
132 | {/each} 133 |
134 | {/each} 135 |
136 | 137 |
138 | {#if won || data.answers.length >= 6} 139 | {#if !won && data.answer} 140 |

the answer was "{data.answer}"

141 | {/if} 142 | 145 | {:else} 146 |
147 | 148 | 149 | 158 | 159 | {#each ['qwertyuiop', 'asdfghjkl', 'zxcvbnm'] as row} 160 |
161 | {#each row as letter} 162 | 174 | {/each} 175 |
176 | {/each} 177 |
178 | {/if} 179 |
180 |
181 | 182 | {#if won} 183 |
193 | {/if} 194 | 195 | 407 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/routes/sverdle/game.ts: -------------------------------------------------------------------------------- 1 | import { words, allowed } from './words.server'; 2 | 3 | export class Game { 4 | index: number; 5 | guesses: string[]; 6 | answers: string[]; 7 | answer: string; 8 | 9 | /** 10 | * Create a game object from the player's cookie, or initialise a new game 11 | */ 12 | constructor(serialized: string | undefined = undefined) { 13 | if (serialized) { 14 | const [index, guesses, answers] = serialized.split('-'); 15 | 16 | this.index = +index; 17 | this.guesses = guesses ? guesses.split(' ') : []; 18 | this.answers = answers ? answers.split(' ') : []; 19 | } else { 20 | this.index = Math.floor(Math.random() * words.length); 21 | this.guesses = ['', '', '', '', '', '']; 22 | this.answers = []; 23 | } 24 | 25 | this.answer = words[this.index]; 26 | } 27 | 28 | /** 29 | * Update game state based on a guess of a five-letter word. Returns 30 | * true if the guess was valid, false otherwise 31 | */ 32 | enter(letters: string[]) { 33 | const word = letters.join(''); 34 | const valid = allowed.has(word); 35 | 36 | if (!valid) return false; 37 | 38 | this.guesses[this.answers.length] = word; 39 | 40 | const available = Array.from(this.answer); 41 | const answer = Array(5).fill('_'); 42 | 43 | // first, find exact matches 44 | for (let i = 0; i < 5; i += 1) { 45 | if (letters[i] === available[i]) { 46 | answer[i] = 'x'; 47 | available[i] = ' '; 48 | } 49 | } 50 | 51 | // then find close matches (this has to happen 52 | // in a second step, otherwise an early close 53 | // match can prevent a later exact match) 54 | for (let i = 0; i < 5; i += 1) { 55 | if (answer[i] === '_') { 56 | const index = available.indexOf(letters[i]); 57 | if (index !== -1) { 58 | answer[i] = 'c'; 59 | available[index] = ' '; 60 | } 61 | } 62 | } 63 | 64 | this.answers.push(answer.join('')); 65 | 66 | return true; 67 | } 68 | 69 | /** 70 | * Serialize game state so it can be set as a cookie 71 | */ 72 | toString() { 73 | return `${this.index}-${this.guesses.join(' ')}-${this.answers.join(' ')}`; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/routes/sverdle/how-to-play/+page.svelte: -------------------------------------------------------------------------------- 1 | 2 | How to play Sverdle 3 | 4 | 5 | 6 |
7 |

How to play Sverdle

8 | 9 |

10 | Sverdle is a clone of Wordle, the 11 | word guessing game. To play, enter a five-letter English word. For example: 12 |

13 | 14 |
15 | r 16 | i 17 | t 18 | z 19 | y 20 |
21 | 22 |

23 | The y is in the right place. r and 24 | t 25 | are the right letters, but in the wrong place. The other letters are wrong, and can be discarded. 26 | Let's make another guess: 27 |

28 | 29 |
30 | p 31 | a 32 | r 33 | t 34 | y 35 |
36 | 37 |

This time we guessed right! You have six guesses to get the word.

38 | 39 |

40 | Unlike the original Wordle, Sverdle runs on the server instead of in the browser, making it 41 | impossible to cheat. It uses <form> and cookies to submit data, meaning you can 42 | even play with JavaScript disabled! 43 |

44 |
45 | 46 | 96 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/routes/sverdle/how-to-play/+page.ts: -------------------------------------------------------------------------------- 1 | import { dev } from '$app/environment'; 2 | 3 | // we don't need any JS on this page, though we'll load 4 | // it in dev so that we get hot module replacement 5 | export const csr = dev; 6 | 7 | // since there's no dynamic data here, we can prerender 8 | // it so that it gets served as a static asset in production 9 | export const prerender = true; 10 | -------------------------------------------------------------------------------- /e2e/sveltekit/src/routes/sverdle/reduced-motion.ts: -------------------------------------------------------------------------------- 1 | import { readable } from 'svelte/store'; 2 | import { browser } from '$app/environment'; 3 | 4 | const reduced_motion_query = '(prefers-reduced-motion: reduce)'; 5 | 6 | const get_initial_motion_preference = () => { 7 | if (!browser) return false; 8 | return window.matchMedia(reduced_motion_query).matches; 9 | }; 10 | 11 | export const reduced_motion = readable(get_initial_motion_preference(), (set) => { 12 | if (browser) { 13 | const set_reduced_motion = (event: MediaQueryListEvent) => { 14 | set(event.matches); 15 | }; 16 | const media_query_list = window.matchMedia(reduced_motion_query); 17 | media_query_list.addEventListener('change', set_reduced_motion); 18 | 19 | return () => { 20 | media_query_list.removeEventListener('change', set_reduced_motion); 21 | }; 22 | } 23 | }); 24 | -------------------------------------------------------------------------------- /e2e/sveltekit/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/svelteness/svelte-jester/161609a4bb3e67f9b55e5ace0dc3f9844b3178db/e2e/sveltekit/static/favicon.png -------------------------------------------------------------------------------- /e2e/sveltekit/static/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /e2e/sveltekit/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-auto' 2 | import { vitePreprocess } from '@sveltejs/kit/vite' 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | // Consult https://kit.svelte.dev/docs/integrations#preprocessors 7 | // for more information about preprocessors 8 | preprocess: vitePreprocess(), 9 | 10 | kit: { 11 | // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. 12 | // If your environment is not supported or you settled on a specific environment, switch out the adapter. 13 | // See https://kit.svelte.dev/docs/adapters for more information about adapters. 14 | adapter: adapter() 15 | } 16 | } 17 | 18 | export default config 19 | -------------------------------------------------------------------------------- /e2e/sveltekit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true 12 | }, 13 | "exclude": [ 14 | "src/**/*.spec.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /e2e/sveltekit/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "isolatedModules": false 5 | }, 6 | "exclude": [ 7 | "src/**" 8 | ], 9 | "include": [ 10 | "src/**/*.spec.ts" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /e2e/sveltekit/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite'; 2 | import { defineConfig } from 'vite'; 3 | 4 | export default defineConfig({ 5 | plugins: [sveltekit()] 6 | }); 7 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * For a detailed explanation regarding each configuration property and type check, visit: 3 | * https://jestjs.io/docs/en/configuration.html 4 | */ 5 | export default { 6 | coverageProvider: 'v8', 7 | 8 | moduleFileExtensions: ['js', 'cjs'], 9 | 10 | testMatch: ['**/?(*.)+(spec|test).?(c)[j]s?(x)'] 11 | } 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-jester", 3 | "version": "5.0.0", 4 | "description": "A Jest transformer for Svelte - compile your components before importing them into tests", 5 | "type": "module", 6 | "exports": "./dist/transformer.mjs", 7 | "license": "MIT", 8 | "engines": { 9 | "node": ">=18", 10 | "pnpm": "^8.0.0" 11 | }, 12 | "homepage": "https://github.com/svelteness/svelte-jester#readme", 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/svelteness/svelte-jester.git" 16 | }, 17 | "bugs": { 18 | "url": "https://github.com/svelteness/svelte-jester/issues" 19 | }, 20 | "keywords": [ 21 | "svelte-jester", 22 | "jest", 23 | "svelte", 24 | "sveltekit", 25 | "compile", 26 | "transformer", 27 | "preprocess", 28 | "test" 29 | ], 30 | "files": [ 31 | "dist/**/*" 32 | ], 33 | "scripts": { 34 | "build": "rollup -c rollup.config.cjs", 35 | "toc": "doctoc README.md", 36 | "lint": "standard --fix --env jest", 37 | "test": "pnpm test:esm && pnpm test:cjs", 38 | "test:esm": "pnpm build && cross-env NODE_OPTIONS=--experimental-vm-modules jest src/__tests__/transformer.test.js", 39 | "test:cjs": "pnpm build && jest src/__tests__/transformer.test.cjs", 40 | "e2e": "pnpm e2e:svelte-3 && pnpm e2e:svelte-4 && pnpm e2e:svelte-5 && pnpm e2e:sveltekit", 41 | "e2e:svelte-3": "cd e2e/svelte-3 && pnpm test", 42 | "e2e:svelte-4": "cd e2e/svelte-4 && pnpm test", 43 | "e2e:svelte-5": "cd e2e/svelte-5 && pnpm test", 44 | "e2e:sveltekit": "cd e2e/sveltekit && pnpm test", 45 | "test:nocache": "pnpm install && jest --clearCache && pnpm test -- --no-cache", 46 | "test:watch": "pnpm test -- --watch", 47 | "test:update": "pnpm test -- --updateSnapshot --coverage", 48 | "setup": "pnpm install && pnpm validate", 49 | "validate": "pnpm lint && pnpm test:nocache && pnpm e2e", 50 | "release": "standard-version" 51 | }, 52 | "standard-version": { 53 | "scripts": { 54 | "prerelease": "pnpm validate" 55 | } 56 | }, 57 | "peerDependencies": { 58 | "jest": ">= 27", 59 | "svelte": ">= 3" 60 | }, 61 | "devDependencies": { 62 | "@rollup/plugin-node-resolve": "^15.1.0", 63 | "@sveltejs/adapter-static": "^3.0.0", 64 | "@types/jest": "^29.5.3", 65 | "cross-env": "^7.0.3", 66 | "doctoc": "^2.2.1", 67 | "jest": "^29.6.1", 68 | "jest-circus": "^29.6.1", 69 | "rollup": "^3.26.3", 70 | "rollup-plugin-copy-assets": "^2.0.3", 71 | "sass": "^1.64.1", 72 | "standard": "^17.1.0", 73 | "standard-version": "^9.5.0", 74 | "svelte-preprocess": "^5.0.4", 75 | "typescript": "^5.1.6" 76 | }, 77 | "packageManager": "pnpm@8.6.5", 78 | "standard": { 79 | "globals": [ 80 | "jest", 81 | "it", 82 | "expect", 83 | "describe", 84 | "$state" 85 | ] 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - '.' 3 | - 'e2e/*' 4 | -------------------------------------------------------------------------------- /rollup.config.cjs: -------------------------------------------------------------------------------- 1 | const resolve = require('@rollup/plugin-node-resolve').default 2 | const copy = require('rollup-plugin-copy-assets') 3 | const pkg = require('./package.json') 4 | 5 | const external = [].concat( 6 | Object.keys(pkg.peerDependencies), 7 | 'svelte/compiler' 8 | ) 9 | 10 | const input = 'src/transformer.js' 11 | 12 | module.exports = [ 13 | { 14 | input, 15 | output: { 16 | file: 'dist/transformer.cjs', 17 | format: 'cjs', 18 | exports: 'default' 19 | }, 20 | external, 21 | plugins: [ 22 | resolve(), 23 | copy({ 24 | assets: [ 25 | 'src/preprocess.js' 26 | ] 27 | }) 28 | ] 29 | }, 30 | { 31 | input, 32 | output: { 33 | file: 'dist/transformer.mjs', 34 | format: 'esm' 35 | }, 36 | external, 37 | plugins: [ 38 | resolve() 39 | ] 40 | } 41 | ] 42 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/BasicComp.svelte: -------------------------------------------------------------------------------- 1 | 19 | 20 |

Hello {name}!

21 | 22 | 23 | {count} 24 | 25 | 26 | 27 | 28 | {nodeEnv} 29 | 30 | 41 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/SassComp.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
Hello {name}
6 | 7 | 16 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/TypescriptComp.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
Hello {name}
6 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/svelte.config.cjs: -------------------------------------------------------------------------------- 1 | const { replace } = require('svelte-preprocess') 2 | 3 | console.log('This should not influence the compiler/preprocessor') 4 | 5 | module.exports = { 6 | preprocess: [ 7 | replace([ 8 | [/Hello/gi, 'Bye'], 9 | // replace env var 10 | [/process\.env\.NODE_ENV/gi, JSON.stringify(process.env.NODE_ENV)] 11 | ]) 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/sveltekit.config.js: -------------------------------------------------------------------------------- 1 | import sveltePreprocess from 'svelte-preprocess' 2 | import adapter from '@sveltejs/adapter-static' 3 | const { replace } = sveltePreprocess 4 | 5 | console.log('This should not influence the compiler/preprocessor') 6 | 7 | const config = { 8 | kit: { 9 | adapter: adapter() 10 | }, 11 | preprocess: [ 12 | replace([ 13 | // strip style tag 14 | [/|([^]*?)<\/style>|\/>)/gi, ''], 15 | [/Hello/gi, 'Bye'], 16 | // replace env var 17 | [/process\.env\.NODE_ENV/gi, JSON.stringify(process.env.NODE_ENV)] 18 | ]) 19 | ] 20 | } 21 | export default config 22 | -------------------------------------------------------------------------------- /src/__tests__/transformer.test.cjs: -------------------------------------------------------------------------------- 1 | const { readFileSync } = require('fs') 2 | const { resolve } = require('path') 3 | 4 | const transformer = require('../../dist/transformer.cjs') 5 | 6 | const runTransformer = (filename, options) => { 7 | const path = require.resolve(`./fixtures/${filename}.svelte`) 8 | const source = readFileSync(path).toString() 9 | const result = transformer.process(source, path, { 10 | transformerConfig: { svelteVersion: '3', ...options } 11 | }) 12 | expect(result.code).toBeDefined() 13 | expect(result.code).toContain('SvelteComponent') 14 | expect(result.map).toBeDefined() 15 | return result.code 16 | } 17 | 18 | describe('CJS transformer', () => { 19 | it('should transform basic component', () => { 20 | runTransformer('BasicComp') 21 | }) 22 | 23 | it('should transform when using sass preprocessor', () => { 24 | runTransformer('SassComp', { preprocess: true }) 25 | }) 26 | 27 | it('should transform when using full path to preprocess', () => { 28 | const preprocessPath = resolve(__dirname, '../../_svelte.config.cjs') 29 | runTransformer('SassComp', { preprocess: preprocessPath }) 30 | }) 31 | 32 | it('should search for "svelte.config.cjs" as well as "svelte.config.js"', () => { 33 | const results = runTransformer('BasicComp', { preprocess: true, rootMode: 'upward' }) 34 | // this is a little brittle, but it demonstrates that the replacements in 35 | // "svelte.config.cjs" are working 36 | expect(results).toContain('text("Bye ");') 37 | }) 38 | 39 | it('should transform when using typescript preprocessor', () => { 40 | runTransformer('TypescriptComp', { preprocess: true }) 41 | }) 42 | 43 | it('should transform basic component and keep styles', () => { 44 | const code = runTransformer('BasicComp') 45 | expect(code).toContain('add_css(target)') 46 | expect(code).toContain('.counter.active') 47 | }) 48 | 49 | it('should accept compiler options', () => { 50 | const code = runTransformer('BasicComp', { compilerOptions: { css: false } }) 51 | expect(code).not.toContain('add_css(target)') 52 | expect(code).not.toContain('.counter.active') 53 | }) 54 | 55 | it('should output code to console when debug is true', () => { 56 | console.log = jest.fn() 57 | const code = runTransformer('BasicComp', { debug: true }) 58 | const esInterop = 'Object.defineProperty(exports, "__esModule", { value: true });' 59 | expect(console.log).toHaveBeenCalledWith(code.replace(esInterop, '')) 60 | }) 61 | 62 | it('should accept maxBuffer option for preprocess buffer limit', () => { 63 | expect( 64 | () => runTransformer('SassComp', { preprocess: true, maxBuffer: 1 }) 65 | ).toThrow(/^spawnSync .* ENOBUFS$/) 66 | runTransformer('SassComp', { preprocess: true, maxBuffer: 5 * 1024 * 1024 }) 67 | }) 68 | 69 | it('should fail, if console.logs are enabled during preprocessing and there is a console.log statement in the svelte config', () => { 70 | expect( 71 | () => runTransformer('BasicComp', { preprocess: true, rootMode: 'upward', showConsoleLog: true }) 72 | ).toThrow(/^Unexpected token .*T.*/) 73 | }) 74 | 75 | it('should pass, if console.logs are disabled (default) during preprocessing and there is a console.log statement in the svelte config', () => { 76 | runTransformer('BasicComp', { preprocess: true, rootMode: 'upward' }) 77 | }) 78 | 79 | it('should pass, if console.logs are disabled during preprocessing and there is a console.log statement in the svelte config', () => { 80 | runTransformer('BasicComp', { preprocess: true, rootMode: 'upward', showConsoleLog: false }) 81 | runTransformer('BasicComp', { preprocess: true, rootMode: 'upward', showConsoleLog: 'false' }) 82 | }) 83 | 84 | it('should pass and transform process.env.NODE_ENV variable', () => { 85 | const code = runTransformer('BasicComp', { preprocess: true, rootMode: 'upward' }) 86 | 87 | // JEST sets NODE_ENV to test automatically 88 | expect(code).toContain('test') 89 | }) 90 | }) 91 | -------------------------------------------------------------------------------- /src/__tests__/transformer.test.js: -------------------------------------------------------------------------------- 1 | import { readFileSync } from 'fs' 2 | import { dirname } from 'path' 3 | import { fileURLToPath } from 'url' 4 | import { jest } from '@jest/globals' 5 | 6 | import { isSvelte3 } from '../utils.js' 7 | import transformer from '../../dist/transformer.mjs' 8 | 9 | // Node API __dirname is missing in ESM 10 | export const __dirname = dirname(fileURLToPath(import.meta.url)) 11 | 12 | const runTransformer = async (filename, options) => { 13 | const path = `${__dirname}/fixtures/${filename}.svelte` 14 | const source = readFileSync(path).toString() 15 | const result = await transformer.processAsync(source, path, { transformerConfig: options }) 16 | expect(result.code).toBeDefined() 17 | expect(result.code).toContain('SvelteComponent') 18 | expect(result.map).toBeDefined() 19 | return result.code 20 | } 21 | 22 | describe('ESM transformer', () => { 23 | it('should transform with config in ESM format', async () => { 24 | const svelteKitConfigPath = `${__dirname}/fixtures/sveltekit.config.js` 25 | const results = await runTransformer('BasicComp', { 26 | preprocess: svelteKitConfigPath 27 | }) 28 | // this is a little brittle, but it demonstrates that the replacements in 29 | // "sveltekit.config.js" are working 30 | expect(results).toContain('text("Bye ");') 31 | }) 32 | 33 | it('should transform basic component', async () => { 34 | await runTransformer('BasicComp') 35 | }) 36 | 37 | it('should transform when using sass preprocessor', async () => { 38 | await runTransformer('SassComp', { preprocess: true }) 39 | }) 40 | 41 | it('should transform when using full path to preprocess', async () => { 42 | const preprocessPath = `${__dirname}/../../_svelte.config.cjs` 43 | await runTransformer('SassComp', { preprocess: preprocessPath }) 44 | }) 45 | 46 | it('should search for "svelte.config.cjs" as well as "svelte.config.js"', async () => { 47 | const results = await runTransformer('BasicComp', { 48 | preprocess: true, 49 | rootMode: 'upward' 50 | }) 51 | // this is a little brittle, but it demonstrates that the replacements in 52 | // "svelte.config.cjs" are working 53 | expect(results).toContain('text("Bye ");') 54 | }) 55 | 56 | it('should transform when using typescript preprocessor', async () => { 57 | await runTransformer('TypescriptComp', { preprocess: true }) 58 | }) 59 | 60 | it('should transform basic component and keep styles', async () => { 61 | const code = await runTransformer('BasicComp') 62 | expect(code).toContain('add_css(target)') 63 | expect(code).toContain('.counter.active') 64 | }) 65 | 66 | it('should accept compiler options', async () => { 67 | const code = await runTransformer('BasicComp', { 68 | compilerOptions: { css: isSvelte3() ? false : 'external' } 69 | }) 70 | expect(code).not.toContain('add_css(target)') 71 | expect(code).not.toContain('.counter.active') 72 | }) 73 | 74 | it('should output code to console when debug is true', async () => { 75 | console.log = jest.fn() 76 | const code = await runTransformer('BasicComp', { debug: true }) 77 | const esInterop = 78 | 'Object.defineProperty(exports, "__esModule", { value: true });' 79 | expect(console.log).toHaveBeenCalledTimes(1) 80 | expect(console.log).toHaveBeenCalledWith(code.replace(esInterop, '')) 81 | }) 82 | 83 | it('should pass, if console.logs are disabled (default) during preprocessing and there is a console.log statement in the svelte config', async () => { 84 | await runTransformer('BasicComp', { preprocess: true, rootMode: 'upward' }) 85 | }) 86 | 87 | it('should pass, if console.logs are disabled during preprocessing and there is a console.log statement in the svelte config', async () => { 88 | await runTransformer('BasicComp', { 89 | preprocess: true, 90 | rootMode: 'upward', 91 | showConsoleLog: false 92 | }) 93 | await runTransformer('BasicComp', { 94 | preprocess: true, 95 | rootMode: 'upward', 96 | showConsoleLog: 'false' 97 | }) 98 | }) 99 | 100 | it('should pass and transform process.env.NODE_ENV variable', async () => { 101 | const code = await runTransformer('BasicComp', { 102 | preprocess: true, 103 | rootMode: 'upward' 104 | }) 105 | 106 | // JEST sets NODE_ENV to test automatically 107 | expect(code).toContain('test') 108 | }) 109 | }) 110 | -------------------------------------------------------------------------------- /src/preprocess.js: -------------------------------------------------------------------------------- 1 | import { preprocess } from 'svelte/compiler' 2 | import { pathToFileURL } from 'url' 3 | 4 | const { source, filename, svelteConfig, showConsoleLog } = process.env 5 | 6 | // convert option string to boolean 7 | const showConsoleLogOption = showConsoleLog && showConsoleLog.toLowerCase() === 'true' 8 | 9 | // redefine console.log to hide its output, so it does not interfere with the svelte-compiler 10 | if (!showConsoleLogOption && console) { 11 | console.log = console.error = console.info = console.debug = console.warn = console.trace = console.dir = console.dirxml = console.group = console.groupEnd = console.time = console.timeEnd = console.assert = console.profile = () => {} 12 | } 13 | 14 | import(pathToFileURL(svelteConfig)).then(configImport => { 15 | // ESM or CommonJS 16 | const config = configImport.default ? configImport.default : configImport 17 | 18 | preprocess(source, config.preprocess || {}, { filename }).then((r) => { 19 | process.stdout.write(JSON.stringify(r)) 20 | }) 21 | }).catch(err => process.stderr.write(err)) 22 | -------------------------------------------------------------------------------- /src/svelteconfig.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import path from 'path' 3 | 4 | const configFilenames = ['svelte.config.js', 'svelte.config.cjs'] 5 | 6 | export function getSvelteConfig (rootMode, filename, preprocess) { 7 | let configFile = null 8 | 9 | if (typeof preprocess === 'boolean') { 10 | configFile = 11 | rootMode === 'upward' 12 | ? findConfigFile(path.dirname(filename)) 13 | : getConfigFile(process.cwd()) 14 | } else if (typeof preprocess === 'string') { 15 | configFile = preprocess 16 | } 17 | 18 | if (configFile === null || !fs.existsSync(configFile)) { 19 | throw Error( 20 | `Could not find ${configFilenames.join(' or ')} or ${configFile}.` 21 | ) 22 | } 23 | 24 | return configFile 25 | } 26 | 27 | const getConfigFile = (searchDir) => { 28 | for (const configFilename of configFilenames) { 29 | const filePath = path.resolve(searchDir, configFilename) 30 | if (fs.existsSync(filePath)) { 31 | return filePath 32 | } 33 | } 34 | 35 | return null 36 | } 37 | 38 | const findConfigFile = (searchDir) => { 39 | const filePath = getConfigFile(searchDir) 40 | if (filePath !== null) { 41 | return filePath 42 | } 43 | 44 | const parentDir = path.resolve(searchDir, '..') 45 | return parentDir !== searchDir ? findConfigFile(parentDir) : null // Stop walking at filesystem root 46 | } 47 | -------------------------------------------------------------------------------- /src/transformer.js: -------------------------------------------------------------------------------- 1 | import { execSync } from 'child_process' 2 | import { basename, extname } from 'path' 3 | import { pathToFileURL } from 'url' 4 | import * as SvelteCompiler from 'svelte/compiler' 5 | 6 | import { getSvelteConfig } from './svelteconfig.js' 7 | import { dynamicImport, IS_COMMON_JS, isSvelte3, isSvelteModule } from './utils.js' 8 | 9 | const currentFileExtension = (global.__dirname !== undefined ? extname(__filename) : extname(pathToFileURL(import.meta.url).toString())).replace('.', '') 10 | 11 | /** 12 | * Jest will only call this method when running in ESM mode. 13 | */ 14 | const processAsync = async (source, filename, jestOptions) => { 15 | const options = jestOptions && jestOptions.transformerConfig ? jestOptions.transformerConfig : {} 16 | const { preprocess, rootMode, debug } = options 17 | 18 | if (IS_COMMON_JS) { 19 | throw new Error('Running svelte-jester-transformer async in unsupported CJS mode') 20 | } 21 | 22 | if (debug) { 23 | console.debug(`Running svelte-jester-transformer async in mode ${currentFileExtension}.`) 24 | } 25 | 26 | if (!preprocess) { 27 | return compiler('esm', options, filename, source) 28 | } 29 | 30 | const svelteConfigPath = getSvelteConfig(rootMode, filename, preprocess) 31 | const svelteConfig = await dynamicImport(svelteConfigPath) 32 | const processed = await SvelteCompiler.preprocess( 33 | source, 34 | svelteConfig.default.preprocess || {}, 35 | { filename } 36 | ) 37 | 38 | return compiler('esm', options, filename, processed.code, processed.map) 39 | } 40 | 41 | /** 42 | * Starts a new process, so it has a higher overhead than processAsync. 43 | * However, Jest calls this method in CJS mode. 44 | */ 45 | const processSync = (source, filename, jestOptions) => { 46 | const options = jestOptions && jestOptions.transformerConfig ? jestOptions.transformerConfig : {} 47 | const { preprocess, rootMode, maxBuffer, showConsoleLog, debug, svelteVersion } = options 48 | 49 | if (!isSvelte3(svelteVersion)) { 50 | throw new Error('Jest is being called in CJS mode. You must use ESM mode in Svelte 4+') 51 | } 52 | 53 | if (!IS_COMMON_JS) { 54 | throw new Error('Running svelte-jester-transformer sync in unsupported ESM mode') 55 | } 56 | 57 | if (debug) { 58 | console.debug(`Running svelte-jester-transformer sync in mode ${currentFileExtension}.`) 59 | } 60 | 61 | if (!preprocess) { 62 | return compiler('cjs', options, filename, source) 63 | } 64 | 65 | const svelteConfig = getSvelteConfig(rootMode, filename, preprocess) 66 | const preprocessor = require.resolve('./preprocess.js') 67 | 68 | const preprocessResult = execSync( 69 | `node --unhandled-rejections=strict --abort-on-uncaught-exception "${preprocessor}"`, 70 | { 71 | env: { ...process.env, source, filename, svelteConfig, showConsoleLog }, 72 | maxBuffer: maxBuffer || 10 * 1024 * 1024 73 | } 74 | ).toString() 75 | 76 | const parsedPreprocessResult = JSON.parse(preprocessResult) 77 | return compiler('cjs', options, filename, parsedPreprocessResult.code, parsedPreprocessResult.map) 78 | } 79 | 80 | const compiler = (format, options = {}, filename, processedCode, processedMap) => { 81 | const opts = { 82 | filename: basename(filename), 83 | css: isSvelte3(options.svelteVersion) ? true : 'injected', 84 | accessors: true, 85 | dev: true, 86 | sourcemap: processedMap, 87 | ...options.compilerOptions 88 | } 89 | 90 | if (isSvelte3(options.svelteVersion)) { 91 | opts.format = format 92 | } 93 | 94 | const compile = isSvelteModule(filename) ? compileModule : compileComponent 95 | 96 | let result 97 | try { 98 | result = compile(processedCode, opts) 99 | } catch (error) { 100 | let msg = error.message 101 | if (error.frame) { 102 | msg += '\n' + error.frame 103 | } 104 | console.error(msg) 105 | throw error 106 | } 107 | 108 | if (options.debug) { 109 | console.log(result.js.code) 110 | } 111 | 112 | const esInterop = format === 'cjs' ? 'Object.defineProperty(exports, "__esModule", { value: true });' : '' 113 | 114 | return { 115 | code: result.js.code + esInterop, 116 | map: JSON.stringify(result.js.map) 117 | } 118 | } 119 | 120 | const compileComponent = (processedCode, opts) => { 121 | return SvelteCompiler.compile(processedCode, opts) 122 | } 123 | 124 | const compileModule = (processedCode, opts) => { 125 | return SvelteCompiler.compileModule(processedCode, { 126 | filename: opts.filename, 127 | dev: opts.dev, 128 | generate: opts.ssr ? 'server' : 'client' 129 | }) 130 | } 131 | 132 | export default { 133 | process: processSync, 134 | processAsync 135 | } 136 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | import { pathToFileURL } from 'url' 2 | import * as SvelteCompiler from 'svelte/compiler' 3 | 4 | export const dynamicImport = async (filename) => import(pathToFileURL(filename).toString()) 5 | 6 | export const IS_COMMON_JS = typeof module !== 'undefined' 7 | 8 | export const isSvelte3 = (version = SvelteCompiler.VERSION) => version.startsWith('3') 9 | 10 | const DEFAULT_SVELTE_MODULE_INFIX = ['.svelte.'] 11 | 12 | const DEFAULT_SVELTE_MODULE_EXT = ['.js', '.ts'] 13 | 14 | export const isSvelteModule = (filename) => 15 | typeof SvelteCompiler.compileModule === 'function' && 16 | DEFAULT_SVELTE_MODULE_INFIX.some((infix) => filename.includes(infix)) && 17 | DEFAULT_SVELTE_MODULE_EXT.some((ext) => filename.endsWith(ext)) 18 | -------------------------------------------------------------------------------- /svelte.config.cjs: -------------------------------------------------------------------------------- 1 | const sveltePreprocess = require('svelte-preprocess') 2 | 3 | module.exports = { preprocess: sveltePreprocess() } 4 | --------------------------------------------------------------------------------