├── .babelrc ├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── .npmignore ├── .npmrc ├── .tav.yml ├── LICENSE.txt ├── README.md ├── jest.config.js ├── other └── cricket.png ├── package.json ├── rollup.config.js ├── src ├── __tests__ │ └── select-event.test.tsx ├── act-compat.ts └── index.ts ├── tsconfig.build.json └── tsconfig.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["@babel/plugin-proposal-class-properties"], 3 | "presets": ["@babel/preset-react", "@babel/preset-typescript"], 4 | "env": { 5 | "test": { 6 | "presets": ["@babel/preset-env", "@babel/preset-typescript"], 7 | "plugins": ["@babel/plugin-transform-runtime"] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | ignore: 9 | - dependency-name: "@types/react-select" 10 | versions: 11 | - 4.0.11 12 | - 4.0.12 13 | - 4.0.7 14 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - '+([0-9])?(.{+([0-9]),x}).x' 6 | - 'main' 7 | - 'master' 8 | - 'ci' 9 | - 'test' 10 | - 'next' 11 | - 'next-major' 12 | - 'beta' 13 | - 'alpha' 14 | - '!all-contributors/**' 15 | pull_request: {} 16 | jobs: 17 | build: 18 | runs-on: ubuntu-latest 19 | strategy: 20 | matrix: 21 | node: ['14', '16'] 22 | name: Build & test (Node ${{ matrix.node }}) 23 | steps: 24 | - uses: actions/checkout@v2 25 | - name: Setup node 26 | uses: actions/setup-node@v2 27 | with: 28 | node-version: ${{ matrix.node }} 29 | 30 | # Install & build & test: 31 | - run: npm install 32 | - run: npm run type:check 33 | - run: npm run prettier:check 34 | - run: npm run test:all-versions 35 | - run: npm run build 36 | - run: npm pack 37 | 38 | coverage: 39 | needs: build 40 | runs-on: ubuntu-latest 41 | steps: 42 | - uses: actions/checkout@v2 43 | - name: Setup node 44 | uses: actions/setup-node@v2 45 | with: 46 | node-version: 16 47 | - run: npm install 48 | - run: npm install -g codecov 49 | - run: npm test -- --coverage # enforce 100% coverage when testing against the latest react-select 50 | - run: codecov 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | lib 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .babelrc 2 | .git 3 | .gitignore 4 | .npmignore 5 | .npmrc 6 | .prettierrc 7 | .tav.yml 8 | *.tgz 9 | coverage 10 | jest.config.js 11 | node_modules 12 | other 13 | rollup.config.js 14 | tsconfig.build.json 15 | tsconfig.json 16 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.tav.yml: -------------------------------------------------------------------------------- 1 | react-select: 2 | - versions: ^2.1 || ^3.0.2 3 | commands: npm test 4 | # we can't test agains 2.0.0 because of https://github.com/JedWatson/react-select/pull/2903 5 | peerDependencies: 6 | - react@16 7 | - react-dom@16 8 | - versions: ^4 || ^5 9 | commands: npm test 10 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2019 Romain Bertrand 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

react-select-event

3 | 4 | cricket 5 | 6 | 7 |

Simulate user events on react-select elements, for use with react-testing-library.

8 | 9 |
10 |
11 | 12 |
13 | 14 | [![npm version](https://badge.fury.io/js/react-select-event.svg)](https://badge.fury.io/js/react-select-event) 15 | [![Build Status](https://github.com/romgain/react-select-event/actions/workflows/ci.yml/badge.svg)](https://github.com/romgain/react-select-event/actions) 16 | [![Coverage report](https://codecov.io/gh/romgain/react-select-event/branch/master/graph/badge.svg)](https://codecov.io/gh/romgain/react-select-event) 17 | [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier) 18 | 19 | ## Install 20 | 21 | ```bash 22 | npm install --save-dev react-select-event 23 | ``` 24 | 25 | Import `react-select-event` in your unit tests: 26 | 27 | ```js 28 | import selectEvent from "react-select-event"; 29 | // or 30 | const selectEvent = require("react-select-event"); 31 | ``` 32 | 33 | ### Supported versions of `react-select` 34 | 35 | This library is tested against all versions of `react-select` starting from `2.1.0`. 36 | 37 | ## API 38 | 39 | Every helper exported by `react-select-event` takes a handle on the `react-select` input field as its first argument. For instance, this can be: `getByLabelText("Your label name")`. 40 | 41 | ### `select(input: HTMLElement, optionOrOptions: Matcher | Array, config?: object): Promise` 42 | 43 | The `optionOrOptions` parameter can be any valid dom-testing-library [TextMatch](https://testing-library.com/docs/queries/about#textmatch) object (eg. string, regex, function, number). 44 | 45 | Select one or more values in a react-select dropdown. 46 | 47 | ```jsx 48 | const { getByRole, getByLabelText } = render( 49 |
50 | 51 | 105 |
106 | ); 107 | await selectEvent.select(getByLabelText("Food"), ["Strawberry", "Mango"], { 108 | container: document.body, 109 | }); 110 | expect(getByRole("form")).toHaveFormValues({ food: ["strawberry", "mango"] }); 111 | ``` 112 | 113 | The container can also be passed in as a function if it needs to be lazily evaluated: 114 | 115 | ```jsx 116 | const { getByRole, getByLabelText } = render( 117 |
118 | 119 | 211 |
212 | ); 213 | expect(queryByText("Pizza")).toBeNull(); 214 | selectEvent.openMenu(getByLabelText("Food")); 215 | expect(getByText("Pizza")).toBeInTheDocument(); 216 | ``` 217 | 218 | ## Credits 219 | 220 | All the credit goes to [Daniel](https://stackoverflow.com/users/164268/daniel) and his StackOverflow answer: [https://stackoverflow.com/a/56085734](https://stackoverflow.com/a/56085734). 221 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: "jsdom", 3 | coverageThreshold: { 4 | global: { 5 | branches: 100, 6 | functions: 100, 7 | lines: 100, 8 | statements: 100 9 | } 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /other/cricket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/romgain/react-select-event/8619e8b3da349eadfa7321ea4aa2b7eee7209f9f/other/cricket.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-select-event", 3 | "version": "5.5.1", 4 | "description": "Simulate react-select events for react-testing-library", 5 | "main": "lib/react-select-event.cjs.js", 6 | "module": "lib/react-select-event.es.js", 7 | "types": "lib/index.d.ts", 8 | "scripts": { 9 | "clean": "rimraf lib", 10 | "build": "npm run clean && npm run build:lib && npm run build:types", 11 | "build:lib": "rollup -c", 12 | "build:types": "tsc -p tsconfig.build.json", 13 | "prettier:check": "prettier --list-different \"src/**/*.{ts,tsx,js,md}\" \"**/*.md\"", 14 | "prettier:apply": "prettier --write \"src/**/*.{ts,tsx,js}\" \"**/*.md\"", 15 | "type:check": "tsc --noEmit", 16 | "prepublishOnly": "npm run build", 17 | "test": "jest", 18 | "test:all-versions": "tav" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/romgain/react-select-event.git" 23 | }, 24 | "keywords": [ 25 | "react-testing-library", 26 | "dom-testing-library", 27 | "react-select", 28 | "testing", 29 | "javascript", 30 | "unit-testing" 31 | ], 32 | "author": "Romain Bertrand", 33 | "license": "MIT", 34 | "bugs": { 35 | "url": "https://github.com/romgain/react-select-event/issues" 36 | }, 37 | "homepage": "https://github.com/romgain/react-select-event#readme", 38 | "dependencies": { 39 | "@testing-library/dom": ">=7" 40 | }, 41 | "devDependencies": { 42 | "@babel/core": "^7.4.5", 43 | "@babel/plugin-proposal-class-properties": "^7.4.4", 44 | "@babel/plugin-transform-runtime": "^7.4.4", 45 | "@babel/preset-env": "^7.4.4", 46 | "@babel/preset-react": "^7.0.0", 47 | "@babel/preset-typescript": "^7.3.3", 48 | "@testing-library/jest-dom": "^5.0.1", 49 | "@testing-library/react": "^12.1.5", 50 | "@types/jest": "^29.1.2", 51 | "@types/react": "^17.0.47", 52 | "@types/react-select": "^5.0.1", 53 | "jest": "^27.0.4", 54 | "prettier": "^2.0.2", 55 | "react": "^17.0.2", 56 | "react-dom": "^17.0.2", 57 | "react-select": "^5.0.0", 58 | "rimraf": "^3.0.0", 59 | "rollup": "^2.0.3", 60 | "rollup-plugin-babel": "^4.3.2", 61 | "rollup-plugin-node-resolve": "^5.0.0", 62 | "test-all-versions": "^5.0.0", 63 | "typescript": "^4.0.2" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from "rollup-plugin-node-resolve"; 2 | import babel from "rollup-plugin-babel"; 3 | import pkg from "./package.json"; 4 | 5 | export default [ 6 | { 7 | input: "src/index.ts", 8 | external: ["@testing-library/dom"], 9 | plugins: [ 10 | resolve({ extensions: [".js", ".ts"] }), 11 | babel({ extensions: [".js", ".ts"] }) 12 | ], 13 | output: [ 14 | { file: pkg.main, format: "cjs", exports: "named" }, 15 | { file: pkg.module, format: "es" } 16 | ] 17 | } 18 | ]; 19 | -------------------------------------------------------------------------------- /src/__tests__/select-event.test.tsx: -------------------------------------------------------------------------------- 1 | import "@testing-library/jest-dom/extend-expect"; 2 | 3 | import { fireEvent, render } from "@testing-library/react"; 4 | 5 | import React from "react"; 6 | import Select from "react-select"; 7 | import selectEvent from ".."; 8 | 9 | let Async: any; 10 | let Creatable: any; 11 | let AsyncCreatable: any; 12 | let IS_V2 = false; 13 | try { 14 | // v3 15 | Async = require("react-select/async").default; 16 | Creatable = require("react-select/creatable").default; 17 | AsyncCreatable = require("react-select/async-creatable").default; 18 | } catch (_) { 19 | // v2 20 | Async = require("react-select/lib/Async").default; 21 | Creatable = require("react-select/lib/Creatable").default; 22 | AsyncCreatable = require("react-select/lib/AsyncCreatable").default; 23 | IS_V2 = true; 24 | } 25 | 26 | const skip_on_v2 = IS_V2 ? xit : it; 27 | 28 | type Callback = (options: Options) => void; 29 | interface Option { 30 | label: string; 31 | value: string; 32 | } 33 | type Options = Array