diff options
author | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-03-08 14:43:43 +0100 |
---|---|---|
committer | Grégoire Aubert <gregaubert@users.noreply.github.com> | 2017-03-13 10:03:16 +0100 |
commit | df0aad09cff6801af52be40e993cb2a57009676e (patch) | |
tree | 29eab9d853616d42f5d6e754df891a8a3590a22d | |
parent | b7587766c4bb8967d177e308bf35e4fc8bd7f3b2 (diff) | |
download | sonarqube-df0aad09cff6801af52be40e993cb2a57009676e.tar.gz sonarqube-df0aad09cff6801af52be40e993cb2a57009676e.zip |
SONAR-8878 Add ut and it's for Language, Search and Sort filters
9 files changed, 543 insertions, 0 deletions
diff --git a/it/it-tests/src/test/java/it/projectSearch/ProjectsPageTest.java b/it/it-tests/src/test/java/it/projectSearch/ProjectsPageTest.java index 70c9f708f4a..29128f15556 100644 --- a/it/it-tests/src/test/java/it/projectSearch/ProjectsPageTest.java +++ b/it/it-tests/src/test/java/it/projectSearch/ProjectsPageTest.java @@ -101,4 +101,29 @@ public class ProjectsPageTest { page.shouldHaveTotal(2).shouldDisplayAllProjects(); } + @Test + public void should_add_language() { + ProjectsPage page = nav.openProjects(); + page.getFacetByProperty("languages") + .selectOptionItem("xoo2") + .shouldHaveValue("xoo2", "0"); + } + + @Test + public void should_sort_by_facet() { + ProjectsPage page = nav.openProjects(); + page.getFacetByProperty("duplications") + .sortListDesc(); + page.getProjectByIdx(0).shouldHaveMeasure("duplicated_lines_density", "63.7%"); + page.getFacetByProperty("duplications") + .sortListAsc(); + page.getProjectByIdx(0).shouldHaveMeasure("duplicated_lines_density", "0.0%"); + } + + @Test + public void should_search_for_project() { + ProjectsPage page = nav.openProjects(); + page.searchProject("s").shouldHaveTotal(2); + page.searchProject("sam").shouldHaveTotal(1); + } } diff --git a/it/it-tests/src/test/java/pageobjects/projects/FacetItem.java b/it/it-tests/src/test/java/pageobjects/projects/FacetItem.java index ec9e4c8f0e4..2d0adce7de4 100644 --- a/it/it-tests/src/test/java/pageobjects/projects/FacetItem.java +++ b/it/it-tests/src/test/java/pageobjects/projects/FacetItem.java @@ -20,7 +20,9 @@ package pageobjects.projects; import com.codeborne.selenide.Condition; +import com.codeborne.selenide.ElementsCollection; import com.codeborne.selenide.SelenideElement; +import org.openqa.selenium.WebElement; public class FacetItem { @@ -38,4 +40,29 @@ public class FacetItem { public void selectValue(String key) { this.elt.$(".facet[data-key=\"" + key + "\"]").click(); } + + public FacetItem selectOptionItem(String value) { + this.elt.$(".Select-input input").val(value).pressEnter(); + return this; + } + + public FacetItem sortListDesc() { + this.getSortingButton("-").click(); + return this; + } + + public FacetItem sortListAsc() { + this.getSortingButton("[a-zA-Z ]").click(); + return this; + } + + public SelenideElement getSortingButton(String selector) { + ElementsCollection buttons = this.elt.$$(".projects-facet-sort a"); + return buttons.find(new Condition("AttributeMatch") { + @Override + public boolean apply(WebElement webElement) { + return webElement.getAttribute("href").matches(".*sort=" + selector + ".*"); + } + }); + } } diff --git a/it/it-tests/src/test/java/pageobjects/projects/ProjectsPage.java b/it/it-tests/src/test/java/pageobjects/projects/ProjectsPage.java index 0cc1b638a11..de3b50834fa 100644 --- a/it/it-tests/src/test/java/pageobjects/projects/ProjectsPage.java +++ b/it/it-tests/src/test/java/pageobjects/projects/ProjectsPage.java @@ -49,6 +49,10 @@ public class ProjectsPage { return new ProjectItem(element); } + public ProjectItem getProjectByIdx(Integer idx) { + return new ProjectItem(getProjects().get(idx)); + } + public FacetItem getFacetByProperty(String facetProperty) { SelenideElement element = getFacets().find(Condition.attribute("data-key", facetProperty)); return new FacetItem(element); @@ -79,4 +83,10 @@ public class ProjectsPage { $("#favorite-projects").click(); return shouldDisplayFavoriteProjects(); } + + public ProjectsPage searchProject(String search) { + SelenideElement searchInput = $(".projects-facet-search input"); + searchInput.setValue("").sendKeys(search); + return this; + } } diff --git a/server/sonar-web/src/main/js/apps/projects/filters/__tests__/LanguageFilterFooter-test.js b/server/sonar-web/src/main/js/apps/projects/filters/__tests__/LanguageFilterFooter-test.js new file mode 100644 index 00000000000..1c90902fe30 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/filters/__tests__/LanguageFilterFooter-test.js @@ -0,0 +1,62 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 React from 'react'; +import { shallow } from 'enzyme'; +import LanguageFilterFooter from '../LanguageFilterFooter'; + +const languages = { + java: { + key: 'java', + name: 'Java' + }, + cs: { + key: 'cs', + name: 'C#' + }, + js: { + key: 'js', + name: 'JavaScript' + }, + flex: { + key: 'flex', + name: 'Flex' + }, + php: { + key: 'php', + name: 'PHP' + }, + py: { + key: 'py', + name: 'Python' + } +}; +const facet = { java: 39, cs: 4, js: 1 }; + +it('should render the languages without the ones in the facet', () => { + const wrapper = shallow( + <LanguageFilterFooter + property="foo" + query={{ languages: null }} + facet={facet} + languages={languages}/> + ); + expect(wrapper).toMatchSnapshot(); + expect(wrapper.find('Select').props().options.length).toBe(3); +}); diff --git a/server/sonar-web/src/main/js/apps/projects/filters/__tests__/SearchFilter-test.js b/server/sonar-web/src/main/js/apps/projects/filters/__tests__/SearchFilter-test.js new file mode 100644 index 00000000000..c72c3328178 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/filters/__tests__/SearchFilter-test.js @@ -0,0 +1,51 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 React from 'react'; +import { shallow } from 'enzyme'; +import SearchFilter from '../SearchFilter'; + +it('should render correctly without any search query', () => { + const wrapper = shallow( + <SearchFilter + handleSearch={() => {}} + query={{ search: null }}/> + ); + expect(wrapper).toMatchSnapshot(); +}); + +it('should render with a search query', () => { + const wrapper = shallow( + <SearchFilter + handleSearch={() => {}} + query={{ search: 'foo' }}/> + ); + expect(wrapper).toMatchSnapshot(); +}); + +it('should display a help message when there is less than 2 characters', () => { + const wrapper = shallow( + <SearchFilter + handleSearch={() => {}} + query={{ search: 'a' }}/> + ); + expect(wrapper).toMatchSnapshot(); + wrapper.setState({ userQuery: 'foo' }); + expect(wrapper).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/projects/filters/__tests__/SortingFilter-test.js b/server/sonar-web/src/main/js/apps/projects/filters/__tests__/SortingFilter-test.js new file mode 100644 index 00000000000..98134517425 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/filters/__tests__/SortingFilter-test.js @@ -0,0 +1,71 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 React from 'react'; +import { shallow } from 'enzyme'; +import SortingFilter from '../SortingFilter'; + +it('should render with default parameters and empty query', () => { + const wrapper = shallow( + <SortingFilter + property="foo" + query={{}}/> + ); + expect(wrapper).toMatchSnapshot(); + const sortingFilter = wrapper.instance(); + expect(sortingFilter.isSortActive('left')).toBeFalsy(); + expect(sortingFilter.isSortActive('right')).toBeFalsy(); +}); + +it('should render with custom parameters', () => { + const wrapper = shallow( + <SortingFilter + property="foo" + query={{}} + sortDesc="right" + leftText="worst" + rightText="best"/> + ); + expect(wrapper).toMatchSnapshot(); +}); + +it('should render correctly with matching query', () => { + const wrapper = shallow( + <SortingFilter + property="foo" + query={{ sort: '-foo', languages: 'php,cpp' }} + sortDesc="right"/> + ); + expect(wrapper).toMatchSnapshot(); + const sortingFilter = wrapper.instance(); + expect(sortingFilter.isSortActive('left')).toBeFalsy(); + expect(sortingFilter.isSortActive('right')).toBeTruthy(); +}); + +it('should render correctly with no matching query', () => { + const wrapper = shallow( + <SortingFilter + property="foo" + query={{ sort: 'bar' }}/> + ); + expect(wrapper).toMatchSnapshot(); + const sortingFilter = wrapper.instance(); + expect(sortingFilter.isSortActive('left')).toBeFalsy(); + expect(sortingFilter.isSortActive('right')).toBeFalsy(); +}); diff --git a/server/sonar-web/src/main/js/apps/projects/filters/__tests__/__snapshots__/LanguageFilterFooter-test.js.snap b/server/sonar-web/src/main/js/apps/projects/filters/__tests__/__snapshots__/LanguageFilterFooter-test.js.snap new file mode 100644 index 00000000000..22d352f4ca5 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/filters/__tests__/__snapshots__/LanguageFilterFooter-test.js.snap @@ -0,0 +1,58 @@ +exports[`test should render the languages without the ones in the facet 1`] = ` +<Select + addLabelText="Add \"{label}\"?" + arrowRenderer={[Function]} + autosize={true} + backspaceRemoves={true} + backspaceToRemoveMessage="Press backspace to remove {label}" + className="input-super-large" + clearAllText="Clear all" + clearValueText="Clear value" + clearable={false} + delimiter="," + disabled={false} + escapeClearsValue={true} + filterOptions={[Function]} + ignoreAccents={true} + ignoreCase={true} + inputProps={Object {}} + isLoading={false} + joinValues={false} + labelKey="label" + matchPos="any" + matchProp="any" + menuBuffer={0} + menuRenderer={[Function]} + multi={false} + noResultsText="No results found" + onBlurResetsInput={true} + onChange={[Function]} + onCloseResetsInput={true} + openAfterFocus={false} + optionComponent={[Function]} + options={ + Array [ + Object { + "label": "Flex", + "value": "flex", + }, + Object { + "label": "PHP", + "value": "php", + }, + Object { + "label": "Python", + "value": "py", + }, + ] + } + pageSize={5} + placeholder="search_verb" + required={false} + scrollMenuIntoView={true} + searchable={true} + simpleValue={false} + tabSelectsValue={true} + valueComponent={[Function]} + valueKey="value" /> +`; diff --git a/server/sonar-web/src/main/js/apps/projects/filters/__tests__/__snapshots__/SearchFilter-test.js.snap b/server/sonar-web/src/main/js/apps/projects/filters/__tests__/__snapshots__/SearchFilter-test.js.snap new file mode 100644 index 00000000000..55bfe8e9fa9 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/filters/__tests__/__snapshots__/SearchFilter-test.js.snap @@ -0,0 +1,71 @@ +exports[`test should display a help message when there is less than 2 characters 1`] = ` +<div + className="projects-facet-search" + data-key="search"> + <input + autoComplete="off" + className="input-super-large touched" + onChange={[Function]} + placeholder="projects.search" + type="search" + value="a" /> + <span + className="note spacer-left"> + select2.tooShort.2 + </span> +</div> +`; + +exports[`test should display a help message when there is less than 2 characters 2`] = ` +<div + className="projects-facet-search" + data-key="search"> + <input + autoComplete="off" + className="input-super-large" + onChange={[Function]} + placeholder="projects.search" + type="search" + value="foo" /> + <span + className="note spacer-left"> + select2.tooShort.2 + </span> +</div> +`; + +exports[`test should render correctly without any search query 1`] = ` +<div + className="projects-facet-search" + data-key="search"> + <input + autoComplete="off" + className="input-super-large" + onChange={[Function]} + placeholder="projects.search" + type="search" + value="" /> + <span + className="note spacer-left"> + select2.tooShort.2 + </span> +</div> +`; + +exports[`test should render with a search query 1`] = ` +<div + className="projects-facet-search" + data-key="search"> + <input + autoComplete="off" + className="input-super-large" + onChange={[Function]} + placeholder="projects.search" + type="search" + value="foo" /> + <span + className="note spacer-left"> + select2.tooShort.2 + </span> +</div> +`; diff --git a/server/sonar-web/src/main/js/apps/projects/filters/__tests__/__snapshots__/SortingFilter-test.js.snap b/server/sonar-web/src/main/js/apps/projects/filters/__tests__/__snapshots__/SortingFilter-test.js.snap new file mode 100644 index 00000000000..a7a70e63f93 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/filters/__tests__/__snapshots__/SortingFilter-test.js.snap @@ -0,0 +1,168 @@ +exports[`test should render correctly with matching query 1`] = ` +<div + className="projects-facet-sort"> + <span> + projects.sort_list + </span> + <div + className="spacer-left button-group"> + <Link + className="button button-small button-grey" + onClick={[Function]} + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/projects", + "query": Object { + "languages": "php,cpp", + "sort": "foo", + }, + } + }> + worst + </Link> + <Link + className="button button-small button-grey button-active" + onClick={[Function]} + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/projects", + "query": Object { + "languages": "php,cpp", + }, + } + }> + best + </Link> + </div> +</div> +`; + +exports[`test should render correctly with no matching query 1`] = ` +<div + className="projects-facet-sort"> + <span> + projects.sort_list + </span> + <div + className="spacer-left button-group"> + <Link + className="button button-small button-grey" + onClick={[Function]} + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/projects", + "query": Object { + "sort": "-foo", + }, + } + }> + worst + </Link> + <Link + className="button button-small button-grey" + onClick={[Function]} + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/projects", + "query": Object { + "sort": "foo", + }, + } + }> + best + </Link> + </div> +</div> +`; + +exports[`test should render with custom parameters 1`] = ` +<div + className="projects-facet-sort"> + <span> + projects.sort_list + </span> + <div + className="spacer-left button-group"> + <Link + className="button button-small button-grey" + onClick={[Function]} + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/projects", + "query": Object { + "sort": "foo", + }, + } + }> + worst + </Link> + <Link + className="button button-small button-grey" + onClick={[Function]} + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/projects", + "query": Object { + "sort": "-foo", + }, + } + }> + best + </Link> + </div> +</div> +`; + +exports[`test should render with default parameters and empty query 1`] = ` +<div + className="projects-facet-sort"> + <span> + projects.sort_list + </span> + <div + className="spacer-left button-group"> + <Link + className="button button-small button-grey" + onClick={[Function]} + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/projects", + "query": Object { + "sort": "-foo", + }, + } + }> + worst + </Link> + <Link + className="button button-small button-grey" + onClick={[Function]} + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/projects", + "query": Object { + "sort": "foo", + }, + } + }> + best + </Link> + </div> +</div> +`; |