From 831d2afc934c0905ffbe11ba2fcaa21276e13859 Mon Sep 17 00:00:00 2001
From: Ross MacPhee <10212476+rossyman@users.noreply.github.com>
Date: Mon, 29 Mar 2021 22:40:31 +0100
Subject: [PATCH] Initialise Svelte Jest adder
---
.gitignore | 79 ++-------------
README.md | 84 +++++++++++++++-
package.json | 25 +++++
preset.ts | 201 +++++++++++++++++++++++++++++++++++++
templates/.babelrc | 12 +++
templates/index.spec.js | 8 ++
templates/jest.config.json | 11 ++
7 files changed, 345 insertions(+), 75 deletions(-)
create mode 100644 package.json
create mode 100644 preset.ts
create mode 100644 templates/.babelrc
create mode 100644 templates/index.spec.js
create mode 100644 templates/jest.config.json
diff --git a/.gitignore b/.gitignore
index 6704566..8a97ee8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,9 +2,6 @@
logs
*.log
npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
@@ -15,34 +12,9 @@ pids
*.seed
*.pid.lock
-# Directory for instrumented libs generated by jscoverage/JSCover
-lib-cov
-
-# Coverage directory used by tools like istanbul
-coverage
-*.lcov
-
-# nyc test coverage
-.nyc_output
-
-# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
-.grunt
-
-# Bower dependency directory (https://bower.io/)
-bower_components
-
-# node-waf configuration
-.lock-wscript
-
-# Compiled binary addons (https://nodejs.org/api/addons.html)
-build/Release
-
-# Dependency directories
+# Dependencies
node_modules/
-jspm_packages/
-
-# TypeScript v1 declaration files
-typings/
+package-lock.json
# TypeScript cache
*.tsbuildinfo
@@ -53,52 +25,13 @@ typings/
# Optional eslint cache
.eslintcache
-# Microbundle cache
-.rpt2_cache/
-.rts2_cache_cjs/
-.rts2_cache_es/
-.rts2_cache_umd/
-
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
-# Yarn Integrity file
-.yarn-integrity
-
-# dotenv environment variables file
-.env
-.env.test
-
-# parcel-bundler cache (https://parceljs.org/)
-.cache
-
-# Next.js build output
-.next
-
-# Nuxt.js build / generate output
-.nuxt
-dist
-
-# Gatsby files
-.cache/
-# Comment in the public line in if your project uses Gatsby and *not* Next.js
-# https://nextjs.org/blog/next-9-1#public-directory-support
-# public
-
-# vuepress build output
-.vuepress/dist
-
-# Serverless directories
-.serverless/
-
-# FuseBox cache
-.fusebox/
-
-# DynamoDB Local files
-.dynamodb/
-
-# TernJS port file
-.tern-port
+# IDE Specific files
+.idea/
+.vscode/
+.history/
diff --git a/README.md b/README.md
index 1de74ba..4290911 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,82 @@
-# svelte-add-jest
-SvelteKit adder for Jest unit testing
+
Welcome to svelte-add-jest 👋
+
+
+
+
+
+
+
+## ❓ What is this?
+
+This is an **experimental** command to run to add Jest to your SvelteKit project.
+
+## 🛠 Usage
+
+You must start with a fresh copy of the official SvelteKit template, which is currently created by running this command:
+
+```sh
+npm init svelte@next
+```
+
+Once that is set up, run this command in your project directory to set up Jest:
+
+```sh
+npx svelte-add jest
+```
+
+After the preset runs,
+
+- You can apply _another_ [Svelte Adder](https://github.com/svelte-add/svelte-adders) to your project for more functionality.
+
+### ⚙️ Options
+
+| Description | Flag | Negated | Default |
+|----------------------|-----------------------------|--------------------------------|-----------------|
+| Interactive Mode | `--interaction` | `--no-interaction` | True |
+| Jest DOM Support | `--jest-dom` | `--no-jest-dom` | True |
+| Generate Example | `--examples` | `--no-examples` | True |
+
+## 👀 See Also
+
+- [Svelte Testing Library Docs](https://testing-library.com/docs/svelte-testing-library/intro/)
+- [Jest DOM](https://github.com/testing-library/jest-dom#usage)
+- [Jest](https://jestjs.io)
+
+## 🤝 Contributing
+
+Contributions, issues and feature requests are welcome!
Feel free to check [issues page](https://github.com/rossyman/svelte-add-jest/issues).
+
+### 😵 Help! I have a question
+
+[Create an issue](https://github.com/svelte-add/jest/issues/new) and we'll try to help.
+
+### 😡 Fix! There is something that needs improvement
+
+[Create an issue](https://github.com/rossyman/svelte-add-jest/issues/new) or [pull request](https://github.com/rossyman/svelte-add-jest/pulls) and we'll try to fix.
+
+These are new tools, so there are likely to be problems in this project. Thank you for bringing them to our attention or fixing them for us.
+
+## Show your support
+
+Give a ⭐️ if this project helped you!
+
+## Author
+
+👤 **Ross MacPhee**
+
+- Twitter: [@rossco___](https://twitter.com/rossco___)
+- Github: [@rossyman](https://github.com/rossyman)
+- LinkedIn: [@ross-macphee](https://linkedin.com/in/ross-macphee)
+
+👤 **Brady Wiggins**
+
+- Github: [@FractalHQ](https://github.com/FractalHQ)
+
+## 📝 License
+
+Copyright © 2021 - Ross MacPhee & Brady Wiggins.
+This project is [MIT](https://github.com/rossyman/svelte-add-jest/blob/main/LICENSE) licensed.
+
+---
+
+_This README was generated with ❤️ by [readme-md-generator](https://github.com/kefranabg/readme-md-generator)_
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..a33c365
--- /dev/null
+++ b/package.json
@@ -0,0 +1,25 @@
+{
+ "private": true,
+ "name": "@rossyman/svelte-add-jest",
+ "version": "1.0.0",
+ "description": "SvelteKit adder for Jest unit testing",
+ "license": "MIT",
+ "keywords": [
+ "svelte",
+ "sveltekit",
+ "svelte-kit",
+ "jest",
+ "unit-test",
+ "test"
+ ],
+ "repository": "github:rossyman/svelte-add-jest",
+ "bugs": "https://github.com/rossyman/svelte-add-jest/issues",
+ "contributors": [
+ "Ross MacPhee (https://github.com/rossyman)",
+ "Brady Wiggins (https://github.com/FractalHQ)"
+ ],
+ "preset": "preset.ts",
+ "devDependencies": {
+ "apply": "^0.2.13"
+ }
+}
diff --git a/preset.ts b/preset.ts
new file mode 100644
index 0000000..cdd7c9b
--- /dev/null
+++ b/preset.ts
@@ -0,0 +1,201 @@
+import { Preset, color } from 'apply';
+
+type Dependencies = {
+ [key: string]: {
+ version: string;
+ type?: 'DEV' | 'PEER';
+ reliesOn?: string;
+ }
+}
+
+type Configuration = {
+ [key: string]: {
+ message: string;
+ default: any;
+ question?: true;
+ }
+}
+
+/**
+ * Svelte adder utility class.
+ *
+ * Used to simplify interaction with Preset and approach
+ * file-structure modification in a configuration-based way.
+ */
+abstract class Adder {
+
+ /**
+ * The adder's name, which is displayed as the name
+ * of the Preset. Specified on the implementation level.
+ *
+ * @protected
+ */
+ protected abstract readonly ADDER_NAME: string;
+
+ /**
+ * A dictionary of configuration options. Each option
+ * will either be determined interactively; when the
+ * `--interaction` flag is present, or through CLI flags.
+ *
+ * @protected
+ */
+ protected abstract readonly CONFIGURATION: Configuration;
+
+ /**
+ * A dictionary of required dependencies. Each dependency
+ * has an associated version, and the type can be either
+ * explicitly set as 'DEV' or 'PEER', or implicitly
+ * inferred as a core dependency when left `undefined`.
+ *
+ * Each dependency can also specify whether or not they
+ * should be installed based on the presence of a
+ * configuration option, defined in `CONFIGURATION`.
+ *
+ * @protected
+ */
+ protected abstract readonly REQUIRED_DEPENDENCIES: Dependencies;
+
+ /**
+ * Runs an adder. Initialises all configuration and
+ * dependencies, followed by running the implementation
+ * specific functionality.
+ */
+ run(): void {
+ this.initialiseAdder();
+ }
+
+ /**
+ * Safely extracts a file, ensuring the user acknowledges
+ * that their previously defined data will be overwritten.
+ *
+ * @param title The title of the specific action being
+ * performed.
+ * @param filename The filename to move from the templates
+ * folder.
+ * @protected
+ */
+ protected safeExtract(title: string, filename: string) {
+ return Preset.extract(filename).whenConflict('ask').withTitle(title);
+ }
+
+ protected getConfiguration(key): T {
+ return Preset.isInteractive() ? Preset.prompts[key] : Preset.options[key];
+ }
+
+ private initialiseAdder(): void {
+ Preset.setName(this.ADDER_NAME);
+ this.setupConfiguration();
+ this.setupDependencies();
+ }
+
+ private setupConfiguration(): void {
+
+ Object.keys(this.CONFIGURATION).forEach(configurationKey => {
+
+ const configuration = this.CONFIGURATION[configurationKey];
+
+ this.configure(
+ configurationKey,
+ configuration.message,
+ configuration.default,
+ configuration.question || false
+ );
+ });
+ }
+
+ private setupDependencies(): void {
+
+ Preset.group(preset => {
+
+ Object.keys(this.REQUIRED_DEPENDENCIES).forEach(dependencyName => {
+
+ const dependencyConfig = this.REQUIRED_DEPENDENCIES[dependencyName];
+
+ let action;
+
+ switch (dependencyConfig.type) {
+ case 'DEV':
+ action = preset.editNodePackages().addDev(dependencyName, dependencyConfig.version);
+ break;
+ case 'PEER':
+ action = preset.editNodePackages().addPeer(dependencyName, dependencyConfig.version);
+ break;
+ case undefined:
+ action = preset.editNodePackages().add(dependencyName, dependencyConfig.version);
+ break;
+ }
+
+ action.if(() => dependencyConfig.reliesOn
+ ? this.getConfiguration(dependencyConfig.reliesOn)
+ : true
+ );
+ });
+
+ }).withTitle('Adding required dependencies');
+ }
+
+ private configure(key: string, msg: string, init: any, confirm: boolean): void {
+
+ Preset
+ .group(preset => {
+ preset.confirm(key, msg, init).if(() => confirm);
+ preset.input(key, msg, init).if(() => !confirm);
+ })
+ .withoutTitle()
+ .ifInteractive();
+
+ Preset
+ .group(preset => preset.option(key, init))
+ .withoutTitle()
+ .if(() => !Preset.isInteractive());
+ }
+}
+
+class SvelteJestAdder extends Adder {
+
+ protected readonly ADDER_NAME = '@rossyman/svelte-add-jest';
+
+ protected readonly CONFIGURATION: Configuration = {
+ 'jest-dom': {message: 'Enable Jest DOM support?', default: true, question: true},
+ 'examples': {message: 'Generate example test file?', default: true, question: true}
+ };
+
+ protected readonly REQUIRED_DEPENDENCIES: Dependencies = {
+ '@babel/core': {version: '^7.13.0', type: 'DEV'},
+ '@babel/preset-env': {version: '^7.13.0', type: 'DEV'},
+ 'jest': {version: '^26.6.0', type: 'DEV'},
+ 'babel-jest': {version: '^26.6.0', type: 'DEV'},
+ 'svelte-jester': {version: '^1.3.0', type: 'DEV'},
+ '@testing-library/svelte': {version: '^3.0.0', type: 'DEV'},
+ '@testing-library/jest-dom': {version: '^5.11.0', type: 'DEV', reliesOn: 'jest-dom'},
+ };
+
+ run(): void {
+
+ super.run();
+
+ this.safeExtract('Initializing Jest config', 'jest.config.json');
+ this.safeExtract('Initializing Babel config', '.babelrc');
+
+ Preset
+ .editJson('jest.config.json')
+ .merge({setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect']})
+ .withTitle('Enabling Jest DOM Support')
+ .if(() => this.getConfiguration('jest-dom'));
+
+ this.safeExtract('Initializing example test file', 'index.spec.js')
+ .to('src/routes/')
+ .if(() => this.getConfiguration('examples') && this.getConfiguration('jest-dom'));
+
+ Preset
+ .editJson('package.json')
+ .merge({scripts: {'test': 'jest src --config jest.config.json', 'test:watch': 'npm run test -- --watch'}})
+ .withTitle('Adding test scripts to package.json');
+
+ Preset
+ .instruct(`Run ${color.magenta("npm install")}, ${color.magenta("pnpm install")}, or ${color.magenta("yarn")} to install dependencies`)
+ .withHeading("What's next?");
+ }
+}
+
+new SvelteJestAdder().run();
diff --git a/templates/.babelrc b/templates/.babelrc
new file mode 100644
index 0000000..522c7e1
--- /dev/null
+++ b/templates/.babelrc
@@ -0,0 +1,12 @@
+{
+ "presets": [
+ [
+ "@babel/preset-env",
+ {
+ "targets": {
+ "node": "current"
+ }
+ }
+ ]
+ ]
+}
\ No newline at end of file
diff --git a/templates/index.spec.js b/templates/index.spec.js
new file mode 100644
index 0000000..3315722
--- /dev/null
+++ b/templates/index.spec.js
@@ -0,0 +1,8 @@
+import "@testing-library/jest-dom/extend-expect";
+import { render } from "@testing-library/svelte";
+import index from "./index.svelte";
+
+test("shows proper heading when rendered", () => {
+ const { getByText } = render(index);
+ expect(getByText("Hello world!")).toBeInTheDocument();
+});
diff --git a/templates/jest.config.json b/templates/jest.config.json
new file mode 100644
index 0000000..4907484
--- /dev/null
+++ b/templates/jest.config.json
@@ -0,0 +1,11 @@
+{
+ "transform": {
+ "^.+\\.js$": "babel-jest",
+ "^.+\\.svelte$": "svelte-jester"
+ },
+ "moduleNameMapper": {
+ "^\\$lib(.*)$": "/src/lib$1",
+ "^\\$app(.*)$": [".svelte/dev/runtime/app/*", ".svelte/build/runtime/app/*"]
+ },
+ "moduleFileExtensions": ["js", "svelte"]
+}