From e1294b135d9096e19ad4580da2875f5adc310bfc Mon Sep 17 00:00:00 2001 From: Matan Kushner Date: Tue, 18 Sep 2018 22:57:40 -0400 Subject: [PATCH 1/2] feat(queryBySelectText): add get/query by select text --- .size-snapshot.json | 6 +- .../__snapshots__/element-queries.js.snap | 34 ++++++---- src/__tests__/element-queries.js | 67 ++++++++++++++++++- src/__tests__/text-matchers.js | 27 ++++++++ src/queries.js | 37 ++++++++++ typings/queries.d.ts | 4 ++ 6 files changed, 159 insertions(+), 16 deletions(-) diff --git a/.size-snapshot.json b/.size-snapshot.json index 87faf7e0..094d20cb 100644 --- a/.size-snapshot.json +++ b/.size-snapshot.json @@ -1,7 +1,7 @@ { "dist/dom-testing-library.umd.js": { - "bundled": 111046, - "minified": 49098, - "gzipped": 14989 + "bundled": 115443, + "minified": 50960, + "gzipped": 15294 } } diff --git a/src/__tests__/__snapshots__/element-queries.js.snap b/src/__tests__/__snapshots__/element-queries.js.snap index 08d5ca44..3083fd27 100644 --- a/src/__tests__/__snapshots__/element-queries.js.snap +++ b/src/__tests__/__snapshots__/element-queries.js.snap @@ -9,7 +9,7 @@ exports[`get throws a useful error message 1`] = ` `; exports[`get throws a useful error message 2`] = ` -"Unable to find an element with the placeholder text of: LucyRicardo +"Unable to find a element with the selected option's text: LucyRicardo"`; + +exports[`get throws a useful error message without DOM in Cypress 3`] = `"Unable to find an element with the placeholder text of: LucyRicardo"`; -exports[`get throws a useful error message without DOM in Cypress 3`] = `"Unable to find an element with the text: LucyRicardo. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible."`; +exports[`get throws a useful error message without DOM in Cypress 4`] = `"Unable to find an element with the text: LucyRicardo. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible."`; -exports[`get throws a useful error message without DOM in Cypress 4`] = `"Unable to find an element by: [data-testid=\\"LucyRicardo\\"]"`; +exports[`get throws a useful error message without DOM in Cypress 5`] = `"Unable to find an element by: [data-testid=\\"LucyRicardo\\"]"`; -exports[`get throws a useful error message without DOM in Cypress 5`] = `"Unable to find an element with the alt text: LucyRicardo"`; +exports[`get throws a useful error message without DOM in Cypress 6`] = `"Unable to find an element with the alt text: LucyRicardo"`; -exports[`get throws a useful error message without DOM in Cypress 6`] = `"Unable to find an element with the title: LucyRicardo."`; +exports[`get throws a useful error message without DOM in Cypress 7`] = `"Unable to find an element with the title: LucyRicardo."`; -exports[`get throws a useful error message without DOM in Cypress 7`] = `"Unable to find an element with the value: LucyRicardo."`; +exports[`get throws a useful error message without DOM in Cypress 8`] = `"Unable to find an element with the value: LucyRicardo."`; exports[`label with no form control 1`] = ` "Found a label with the text of: /alone/, however no form control was found associated to that label. Make sure you're using the \\"for\\" attribute or \\"aria-labelledby\\" attribute correctly. diff --git a/src/__tests__/element-queries.js b/src/__tests__/element-queries.js index e1274e6e..ff1d453d 100644 --- a/src/__tests__/element-queries.js +++ b/src/__tests__/element-queries.js @@ -8,6 +8,7 @@ beforeEach(() => { test('query can return null', () => { const { queryByLabelText, + queryBySelectText, queryByPlaceholderText, queryByText, queryByTestId, @@ -15,6 +16,7 @@ test('query can return null', () => { } = render('
') expect(queryByTestId('LucyRicardo')).toBeNull() expect(queryByLabelText('LucyRicardo')).toBeNull() + expect(queryBySelectText('LucyRicardo')).toBeNull() expect(queryByPlaceholderText('LucyRicardo')).toBeNull() expect(queryByText('LucyRicardo')).toBeNull() expect(queryByAltText('LucyRicardo')).toBeNull() @@ -23,6 +25,7 @@ test('query can return null', () => { test('get throws a useful error message', () => { const { getByLabelText, + getBySelectText, getByPlaceholderText, getByText, getByTestId, @@ -32,6 +35,7 @@ test('get throws a useful error message', () => { getByRole, } = render('
') expect(() => getByLabelText('LucyRicardo')).toThrowErrorMatchingSnapshot() + expect(() => getBySelectText('LucyRicardo')).toThrowErrorMatchingSnapshot() expect(() => getByPlaceholderText('LucyRicardo'), ).toThrowErrorMatchingSnapshot() @@ -188,8 +192,50 @@ test('query/get element by its value', () => {
`) - expect(queryByValue('Norris').placeholder).toEqual('lastname') expect(getByValue('Norris').placeholder).toEqual('lastname') + expect(queryByValue('Norris').placeholder).toEqual('lastname') +}) + +test('query/get select by text with the default option selected', () => { + const {getBySelectText, queryBySelectText} = render(` + + `) + + expect(getBySelectText('State').id).toEqual('state-select') + expect(queryBySelectText('State').id).toEqual('state-select') +}) + +test('query/get select by text with one option selected', () => { + const {getBySelectText, queryBySelectText} = render(` + + `) + + expect(getBySelectText('Alaska').id).toEqual('state-select') + expect(queryBySelectText('Alaska').id).toEqual('state-select') +}) + +test('query/get select by text with multiple options selected', () => { + const {getBySelectText, queryBySelectText} = render(` + + `) + + expect(getBySelectText('Alabama').id).toEqual('state-select') + expect(queryBySelectText('Alaska').id).toEqual('state-select') }) test('can get elements by data-testid attribute', () => { @@ -209,6 +255,7 @@ test('getAll* matchers return an array', () => { getAllByAltText, getAllByTestId, getAllByLabelText, + getAllBySelectText, getAllByPlaceholderText, getAllByText, getAllByRole, @@ -229,6 +276,16 @@ test('getAll* matchers return an array', () => {

Where to next?

+ +
, `) expect(getAllByAltText(/finding.*poster$/i)).toHaveLength(2) @@ -236,6 +293,8 @@ test('getAll* matchers return an array', () => { expect(getAllByTestId('poster')).toHaveLength(3) expect(getAllByPlaceholderText(/The Rock/)).toHaveLength(1) expect(getAllByLabelText('User Name')).toHaveLength(1) + expect(getAllBySelectText('Japanese cars')).toHaveLength(1) + expect(getAllBySelectText(/cars$/)).toHaveLength(2) expect(getAllByText(/^where/i)).toHaveLength(1) expect(getAllByRole(/container/i)).toHaveLength(1) }) @@ -245,6 +304,7 @@ test('getAll* matchers throw for 0 matches', () => { getAllByAltText, getAllByTestId, getAllByLabelText, + getAllBySelectText, getAllByPlaceholderText, getAllByText, getAllByRole, @@ -258,6 +318,7 @@ test('getAll* matchers throw for 0 matches', () => { expect(() => getAllByAltText('nope')).toThrow() expect(() => getAllByLabelText('nope')).toThrow() expect(() => getAllByLabelText('no matches please')).toThrow() + expect(() => getAllBySelectText('nope')).toThrow() expect(() => getAllByPlaceholderText('nope')).toThrow() expect(() => getAllByText('nope')).toThrow() expect(() => getAllByRole('nope')).toThrow() @@ -268,6 +329,7 @@ test('queryAll* matchers return an array for 0 matches', () => { queryAllByAltText, queryAllByTestId, queryAllByLabelText, + queryAllBySelectText, queryAllByPlaceholderText, queryAllByText, queryAllByRole, @@ -278,6 +340,7 @@ test('queryAll* matchers return an array for 0 matches', () => { expect(queryAllByTestId('nope')).toHaveLength(0) expect(queryAllByAltText('nope')).toHaveLength(0) expect(queryAllByLabelText('nope')).toHaveLength(0) + expect(queryAllBySelectText('nope')).toHaveLength(0) expect(queryAllByPlaceholderText('nope')).toHaveLength(0) expect(queryAllByText('nope')).toHaveLength(0) expect(queryAllByRole('nope')).toHaveLength(0) @@ -429,6 +492,7 @@ test('get throws a useful error message without DOM in Cypress', () => { window.Cypress = {} const { getByLabelText, + getBySelectText, getByPlaceholderText, getByText, getByTestId, @@ -437,6 +501,7 @@ test('get throws a useful error message without DOM in Cypress', () => { getByValue, } = render('
') expect(() => getByLabelText('LucyRicardo')).toThrowErrorMatchingSnapshot() + expect(() => getBySelectText('LucyRicardo')).toThrowErrorMatchingSnapshot() expect(() => getByPlaceholderText('LucyRicardo'), ).toThrowErrorMatchingSnapshot() diff --git a/src/__tests__/text-matchers.js b/src/__tests__/text-matchers.js index 4cc66303..5cf7b359 100644 --- a/src/__tests__/text-matchers.js +++ b/src/__tests__/text-matchers.js @@ -38,6 +38,15 @@ cases( query: `Dwayne 'The Rock' Johnson`, queryFn: `queryAllByPlaceholderText`, }, + queryAllBySelectText: { + dom: ` + `, + query: `Option 1`, + queryFn: `queryAllBySelectText`, + }, queryAllByText: { dom: `

Some content

`, query: `Some content`, @@ -84,6 +93,15 @@ cases( query: /^Dwayne/, queryFn: `queryAllByPlaceholderText`, }, + queryAllBySelectText: { + dom: ` + `, + query: `Option 1`, + queryFn: `queryAllBySelectText`, + }, queryAllByText: { dom: `

@@ -137,6 +155,15 @@ cases( query: `Dwayne 'The Rock' Johnson`, queryFn: `queryAllByPlaceholderText`, }, + queryAllBySelectText: { + dom: ` + `, + query: `Option 1`, + queryFn: `queryAllBySelectText`, + }, queryAllByLabelText: { dom: ` diff --git a/src/queries.js b/src/queries.js index 86e31848..63648438 100644 --- a/src/queries.js +++ b/src/queries.js @@ -100,6 +100,24 @@ function queryByTitle(...args) { return firstResultOrNull(queryAllByTitle, ...args) } +function queryAllBySelectText( + container, + text, + {exact = true, collapseWhitespace = true, trim = true} = {}, +) { + const matcher = exact ? matches : fuzzyMatches + const matchOpts = {collapseWhitespace, trim} + return Array.from(container.querySelectorAll('select')).filter(selectNode => + Array.from(selectNode.selectedOptions).some(optionNode => + matcher(getNodeText(optionNode), optionNode, text, matchOpts), + ), + ) +} + +function queryBySelectText(...args) { + return firstResultOrNull(queryAllBySelectText, ...args) +} + const queryByPlaceholderText = queryByAttribute.bind(null, 'placeholder') const queryAllByPlaceholderText = queryAllByAttribute.bind(null, 'placeholder') const queryByTestId = queryByAttribute.bind(null, 'data-testid') @@ -255,6 +273,21 @@ function getByRole(...args) { return firstResultOrNull(getAllByRole, ...args) } +function getAllBySelectText(container, text, ...rest) { + const els = queryAllBySelectText(container, text, ...rest) + if (!els.length) { + throw getElementError( + `Unable to find a ` whose selected ` +// +// +// +// +const selectNode = getBySelectText(container, 'Day of the Week') +``` + +> Note: It is highly preferred to use `getByLabelText` over this method. This +> method should only be used in the event where there is no label text available. + ### `getByText` ```typescript @@ -278,7 +308,7 @@ matching the given [`TextMatch`](#textmatch). const aboutAnchorNode = getByText(container, 'about') ``` -> NOTE: see [`getbylabeltext`](#getbylabeltext) for more details on how and when to use the `selector` option +> NOTE: see [`getByLabelText`](#getbylabeltext) for more details on how and when to use the `selector` option ### `getByAltText` @@ -955,7 +985,7 @@ Thanks goes to these people ([emoji key][emojis]): | [
Anto Aravinth](https://github.com/antoaravinth)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=antoaravinth "Code") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=antoaravinth "Tests") [πŸ“–](https://github.com/kentcdodds/dom-testing-library/commits?author=antoaravinth "Documentation") | [
Jonah Moses](https://github.com/JonahMoses)
[πŸ“–](https://github.com/kentcdodds/dom-testing-library/commits?author=JonahMoses "Documentation") | [
Łukasz Gandecki](http://team.thebrain.pro)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=lgandecki "Code") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=lgandecki "Tests") [πŸ“–](https://github.com/kentcdodds/dom-testing-library/commits?author=lgandecki "Documentation") | [
Ivan Babak](https://sompylasar.github.io)
[πŸ›](https://github.com/kentcdodds/dom-testing-library/issues?q=author%3Asompylasar "Bug reports") [πŸ€”](#ideas-sompylasar "Ideas, Planning, & Feedback") [πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=sompylasar "Code") [πŸ“–](https://github.com/kentcdodds/dom-testing-library/commits?author=sompylasar "Documentation") | [
Jesse Day](https://github.com/jday3)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=jday3 "Code") | [
Ernesto GarcΓ­a](http://gnapse.github.io)
[πŸ’¬](#question-gnapse "Answering Questions") [πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=gnapse "Code") [πŸ“–](https://github.com/kentcdodds/dom-testing-library/commits?author=gnapse "Documentation") | [
Josef Maxx Blake](http://jomaxx.com)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=jomaxx "Code") [πŸ“–](https://github.com/kentcdodds/dom-testing-library/commits?author=jomaxx "Documentation") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=jomaxx "Tests") | | [
Alex Cook](https://github.com/alecook)
[πŸ“–](https://github.com/kentcdodds/dom-testing-library/commits?author=alecook "Documentation") [πŸ’‘](#example-alecook "Examples") | [
Daniel Cook](https://github.com/dfcook)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=dfcook "Code") [πŸ“–](https://github.com/kentcdodds/dom-testing-library/commits?author=dfcook "Documentation") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=dfcook "Tests") | [
Thomas Chia](https://github.com/thchia)
[πŸ›](https://github.com/kentcdodds/dom-testing-library/issues?q=author%3Athchia "Bug reports") [πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=thchia "Code") | [
Tim Deschryver](https://github.com/tdeschryver)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=tdeschryver "Code") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=tdeschryver "Tests") | [
Alex Krolick](https://alexkrolick.com)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=alexkrolick "Code") | [
Maddi Joyce](http://www.maddijoyce.com)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=maddijoyce "Code") | [
Peter Kamps](https://github.com/npeterkamps)
[πŸ›](https://github.com/kentcdodds/dom-testing-library/issues?q=author%3Anpeterkamps "Bug reports") [πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=npeterkamps "Code") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=npeterkamps "Tests") | | [
Jonathan Stoye](http://jonathanstoye.de)
[πŸ“–](https://github.com/kentcdodds/dom-testing-library/commits?author=JonathanStoye "Documentation") | [
Sanghyeon Lee](https://github.com/yongdamsh)
[πŸ’‘](#example-yongdamsh "Examples") | [
Justice Mba ](https://github.com/Dajust)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=Dajust "Code") [πŸ“–](https://github.com/kentcdodds/dom-testing-library/commits?author=Dajust "Documentation") [πŸ€”](#ideas-Dajust "Ideas, Planning, & Feedback") | [
Wayne Crouch](https://github.com/wgcrouch)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=wgcrouch "Code") | [
Ben Elliott](http://benjaminelliott.co.uk)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=benelliott "Code") | [
Ruben Costa](http://nuances.co)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=rubencosta "Code") | [
Robert Smith](http://rbrtsmith.com/)
[πŸ›](https://github.com/kentcdodds/dom-testing-library/issues?q=author%3Arbrtsmith "Bug reports") [πŸ€”](#ideas-rbrtsmith "Ideas, Planning, & Feedback") [πŸ“–](https://github.com/kentcdodds/dom-testing-library/commits?author=rbrtsmith "Documentation") | -| [
dadamssg](https://github.com/dadamssg)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=dadamssg "Code") | [
Neil Kistner](https://neilkistner.com/)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=wyze "Code") | [
Ben Chauvette](http://bdchauvette.net/)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=bdchauvette "Code") | [
Jeff Baumgardt](https://github.com/JeffBaumgardt)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=JeffBaumgardt "Code") [πŸ“–](https://github.com/kentcdodds/dom-testing-library/commits?author=JeffBaumgardt "Documentation") | +| [
dadamssg](https://github.com/dadamssg)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=dadamssg "Code") | [
Neil Kistner](https://neilkistner.com/)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=wyze "Code") | [
Ben Chauvette](http://bdchauvette.net/)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=bdchauvette "Code") | [
Jeff Baumgardt](https://github.com/JeffBaumgardt)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=JeffBaumgardt "Code") [πŸ“–](https://github.com/kentcdodds/dom-testing-library/commits?author=JeffBaumgardt "Documentation") | [
Matan Kushner](http://matchai.me)
[πŸ’»](https://github.com/kentcdodds/dom-testing-library/commits?author=matchai "Code") [πŸ“–](https://github.com/kentcdodds/dom-testing-library/commits?author=matchai "Documentation") [πŸ€”](#ideas-matchai "Ideas, Planning, & Feedback") [⚠️](https://github.com/kentcdodds/dom-testing-library/commits?author=matchai "Tests") |