diff options
author | Mathieu Suen <mathieu.suen@sonarsource.com> | 2021-09-15 09:40:35 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2021-09-16 20:03:30 +0000 |
commit | 08d22267853e09b119fd6b85f3a3c829c480f072 (patch) | |
tree | e01b6d22489fe606dd0d7b2077f53d892949eb03 | |
parent | 34f1ac3955290cba9ba73fd07e98dc7a9fa9c0e5 (diff) | |
download | sonarqube-08d22267853e09b119fd6b85f3a3c829c480f072.tar.gz sonarqube-08d22267853e09b119fd6b85f3a3c829c480f072.zip |
SONAR-15391 Fix special caracter search in documentation
6 files changed, 178 insertions, 28 deletions
diff --git a/server/sonar-docs/src/components/Search.tsx b/server/sonar-docs/src/components/Search.tsx index 3733edb81d9..f688447b3bc 100644 --- a/server/sonar-docs/src/components/Search.tsx +++ b/server/sonar-docs/src/components/Search.tsx @@ -146,6 +146,7 @@ export default class Search extends React.PureComponent<Props, State> { value, this.index.search( value + .replace(/[\^\-+:~*]/g, '') .split(/\s+/) .map(s => `${s}~1 ${s}*`) .join(' ') diff --git a/server/sonar-docs/src/components/__tests__/Search-test.tsx b/server/sonar-docs/src/components/__tests__/Search-test.tsx new file mode 100644 index 00000000000..4101c0e7c49 --- /dev/null +++ b/server/sonar-docs/src/components/__tests__/Search-test.tsx @@ -0,0 +1,124 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { shallow } from 'enzyme'; +import lunr from 'lunr'; +import * as React from 'react'; +import { MarkdownRemark } from '../../@types/graphql-types'; +import Search from '../Search'; + +jest.mock('lunr', () => ({ + __esModule: true, + default: jest.fn(() => ({ + search: jest.fn(() => [ + { + ref: 'lorem/origin', + matchData: { + metadata: { + simply: { + title: { position: [[19, 5]] }, + text: { + position: [ + [15, 6], + [28, 4] + ], + tokenContext: ['is simply dummy', 'simply dummy text'] + } + } + } + } + }, + { + ref: 'foobar', + matchData: { + metadata: { + simply: { + title: { position: [[23, 4]] }, + text: { + position: [ + [111, 6], + [118, 4] + ], + tokenContext: ['keywords simply text'] + } + } + } + } + } + ]) + })) +})); + +function mockMarkdownRemark(override: Partial<MarkdownRemark>): MarkdownRemark { + return { + id: 'id', + parent: null, + children: null, + internal: null, + frontmatter: null, + rawMarkdownBody: null, + fileAbsolutePath: null, + fields: null, + html: null, + htmlAst: null, + excerpt: null, + headings: null, + timeToRead: null, + tableOfContents: null, + wordCount: null, + ...override + }; +} + +const pages = [ + mockMarkdownRemark({ + html: + 'Lorem Ipsum is simply dummy text of the printing and typesetting ' + + "industry. Lorem Ipsum has been the industry's standard dummy text ever " + + 'since the 1500s, when an unknown printer took a galley of type and ' + + 'scrambled it to make a type specimen book.' + }), + mockMarkdownRemark({ + html: + 'Contrary to popular belief, Lorem Ipsum is not simply random text. ' + + 'It has roots in a piece of classical Latin literature from 45 BC, making' + + ' it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney' + + ' College in Virginia, looked up one of the more obscure Latin words.' + }), + mockMarkdownRemark({ + html: + 'Foobar is a universal variable understood to represent whatever is ' + + 'being discussed. Now we need some keywords: simply text.' + }) +]; + +it('should search', () => { + const wrapper = shallow<Search>( + <Search + navigation={['lorem/index', 'lorem/origin', 'foobar']} + pages={pages} + onResultsChange={jest.fn()} + /> + ); + wrapper.instance().handleChange({ currentTarget: { value: 'simply text+:' } } as any); + expect(wrapper).toMatchSnapshot(); + expect(lunr).toBeCalled(); + expect(wrapper.instance().index).toBeDefined(); + expect((wrapper.instance().index as any).search).toBeCalledWith('simply~1 simply* text~1 text*'); +}); diff --git a/server/sonar-docs/src/components/__tests__/__snapshots__/Search-test.tsx.snap b/server/sonar-docs/src/components/__tests__/__snapshots__/Search-test.tsx.snap new file mode 100644 index 00000000000..4a1bb57abf8 --- /dev/null +++ b/server/sonar-docs/src/components/__tests__/__snapshots__/Search-test.tsx.snap @@ -0,0 +1,24 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should search 1`] = ` +<div + className="search-container" +> + <input + aria-label="Search" + className="search-input" + onChange={[Function]} + placeholder="Search..." + type="search" + value="simply text+:" + /> + <button + onClick={[Function]} + type="button" + > + <ClearIcon + size={8} + /> + </button> +</div> +`; diff --git a/server/sonar-web/src/main/js/apps/documentation/components/SearchResults.tsx b/server/sonar-web/src/main/js/apps/documentation/components/SearchResults.tsx index 4ec73f848d3..9640472b73c 100644 --- a/server/sonar-web/src/main/js/apps/documentation/components/SearchResults.tsx +++ b/server/sonar-web/src/main/js/apps/documentation/components/SearchResults.tsx @@ -57,6 +57,7 @@ export default class SearchResults extends React.PureComponent<Props> { const results = this.index .search( query + .replace(/[\^\-+:~*]/g, '') .split(/\s+/) .map(s => `${s}~1 ${s}*`) .join(' ') diff --git a/server/sonar-web/src/main/js/apps/documentation/components/__tests__/SearchResults-test.tsx b/server/sonar-web/src/main/js/apps/documentation/components/__tests__/SearchResults-test.tsx index 6c6764a97e2..88d5acffaa3 100644 --- a/server/sonar-web/src/main/js/apps/documentation/components/__tests__/SearchResults-test.tsx +++ b/server/sonar-web/src/main/js/apps/documentation/components/__tests__/SearchResults-test.tsx @@ -90,7 +90,7 @@ it('should search', () => { <SearchResults navigation={['lorem/index', 'lorem/origin', 'foobar']} pages={pages} - query="simply text" + query="si:+mply text" splat="foobar" /> ); diff --git a/server/sonar-web/src/main/js/apps/documentation/components/__tests__/__snapshots__/SearchResults-test.tsx.snap b/server/sonar-web/src/main/js/apps/documentation/components/__tests__/__snapshots__/SearchResults-test.tsx.snap index ae5779ca00c..65b92fef234 100644 --- a/server/sonar-web/src/main/js/apps/documentation/components/__tests__/__snapshots__/SearchResults-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/documentation/components/__tests__/__snapshots__/SearchResults-test.tsx.snap @@ -3,76 +3,76 @@ exports[`should search 1`] = ` <Fragment> <SearchResultEntry - active={true} - key="foobar" + active={false} + key="lorem/origin" result={ Object { - "exactMatch": true, + "exactMatch": false, "highlights": Object { "text": Array [ Array [ - 111, + 15, 6, ], Array [ - 118, + 28, 4, ], ], "title": Array [ Array [ - 23, - 4, + 19, + 5, ], ], }, - "longestTerm": "simply", + "longestTerm": "", "page": Object { - "content": "Foobar is a universal variable understood to represent whatever is being discussed. Now we need some keywords: simply text.", + "content": "Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words.", "navTitle": undefined, - "relativeName": "foobar", - "text": "Foobar is a universal variable understood to represent whatever is being discussed. Now we need some keywords: simply text.", - "title": "Where does Foobar come from?", - "url": "/foobar", + "relativeName": "lorem/origin", + "text": "Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words.", + "title": "Where does it come from?", + "url": "/lorem/origin", }, - "query": "simply text", + "query": "si:+mply text", } } /> <SearchResultEntry - active={false} - key="lorem/origin" + active={true} + key="foobar" result={ Object { "exactMatch": false, "highlights": Object { "text": Array [ Array [ - 15, + 111, 6, ], Array [ - 28, + 118, 4, ], ], "title": Array [ Array [ - 19, - 5, + 23, + 4, ], ], }, - "longestTerm": "simply", + "longestTerm": "", "page": Object { - "content": "Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words.", + "content": "Foobar is a universal variable understood to represent whatever is being discussed. Now we need some keywords: simply text.", "navTitle": undefined, - "relativeName": "lorem/origin", - "text": "Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words.", - "title": "Where does it come from?", - "url": "/lorem/origin", + "relativeName": "foobar", + "text": "Foobar is a universal variable understood to represent whatever is being discussed. Now we need some keywords: simply text.", + "title": "Where does Foobar come from?", + "url": "/foobar", }, - "query": "simply text", + "query": "si:+mply text", } } /> |