├── .babelrc.js ├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .prettierrc ├── README.md ├── examples └── jest │ ├── .babelrc.js │ ├── .gitignore │ ├── README.md │ ├── jest.config.js │ ├── package-lock.json │ ├── package.json │ ├── public │ ├── crops │ │ ├── crops-1.json │ │ ├── crops-10.json │ │ ├── crops-2.json │ │ ├── crops-3.json │ │ ├── crops-4.json │ │ ├── crops-5.json │ │ ├── crops-6.json │ │ ├── crops-7.json │ │ ├── crops-8.json │ │ └── crops-9.json │ └── index.html │ ├── rollup.config.js │ ├── src │ ├── App.svelte │ ├── get.js │ ├── less.js │ └── main.js │ ├── test │ ├── app.test.js │ └── mockData.js │ └── yarn.lock ├── jest.config.js ├── package.json ├── preprocess.js ├── require.js ├── rollup.config.js ├── src └── render.js ├── test ├── Hello.test.js ├── Hello10.test.js ├── Hello11.test.js ├── Hello2.test.js ├── Hello3.test.js ├── Hello4.test.js ├── Hello5.test.js ├── Hello6.test.js ├── Hello7.test.js ├── Hello8.test.js ├── Hello9.test.js ├── Input.test.js ├── compilerOptions.test.js ├── index.test.js ├── less.js ├── require-hook.js ├── src │ ├── components │ │ ├── Compiler.svelte │ │ ├── Hello.svelte │ │ ├── Inputs.svelte │ │ ├── List.svelte │ │ └── Nav.svelte │ └── routes │ │ └── index.svelte └── util.js ├── transform.js └── yarn.lock /.babelrc.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | 4 | return { 5 | presets: ['@babel/preset-env'], 6 | plugins: ['@babel/plugin-transform-runtime'], 7 | }; 8 | }; 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | indent_style = space 7 | indent_size = 2 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | 11 | [test/**/expected.css] 12 | insert_final_newline = false 13 | 14 | [{package.json,.travis.yml,.eslintrc.json}] 15 | indent_style = space 16 | indent_size = 2 -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "rules": { 4 | "indent": [2, 2, { "SwitchCase": 1 }], 5 | "semi": [2, "always"], 6 | "keyword-spacing": [2, { "before": true, "after": true }], 7 | "space-before-blocks": [2, "always"], 8 | "no-mixed-spaces-and-tabs": [2, "smart-tabs"], 9 | "no-cond-assign": 0, 10 | "no-unused-vars": 2, 11 | "object-shorthand": [2, "always"], 12 | "no-const-assign": 2, 13 | "no-class-assign": 2, 14 | "no-this-before-super": 2, 15 | "no-var": 2, 16 | "no-unreachable": 2, 17 | "valid-typeof": 2, 18 | "quote-props": [2, "as-needed"], 19 | "one-var": 0, 20 | "prefer-arrow-callback": 2, 21 | "prefer-const": [2, { "destructuring": "all" }], 22 | "arrow-spacing": 2, 23 | "no-inner-declarations": 0, 24 | "@typescript-eslint/explicit-function-return-type": 0 25 | }, 26 | "overrides": [ 27 | { 28 | "files": ["**.ts"], 29 | "rules": { 30 | "import/export": 0, 31 | "import/no-unresolved": 0 32 | } 33 | }, 34 | { 35 | "files": ["**.js"], 36 | "rules": { 37 | "@typescript-eslint/camelcase": 0 38 | } 39 | } 40 | ], 41 | "env": { 42 | "es6": true, 43 | "browser": true, 44 | "node": true, 45 | "jest": true 46 | }, 47 | "extends": [ 48 | "eslint:recommended", 49 | "plugin:import/errors", 50 | "plugin:import/warnings", 51 | "prettier" 52 | ], 53 | "plugins": ["import", "svelte3", "jsdoc"], 54 | "parserOptions": { 55 | "ecmaVersion": 6, 56 | "sourceType": "module" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # macOS stuff 2 | .DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | 6 | # duh 7 | /node_modules/ 8 | 9 | # build 10 | /dist 11 | 12 | # logs 13 | logs 14 | *.log 15 | npm-debug.log* 16 | yarn-debug.log* 17 | yarn-error.log* 18 | 19 | # testy stuff 20 | coverage 21 | .nyc_output 22 | 23 | # editor 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { "useTabs": false, "singleQuote": true, "trailingComma": "es5" } 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # svelte-test 2 | 3 | Transforms and examples for testing Svelte components. 4 | 5 | There are details on the transforms below. You can view example test setups in [`/examples/`](https://github.com/pngwn/svelte-test/tree/master/examples/). 6 | 7 | --- 8 | 9 | - [I am using Jest](#svelte-testtransform) 10 | - [I am not using Jest](#svelte-testrequire) 11 | 12 | --- 13 | 14 | ## svelte-test/transform 15 | 16 | Install `jest` and `svelte-test`. 17 | 18 | ```bash 19 | yarn add --dev jest svelte-test # or npm i -D jest 20 | ``` 21 | 22 | In your jest config file add `svelte-test/transform` as a transform for Svelte components (whatever file extension you use). Add any preprocessors to `globals.svelte.preprocess` and any custom compiler options to `globals.svelte.compilerOptions`. Your Jest config file will need to be a javascript file. 23 | 24 | The `jest.config.js` should look something like this: 25 | 26 | ```js 27 | module.exports = { 28 | testPathIgnorePatterns: ['/node_modules/', '/cypress/'], 29 | transform: { 30 | '^.+\\.svelte$': 'svelte-test/transform', 31 | }, 32 | globals: { 33 | svelte: { 34 | preprocess: preprocess(), 35 | compilerOptions: { 36 | accessors: true, 37 | }, 38 | }, 39 | }, 40 | }; 41 | ``` 42 | 43 | ### babel? 44 | 45 | You will probably need to install babel as well, to save you a lifetime of hell I will provide basic instructions. 46 | 47 | Install `babel-jest`, `@babel/core`, and `@babel/preset-env`. 48 | 49 | ```bash 50 | yarn add --dev babel-jest @babel/core @babel/preset-env #or npm i ... 51 | ``` 52 | 53 | Create a `babel.config.js` that looks like this: 54 | 55 | ```js 56 | module.exports = function(api) { 57 | api.cache(true); 58 | 59 | return { 60 | presets: [ 61 | [ 62 | '@babel/preset-env', 63 | { 64 | targets: { 65 | node: 'current', 66 | }, 67 | }, 68 | ], 69 | ], 70 | }; 71 | }; 72 | ``` 73 | 74 | ### success! 75 | 76 | You can now do this in your tests: 77 | 78 | ```js 79 | import App from '../App.svelte'; 80 | 81 | test('The component should exist', () => { 82 | const component = new App({ target: document.body }); 83 | 84 | expect(component).toBeTruthy(); 85 | }); 86 | ``` 87 | 88 | You may now go on with your life. 89 | 90 | ## svelte-test/require 91 | 92 | If you are not using jest you can still hook into node `require`s and get back a real, _genuine_, compiled component. What you do with that component is your business. 93 | 94 | Install `require-extension-hooks` and `svelte-test`: 95 | 96 | ```bash 97 | yarn add --dev require-extension-hooks svelte-test # or npm i ... 98 | ``` 99 | 100 | Wherever you are doing your magic, import `require-extension-hooks` and `svelte-test/require`. 101 | 102 | ```js 103 | const hooks = require('require-extension-hooks'); 104 | const svelte = require('svelte-test/require'); 105 | ``` 106 | 107 | You need to pass the `svelte()` function the _absolute path_ to your preprocessors as the first argument and any compiler options as the second argument, I haven't completely thought through the API so this may change in the future. You can then `push` the svelte function as a require hook for your component file extension like so: 108 | 109 | ```js 110 | const hooks = require('require-extension-hooks'); 111 | const svelte = require('svelte-test/require'); 112 | const { join } = require('path'); 113 | 114 | const preprocessors = join(__dirname, './less.js'); 115 | const compilerOptions = { accessors: true }; 116 | 117 | const extensionHook = svelte(preprocessors, compilerOptions); 118 | 119 | hooks('.svelte').push(extensionHook); 120 | 121 | // You can just require it 122 | const App = require('./App.svelte'); 123 | 124 | // This is now a constructor function as expected. 125 | const app = new App(options); 126 | ``` 127 | -------------------------------------------------------------------------------- /examples/jest/.babelrc.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | module.exports = function (api) { 4 | api.cache(true); 5 | 6 | return { 7 | "presets": ["@babel/preset-env"], 8 | "plugins": ["@babel/plugin-transform-runtime"] 9 | }; 10 | } -------------------------------------------------------------------------------- /examples/jest/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | public/bundle.* -------------------------------------------------------------------------------- /examples/jest/README.md: -------------------------------------------------------------------------------- 1 | # Jest 2 | 3 | Testing svelte components with [Jest](https://jestjs.io/) requires a little setuo but is relatively straighforward. We will walk through the steps here. 4 | 5 | # Basic Setup 6 | 7 | First we need to install `jest` and `svelte-test` in order to transform Svelte components as we import them. 8 | 9 | With [npm](https://www.npmjs.com/): 10 | 11 | ```bash 12 | npm install --save-dev jest svelte-test 13 | ``` 14 | 15 | Or with [yarn](https://yarnpkg.com/en/): 16 | 17 | ```bash 18 | yarn add --dev jest svelte-test 19 | ``` 20 | 21 | Now we just need to make sure Svelte components are transformed into valid javascript when they are imported. 22 | 23 | Create a `jest.config.js` file in the root of your application and add the following: 24 | 25 | ```js 26 | // jest.config.js 27 | 28 | module.exports = { 29 | transform: { 30 | '^.+\\.svelte$': 'svelte-test/transform', 31 | }, 32 | }; 33 | ``` 34 | 35 | \*You can pass additional options to `svelte-test/transform`, see the [`svelte-test` readme] for more details 36 | 37 | To run our tests we will need to add a test script to `package.json` like so: 38 | 39 | ```js 40 | // package.json 41 | 42 | { 43 | // ...otherConfig, 44 | "scripts": { 45 | // ...otherScripts 46 | "test": "jest" 47 | } 48 | } 49 | ``` 50 | 51 | You can now import Svelte components and they will be compiled as they are imported, the component constructor will be on the `default` property of the imported object. 52 | 53 | ```js 54 | const App = require('./App.svelte'); 55 | 56 | test('a test', () => { 57 | const app = new App.default({ options }); 58 | 59 | expect(app).toBeTruthy(); 60 | }); 61 | ``` 62 | 63 | ## Using babel 64 | 65 | You may want to import components into your tests using esm syntax (`import x from './y'`) and perhaps make use of ptehr language fetaures not fully supported in a node environment. To do this we will add a [babel](https://babeljs.io/) transform to make sure our code can run properly in node. 66 | 67 | We will need `babel-jest`, `@babel/core`, and `@babel/preset-env`. We will also add `@babel/plugin-transform-runtime` to make sure we can use `async`/`await` syntax in our tests. 68 | 69 | With npm: 70 | 71 | ```bash 72 | npm install --save-dev babel-jest @babel/core @babel/preset-env @babel/plugin-transform-runtime 73 | ``` 74 | 75 | Or with yarn: 76 | 77 | ```bash 78 | yarn add --dev babel-jest @babel/core @babel/preset-env @babel/plugin-transform-runtime 79 | ``` 80 | 81 | We will need a `babel.config.js` in the the root of our project that looks like this: 82 | 83 | ```js 84 | // babel.config.js 85 | 86 | module.exports = function(api) { 87 | api.cache(true); 88 | 89 | return { 90 | presets: ['@babel/preset-env'], 91 | plugins: ['@babel/plugin-transform-runtime'], 92 | }; 93 | }; 94 | ``` 95 | 96 | And we will need to add another transform to our `jest.config.js`, this time for javascript files: 97 | 98 | ```diff 99 | module.exports = { 100 | transform: { 101 | '^.+\\.svelte$': 'svelte-test/transform', 102 | + '^.+\\.js$': 'babel-jest', 103 | }, 104 | }; 105 | ``` 106 | 107 | Now we should be able to write code similar to that in your components: 108 | 109 | ```js 110 | import App from './App.svelte'; 111 | 112 | test('a test', () => { 113 | const app = new App.default({ options }); 114 | 115 | expect(app).toBeTruthy(); 116 | }); 117 | ``` 118 | 119 | ## Adding some DOM helpers 120 | 121 | DOM testing can get pretty tedious if you need to mount and destroy your components manually, not to mention querying the DOM and firing events to make assertions. Needing to access the `default` property of the import everytime might also get annoying. 122 | 123 | To ease this pain install `@testing-library/svelte`. 124 | 125 | With npm: 126 | 127 | ```bash 128 | npm install --save-dev @testing-library/svelte 129 | ``` 130 | 131 | Or with yarn: 132 | 133 | ```bash 134 | yarn add --dev @testing-library/svelte 135 | ``` 136 | 137 | Now we can use `testing-library` helpers to make testing the DOM a little simpler: 138 | 139 | ```js 140 | import { render, fireEvent, cleanup } from '@testing-library/svelte'; 141 | import App from './App.svelte'; 142 | 143 | beforeEach(cleanup); 144 | 145 | test('A DOM test', async () => { 146 | const { getByLabelText, getByText } = render(App, { 147 | props: { name: 'World' }, 148 | }); 149 | 150 | const button = getByLabelText('Submit'); 151 | await fireEvent.click(button); 152 | 153 | expect(() => getByText('Hello Jeremiah')).not.toThrow(); 154 | }); 155 | ``` 156 | 157 | You can find out more about these DOM helpers in the [`testing-library` documentation](https://testing-library.com/docs/svelte-testing-library/intro). 158 | -------------------------------------------------------------------------------- /examples/jest/jest.config.js: -------------------------------------------------------------------------------- 1 | const transformLess = require('./src/less.js'); 2 | 3 | module.exports = { 4 | transform: { 5 | '^.+\\.svelte$': 'svelte-test/transform', 6 | '^.+\\.js$': 'babel-jest', 7 | }, 8 | globals: { 9 | svelte: { 10 | preprocess: [transformLess], 11 | }, 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /examples/jest/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-app", 3 | "version": "1.0.0", 4 | "devDependencies": { 5 | "@babel/core": "^7.4.5", 6 | "@babel/preset-env": "^7.4.5", 7 | "@babel/plugin-transform-runtime": "^7.4.4", 8 | "@testing-library/svelte": "^1.7.1", 9 | "babel-jest": "^24.8.0", 10 | "jest": "^24.8.0", 11 | "less": "^3.9.0", 12 | "npm-run-all": "^4.1.5", 13 | "rollup": "^1.10.1", 14 | "rollup-plugin-commonjs": "^10.0.0", 15 | "rollup-plugin-livereload": "^1.0.0", 16 | "rollup-plugin-node-resolve": "^5.0.0", 17 | "rollup-plugin-svelte": "^5.0.3", 18 | "rollup-plugin-terser": "^5.0.0", 19 | "sirv-cli": "^0.4.0", 20 | "svelte": "^3.4.4", 21 | "svelte-test": "^0.2.0" 22 | }, 23 | "scripts": { 24 | "build": "rollup -c", 25 | "autobuild": "rollup -c -w", 26 | "dev": "run-p start:dev autobuild", 27 | "start": "sirv public", 28 | "start:dev": "sirv public --dev", 29 | "test": "jest" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/jest/public/crops/crops-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "next": 2, 3 | "data": [ 4 | { 5 | "name": "Abaca (Manila hemp)", 6 | "latin": " Musa textilis", 7 | "number": "9213", 8 | "oldnumber": "2.2.4.1" 9 | }, 10 | { 11 | "name": "Alfalfa for fodder", 12 | "latin": "Medicago sativa", 13 | "number": "911", 14 | "oldnumber": "1.7.1.1" 15 | }, 16 | { 17 | "name": "Alfalfa for seed", 18 | "latin": "Medicago sativa", 19 | "number": "911", 20 | "oldnumber": "1.8.2" 21 | }, 22 | { 23 | "name": "Almond", 24 | "latin": "Prunus dulcis", 25 | "number": "361", 26 | "oldnumber": "2.1.7.1" 27 | }, 28 | { 29 | "name": "Anise seeds", 30 | "latin": "Pimpinella anisum", 31 | "number": "6212", 32 | "oldnumber": "1.4.3.4" 33 | }, 34 | { 35 | "name": "Apple", 36 | "latin": "Malus sylvestris", 37 | "number": "351", 38 | "oldnumber": "2.1.2.1" 39 | }, 40 | { 41 | "name": "Apricot", 42 | "latin": "Prunus armeniaca", 43 | "number": "352", 44 | "oldnumber": "2.1.3.1" 45 | }, 46 | { 47 | "name": "Areca (betel nut)", 48 | "latin": "Areca catechu", 49 | "number": "992", 50 | "oldnumber": "2.2.7.6" 51 | }, 52 | { 53 | "name": "Arracha", 54 | "latin": "Arracacia xanthorrhiza", 55 | "number": "59", 56 | "oldnumber": "1.2.9" 57 | }, 58 | { 59 | "name": "Arrowroot", 60 | "latin": "Maranta arundinacea", 61 | "number": "59", 62 | "oldnumber": "1.2.5" 63 | }, 64 | { 65 | "name": "Artichoke", 66 | "latin": "Cynara scolymus", 67 | "number": "211", 68 | "oldnumber": "1.5.1.0.1" 69 | }, 70 | { 71 | "name": "Asparagus", 72 | "latin": "Asparagus officinalis", 73 | "number": "212", 74 | "oldnumber": "1.5.1.0.2" 75 | }, 76 | { 77 | "name": "Avocado", 78 | "latin": "Persea americana", 79 | "number": "311", 80 | "oldnumber": "2.1.6.0.1" 81 | }, 82 | { 83 | "name": "Bajra (Pearl millet)", 84 | "latin": " Pennisetum americanum", 85 | "number": "18", 86 | "oldnumber": "1.1.5.1.2" 87 | }, 88 | { 89 | "name": "Bambara groundnut", 90 | "latin": "Vigna subterranea", 91 | "number": "79", 92 | "oldnumber": "1.3.9" 93 | }, 94 | { 95 | "name": "Banana", 96 | "latin": "Musa paradisiaca", 97 | "number": "312", 98 | "oldnumber": "2.1.6.0.2" 99 | }, 100 | { 101 | "name": "Barley", 102 | "latin": "Hordeum vulgare", 103 | "number": "15", 104 | "oldnumber": "1.1.4" 105 | }, 106 | { 107 | "name": "Beans, dry, edible, for grains", 108 | "latin": "Phaseolus vulgaris", 109 | "number": "71", 110 | "oldnumber": "1.3.1" 111 | }, 112 | { 113 | "name": "Beans, harvested green", 114 | "latin": "Phaseolus and Vigna spp.", 115 | "number": "71", 116 | "oldnumber": "1.5.4.1" 117 | }, 118 | { 119 | "name": "Beet, fodder (mangel)", 120 | "latin": "Beta vulgaris", 121 | "number": "81", 122 | "oldnumber": "1.7.5.0.5" 123 | }, 124 | { 125 | "name": "Beet, red", 126 | "latin": "Beta vulgaris", 127 | "number": "81", 128 | "oldnumber": "1.5.3.5" 129 | }, 130 | { 131 | "name": "Beet, sugar", 132 | "latin": "Beta vulgaris", 133 | "number": "81", 134 | "oldnumber": "1.4.1.2" 135 | }, 136 | { 137 | "name": "Beet, sugar for fodder", 138 | "latin": "Beta vulgaris", 139 | "number": "81", 140 | "oldnumber": "1.7.5.0.6" 141 | }, 142 | { 143 | "name": "Beet, sugar for seeds", 144 | "latin": "Beta vulgaris", 145 | "number": "81", 146 | "oldnumber": "1.8.1" 147 | }, 148 | { 149 | "name": "Bergamot", 150 | "latin": "Citrus bergamia", 151 | "number": "329", 152 | "oldnumber": "2.1.1.6" 153 | }, 154 | { 155 | "name": "Betel nut", 156 | "latin": "Areca catechu", 157 | "number": "992", 158 | "oldnumber": "2.2.7.6" 159 | }, 160 | { 161 | "name": "Black pepper", 162 | "latin": "Piper nigrum", 163 | "number": "6221", 164 | "oldnumber": "2.2.3.1" 165 | }, 166 | { 167 | "name": "Black wattle", 168 | "latin": "Acacia mearnsii", 169 | "number": "992", 170 | "oldnumber": "2.2.5.2" 171 | }, 172 | { 173 | "name": "Blackberries of various species", 174 | "latin": "Rubus spp.", 175 | "number": "349", 176 | "oldnumber": "2.1.5.7" 177 | }, 178 | { 179 | "name": "Blueberry", 180 | "latin": "Vaccinium spp.", 181 | "number": "346", 182 | "oldnumber": "2.1.5.1" 183 | } 184 | ] 185 | } 186 | -------------------------------------------------------------------------------- /examples/jest/public/crops/crops-10.json: -------------------------------------------------------------------------------- 1 | { 2 | "next": null, 3 | "data": [ 4 | { 5 | "name": "Tomato", 6 | "latin": "Lycopersicon esculentum", 7 | "number": "223", 8 | "oldnumber": "1.5.2.1.0" 9 | }, 10 | { 11 | "name": "Trefoil", 12 | "latin": "Lotus spp. (about", 13 | "number": "1", 14 | "oldnumber": "00" 15 | }, 16 | { 17 | "name": "Triticale for fodder", 18 | "latin": "Hybrid of Triticum aestivum and Secale cereale", 19 | "number": "17", 20 | "oldnumber": "1.7.3.2" 21 | }, 22 | { 23 | "name": "Turnip, edible", 24 | "latin": "Brassica rapa", 25 | "number": "232", 26 | "oldnumber": "1.5.3.7" 27 | }, 28 | { 29 | "name": "Turnip, for fodder", 30 | "latin": "Brassica rapa", 31 | "number": "232", 32 | "oldnumber": "1.7.5.0.9" 33 | }, 34 | { 35 | "name": "Urena (Congo jute)", 36 | "latin": "Urena lobata", 37 | "number": "9214", 38 | "oldnumber": "1.4.4.5" 39 | }, 40 | { 41 | "name": "Vanilla", 42 | "latin": "Vanilla planifolia", 43 | "number": "6226", 44 | "oldnumber": "2.2.3.6" 45 | }, 46 | { 47 | "name": "Vetch for grain", 48 | "latin": "Vicia sativa", 49 | "number": "79", 50 | "oldnumber": "1.3.8" 51 | }, 52 | { 53 | "name": "Watermelon", 54 | "latin": "Citrullus lanatus", 55 | "number": "224", 56 | "oldnumber": "1.5.2.1.1" 57 | }, 58 | { 59 | "name": "Wheat", 60 | "latin": "Triticum aestivum", 61 | "number": "11", 62 | "oldnumber": "1.1.1" 63 | }, 64 | { 65 | "name": "Yam", 66 | "latin": "Dioscorea spp. (over", 67 | "number": "1", 68 | "oldnumber": "20" 69 | }, 70 | { 71 | "name": "Yerba mate", 72 | "latin": "Ilex paraguariensis", 73 | "number": "613", 74 | "oldnumber": "2.2.1.5" 75 | } 76 | ] 77 | } 78 | -------------------------------------------------------------------------------- /examples/jest/public/crops/crops-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "next": 3, 3 | "data": [ 4 | { 5 | "name": "Brazil nut", 6 | "latin": "Bertholletia excelsa", 7 | "number": "369", 8 | "oldnumber": "2.1.7.6" 9 | }, 10 | { 11 | "name": "Breadfruit", 12 | "latin": "Artocarpus altilis", 13 | "number": "319", 14 | "oldnumber": "2.1.6.0.3" 15 | }, 16 | { 17 | "name": "Broad bean, dry", 18 | "latin": "Vicia faba", 19 | "number": "72", 20 | "oldnumber": "1.3.2" 21 | }, 22 | { 23 | "name": "Broad bean, harvested green ", 24 | "latin": "Vicia faba", 25 | "number": "72", 26 | "oldnumber": "1.5.4.3" 27 | }, 28 | { 29 | "name": "Broccoli", 30 | "latin": "Brassica oleracea var. botrytis", 31 | "number": "214", 32 | "oldnumber": "1.5.5.1" 33 | }, 34 | { 35 | "name": "Broom millet", 36 | "latin": "Sorghum bicolor", 37 | "number": "18", 38 | "oldnumber": "1.4.5.4" 39 | }, 40 | { 41 | "name": "Broom sorghum", 42 | "latin": "Sorghum bicolor", 43 | "number": "14", 44 | "oldnumber": "1.4.5.4" 45 | }, 46 | { 47 | "name": "Brussels sprouts", 48 | "latin": "Brassica oleracea var.gemmifera", 49 | "number": "219", 50 | "oldnumber": "1.5.1.0.3" 51 | }, 52 | { 53 | "name": "Buckwheat", 54 | "latin": "Fagopyrum esculentum", 55 | "number": "192", 56 | "oldnumber": "1.1.9" 57 | }, 58 | { 59 | "name": "Cabbage (red, white, Savoy)", 60 | "latin": "Brassica oleracea var.capitata", 61 | "number": "213", 62 | "oldnumber": "1.5.1.0.4" 63 | }, 64 | { 65 | "name": "Cabbage, Chinese", 66 | "latin": "Brassica chinensis", 67 | "number": "213", 68 | "oldnumber": "1.5.1.0.7" 69 | }, 70 | { 71 | "name": "Cabbage, for fodder", 72 | "latin": "Brassica spp.", 73 | "number": "213", 74 | "oldnumber": "1.7.5.0.1" 75 | }, 76 | { 77 | "name": "Cacao (cocoa)", 78 | "latin": "Theobroma cacao", 79 | "number": "614", 80 | "oldnumber": "2.2.1.2" 81 | }, 82 | { 83 | "name": "Cantaloupe", 84 | "latin": "Cucumis melo", 85 | "number": "225", 86 | "oldnumber": "1.5.2.0.1" 87 | }, 88 | { 89 | "name": "Caraway seeds", 90 | "latin": "Carum carvi", 91 | "number": "6219", 92 | "oldnumber": "1.4.3.4" 93 | }, 94 | { 95 | "name": "Cardamom", 96 | "latin": "Elettaria cardamomum", 97 | "number": "6222", 98 | "oldnumber": "2.2.3.7" 99 | }, 100 | { 101 | "name": "Cardoon", 102 | "latin": "Cynara cardunculus", 103 | "number": "219", 104 | "oldnumber": "1.5.1.1.5" 105 | }, 106 | { 107 | "name": "Carob", 108 | "latin": "Ceratonia siliqua", 109 | "number": "39", 110 | "oldnumber": "2.1.6.1.5" 111 | }, 112 | { 113 | "name": "Carrot, edible", 114 | "latin": "Daucus carota ssp. sativa", 115 | "number": "231", 116 | "oldnumber": "1.5.3.1" 117 | }, 118 | { 119 | "name": "Carrot, for fodder ", 120 | "latin": "Daucus carota ssp. sativa", 121 | "number": "231", 122 | "oldnumber": "1.7.5.1.0" 123 | }, 124 | { 125 | "name": "Cashew nuts", 126 | "latin": "Anacardium occidentale", 127 | "number": "362", 128 | "oldnumber": "2.1.7.2" 129 | }, 130 | { 131 | "name": "Cassava (manioc)", 132 | "latin": "Manihot esculenta", 133 | "number": "53", 134 | "oldnumber": "1.2.3" 135 | }, 136 | { 137 | "name": "Castor bean", 138 | "latin": "Ricinus communis", 139 | "number": "431", 140 | "oldnumber": "1.4.2.1.0" 141 | }, 142 | { 143 | "name": "Cauliflower", 144 | "latin": "Brassica oleracea var.botrytis", 145 | "number": "214", 146 | "oldnumber": "1.5.5.1" 147 | }, 148 | { 149 | "name": "Celeriac", 150 | "latin": "Apium graveolens var. rapaceum", 151 | "number": "239", 152 | "oldnumber": "1.5.3.8" 153 | }, 154 | { 155 | "name": "Celery", 156 | "latin": "Apium graveolens", 157 | "number": "219", 158 | "oldnumber": "1.5.1.0.5" 159 | }, 160 | { 161 | "name": "Chayote", 162 | "latin": "Sechium edule", 163 | "number": "229", 164 | "oldnumber": "1.5.2.1.2" 165 | }, 166 | { 167 | "name": "Cherry (all varieties)", 168 | "latin": "Prunus spp.", 169 | "number": "353", 170 | "oldnumber": "2.1.3.2" 171 | }, 172 | { 173 | "name": "Chestnut", 174 | "latin": "Castanea sativa", 175 | "number": "363", 176 | "oldnumber": "2.1.7.4" 177 | }, 178 | { 179 | "name": "Chickpea (gram pea)", 180 | "latin": "Cicer arietinum", 181 | "number": "73", 182 | "oldnumber": "1.3.4" 183 | } 184 | ] 185 | } 186 | -------------------------------------------------------------------------------- /examples/jest/public/crops/crops-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "next": 4, 3 | "data": [ 4 | { 5 | "name": "Chicory", 6 | "latin": "Cichorium intybus", 7 | "number": "217", 8 | "oldnumber": "1.4.5.2" 9 | }, 10 | { 11 | "name": "Chicory for greens", 12 | "latin": "Cichorium intybus", 13 | "number": "217", 14 | "oldnumber": "1.5.1.0.6" 15 | }, 16 | { 17 | "name": "Chili, dry (all varieties) ", 18 | "latin": "Capsicum spp. (annuum)", 19 | "number": "6211", 20 | "oldnumber": "1.4.3.1" 21 | }, 22 | { 23 | "name": "Chili, fresh (all varieties) ", 24 | "latin": "Capsicum spp. (annuum)", 25 | "number": "6211", 26 | "oldnumber": "1.5.2.0.2" 27 | }, 28 | { 29 | "name": "Cinnamon", 30 | "latin": "Cinnamomum verum", 31 | "number": "6223", 32 | "oldnumber": "2.2.3.2" 33 | }, 34 | { 35 | "name": "Citron", 36 | "latin": "Citrus medica", 37 | "number": "329", 38 | "oldnumber": "2.1.1.6" 39 | }, 40 | { 41 | "name": "Clementine", 42 | "latin": "Citrus reticulata", 43 | "number": "324", 44 | "oldnumber": "2.1.1.2" 45 | }, 46 | { 47 | "name": "Clove", 48 | "latin": "Eugenia aromatica (Syzygium aromaticum)", 49 | "number": "6224", 50 | "oldnumber": "2.2.3.3" 51 | }, 52 | { 53 | "name": "Clover for fodder (all varieties)", 54 | "latin": "Trifolium spp.", 55 | "number": "911", 56 | "oldnumber": "1.7.1.2" 57 | }, 58 | { 59 | "name": "Clover for seed (all varieties)", 60 | "latin": "Trifolium spp.", 61 | "number": "911", 62 | "oldnumber": "1.8.3" 63 | }, 64 | { 65 | "name": "Cocoa (cacao)", 66 | "latin": "Theobroma cacao", 67 | "number": "614", 68 | "oldnumber": "2.2.1.2" 69 | }, 70 | { 71 | "name": "Coconut", 72 | "latin": "Cocos nucifera", 73 | "number": "441", 74 | "oldnumber": "2.2.2.1" 75 | }, 76 | { 77 | "name": "Cocoyam", 78 | "latin": "Colocasia esculenta", 79 | "number": "59", 80 | "oldnumber": "1.2.8" 81 | }, 82 | { 83 | "name": "Coffee", 84 | "latin": "Coffea spp.", 85 | "number": "611", 86 | "oldnumber": "2.2.1.1" 87 | }, 88 | { 89 | "name": "Cola nut (all varieties)", 90 | "latin": "Cola acuminata", 91 | "number": "619", 92 | "oldnumber": "2.2.1.6" 93 | }, 94 | { 95 | "name": "Colza (rapeseed)", 96 | "latin": "Brassica napus", 97 | "number": "435", 98 | "oldnumber": "1.4.2.0.5" 99 | }, 100 | { 101 | "name": "Corn (maize), for cereals", 102 | "latin": "Zea mays", 103 | "number": "12", 104 | "oldnumber": "1.1.3" 105 | }, 106 | { 107 | "name": "Corn (maize), for silage", 108 | "latin": "Zea mays", 109 | "number": "12", 110 | "oldnumber": "1.7.3.1" 111 | }, 112 | { 113 | "name": "Corn (sweet), for vegetable", 114 | "latin": "Zea mays", 115 | "number": "12", 116 | "oldnumber": "1.5.5.2" 117 | }, 118 | { 119 | "name": "Corn for salad", 120 | "latin": "Valerianella locusta", 121 | "number": "219", 122 | "oldnumber": "1.5.1.1.5" 123 | }, 124 | { 125 | "name": "Cotton (all varieties)", 126 | "latin": "Gossypium spp.", 127 | "number": "9211", 128 | "oldnumber": "1.4.4.1" 129 | }, 130 | { 131 | "name": "Cottonseed (all varieties)", 132 | "latin": "Gossypium spp.", 133 | "number": "9211", 134 | "oldnumber": "1.4.2.0.8" 135 | }, 136 | { 137 | "name": "Cowpea, for grain", 138 | "latin": "Vigna unguiculata", 139 | "number": "74", 140 | "oldnumber": "1.3.6" 141 | }, 142 | { 143 | "name": "Cowpea, harvested green", 144 | "latin": "Vigna unguiculata", 145 | "number": "74", 146 | "oldnumber": "1.5.4.3" 147 | }, 148 | { 149 | "name": "Cranberry", 150 | "latin": "Vaccinium spp.", 151 | "number": "349", 152 | "oldnumber": "2.1.5.2" 153 | }, 154 | { 155 | "name": "Cress", 156 | "latin": "Lepidium sativum", 157 | "number": "219", 158 | "oldnumber": "1.5.1.0.8" 159 | }, 160 | { 161 | "name": "Cucumber", 162 | "latin": "Cucumis sativus", 163 | "number": "221", 164 | "oldnumber": "1.5.2.0.3" 165 | }, 166 | { 167 | "name": "Currants (all varieties)", 168 | "latin": "Ribes spp.", 169 | "number": "341", 170 | "oldnumber": "2.1.5.3" 171 | }, 172 | { 173 | "name": "Custard apple", 174 | "latin": "Annona reticulate", 175 | "number": "319", 176 | "oldnumber": "2.1.6.0.4" 177 | }, 178 | { 179 | "name": "Dasheen", 180 | "latin": "Colocasia esculenta", 181 | "number": "59", 182 | "oldnumber": "1.2.8" 183 | } 184 | ] 185 | } 186 | -------------------------------------------------------------------------------- /examples/jest/public/crops/crops-4.json: -------------------------------------------------------------------------------- 1 | { 2 | "next": 5, 3 | "data": [ 4 | { 5 | "name": "Dates", 6 | "latin": "Phoenix dactylifera", 7 | "number": "313", 8 | "oldnumber": "2.1.6.0.5" 9 | }, 10 | { 11 | "name": "Drumstick tree", 12 | "latin": "Moringa oleifera", 13 | "number": "6229", 14 | "oldnumber": "2.2.3.8" 15 | }, 16 | { 17 | "name": "Durra (sorghum)", 18 | "latin": "Sorghum bicolour", 19 | "number": "14", 20 | "oldnumber": "1.1.5.2" 21 | }, 22 | { 23 | "name": "Durum wheat", 24 | "latin": "Triticum durum", 25 | "number": "11", 26 | "oldnumber": "1.1.1.1.1" 27 | }, 28 | { 29 | "name": "Earth pea", 30 | "latin": "Vigna subterranea", 31 | "number": "79", 32 | "oldnumber": "1.3.9" 33 | }, 34 | { 35 | "name": "Eggplant", 36 | "latin": "Solanum melongena", 37 | "number": "222", 38 | "oldnumber": "1.5.2.0.4" 39 | }, 40 | { 41 | "name": "Endive", 42 | "latin": "Cichorium endivia", 43 | "number": "219", 44 | "oldnumber": "1.5.1.0.9" 45 | }, 46 | { 47 | "name": "Fennel", 48 | "latin": "Foeniculum vulgare", 49 | "number": "219", 50 | "oldnumber": "1.5.1.1.5" 51 | }, 52 | { 53 | "name": "Fig", 54 | "latin": "Ficus carica", 55 | "number": "314", 56 | "oldnumber": "2.1.6.0.6" 57 | }, 58 | { 59 | "name": "Filbert (Hazelnut)", 60 | "latin": "Corylus avellana", 61 | "number": "364", 62 | "oldnumber": "2.1.7.5" 63 | }, 64 | { 65 | "name": "Fique", 66 | "latin": "Furcraea macrophylla", 67 | "number": "9219", 68 | "oldnumber": "2.2.4.6" 69 | }, 70 | { 71 | "name": "Flax for fibre", 72 | "latin": "Linum usitatissimum", 73 | "number": "9213", 74 | "oldnumber": "1.4.4.2" 75 | }, 76 | { 77 | "name": "Flax for oil seed (linseed)", 78 | "latin": "Linum usitatissimum", 79 | "number": "9213", 80 | "oldnumber": "1.4.2.0.3" 81 | }, 82 | { 83 | "name": "Formio (New Zealand flax)", 84 | "latin": "Phormium tenax", 85 | "number": "9214", 86 | "oldnumber": "2.2.4.4" 87 | }, 88 | { 89 | "name": "Garlic, dry ", 90 | "latin": "Allium sativum", 91 | "number": "233", 92 | "oldnumber": "1.2.7" 93 | }, 94 | { 95 | "name": "Garlic, green", 96 | "latin": "Allium sativum", 97 | "number": "233", 98 | "oldnumber": "1.5.3.2" 99 | }, 100 | { 101 | "name": "Ginger", 102 | "latin": "Zingiber officinale", 103 | "number": "6225", 104 | "oldnumber": "2.2.3.4" 105 | }, 106 | { 107 | "name": "Gooseberry (all varieties)", 108 | "latin": "Ribes spp.", 109 | "number": "342", 110 | "oldnumber": "2.1.5.4" 111 | }, 112 | { 113 | "name": "Gram pea (chickpea)", 114 | "latin": "Cicer arietinum", 115 | "number": "73", 116 | "oldnumber": "1.3.4" 117 | }, 118 | { 119 | "name": "Grape", 120 | "latin": "Vitis vinifera", 121 | "number": "33", 122 | "oldnumber": "2.1.4" 123 | }, 124 | { 125 | "name": "Grapefruit", 126 | "latin": "Citrus paradisi", 127 | "number": "321", 128 | "oldnumber": "2.1.1.4" 129 | }, 130 | { 131 | "name": "Grapes for raisins", 132 | "latin": "Vitis vinifera", 133 | "number": "33", 134 | "oldnumber": "2.1.4.3" 135 | }, 136 | { 137 | "name": "Grapes for table use", 138 | "latin": "Vitis vinifera", 139 | "number": "33", 140 | "oldnumber": "2.1.4.2" 141 | }, 142 | { 143 | "name": "Grapes for wine", 144 | "latin": "Vitis vinifera", 145 | "number": "33", 146 | "oldnumber": "2.1.4.1" 147 | }, 148 | { 149 | "name": "Grass esparto", 150 | "latin": "Lygeum spartum", 151 | "number": "991", 152 | "oldnumber": "1.4.5.4" 153 | }, 154 | { 155 | "name": "Grass, orchard ", 156 | "latin": "Dactylis glomerata", 157 | "number": "911", 158 | "oldnumber": "1.7.2.1" 159 | }, 160 | { 161 | "name": "Grass, Sudan", 162 | "latin": "Sorghum bicolor var. sudanense", 163 | "number": "911", 164 | "oldnumber": "1.7.2.1" 165 | }, 166 | { 167 | "name": "Groundnut (peanut)", 168 | "latin": "Arachis hypogaea", 169 | "number": "42", 170 | "oldnumber": "1.4.2.0.1" 171 | }, 172 | { 173 | "name": "Guava", 174 | "latin": "Psidium guajava", 175 | "number": "319", 176 | "oldnumber": "2.1.6.0.7" 177 | }, 178 | { 179 | "name": "Guinea corn (sorghum)", 180 | "latin": "Sorghum bicolor", 181 | "number": "14", 182 | "oldnumber": "1.1.5.2" 183 | } 184 | ] 185 | } 186 | -------------------------------------------------------------------------------- /examples/jest/public/crops/crops-5.json: -------------------------------------------------------------------------------- 1 | { 2 | "next": 6, 3 | "data": [ 4 | { 5 | "name": "Hazelnut (filbert)", 6 | "latin": "Corylus avellana", 7 | "number": "364", 8 | "oldnumber": "2.1.7.5" 9 | }, 10 | { 11 | "name": "Hemp fibre", 12 | "latin": "Cannabis sativa ssp. indica", 13 | "number": "9213", 14 | "oldnumber": "1.4.4.3" 15 | }, 16 | { 17 | "name": "Hemp, ", 18 | "latin": "Manila (abaca) Musa textilis", 19 | "number": "922", 20 | "oldnumber": "2.2.4.1" 21 | }, 22 | { 23 | "name": "Hemp, sun ", 24 | "latin": "Crotalaria juncea", 25 | "number": "9213", 26 | "oldnumber": "1.4.4.5" 27 | }, 28 | { 29 | "name": "Hempseed", 30 | "latin": "Cannabis sativa (marijuana)", 31 | "number": "439", 32 | "oldnumber": "1.4.2.1.1" 33 | }, 34 | { 35 | "name": "Henequen", 36 | "latin": "Agave fourcroydes", 37 | "number": "922", 38 | "oldnumber": "2.2.4.2" 39 | }, 40 | { 41 | "name": "Henna", 42 | "latin": "Lawsonia inermis", 43 | "number": "911", 44 | "oldnumber": "1.4.5.4" 45 | }, 46 | { 47 | "name": "Hop", 48 | "latin": "Humulus lupulus", 49 | "number": "619", 50 | "oldnumber": "2.2.1.4" 51 | }, 52 | { 53 | "name": "Horse bean", 54 | "latin": "Vicia faba", 55 | "number": "72", 56 | "oldnumber": "1.3.2" 57 | }, 58 | { 59 | "name": "Horseradish", 60 | "latin": "Armoracia rusticana", 61 | "number": "239", 62 | "oldnumber": "1.5.3.8" 63 | }, 64 | { 65 | "name": "Hybrid maize", 66 | "latin": "Zea mays", 67 | "number": "12", 68 | "oldnumber": "1.1.3.1" 69 | }, 70 | { 71 | "name": "Indigo", 72 | "latin": "Indigofera tinctoria", 73 | "number": "991", 74 | "oldnumber": "1.4.5.4" 75 | }, 76 | { 77 | "name": "Jasmine", 78 | "latin": "Jasminum spp.", 79 | "number": "952", 80 | "oldnumber": "2.2.6.2" 81 | }, 82 | { 83 | "name": "Jerusalem artichoke", 84 | "latin": "Helianthus tuberosus", 85 | "number": "211", 86 | "oldnumber": "1.7.5.0.2" 87 | }, 88 | { 89 | "name": "Jowar (sorghum)", 90 | "latin": "Sorghum bicolor", 91 | "number": "14", 92 | "oldnumber": "1.1.5.2" 93 | }, 94 | { 95 | "name": "Kale", 96 | "latin": "Brassica oleracea var. acephala", 97 | "number": "219", 98 | "oldnumber": "1.5.1.1.0" 99 | }, 100 | { 101 | "name": "Kapok", 102 | "latin": "Ceiba pentandra", 103 | "number": "922", 104 | "oldnumber": "2.2.4.3" 105 | }, 106 | { 107 | "name": "Kenaf", 108 | "latin": "Hibiscus cannabinus", 109 | "number": "9212", 110 | "oldnumber": "1.4.4.5" 111 | }, 112 | { 113 | "name": "Kohlrabi", 114 | "latin": "Brassica oleracea var. gongylodes", 115 | "number": "239", 116 | "oldnumber": "1.5.3.6" 117 | }, 118 | { 119 | "name": "Lemon", 120 | "latin": "Citrus limon", 121 | "number": "322", 122 | "oldnumber": "2.1.1.3" 123 | }, 124 | { 125 | "name": "Lemon grass", 126 | "latin": "Cymbopogon citratus", 127 | "number": "922", 128 | "oldnumber": "2.2.7.7" 129 | }, 130 | { 131 | "name": "Lentil", 132 | "latin": "Lens culinaris", 133 | "number": "75", 134 | "oldnumber": "1.3.5" 135 | }, 136 | { 137 | "name": "Lespedeza (all varieties)", 138 | "latin": "Lespedeza spp.", 139 | "number": "911", 140 | "oldnumber": "1.7.1.3" 141 | }, 142 | { 143 | "name": "Lettuce", 144 | "latin": "Lactuca sativa var. capitata", 145 | "number": "215", 146 | "oldnumber": "1.5.1.1.2" 147 | }, 148 | { 149 | "name": "Lime, sour", 150 | "latin": "Citrus aurantifolia", 151 | "number": "322", 152 | "oldnumber": "2.1.1.5" 153 | }, 154 | { 155 | "name": "Lime, sweet ", 156 | "latin": "Citrus limetta", 157 | "number": "322", 158 | "oldnumber": "2.1.1.6" 159 | }, 160 | { 161 | "name": "Linseed (flax for oil seed)", 162 | "latin": "Linum usitatissimum", 163 | "number": "432", 164 | "oldnumber": "1.4.2.0.3" 165 | }, 166 | { 167 | "name": "Liquorice", 168 | "latin": "Glycyrrhiza glabra", 169 | "number": "931", 170 | "oldnumber": "1.4.3.3" 171 | }, 172 | { 173 | "name": "Litchi", 174 | "latin": "Litchi chinensis", 175 | "number": "319", 176 | "oldnumber": "2.1.6.1.5" 177 | }, 178 | { 179 | "name": "Loquat", 180 | "latin": "Eriobotrya japonica", 181 | "number": "359", 182 | "oldnumber": "2.1.2.5" 183 | } 184 | ] 185 | } 186 | -------------------------------------------------------------------------------- /examples/jest/public/crops/crops-6.json: -------------------------------------------------------------------------------- 1 | { 2 | "next": 7, 3 | "data": [ 4 | { 5 | "name": "Lupine (all varieties)", 6 | "latin": "Lupinus spp.", 7 | "number": "76", 8 | "oldnumber": "1.3.9" 9 | }, 10 | { 11 | "name": "Macadamia (Queensland nut)", 12 | "latin": "Macadamia spp. ternifolia", 13 | "number": "369", 14 | "oldnumber": "2.1.7.6" 15 | }, 16 | { 17 | "name": "Mace", 18 | "latin": "Myristica fragrans", 19 | "number": "6222", 20 | "oldnumber": "2.2.3.5" 21 | }, 22 | { 23 | "name": "Maguey", 24 | "latin": "Agave atrovirens", 25 | "number": "922", 26 | "oldnumber": "2.2.4.6" 27 | }, 28 | { 29 | "name": "Maize (corn)", 30 | "latin": "Zea mays", 31 | "number": "12", 32 | "oldnumber": "1.1.3" 33 | }, 34 | { 35 | "name": "Maize (corn) for silage", 36 | "latin": "Zea mays", 37 | "number": "12", 38 | "oldnumber": "1.7.3.1" 39 | }, 40 | { 41 | "name": "Maize (hybrid)", 42 | "latin": "Zea mays", 43 | "number": "12", 44 | "oldnumber": "1.1.3.1" 45 | }, 46 | { 47 | "name": "Maize, ordinary", 48 | "latin": "Zea mays", 49 | "number": "12", 50 | "oldnumber": "1.1.3.2" 51 | }, 52 | { 53 | "name": "Mandarin", 54 | "latin": "Citrus reticulata", 55 | "number": "324", 56 | "oldnumber": "2.1.1.2" 57 | }, 58 | { 59 | "name": "Mangel (fodder beet)", 60 | "latin": "Beta vulgaris", 61 | "number": "81", 62 | "oldnumber": "1.7.5.0.5" 63 | }, 64 | { 65 | "name": "Mango", 66 | "latin": "Mangifera indica", 67 | "number": "315", 68 | "oldnumber": "2.1.6.0.8" 69 | }, 70 | { 71 | "name": "Manioc (cassava)", 72 | "latin": "Manihot esculenta", 73 | "number": "53", 74 | "oldnumber": "1.2.3" 75 | }, 76 | { 77 | "name": "Medlar", 78 | "latin": "Mespilus germanica", 79 | "number": "359", 80 | "oldnumber": "2.1.2.4" 81 | }, 82 | { 83 | "name": "Melon (except watermelon)", 84 | "latin": "Cucumis melo", 85 | "number": "225", 86 | "oldnumber": "1.5.2.0.1" 87 | }, 88 | { 89 | "name": "Millet broom", 90 | "latin": "Sorghum bicolor", 91 | "number": "18", 92 | "oldnumber": "1.4.5.4" 93 | }, 94 | { 95 | "name": "Millet, bajra ", 96 | "latin": "Pennisetum americanum", 97 | "number": "18", 98 | "oldnumber": "1.1.5.1.2" 99 | }, 100 | { 101 | "name": "Millet, bulrush ", 102 | "latin": "Pennisetum americanum", 103 | "number": "18", 104 | "oldnumber": "1.1.5.1.1" 105 | }, 106 | { 107 | "name": "Millet, finger ", 108 | "latin": "Eleusine coracana", 109 | "number": "18", 110 | "oldnumber": "1.1.5.1.1" 111 | }, 112 | { 113 | "name": "Millet, foxtail ", 114 | "latin": "Setaria italica", 115 | "number": "18", 116 | "oldnumber": "1.1.5.1.2" 117 | }, 118 | { 119 | "name": "Millet, ", 120 | "latin": "Japanese Echinochloa esculenta", 121 | "number": "18", 122 | "oldnumber": "1.1.5.1.2" 123 | }, 124 | { 125 | "name": "Millet, pearl (bajra, bulrush) ", 126 | "latin": "Pennisetum americanum", 127 | "number": "18", 128 | "oldnumber": "1.1.5.1.1" 129 | }, 130 | { 131 | "name": "Millet, proso ", 132 | "latin": "Panicum miliaceum", 133 | "number": "18", 134 | "oldnumber": "1.1.5.1.1" 135 | }, 136 | { 137 | "name": "Mint (all varieties)", 138 | "latin": "Mentha spp.", 139 | "number": "6219", 140 | "oldnumber": "1.4.3.2" 141 | }, 142 | { 143 | "name": "Mulberry for fruit (all varieties)", 144 | "latin": "Morus spp.", 145 | "number": "39", 146 | "oldnumber": "2.1.6.1.5" 147 | }, 148 | { 149 | "name": "Mulberry for silkworms", 150 | "latin": "Morus alba", 151 | "number": "39", 152 | "oldnumber": "2.2.7.2" 153 | }, 154 | { 155 | "name": "Nectarine", 156 | "latin": "Prunus persica var. nectarina", 157 | "number": "354", 158 | "oldnumber": "2.1.3.5" 159 | }, 160 | { 161 | "name": "New Zealand flax (formio)", 162 | "latin": "Phormium tenax", 163 | "number": "922", 164 | "oldnumber": "2.2.4.4" 165 | }, 166 | { 167 | "name": "Niger seed", 168 | "latin": "Guizotia abyssinica", 169 | "number": "434", 170 | "oldnumber": "1.4.2.1.1" 171 | }, 172 | { 173 | "name": "Nutmeg", 174 | "latin": "Myristica fragrans", 175 | "number": "6222", 176 | "oldnumber": "2.2.3.5" 177 | }, 178 | { 179 | "name": "Oil palm", 180 | "latin": "Elaeis guineensis", 181 | "number": "443", 182 | "oldnumber": "2.2.2.2" 183 | } 184 | ] 185 | } 186 | -------------------------------------------------------------------------------- /examples/jest/public/crops/crops-7.json: -------------------------------------------------------------------------------- 1 | { 2 | "next": 8, 3 | "data": [ 4 | { 5 | "name": "Okra", 6 | "latin": "Abelmoschus esculentus", 7 | "number": "229", 8 | "oldnumber": "1.5.2.0.6" 9 | }, 10 | { 11 | "name": "Olive", 12 | "latin": "Olea europaea", 13 | "number": "442", 14 | "oldnumber": "2.2.2.3" 15 | }, 16 | { 17 | "name": "Onion seed", 18 | "latin": "Allium cepa", 19 | "number": "234", 20 | "oldnumber": "1.8.5" 21 | }, 22 | { 23 | "name": "Onion, dry", 24 | "latin": "Allium cepa", 25 | "number": "234", 26 | "oldnumber": "1.2.6" 27 | }, 28 | { 29 | "name": "Onion, green", 30 | "latin": "Allium cepa", 31 | "number": "234", 32 | "oldnumber": "1.5.3.3" 33 | }, 34 | { 35 | "name": "Opium", 36 | "latin": "Papaver somniferum", 37 | "number": "931", 38 | "oldnumber": "1.4.3.3" 39 | }, 40 | { 41 | "name": "Orange", 42 | "latin": "Citrus sinensis", 43 | "number": "323", 44 | "oldnumber": "2.1.1.1" 45 | }, 46 | { 47 | "name": "Orange, bitter", 48 | "latin": "Citrus aurantium", 49 | "number": "323", 50 | "oldnumber": "2.1.1.6" 51 | }, 52 | { 53 | "name": "Ornamental plants", 54 | "latin": "Various", 55 | "number": "951", 56 | "oldnumber": "1.6.1.2" 57 | }, 58 | { 59 | "name": "Palm palmyra", 60 | "latin": "Borassus flabellifer", 61 | "number": "992", 62 | "oldnumber": "2.2.7.4" 63 | }, 64 | { 65 | "name": "Palm, kernel oil ", 66 | "latin": "Elaeis guineensis", 67 | "number": "443", 68 | "oldnumber": "2.2.2.2" 69 | }, 70 | { 71 | "name": "Palm, oil ", 72 | "latin": "Elaeis guineensis", 73 | "number": "443", 74 | "oldnumber": "2.2.2.2" 75 | }, 76 | { 77 | "name": "Palm, sago ", 78 | "latin": "Metroxylon sagu", 79 | "number": "992", 80 | "oldnumber": "2.2.7.3" 81 | }, 82 | { 83 | "name": "Papaya (pawpaw)", 84 | "latin": "Carica papaya", 85 | "number": "316", 86 | "oldnumber": "2.1.6.0.9" 87 | }, 88 | { 89 | "name": "Parsnip", 90 | "latin": "Pastinaca sativa", 91 | "number": "239", 92 | "oldnumber": "1.5.3.8" 93 | }, 94 | { 95 | "name": "Pea, edible dry, for grain", 96 | "latin": "Pisum sativum", 97 | "number": "77", 98 | "oldnumber": "1.3.3" 99 | }, 100 | { 101 | "name": "Pea, harvested green", 102 | "latin": "Pisum sativum", 103 | "number": "77", 104 | "oldnumber": "1.5.4.2" 105 | }, 106 | { 107 | "name": "Peach", 108 | "latin": "Prunus persica", 109 | "number": "354", 110 | "oldnumber": "2.1.3.3" 111 | }, 112 | { 113 | "name": "Peanut (groundnut)", 114 | "latin": "Arachis hypogaea", 115 | "number": "42", 116 | "oldnumber": "1.4.2.0.1" 117 | }, 118 | { 119 | "name": "Pear", 120 | "latin": "Pyrus communis", 121 | "number": "355", 122 | "oldnumber": "2.1.2.2" 123 | }, 124 | { 125 | "name": "Pecan nut", 126 | "latin": "Carya illinoensis", 127 | "number": "369", 128 | "oldnumber": "2.1.7.6" 129 | }, 130 | { 131 | "name": "Pepper, black ", 132 | "latin": "Piper nigrum", 133 | "number": "6221", 134 | "oldnumber": "2.2.3.1" 135 | }, 136 | { 137 | "name": "Pigeon pea", 138 | "latin": "Cajanus cajan", 139 | "number": "78", 140 | "oldnumber": "1.3.7" 141 | }, 142 | { 143 | "name": "Pineapple", 144 | "latin": "Ananas comosus", 145 | "number": "317", 146 | "oldnumber": "2.1.6.1.1" 147 | }, 148 | { 149 | "name": "Pistachio nut", 150 | "latin": "Pistacia vera", 151 | "number": "365", 152 | "oldnumber": "2.1.7.6" 153 | }, 154 | { 155 | "name": "Plantain", 156 | "latin": "Musa sapientum", 157 | "number": "312", 158 | "oldnumber": "2.1.6.1.2" 159 | }, 160 | { 161 | "name": "Plum", 162 | "latin": "Prunus domestica", 163 | "number": "356", 164 | "oldnumber": "2.1.3.4" 165 | }, 166 | { 167 | "name": "Pomegranate", 168 | "latin": "Punica granatum", 169 | "number": "39", 170 | "oldnumber": "2.1.6.1.3" 171 | }, 172 | { 173 | "name": "Pomelo", 174 | "latin": "Citrus grandis", 175 | "number": "321", 176 | "oldnumber": "2.1.1.4" 177 | }, 178 | { 179 | "name": "Poppy seed", 180 | "latin": "Papaver somniferum", 181 | "number": "439", 182 | "oldnumber": "1.4.2.1.1" 183 | } 184 | ] 185 | } 186 | -------------------------------------------------------------------------------- /examples/jest/public/crops/crops-8.json: -------------------------------------------------------------------------------- 1 | { 2 | "next": 9, 3 | "data": [ 4 | { 5 | "name": "Potato", 6 | "latin": "Solamum tuberosum", 7 | "number": "51", 8 | "oldnumber": "1.2.1" 9 | }, 10 | { 11 | "name": "Potato, sweet", 12 | "latin": "Ipomoea batatas", 13 | "number": "52", 14 | "oldnumber": "1.2.2" 15 | }, 16 | { 17 | "name": "Prune", 18 | "latin": "Prunus domestica", 19 | "number": "356", 20 | "oldnumber": "2.1.3.4" 21 | }, 22 | { 23 | "name": "Pyrethum", 24 | "latin": "Chrysanthemum cinerariaefolium", 25 | "number": "991", 26 | "oldnumber": "1.4.5.3" 27 | }, 28 | { 29 | "name": "Queensland nut", 30 | "latin": "See Macadamia", 31 | "number": "369", 32 | "oldnumber": "2.1.7.6" 33 | }, 34 | { 35 | "name": "Quince", 36 | "latin": "Cydonia oblonga", 37 | "number": "355", 38 | "oldnumber": "2.1.2.3" 39 | }, 40 | { 41 | "name": "Quinoa", 42 | "latin": "Chenopodium quinoa", 43 | "number": "192", 44 | "oldnumber": "1.1.9" 45 | }, 46 | { 47 | "name": "Radish", 48 | "latin": "Raphanus sativus (inc. Cochlearia armoracia)", 49 | "number": "239", 50 | "oldnumber": "1.5.3.4" 51 | }, 52 | { 53 | "name": "Ramie", 54 | "latin": "Boehmeria nivea", 55 | "number": "922", 56 | "oldnumber": "2.2.4.5" 57 | }, 58 | { 59 | "name": "Rapeseed (colza)", 60 | "latin": "Brassica napus", 61 | "number": "435", 62 | "oldnumber": "1.4.2.0.5" 63 | }, 64 | { 65 | "name": "Raspberry (all varieties)", 66 | "latin": "Rubus spp. (over", 67 | "number": "3", 68 | "oldnumber": "60" 69 | }, 70 | { 71 | "name": "Red beet", 72 | "latin": "Beta vulgaris", 73 | "number": "239", 74 | "oldnumber": "1.5.3.5" 75 | }, 76 | { 77 | "name": "Redtop", 78 | "latin": "Agrostis spp.", 79 | "number": "911", 80 | "oldnumber": "1.7.2.1" 81 | }, 82 | { 83 | "name": "Rhea", 84 | "latin": "Boehmeria nivea", 85 | "number": "922", 86 | "oldnumber": "2.2.4.5" 87 | }, 88 | { 89 | "name": "Rhubarb", 90 | "latin": "Rheum spp.", 91 | "number": "219", 92 | "oldnumber": "1.5.1.1.3" 93 | }, 94 | { 95 | "name": "Rose", 96 | "latin": "Rose spp.", 97 | "number": "952", 98 | "oldnumber": "2.2.6.1" 99 | }, 100 | { 101 | "name": "Rubber", 102 | "latin": "Hevea brasiliensis", 103 | "number": "94", 104 | "oldnumber": "2.2.5.1" 105 | }, 106 | { 107 | "name": "Rutabaga (swede)", 108 | "latin": "Brassica napus var. napobrassica", 109 | "number": "239", 110 | "oldnumber": "1.5.3.6" 111 | }, 112 | { 113 | "name": "Rye", 114 | "latin": "Secale cereale", 115 | "number": "16", 116 | "oldnumber": "1.1.7" 117 | }, 118 | { 119 | "name": "Safflower", 120 | "latin": "Carthamus tinctorius", 121 | "number": "436", 122 | "oldnumber": "1.4.2.0.9" 123 | }, 124 | { 125 | "name": "Sainfoin", 126 | "latin": "Onobrychis viciifolia", 127 | "number": "911", 128 | "oldnumber": "1.7.1.3" 129 | }, 130 | { 131 | "name": "Salsify", 132 | "latin": "Tragopogon porrifolius", 133 | "number": "239", 134 | "oldnumber": "1.5.3.8" 135 | }, 136 | { 137 | "name": "Sapodilla", 138 | "latin": "Achras sapota", 139 | "number": "39", 140 | "oldnumber": "2.1.6.1.4" 141 | }, 142 | { 143 | "name": "Sesame", 144 | "latin": "Sesamum indicum", 145 | "number": "437", 146 | "oldnumber": "1.4.2.0.7" 147 | }, 148 | { 149 | "name": "Shea butter (nut)", 150 | "latin": "Vitellaria paradoxa", 151 | "number": "449", 152 | "oldnumber": "2.2.2.4" 153 | }, 154 | { 155 | "name": "Sisal", 156 | "latin": "Agave sisalana", 157 | "number": "922", 158 | "oldnumber": "2.2.4.2" 159 | }, 160 | { 161 | "name": "Sorghum", 162 | "latin": "Sorghum bicolor", 163 | "number": "14", 164 | "oldnumber": "1.1.5.2" 165 | }, 166 | { 167 | "name": "Sorghum, broom", 168 | "latin": "Sorghum bicolor", 169 | "number": "14", 170 | "oldnumber": "1.4.5.4" 171 | }, 172 | { 173 | "name": "Sorghum, durra", 174 | "latin": "Sorghum bicolor", 175 | "number": "14", 176 | "oldnumber": "1.1.5.2" 177 | }, 178 | { 179 | "name": "Sorghum, Guinea corn", 180 | "latin": "Sorghum bicolor", 181 | "number": "14", 182 | "oldnumber": "1.1.5.2" 183 | } 184 | ] 185 | } 186 | -------------------------------------------------------------------------------- /examples/jest/public/crops/crops-9.json: -------------------------------------------------------------------------------- 1 | { 2 | "next": 10, 3 | "data": [ 4 | { 5 | "name": "Sorghum, jowar", 6 | "latin": "Sorghum bicolor", 7 | "number": "14", 8 | "oldnumber": "1.1.5.2" 9 | }, 10 | { 11 | "name": "Sorghum, sweet", 12 | "latin": "Sorghum bicolor", 13 | "number": "183", 14 | "oldnumber": "1.4.1.3" 15 | }, 16 | { 17 | "name": "Soybean", 18 | "latin": "Glycine max", 19 | "number": "41", 20 | "oldnumber": "1.4.2.0.2" 21 | }, 22 | { 23 | "name": "Soybean hay", 24 | "latin": "Glycine max", 25 | "number": "41", 26 | "oldnumber": "1.7.1.3" 27 | }, 28 | { 29 | "name": "Spelt wheat", 30 | "latin": "Triticum spelta", 31 | "number": "192", 32 | "oldnumber": "1.1.9" 33 | }, 34 | { 35 | "name": "Spinach", 36 | "latin": "Spinacia oleracea", 37 | "number": "216", 38 | "oldnumber": "1.5.1.1.4" 39 | }, 40 | { 41 | "name": "Sugar beet", 42 | "latin": "Beta vulgaris", 43 | "number": "81", 44 | "oldnumber": "1.4.1.2" 45 | }, 46 | { 47 | "name": "Sugar beet for fodder", 48 | "latin": "Beta vulgaris", 49 | "number": "81", 50 | "oldnumber": "1.7.5.0.6" 51 | }, 52 | { 53 | "name": "Sugar beet for seed", 54 | "latin": "Beta vulgaris", 55 | "number": "81", 56 | "oldnumber": "1.8.1" 57 | }, 58 | { 59 | "name": "Sugarcane for fodder", 60 | "latin": "Saccharum officinarum", 61 | "number": "82", 62 | "oldnumber": "1.7.5.0.7" 63 | }, 64 | { 65 | "name": "Sugarcane for sugar or alcohol", 66 | "latin": "Saccharum officinarum", 67 | "number": "82", 68 | "oldnumber": "1.4.1.1" 69 | }, 70 | { 71 | "name": "Sugarcane for thatching", 72 | "latin": "Saccharum officinarum", 73 | "number": "82", 74 | "oldnumber": "1.4.5.4" 75 | }, 76 | { 77 | "name": "Sunflower for fodder", 78 | "latin": "Helianthus annuus", 79 | "number": "438", 80 | "oldnumber": "1.7.5.0.4" 81 | }, 82 | { 83 | "name": "Sunflower for oil seed", 84 | "latin": "Helianthus annuus", 85 | "number": "438", 86 | "oldnumber": "1.4.2.0.4" 87 | }, 88 | { 89 | "name": "Sunhemp", 90 | "latin": "Crotalaria juncea", 91 | "number": "9213", 92 | "oldnumber": "1.4.4.5" 93 | }, 94 | { 95 | "name": "Swede", 96 | "latin": "Brassica napus var. napobrassica", 97 | "number": "239", 98 | "oldnumber": "1.5.3.6" 99 | }, 100 | { 101 | "name": "Swede for fodder", 102 | "latin": "Brassica napus var. napobrassica", 103 | "number": "239", 104 | "oldnumber": "1.7.5.0.8" 105 | }, 106 | { 107 | "name": "Sweet corn", 108 | "latin": "Zea mays", 109 | "number": "12", 110 | "oldnumber": "1.5.5.2" 111 | }, 112 | { 113 | "name": "Sweet lime", 114 | "latin": "Citrus limetta", 115 | "number": "322", 116 | "oldnumber": "2.1.1.6" 117 | }, 118 | { 119 | "name": "Sweet pepper", 120 | "latin": "Capsicum annuum", 121 | "number": "6211", 122 | "oldnumber": "1.5.2.0.9" 123 | }, 124 | { 125 | "name": "Sweet potato", 126 | "latin": "Lopmoea batatas", 127 | "number": "52", 128 | "oldnumber": "1.2.2" 129 | }, 130 | { 131 | "name": "Sweet sorghum", 132 | "latin": "Sorghum bicolor", 133 | "number": "183", 134 | "oldnumber": "1.4.1.3" 135 | }, 136 | { 137 | "name": "Tangerine", 138 | "latin": "Citrus reticulata", 139 | "number": "324", 140 | "oldnumber": "2.1.1.2" 141 | }, 142 | { 143 | "name": "Tannia", 144 | "latin": "Xanthosoma sagittifolium", 145 | "number": "59", 146 | "oldnumber": "1.2.8" 147 | }, 148 | { 149 | "name": "Tapioca (cassava)", 150 | "latin": "Manihot esculenta", 151 | "number": "53", 152 | "oldnumber": "1.2.3" 153 | }, 154 | { 155 | "name": "Taro", 156 | "latin": "Colocasia esculenta", 157 | "number": "59", 158 | "oldnumber": "1.2.8" 159 | }, 160 | { 161 | "name": "Tea", 162 | "latin": "Camellia sinensis", 163 | "number": "612", 164 | "oldnumber": "2.2.1.3" 165 | }, 166 | { 167 | "name": "Tef", 168 | "latin": "Eragrostis abyssinica", 169 | "number": "192", 170 | "oldnumber": "1.1.9" 171 | }, 172 | { 173 | "name": "Timothy", 174 | "latin": "Phleum pratense", 175 | "number": "911", 176 | "oldnumber": "1.7.2.1" 177 | }, 178 | { 179 | "name": "Tobacco", 180 | "latin": "Nicotiana tabacum", 181 | "number": "96", 182 | "oldnumber": "1.4.5.1" 183 | } 184 | ] 185 | } 186 | -------------------------------------------------------------------------------- /examples/jest/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Svelte app 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/jest/rollup.config.js: -------------------------------------------------------------------------------- 1 | import svelte from 'rollup-plugin-svelte'; 2 | import resolve from 'rollup-plugin-node-resolve'; 3 | import commonjs from 'rollup-plugin-commonjs'; 4 | import livereload from 'rollup-plugin-livereload'; 5 | import { terser } from 'rollup-plugin-terser'; 6 | 7 | const production = !process.env.ROLLUP_WATCH; 8 | 9 | export default { 10 | input: 'src/main.js', 11 | output: { 12 | sourcemap: true, 13 | format: 'iife', 14 | name: 'app', 15 | file: 'public/bundle.js', 16 | }, 17 | plugins: [ 18 | svelte({ 19 | // enable run-time checks when not in production 20 | dev: !production, 21 | // we'll extract any component CSS out into 22 | // a separate file — better for performance 23 | css: css => { 24 | css.write('public/bundle.css'); 25 | }, 26 | }), 27 | 28 | // If you have external dependencies installed from 29 | // npm, you'll most likely need these plugins. In 30 | // some cases you'll need additional configuration — 31 | // consult the documentation for details: 32 | // https://github.com/rollup/rollup-plugin-commonjs 33 | resolve(), 34 | commonjs(), 35 | 36 | // Watch the `public` directory and refresh the 37 | // browser on changes when not in production 38 | !production && livereload('public'), 39 | 40 | // If we're building for production (npm run build 41 | // instead of npm run dev), minify 42 | production && terser(), 43 | ], 44 | watch: { 45 | clearScreen: false, 46 | }, 47 | }; 48 | -------------------------------------------------------------------------------- /examples/jest/src/App.svelte: -------------------------------------------------------------------------------- 1 | 49 | 50 | 273 | 274 | {#if options} 275 |
276 |
277 | 278 | 279 | 286 | {#if error} 287 | Please enter a name for your crop 288 | {/if} 289 | 290 | 295 | 301 | 306 |
307 | 308 |
309 | 310 | 311 |
312 |
313 | {/if} 314 | 315 |
316 | 317 |

318 | 🌾 319 | 🌾 320 |

321 | 322 |
323 |

good crop

324 |
325 | {#each $crops.data.filter(({ verdict }) => !verdict) as { name, latin, id, verdict } (id)} 326 | 338 | {/each} 339 |
340 |
341 | 342 |
343 |

bad crop

344 |
345 | {#each $crops.data.filter(({ verdict }) => verdict) as { name, latin, id, verdict } (id)} 346 | 358 | {/each} 359 |
360 |
361 | 362 |
363 | 364 |
365 | {#if $crops.next} 366 | 367 | {/if} 368 | 369 | 372 |
373 | -------------------------------------------------------------------------------- /examples/jest/src/get.js: -------------------------------------------------------------------------------- 1 | import { writable } from 'svelte/store'; 2 | 3 | let uuid = 0; 4 | 5 | const getCrops = n => fetch(`./crops/crops-${n}.json`); 6 | 7 | const formatData = ({ name, latin }) => ({ 8 | name, 9 | latin, 10 | verdict: !!~~(Math.random() * 2), 11 | id: uuid++, 12 | }); 13 | 14 | const copy = arr => arr.map(v => ({ ...v })); 15 | 16 | export const fetchStore = () => { 17 | let id = 1, 18 | cache = []; 19 | 20 | const { update, set, subscribe } = writable({ 21 | status: null, 22 | data: [], 23 | next: 1, 24 | }); 25 | 26 | const getSomeCrops = async () => { 27 | update(s => ({ ...s, status: 'pending' })); 28 | 29 | try { 30 | const { next, data } = await (await getCrops(id)).json(); 31 | 32 | const formatted = data.map(formatData); 33 | cache = cache.concat(copy(formatted)); 34 | 35 | update(s => ({ 36 | status: 'loaded', 37 | data: [...s.data, ...formatted], 38 | next, 39 | })); 40 | 41 | id = next; 42 | } catch (e) { 43 | update(s => ({ ...s, status: 'error', message: e.message })); 44 | } 45 | }; 46 | 47 | const reset = () => set({ status: 'loaded', data: copy(cache), next: id }); 48 | 49 | const change = changeId => 50 | update(s => { 51 | const newState = s.data.concat(); 52 | const theOne = newState.find(({ id }) => id === changeId); 53 | theOne.verdict = !theOne.verdict; 54 | return { ...s, data: newState }; 55 | }); 56 | 57 | const remove = changeId => 58 | update(s => ({ ...s, data: s.data.filter(({ id }) => id !== changeId) })); 59 | 60 | const add = ({ name, latin, verdict }) => 61 | update(s => ({ 62 | ...s, 63 | data: [ 64 | ...s.data, 65 | { 66 | name, 67 | latin: latin ? latin : 'Plantywanty Phromthegroundium', 68 | verdict, 69 | id: uuid++, 70 | }, 71 | ], 72 | })); 73 | 74 | return { subscribe, set, update, getSomeCrops, reset, change, remove, add }; 75 | }; 76 | -------------------------------------------------------------------------------- /examples/jest/src/less.js: -------------------------------------------------------------------------------- 1 | const less = require('less'); 2 | 3 | module.exports = function transformLess() { 4 | return { 5 | style: async ({ content, attributes, filename }) => { 6 | if (!attributes.lang || attributes.lang !== 'less') 7 | return { code: content, map: '' }; 8 | 9 | try { 10 | const { css, map, imports } = await less.render(content, { filename }); 11 | return { code: css, dependencies: imports, map }; 12 | } catch (err) { 13 | const { line, column, index: character, extract } = err; 14 | if (!(line && column && extract)) throw err; 15 | 16 | let frame; 17 | if (!extract[0]) { 18 | frame = extract.filter(v => v).map((l, i) => `${line + i}:${l}`); 19 | } else { 20 | frame = extract.filter(v => v).map((l, i) => `${line - 1 + i}:${l}`); 21 | } 22 | 23 | frame.splice(2, 0, '^'.padStart(column + line.toString().length + 2)); 24 | 25 | delete err.line; 26 | delete err.column; 27 | delete err.index; 28 | delete err.extract; 29 | err.frame = frame.join('\n'); 30 | 31 | err.start = { line, column, character }; 32 | err.end = err.start; 33 | 34 | throw err; 35 | } 36 | }, 37 | }; 38 | }(); -------------------------------------------------------------------------------- /examples/jest/src/main.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | }); 6 | export default app; 7 | -------------------------------------------------------------------------------- /examples/jest/test/app.test.js: -------------------------------------------------------------------------------- 1 | import App from '../src/App.svelte'; 2 | import { 3 | render, 4 | cleanup, 5 | fireEvent, 6 | wait, 7 | within, 8 | waitForElement, 9 | } from '@testing-library/svelte'; 10 | 11 | import mockData from './mockData.js'; 12 | 13 | function updateInput(node, value) { 14 | if (node.multiple) { 15 | Array.from(node.children).forEach(v => { 16 | if (value.includes(v.value)) { 17 | v.selected = !v.selected; 18 | } 19 | }); 20 | fireEvent.change(node); 21 | return; 22 | } 23 | node.value = value; 24 | fireEvent.input(node); 25 | } 26 | 27 | // mocking fetch since it doesn't exist in node and i don't want to deal with real data 28 | const fetchMock = jest.fn(); 29 | 30 | global.fetch = fetchMock.mockImplementation(n => { 31 | return Promise.resolve({ ok: true, json: () => mockData[n] }); 32 | }); 33 | 34 | // clear the DOM after each test and reset the fetch mock after all tests 35 | afterEach(cleanup); 36 | afterAll(() => (global.fetch = null)); 37 | 38 | test('smoke: it should compile and render without throwing', () => { 39 | expect(() => render(App)).not.toThrow(); 40 | }); 41 | 42 | test('Clicking the "Load Crops" button should call fetch', async () => { 43 | const { getByText } = render(App); 44 | 45 | // load the crops 46 | const button = getByText('Load more crops'); 47 | fireEvent.click(button); 48 | 49 | expect(fetchMock).toHaveBeenCalled(); 50 | 51 | // clear the internal mock data 52 | fetchMock.mockClear(); 53 | }); 54 | 55 | test('Clicking the "Load Crops" button twice should call fetch twice', async () => { 56 | const { getByText } = render(App); 57 | 58 | const button = getByText('Load more crops'); 59 | fireEvent.click(button); 60 | fireEvent.click(button); 61 | 62 | expect(fetchMock).toHaveBeenCalledTimes(2); 63 | 64 | // clear the mock 65 | fetchMock.mockClear(); 66 | }); 67 | 68 | test('If there are no more items to fetch the "Load Crops" button should not be rendered', async () => { 69 | const { getByText } = render(App); 70 | 71 | // Load two sets of crops 72 | const button = getByText('Load more crops'); 73 | 74 | // fetch returns a promise, so we need to wait for the next tick of the event loop for each request 75 | fireEvent.click(button); 76 | await wait(); 77 | fireEvent.click(button); 78 | await wait(); 79 | 80 | expect(() => getByText('Load more crops')).toThrowError(); 81 | }); 82 | 83 | test('Clicking the "Load Crops" button should render the items to the DOM', async () => { 84 | const { getByText, getByLabelText } = render(App); 85 | 86 | // Load the crops 87 | const button = getByText('Load more crops'); 88 | 89 | fireEvent.click(button); 90 | await wait(); 91 | 92 | // instead of just checking the length of the children, 93 | // we are making sure that the DOM reflects the actual data we loaded 94 | const findItems = () => 95 | Object.values(mockData)[0].data.map(({ name }) => 96 | getByLabelText(new RegExp(name)) 97 | ); 98 | 99 | expect(findItems).not.toThrow(); 100 | }); 101 | 102 | test('Clicking the "Load Crops" button twice should render both sets of items to the DOM', async () => { 103 | const { getByText, getByLabelText } = render(App); 104 | 105 | // Load two sets of crops 106 | const button = getByText('Load more crops'); 107 | 108 | fireEvent.click(button); 109 | await wait(); 110 | fireEvent.click(button); 111 | await wait(); 112 | 113 | // we will concatenate all data resuts to make checking the DOM easier 114 | const items = [ 115 | ...Object.values(mockData)[0].data, 116 | ...Object.values(mockData)[1].data, 117 | ]; 118 | 119 | const findItems = () => 120 | items.map(({ name }) => getByLabelText(new RegExp(name))); 121 | 122 | expect(findItems).not.toThrow(); 123 | }); 124 | 125 | test('Clicking an individual crop in a section should send it to the opposite', async () => { 126 | const { getByText, getByTestId } = render(App); 127 | 128 | // Load the crops 129 | const button = getByText('Load more crops'); 130 | 131 | fireEvent.click(button); 132 | await wait(); 133 | 134 | // Get a reference to the crop container elements 135 | const good = getByTestId('good'); 136 | const bad = getByTestId('bad'); 137 | 138 | // Store the length of the containers children before we do anything 139 | const goodBefore = good.children.length; 140 | const badBefore = bad.children.length; 141 | 142 | // Toggle an item from good to bad 143 | fireEvent.click(good.children[0]); 144 | 145 | // An items should have gone from good to bad 146 | // we need to wait until the transition animation has complete 147 | // we are comparing the stored length properties to the current ones to check 148 | await (() => expect(good.children.length).toBe(goodBefore - 1)); 149 | expect(bad.children.length).toBe(badBefore + 1); 150 | 151 | // Toggle another item from bad to good, and wait for the transition to complete 152 | fireEvent.click(bad.children[0]); 153 | 154 | // Things should be back to how they were 155 | await (() => expect(good.children.length).toBe(goodBefore)); 156 | await (() => expect(bad.children.length).toBe(badBefore)); 157 | }); 158 | 159 | test('Clicking the "Add Crop/ Hide Menu" button should show and hide the add crop form', async () => { 160 | const { getByText, getByLabelText } = render(App); 161 | 162 | // Show the form 163 | const showFormButton = getByText('Add a crop'); 164 | await showFormButton.click(); 165 | 166 | // Make sure it is there, these matchers throw errors if there isn't a match 167 | expect(() => getByLabelText('Common Name')).not.toThrow(); 168 | 169 | // Hide the form 170 | const hideFormButton = getByText('Close menu'); 171 | hideFormButton.click(); 172 | 173 | await (() => expect(() => getByLabelText('Common Name')).toThrow()); 174 | }); 175 | 176 | test('Adding a new crop and submitting the form should make it render into the document', async () => { 177 | const { getByText, getByLabelText, getByTestId } = render(App); 178 | 179 | // Show the form 180 | const showFormButton = getByText('Add a crop'); 181 | await showFormButton.click(); 182 | 183 | // Fill out the form and submit it 184 | const nameInput = getByLabelText('Common Name'); 185 | const latinInput = getByLabelText('Latin Name'); 186 | const goodBadInput = getByLabelText(/Verdict: Good or Bad/); 187 | const submitButton = getByText('Submit'); 188 | 189 | updateInput(nameInput, 'A Tree'); 190 | updateInput(latinInput, 'Treeus Maximus'); 191 | fireEvent.click(goodBadInput); 192 | await fireEvent.click(submitButton); 193 | 194 | // Get the good crop container 195 | const goodCrops = getByTestId('good'); 196 | 197 | expect(() => within(goodCrops).getByText(/A Tree/)).not.toThrow(); 198 | expect(() => within(goodCrops).getByText(/Treeus Maximus/)).not.toThrow(); 199 | }); 200 | 201 | test('Adding a new crop without a name should show a user error and not render into the document', async () => { 202 | const { getByText, getByTestId } = render(App); 203 | 204 | // Show the form 205 | const showFormButton = getByText('Add a crop'); 206 | await showFormButton.click(); 207 | 208 | // Submit the form without filling it 209 | const submitButton = getByText('Submit'); 210 | await fireEvent.click(submitButton); 211 | 212 | // Get the good and bad containers 213 | const goodCrops = getByTestId('good'); 214 | const badCrops = getByTestId('bad'); 215 | 216 | expect(() => getByText(/Please enter a name for your crop/)).not.toThrow(); 217 | expect(goodCrops.children.length).toBe(0); 218 | expect(badCrops.children.length).toBe(0); 219 | }); 220 | 221 | test('Adding a new crop without a latin name should use the default', async () => { 222 | const { getByText, getByLabelText, getByTestId } = render(App); 223 | 224 | // SHow the form 225 | const showFormButton = getByText('Add a crop'); 226 | await showFormButton.click(); 227 | 228 | // Fill it out the form but leave the latin name blank 229 | const nameInput = getByLabelText('Common Name'); 230 | const latinInput = getByLabelText('Latin Name'); 231 | const goodBadInput = getByLabelText(/Verdict: Good or Bad/); 232 | const submitButton = getByText('Submit'); 233 | 234 | updateInput(nameInput, 'A Tree'); 235 | updateInput(latinInput, ''); 236 | fireEvent.click(goodBadInput); 237 | await fireEvent.click(submitButton); 238 | 239 | // Get the good crop container 240 | const goodCrops = getByTestId('good'); 241 | 242 | expect(() => within(goodCrops).getByText(/A Tree/)).not.toThrow(); 243 | expect(() => 244 | within(goodCrops).getByText(/Plantywanty Phromthegroundium/) 245 | ).not.toThrow(); 246 | }); 247 | 248 | test('Adding a new crop without a latin name should use the default', async () => { 249 | const { getByText, getByLabelText, getByTestId } = render(App); 250 | 251 | // Load the crops 252 | const loadCropsbutton = getByText('Load more crops'); 253 | fireEvent.click(loadCropsbutton); 254 | await wait(); 255 | 256 | // Get the quantities of the rendered items 257 | const good = getByTestId('good'); 258 | const bad = getByTestId('bad'); 259 | const goodBefore = good.children.length; 260 | const badBefore = bad.children.length; 261 | 262 | // Toggle an item 263 | fireEvent.click(good.children[0]); 264 | 265 | // Show the Add Crop form 266 | const showFormButton = await waitForElement(() => getByText('Add a crop')); 267 | await showFormButton.click(); 268 | 269 | // Add a crop 270 | const nameInput = getByLabelText('Common Name'); 271 | const latinInput = getByLabelText('Latin Name'); 272 | const goodBadInput = getByLabelText(/Verdict: Good or Bad/); 273 | const submitButton = getByText('Submit'); 274 | updateInput(nameInput, 'A Tree'); 275 | updateInput(latinInput, ''); 276 | fireEvent.click(goodBadInput); 277 | await fireEvent.click(submitButton); 278 | 279 | // Reset the crops 280 | const resetCropsbutton = getByText('Reset crops'); 281 | fireEvent.click(resetCropsbutton); 282 | 283 | await (() => expect(good.children.length).toBe(goodBefore)); 284 | await (() => expect(bad.children.length).toBe(badBefore)); 285 | }); 286 | -------------------------------------------------------------------------------- /examples/jest/test/mockData.js: -------------------------------------------------------------------------------- 1 | export default { 2 | './crops/crops-1.json': { 3 | next: 2, 4 | data: [ 5 | { 6 | name: 'Set 1 - Name 1', 7 | latin: 'Set 1 - Latin 1', 8 | number: '1', 9 | oldnumber: 'old 1', 10 | }, 11 | { 12 | name: 'Set 1 - Name 2', 13 | latin: 'Set 1 - Latin 2', 14 | number: '2', 15 | oldnumber: 'old 2', 16 | }, 17 | { 18 | name: 'Set 1 - Name 3', 19 | latin: 'Set 1 - Latin 3', 20 | number: '3', 21 | oldnumber: 'old 3', 22 | }, 23 | { 24 | name: 'Set 1 - Name 4', 25 | latin: 'Set 1 - Latin 4', 26 | number: '4', 27 | oldnumber: 'old 4', 28 | }, 29 | { 30 | name: 'Set 1 - Name 5', 31 | latin: 'Set 1 - Latin 5', 32 | number: '5', 33 | oldnumber: 'old 5', 34 | }, 35 | ], 36 | }, 37 | './crops/crops-2.json': { 38 | next: null, 39 | data: [ 40 | { 41 | name: 'Set 2 - Name 6', 42 | latin: 'Set2 - Latin 6', 43 | number: '6', 44 | oldnumber: 'old 6', 45 | }, 46 | { 47 | name: 'Set 2 - Name 7', 48 | latin: 'Set 2 - Latin 7', 49 | number: '7', 50 | oldnumber: 'old 7', 51 | }, 52 | { 53 | name: 'Set 2 - Name 8', 54 | latin: 'Set 2 - Latin 8', 55 | number: '8', 56 | oldnumber: 'old 8', 57 | }, 58 | { 59 | name: 'Set 2 - Name 9', 60 | latin: 'Set 2 - Latin 9', 61 | number: '9', 62 | oldnumber: 'old 9', 63 | }, 64 | { 65 | name: 'Set 2 - Name 10', 66 | latin: 'Set 2 - Latin 10', 67 | number: '10', 68 | oldnumber: 'old 10', 69 | }, 70 | ], 71 | }, 72 | }; 73 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | const transformLess = require('./test/less.js'); 2 | 3 | module.exports = { 4 | testPathIgnorePatterns: ['/node_modules/', '/examples/'], 5 | transform: { 6 | '^.+\\.svelte$': './transform.js', 7 | '^.+\\.js$': 'babel-jest', 8 | }, 9 | globals: { 10 | svelte: { 11 | preprocess: [transformLess], 12 | compilerOptions: { 13 | accessors: true, 14 | }, 15 | }, 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-test", 3 | "description": "testing utilities for svelte", 4 | "version": "0.4.0", 5 | "scripts": { 6 | "jest": "jest", 7 | "jest:watch": "jest --watchAll --no-cache", 8 | "build": "rollup -c" 9 | }, 10 | "dependencies": { 11 | "cosmiconfig": "^5.2.0" 12 | }, 13 | "devDependencies": { 14 | "@babel/core": "^7.4.4", 15 | "@babel/plugin-syntax-dynamic-import": "^7.0.0", 16 | "@babel/plugin-transform-runtime": "^7.4.4", 17 | "@babel/preset-env": "^7.4.4", 18 | "@babel/runtime": "^7.0.0", 19 | "@testing-library/svelte": "^1.7.1", 20 | "@types/jest": "^24.0.13", 21 | "babel-jest": "^24.8.0", 22 | "jest": "^24.8.0", 23 | "just-merge": "^1.1.0", 24 | "less": "^3.9.0", 25 | "require-extension-hooks": "^0.3.3", 26 | "rollup": "^1.12.4", 27 | "rollup-plugin-commonjs": "^10.0.0", 28 | "rollup-plugin-node-resolve": "^5.0.0", 29 | "svelte": "^3.0.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /preprocess.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const svelte = require('svelte/compiler'); 4 | 5 | if (process.env.jest) { 6 | const cosmiconfig = require('cosmiconfig'); 7 | const explorer = cosmiconfig('jest'); 8 | 9 | explorer 10 | .search() 11 | .then(result => { 12 | svelte 13 | .preprocess( 14 | process.env.sveltest, 15 | result.config.globals.svelte.preprocess 16 | ) 17 | .then(v => { 18 | process.stdout.write(v.code); 19 | }); 20 | }) 21 | .catch(error => { 22 | throw Error('Something bad happened', error); 23 | }); 24 | } else { 25 | const plugins = require(process.env.svelteplugins); 26 | svelte 27 | .preprocess(process.env.sveltest, plugins) 28 | .then(v => { 29 | process.stdout.write(v.code); 30 | }) 31 | .catch(error => { 32 | throw new Error(error); 33 | }); 34 | } 35 | -------------------------------------------------------------------------------- /require.js: -------------------------------------------------------------------------------- 1 | const svelte = require('svelte/compiler'); 2 | const { execSync } = require('child_process'); 3 | const { join } = require('path'); 4 | 5 | module.exports = (preprocessors, compilerOptions) => ({ content }) => { 6 | const preprocess = join(__dirname, './preprocess.js'); 7 | 8 | let processed = content; 9 | 10 | if (preprocessors) { 11 | process.env.sveltest = content; 12 | process.env.svelteplugins = preprocessors; 13 | processed = execSync(`node ${preprocess}`).toString(); 14 | } 15 | 16 | const compiled = svelte.compile(processed, { 17 | ...compilerOptions, 18 | format: 'cjs', 19 | }); 20 | 21 | return `${compiled.js.code}`; 22 | }; 23 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve'; 2 | import commonjs from 'rollup-plugin-commonjs'; 3 | import pkg from './package.json'; 4 | 5 | const opts = { 6 | plugins: [resolve({ preferBuiltins: true }), commonjs()], 7 | }; 8 | 9 | export default [ 10 | { 11 | ...opts, 12 | input: 'src/render.js', 13 | output: [ 14 | { file: pkg.module, format: 'es', sourcemap: false }, 15 | { file: pkg.main, format: 'cjs', sourcemap: false }, 16 | ], 17 | }, 18 | ]; 19 | -------------------------------------------------------------------------------- /src/render.js: -------------------------------------------------------------------------------- 1 | import { getQueriesForElement, prettyDOM } from 'dom-testing-library'; 2 | 3 | export * from 'dom-testing-library'; 4 | 5 | const mountedContainers = new Set(); 6 | 7 | export function updateInput(node, value) { 8 | if (node.multiple) { 9 | Array.from(node.children).forEach(v => { 10 | if (value.includes(v.value)) { 11 | v.selected = !v.selected; 12 | } 13 | }); 14 | fireEvent.change(node); 15 | return; 16 | } 17 | node.value = value; 18 | fireEvent.input(node); 19 | } 20 | 21 | export const render = ( 22 | Component, 23 | { target = document.createElement('div'), ...options } = {} 24 | ) => { 25 | document.body.appendChild(target); 26 | 27 | const ComponentConstructor = Component.default || Component; 28 | 29 | const component = new ComponentConstructor({ 30 | ...options, 31 | target, 32 | }); 33 | 34 | mountedContainers.add({ target, component }); 35 | return { 36 | component, 37 | target, 38 | // eslint-disable-next-line no-console 39 | debug: (el = document.body) => console.log(prettyDOM(el)), 40 | ...getQueriesForElement(document.body), 41 | }; 42 | }; 43 | 44 | const cleanupAtContainer = container => { 45 | const { target, component } = container; 46 | component.$destroy(); 47 | /* istanbul ignore else */ 48 | if (target.parentNode === document.body) { 49 | document.body.removeChild(target); 50 | } 51 | mountedContainers.delete(container); 52 | }; 53 | 54 | export const cleanup = () => { 55 | mountedContainers.forEach(cleanupAtContainer); 56 | }; 57 | -------------------------------------------------------------------------------- /test/Hello.test.js: -------------------------------------------------------------------------------- 1 | const { render, fireEvent } = require('@testing-library/svelte'); 2 | import Hello from './src/components/Hello.svelte'; 3 | 4 | test('clicking the button should change the text', async () => { 5 | const { getByText } = render(Hello); 6 | 7 | const button = getByText('Change'); 8 | const button2 = getByText('Change Again'); 9 | const h1 = getByText('Hello World'); 10 | 11 | await fireEvent.click(button); 12 | expect(h1.innerHTML).toBe('Hello Everybody'); 13 | 14 | await fireEvent.click(button2); 15 | expect(h1.innerHTML).toBe('Hello Nobody'); 16 | }); 17 | -------------------------------------------------------------------------------- /test/Hello10.test.js: -------------------------------------------------------------------------------- 1 | const { render, fireEvent } = require('@testing-library/svelte'); 2 | const Hello = require('./src/components/Hello.svelte'); 3 | 4 | test('clicking the button should change the text', async () => { 5 | const { getByText } = render(Hello); 6 | 7 | const button = getByText('Change'); 8 | const button2 = getByText('Change Again'); 9 | const h1 = getByText('Hello World'); 10 | 11 | await fireEvent.click(button); 12 | expect(h1.innerHTML).toBe('Hello Everybody'); 13 | 14 | await fireEvent.click(button2); 15 | expect(h1.innerHTML).toBe('Hello Nobody'); 16 | }); 17 | -------------------------------------------------------------------------------- /test/Hello11.test.js: -------------------------------------------------------------------------------- 1 | const { render, fireEvent } = require('@testing-library/svelte'); 2 | const Hello = require('./src/components/Hello.svelte'); 3 | 4 | test('clicking the button should change the text', async () => { 5 | const { getByText } = render(Hello); 6 | 7 | const button = getByText('Change'); 8 | const button2 = getByText('Change Again'); 9 | const h1 = getByText('Hello World'); 10 | 11 | await fireEvent.click(button); 12 | expect(h1.innerHTML).toBe('Hello Everybody'); 13 | 14 | await fireEvent.click(button2); 15 | expect(h1.innerHTML).toBe('Hello Nobody'); 16 | }); 17 | -------------------------------------------------------------------------------- /test/Hello2.test.js: -------------------------------------------------------------------------------- 1 | const { render, fireEvent } = require('@testing-library/svelte'); 2 | const Hello = require('./src/components/Hello.svelte'); 3 | 4 | test('clicking the button should change the text', async () => { 5 | const { getByText } = render(Hello); 6 | 7 | const button = getByText('Change'); 8 | const button2 = getByText('Change Again'); 9 | const h1 = getByText('Hello World'); 10 | 11 | await fireEvent.click(button); 12 | expect(h1.innerHTML).toBe('Hello Everybody'); 13 | 14 | await fireEvent.click(button2); 15 | expect(h1.innerHTML).toBe('Hello Nobody'); 16 | }); 17 | -------------------------------------------------------------------------------- /test/Hello3.test.js: -------------------------------------------------------------------------------- 1 | const { render, fireEvent } = require('@testing-library/svelte'); 2 | const Hello = require('./src/components/Hello.svelte'); 3 | 4 | test('clicking the button should change the text', async () => { 5 | const { getByText } = render(Hello); 6 | 7 | const button = getByText('Change'); 8 | const button2 = getByText('Change Again'); 9 | const h1 = getByText('Hello World'); 10 | 11 | await fireEvent.click(button); 12 | expect(h1.innerHTML).toBe('Hello Everybody'); 13 | 14 | await fireEvent.click(button2); 15 | expect(h1.innerHTML).toBe('Hello Nobody'); 16 | }); 17 | -------------------------------------------------------------------------------- /test/Hello4.test.js: -------------------------------------------------------------------------------- 1 | const { render, fireEvent } = require('@testing-library/svelte'); 2 | const Hello = require('./src/components/Hello.svelte'); 3 | 4 | test('clicking the button should change the text', async () => { 5 | const { getByText } = render(Hello); 6 | 7 | const button = getByText('Change'); 8 | const button2 = getByText('Change Again'); 9 | const h1 = getByText('Hello World'); 10 | 11 | await fireEvent.click(button); 12 | expect(h1.innerHTML).toBe('Hello Everybody'); 13 | 14 | await fireEvent.click(button2); 15 | expect(h1.innerHTML).toBe('Hello Nobody'); 16 | }); 17 | -------------------------------------------------------------------------------- /test/Hello5.test.js: -------------------------------------------------------------------------------- 1 | const { render, fireEvent } = require('@testing-library/svelte'); 2 | const Hello = require('./src/components/Hello.svelte'); 3 | 4 | test('clicking the button should change the text', async () => { 5 | const { getByText } = render(Hello); 6 | 7 | const button = getByText('Change'); 8 | const button2 = getByText('Change Again'); 9 | const h1 = getByText('Hello World'); 10 | 11 | await fireEvent.click(button); 12 | expect(h1.innerHTML).toBe('Hello Everybody'); 13 | 14 | await fireEvent.click(button2); 15 | expect(h1.innerHTML).toBe('Hello Nobody'); 16 | }); 17 | -------------------------------------------------------------------------------- /test/Hello6.test.js: -------------------------------------------------------------------------------- 1 | const { render, fireEvent } = require('@testing-library/svelte'); 2 | const Hello = require('./src/components/Hello.svelte'); 3 | 4 | test('clicking the button should change the text', async () => { 5 | const { getByText } = render(Hello); 6 | 7 | const button = getByText('Change'); 8 | const button2 = getByText('Change Again'); 9 | const h1 = getByText('Hello World'); 10 | 11 | await fireEvent.click(button); 12 | expect(h1.innerHTML).toBe('Hello Everybody'); 13 | 14 | await fireEvent.click(button2); 15 | expect(h1.innerHTML).toBe('Hello Nobody'); 16 | }); 17 | -------------------------------------------------------------------------------- /test/Hello7.test.js: -------------------------------------------------------------------------------- 1 | const { render, fireEvent } = require('@testing-library/svelte'); 2 | const Hello = require('./src/components/Hello.svelte'); 3 | 4 | test('clicking the button should change the text', async () => { 5 | const { getByText } = render(Hello); 6 | 7 | const button = getByText('Change'); 8 | const button2 = getByText('Change Again'); 9 | const h1 = getByText('Hello World'); 10 | 11 | await fireEvent.click(button); 12 | expect(h1.innerHTML).toBe('Hello Everybody'); 13 | 14 | await fireEvent.click(button2); 15 | expect(h1.innerHTML).toBe('Hello Nobody'); 16 | }); 17 | -------------------------------------------------------------------------------- /test/Hello8.test.js: -------------------------------------------------------------------------------- 1 | const { render, fireEvent } = require('@testing-library/svelte'); 2 | const Hello = require('./src/components/Hello.svelte'); 3 | 4 | test('clicking the button should change the text', async () => { 5 | const { getByText } = render(Hello); 6 | 7 | const button = getByText('Change'); 8 | const button2 = getByText('Change Again'); 9 | const h1 = getByText('Hello World'); 10 | 11 | await fireEvent.click(button); 12 | expect(h1.innerHTML).toBe('Hello Everybody'); 13 | 14 | await fireEvent.click(button2); 15 | expect(h1.innerHTML).toBe('Hello Nobody'); 16 | }); 17 | -------------------------------------------------------------------------------- /test/Hello9.test.js: -------------------------------------------------------------------------------- 1 | const { render, fireEvent } = require('@testing-library/svelte'); 2 | const Hello = require('./src/components/Hello.svelte'); 3 | 4 | test('clicking the button should change the text', async () => { 5 | const { getByText } = render(Hello); 6 | 7 | const button = getByText('Change'); 8 | const button2 = getByText('Change Again'); 9 | const h1 = getByText('Hello World'); 10 | 11 | await fireEvent.click(button); 12 | expect(h1.innerHTML).toBe('Hello Everybody'); 13 | 14 | await fireEvent.click(button2); 15 | expect(h1.innerHTML).toBe('Hello Nobody'); 16 | }); 17 | -------------------------------------------------------------------------------- /test/Input.test.js: -------------------------------------------------------------------------------- 1 | const { render, fireEvent, cleanup } = require('@testing-library/svelte'); 2 | const Inputs = require('./src/components/Inputs.svelte'); 3 | 4 | function updateInput(node, value) { 5 | if (node.multiple) { 6 | Array.from(node.children).forEach(v => { 7 | if (value.includes(v.value)) { 8 | v.selected = !v.selected; 9 | } 10 | }); 11 | fireEvent.change(node); 12 | return; 13 | } 14 | node.value = value; 15 | fireEvent.input(node); 16 | } 17 | 18 | const { getByLabelText, getByText, getAllByLabelText } = render(Inputs); 19 | 20 | afterAll(cleanup); 21 | 22 | test('updating textareas should work', async () => { 23 | const input = getByLabelText('Fill in the textarea:'); 24 | const output = getByText(/Value TA:/); 25 | 26 | await updateInput(input, 'Frank'); 27 | expect(output.innerHTML).toBe('Value TA: Frank'); 28 | }); 29 | 30 | test('updating text inputs should work', async () => { 31 | const input = getByLabelText('Email'); 32 | const output = getByText(/^Value EM:.*/); 33 | 34 | await updateInput(input, 'my@email.com'); 35 | expect(output.innerHTML).toBe('Value EM: my@email.com'); 36 | }); 37 | 38 | test('updating number inputs should work', async () => { 39 | const input = getByLabelText('Age'); 40 | const output = getByText(/Value NU:/); 41 | 42 | await updateInput(input, 25); 43 | expect(output.innerHTML).toBe('Value NU: 25'); 44 | }); 45 | 46 | test('updating color inputs should work', async () => { 47 | const input = getByLabelText('Eye color'); 48 | const output = getByText(/Value CO:/); 49 | 50 | await updateInput(input, '#111111'); 51 | expect(output.innerHTML).toBe('Value CO: #111111'); 52 | }); 53 | 54 | test('updating range inputs should work', async () => { 55 | const input = getByLabelText('Slidey'); 56 | const output = getByText(/Value RA:/); 57 | 58 | await updateInput(input, 50); 59 | expect(output.innerHTML).toBe('Value RA: 50'); 60 | }); 61 | 62 | test('updating Checkbox inputs should work', async () => { 63 | const input = getByLabelText('Is it true what they said?'); 64 | const output = getByText(/Value CB:/); 65 | 66 | await fireEvent.click(input); 67 | expect(output.innerHTML).toBe('Value CB: false'); 68 | }); 69 | 70 | test('updating Checkbox inputs should work', async () => { 71 | const input = getAllByLabelText(/Rice|Beans|Cheese|Guac/); 72 | const output = getByText(/Value CBG:/); 73 | 74 | await input.map(element => fireEvent.click(element)); 75 | expect(output.innerHTML).toBe('Value CBG: Rice,Beans,Cheese,Guac (extra)'); 76 | }); 77 | 78 | test('updating Radio inputs should work', async () => { 79 | const input = getByLabelText(/Plain/); 80 | const output = getByText(/Value RAD:/); 81 | 82 | await fireEvent.click(input); 83 | expect(output.innerHTML).toBe('Value RAD: Plain'); 84 | }); 85 | 86 | test('updating Select elements should work', async () => { 87 | const input = getByLabelText(/abc/); 88 | const output = getByText(/Value SE:/); 89 | 90 | await updateInput(input, 'a'); 91 | expect(output.innerHTML).toBe('Value SE: a'); 92 | }); 93 | 94 | test('updating Multi-Select elements should work', async () => { 95 | const input = getByLabelText(/fillings2/); 96 | const output = getByText(/Value MS:/); 97 | 98 | await updateInput(input, ['Rice', 'Cheese']); 99 | expect(output.innerHTML).toBe('Value MS: Rice,Cheese'); 100 | }); 101 | -------------------------------------------------------------------------------- /test/compilerOptions.test.js: -------------------------------------------------------------------------------- 1 | const { render } = require('@testing-library/svelte'); 2 | import Hello from './src/components/Compiler.svelte'; 3 | 4 | test('accessors should work', async () => { 5 | const { component, getByText, debug } = render(Hello); 6 | 7 | component.word = 'Everybody'; 8 | expect(() => getByText('Hello Everybody')).not.toThrow(); 9 | }); 10 | -------------------------------------------------------------------------------- /test/index.test.js: -------------------------------------------------------------------------------- 1 | const { render } = require('@testing-library/svelte'); 2 | const Hello = require('./src/routes/index.svelte'); 3 | 4 | test('clicking the button should change the text', async () => { 5 | const { getByText } = render(Hello); 6 | 7 | const text = getByText('HIGH FIVE!'); 8 | 9 | expect(text).toBeTruthy(); 10 | }); 11 | -------------------------------------------------------------------------------- /test/less.js: -------------------------------------------------------------------------------- 1 | const less = require('less'); 2 | 3 | module.exports = function transformLess() { 4 | return { 5 | style: async ({ content, attributes, filename }) => { 6 | if (!attributes.lang || attributes.lang !== 'less') 7 | return { code: content, map: '' }; 8 | 9 | try { 10 | const { css, map, imports } = await less.render(content, { filename }); 11 | return { code: css, dependencies: imports, map }; 12 | } catch (err) { 13 | const { line, column, index: character, extract } = err; 14 | if (!(line && column && extract)) throw err; 15 | 16 | let frame; 17 | if (!extract[0]) { 18 | frame = extract.filter(v => v).map((l, i) => `${line + i}:${l}`); 19 | } else { 20 | frame = extract.filter(v => v).map((l, i) => `${line - 1 + i}:${l}`); 21 | } 22 | 23 | frame.splice(2, 0, '^'.padStart(column + line.toString().length + 2)); 24 | 25 | delete err.line; 26 | delete err.column; 27 | delete err.index; 28 | delete err.extract; 29 | err.frame = frame.join('\n'); 30 | 31 | err.start = { line, column, character }; 32 | err.end = err.start; 33 | 34 | throw err; 35 | } 36 | }, 37 | }; 38 | }(); -------------------------------------------------------------------------------- /test/require-hook.js: -------------------------------------------------------------------------------- 1 | var svelte = require('../require'); 2 | var hooks = require('require-extension-hooks'); 3 | const { JSDOM } = require('jsdom'); 4 | const { join } = require('path'); 5 | 6 | const preprocessors = join(__dirname, './less.js'); 7 | const compilerOptions = { accessors: true }; 8 | 9 | hooks('.svelte').push(svelte(preprocessors, compilerOptions)); 10 | 11 | const App = require('./src/components/Compiler.svelte').default; 12 | 13 | console.log(App); 14 | 15 | const doc = new JSDOM(``, { runScripts: 'dangerously' }); 16 | document = doc.window.document; 17 | 18 | const app = new App({ target: doc.window.document.body }); 19 | console.log(app); 20 | console.log(doc.window.document.body.innerHTML); 21 | 22 | app.word = 'Everybody'; 23 | console.log(doc.window.document.body.innerHTML); 24 | -------------------------------------------------------------------------------- /test/src/components/Compiler.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 18 | 19 | 20 | 21 |

Hello {word}

22 | -------------------------------------------------------------------------------- /test/src/components/Hello.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 24 | 25 | 26 | 27 | 28 |

Hello {word}

29 | 30 | 31 | -------------------------------------------------------------------------------- /test/src/components/Inputs.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 39 | 40 |
41 |

Textarea

42 | 43 |