import it.qualityGate.QualityGateUiTest; | import it.qualityGate.QualityGateUiTest; | ||||
import it.settings.PropertySetsTest; | import it.settings.PropertySetsTest; | ||||
import it.settings.SettingsTest; | import it.settings.SettingsTest; | ||||
import it.settings.SubCategoriesTest; | |||||
import it.sourceCode.EncodingTest; | import it.sourceCode.EncodingTest; | ||||
import it.sourceCode.HighlightingTest; | import it.sourceCode.HighlightingTest; | ||||
import it.sourceCode.ProjectCodeTest; | import it.sourceCode.ProjectCodeTest; | ||||
BackgroundTasksTest.class, | BackgroundTasksTest.class, | ||||
// settings | // settings | ||||
PropertySetsTest.class, | PropertySetsTest.class, | ||||
SubCategoriesTest.class, | |||||
SettingsTest.class, | SettingsTest.class, | ||||
// i18n | // i18n | ||||
I18nTest.class, | I18nTest.class, |
// SONAR-2073 | // SONAR-2073 | ||||
"/componentDashboard/DashboardTest/global_dashboard/filter-widget-anonymous.html", | "/componentDashboard/DashboardTest/global_dashboard/filter-widget-anonymous.html", | ||||
// SONAR-3460 | |||||
"/componentDashboard/DashboardTest/global_dashboard/global-admin-dashboards.html", | |||||
// SONAR-3461 | // SONAR-3461 | ||||
"/componentDashboard/DashboardTest/global_dashboard/default-dashboards.html", | "/componentDashboard/DashboardTest/global_dashboard/default-dashboards.html", | ||||
import com.sonar.orchestrator.Orchestrator; | import com.sonar.orchestrator.Orchestrator; | ||||
import com.sonar.orchestrator.locator.FileLocation; | import com.sonar.orchestrator.locator.FileLocation; | ||||
import com.sonar.orchestrator.selenium.Selenese; | |||||
import it.Category1Suite; | import it.Category1Suite; | ||||
import java.util.Date; | import java.util.Date; | ||||
import java.util.List; | import java.util.List; | ||||
import org.sonar.wsclient.services.Measure; | import org.sonar.wsclient.services.Measure; | ||||
import org.sonar.wsclient.services.Resource; | import org.sonar.wsclient.services.Resource; | ||||
import org.sonar.wsclient.services.ResourceQuery; | import org.sonar.wsclient.services.ResourceQuery; | ||||
import pageobjects.Navigation; | |||||
import util.ItUtils; | import util.ItUtils; | ||||
import util.selenium.SeleneseTest; | |||||
import static org.apache.commons.lang.time.DateUtils.addDays; | import static org.apache.commons.lang.time.DateUtils.addDays; | ||||
import static org.assertj.core.api.Assertions.assertThat; | import static org.assertj.core.api.Assertions.assertThat; | ||||
assertThat(measures.get(0).getVariation1()).isEqualTo(17); | assertThat(measures.get(0).getVariation1()).isEqualTo(17); | ||||
// Check on ui that it's possible to define leak period on project | // Check on ui that it's possible to define leak period on project | ||||
new SeleneseTest(Selenese.builder().setHtmlTestsInClasspath("define-leak-period-on-project", | |||||
"/measureHistory/DifferentialPeriodsTest/define-leak-period-on-project.html" | |||||
).build()).runOn(orchestrator); | |||||
Navigation.get(orchestrator).openHomepage().logIn().asAdmin().openSettings("sample") | |||||
.assertSettingDisplayed("sonar.timemachine.period1"); | |||||
} | } | ||||
/** | /** |
import com.sonar.orchestrator.build.SonarScanner; | import com.sonar.orchestrator.build.SonarScanner; | ||||
import com.sonar.orchestrator.selenium.Selenese; | import com.sonar.orchestrator.selenium.Selenese; | ||||
import it.Category1Suite; | import it.Category1Suite; | ||||
import java.io.UnsupportedEncodingException; | |||||
import java.sql.SQLException; | import java.sql.SQLException; | ||||
import java.util.Calendar; | import java.util.Calendar; | ||||
import java.util.GregorianCalendar; | import java.util.GregorianCalendar; | ||||
import org.junit.rules.ExpectedException; | import org.junit.rules.ExpectedException; | ||||
import org.sonar.wsclient.SonarClient; | import org.sonar.wsclient.SonarClient; | ||||
import org.sonar.wsclient.base.HttpException; | import org.sonar.wsclient.base.HttpException; | ||||
import org.sonar.wsclient.services.PropertyQuery; | |||||
import org.sonar.wsclient.services.ResourceQuery; | import org.sonar.wsclient.services.ResourceQuery; | ||||
import org.sonar.wsclient.user.UserParameters; | import org.sonar.wsclient.user.UserParameters; | ||||
import pageobjects.Navigation; | |||||
import pageobjects.settings.SettingsPage; | |||||
import util.selenium.SeleneseTest; | import util.selenium.SeleneseTest; | ||||
import static org.assertj.core.api.Assertions.assertThat; | import static org.assertj.core.api.Assertions.assertThat; | ||||
import static util.ItUtils.projectDir; | import static util.ItUtils.projectDir; | ||||
public class ProjectAdministrationTest { | public class ProjectAdministrationTest { | ||||
private static final String DELETE_WS_ENDPOINT = "api/projects/bulk_delete"; | private static final String DELETE_WS_ENDPOINT = "api/projects/bulk_delete"; | ||||
@ClassRule | @ClassRule | ||||
public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; | public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; | ||||
@Rule | @Rule | ||||
public ExpectedException expectedException = ExpectedException.none(); | public ExpectedException expectedException = ExpectedException.none(); | ||||
@Rule | |||||
public Navigation nav = Navigation.get(orchestrator); | |||||
private static final String PROJECT_KEY = "sample"; | private static final String PROJECT_KEY = "sample"; | ||||
private static final String FILE_KEY = "sample:src/main/xoo/sample/Sample.xoo"; | private static final String FILE_KEY = "sample:src/main/xoo/sample/Sample.xoo"; | ||||
new SeleneseTest( | new SeleneseTest( | ||||
Selenese.builder().setHtmlTestsInClasspath("project-deletion", "/projectAdministration/ProjectAdministrationTest/project-deletion/project-deletion.html").build()) | Selenese.builder().setHtmlTestsInClasspath("project-deletion", "/projectAdministration/ProjectAdministrationTest/project-deletion/project-deletion.html").build()) | ||||
.runOn(orchestrator); | |||||
.runOn(orchestrator); | |||||
} finally { | } finally { | ||||
wsClient.userClient().deactivate(projectAdminUser); | wsClient.userClient().deactivate(projectAdminUser); | ||||
} | } | ||||
assertThat(count("events where category='Version'")).as("Different number of events").isEqualTo(1); | assertThat(count("events where category='Version'")).as("Different number of events").isEqualTo(1); | ||||
} | } | ||||
/** | |||||
* SONAR-3425 | |||||
*/ | |||||
@Test | @Test | ||||
public void project_settings() { | |||||
scanSampleWithDate("2012-01-01"); | |||||
Selenese selenese = Selenese.builder().setHtmlTestsInClasspath("project-settings", | |||||
// SONAR-3425 | |||||
"/projectAdministration/ProjectAdministrationTest/project-settings/override-global-settings.html", | |||||
"/projectAdministration/ProjectAdministrationTest/project-settings/only-on-project-settings.html").build(); | |||||
new SeleneseTest(selenese).runOn(orchestrator); | |||||
// GET /api/properties/sonar.exclusions?resource=sample | |||||
assertThat(orchestrator.getServer().getAdminWsClient().find(PropertyQuery.createForResource("sonar.exclusions", "sample")).getValue()) | |||||
.isEqualTo("my-exclusions"); | |||||
// GET /api/properties?resource=sample | |||||
// Note that this WS is used by SonarLint | |||||
assertThat(orchestrator.getServer().getAdminWsClient().findAll(PropertyQuery.createForResource(null, "sample"))).isNotEmpty(); | |||||
public void display_project_settings() throws UnsupportedEncodingException { | |||||
scanSample(null, null); | |||||
SettingsPage page = nav.logIn().asAdmin().openSettings("sample") | |||||
.assertMenuContains("Analysis Scope") | |||||
.assertMenuContains("Category 1") | |||||
.assertMenuContains("DEV") | |||||
.assertMenuContains("project-only") | |||||
.assertMenuContains("Xoo") | |||||
.assertSettingDisplayed("sonar.dbcleaner.daysBeforeDeletingClosedIssues"); | |||||
page.openCategory("project-only") | |||||
.assertSettingDisplayed("prop_only_on_project"); | |||||
page.openCategory("General") | |||||
.assertStringSettingValue("sonar.dbcleaner.daysBeforeDeletingClosedIssues", "30") | |||||
.assertStringSettingValue("sonar.timemachine.period1", "previous_version") | |||||
.assertBooleanSettingValue("sonar.dbcleaner.cleanDirectory", true) | |||||
.setStringValue("sonar.dbcleaner.daysBeforeDeletingClosedIssues", "1") | |||||
.assertStringSettingValue("sonar.dbcleaner.daysBeforeDeletingClosedIssues", "1"); | |||||
} | } | ||||
/** | |||||
* SONAR-4060 | |||||
*/ | |||||
@Test | @Test | ||||
public void display_module_settings() { | |||||
public void display_module_settings() throws UnsupportedEncodingException { | |||||
orchestrator.executeBuild(SonarScanner.create(projectDir("shared/xoo-multi-modules-sample"))); | orchestrator.executeBuild(SonarScanner.create(projectDir("shared/xoo-multi-modules-sample"))); | ||||
Selenese selenese = Selenese.builder().setHtmlTestsInClasspath("module-settings", | |||||
// SONAR-3425 | |||||
"/projectAdministration/ProjectAdministrationTest/module-settings/display-module-settings.html").build(); | |||||
new SeleneseTest(selenese).runOn(orchestrator); | |||||
nav.logIn().asAdmin() | |||||
.openSettings("com.sonarsource.it.samples:multi-modules-sample:module_a") | |||||
.assertMenuContains("Analysis Scope") | |||||
.assertSettingDisplayed("sonar.coverage.exclusions"); | |||||
} | } | ||||
private void scanSampleWithDate(String date) { | private void scanSampleWithDate(String date) { |
package it.settings; | package it.settings; | ||||
import com.sonar.orchestrator.Orchestrator; | import com.sonar.orchestrator.Orchestrator; | ||||
import com.sonar.orchestrator.selenium.Selenese; | |||||
import it.Category1Suite; | import it.Category1Suite; | ||||
import java.io.UnsupportedEncodingException; | |||||
import java.util.List; | import java.util.List; | ||||
import java.util.Map; | import java.util.Map; | ||||
import org.junit.After; | import org.junit.After; | ||||
import org.junit.BeforeClass; | import org.junit.BeforeClass; | ||||
import org.junit.ClassRule; | import org.junit.ClassRule; | ||||
import org.junit.Rule; | |||||
import org.junit.Test; | import org.junit.Test; | ||||
import org.sonarqube.ws.Settings; | import org.sonarqube.ws.Settings; | ||||
import org.sonarqube.ws.client.setting.ResetRequest; | import org.sonarqube.ws.client.setting.ResetRequest; | ||||
import org.sonarqube.ws.client.setting.SetRequest; | import org.sonarqube.ws.client.setting.SetRequest; | ||||
import org.sonarqube.ws.client.setting.SettingsService; | import org.sonarqube.ws.client.setting.SettingsService; | ||||
import org.sonarqube.ws.client.setting.ValuesRequest; | import org.sonarqube.ws.client.setting.ValuesRequest; | ||||
import util.selenium.SeleneseTest; | |||||
import pageobjects.Navigation; | |||||
import pageobjects.settings.SettingsPage; | |||||
import static com.google.common.collect.Lists.newArrayList; | import static com.google.common.collect.Lists.newArrayList; | ||||
import static java.util.Arrays.asList; | import static java.util.Arrays.asList; | ||||
@ClassRule | @ClassRule | ||||
public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; | public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; | ||||
@Rule | |||||
public Navigation nav = Navigation.get(orchestrator); | |||||
static SettingsService SETTINGS; | static SettingsService SETTINGS; | ||||
@BeforeClass | @BeforeClass | ||||
} | } | ||||
@Test | @Test | ||||
public void support_property_sets() { | |||||
Selenese selenese = Selenese.builder().setHtmlTestsInClasspath("property-sets", | |||||
"/settings/PropertySetsTest/property-sets/create.html", | |||||
"/settings/PropertySetsTest/property-sets/delete.html", | |||||
"/settings/PropertySetsTest/property-sets/reference.html", | |||||
"/settings/PropertySetsTest/property-sets/all_types.html").build(); | |||||
// Use the old runner because it fails with the new Selenium runner | |||||
orchestrator.executeSelenese(selenese); | |||||
// SSF-25 Check that the password has well be setted as now it does not appears in the html source code | |||||
assertPropertySet("sonar.demo", | |||||
asList(entry("password", "abcde"), | |||||
entry("boolean", "true"), | |||||
entry("float", "42.0"), | |||||
entry("license", "abc"), | |||||
entry("list", "AAA"), | |||||
entry("metric", "overall_branch_coverage"), | |||||
entry("regexp", ".*"), | |||||
entry("text", "text"))); | |||||
public void support_property_sets() throws UnsupportedEncodingException { | |||||
SettingsPage page = nav.logIn().asAdmin().openSettings(null).openCategory("DEV") | |||||
.assertSettingDisplayed("sonar.test.jira.servers"); | |||||
page.getPropertySetInput("sonar.test.jira.servers") | |||||
.setFieldValue("key", "jira1") | |||||
.setFieldValue("url", "http://jira") | |||||
.setFieldValue("port", "12345") | |||||
.save(); | |||||
assertPropertySet("sonar.test.jira.servers", asList( | |||||
entry("key", "jira1"), | |||||
entry("url", "http://jira"), | |||||
entry("port", "12345"))); | |||||
} | } | ||||
@Test | @Test | ||||
public void support_property_sets_with_auto_generated_keys() { | |||||
new SeleneseTest( | |||||
Selenese.builder().setHtmlTestsInClasspath("create-auto-generated", | |||||
"/settings/PropertySetsTest/auto-generated/create.html").build()).runOn(orchestrator); | |||||
assertPropertySet("sonar.autogenerated", asList(entry("value", "FIRST")), asList(entry("value", "SECOND")), asList(entry("value", "THIRD"))); | |||||
new SeleneseTest(Selenese.builder().setHtmlTestsInClasspath("update-auto-generated", | |||||
"/settings/PropertySetsTest/auto-generated/update.html").build()).runOn(orchestrator); | |||||
assertPropertySet("sonar.autogenerated", asList(entry("value", "FIRST")), asList(entry("value", "THIRD"))); | |||||
public void support_property_sets_with_auto_generated_keys() throws UnsupportedEncodingException { | |||||
SettingsPage page = nav.logIn().asAdmin().openSettings(null).openCategory("DEV") | |||||
.assertSettingDisplayed("sonar.autogenerated"); | |||||
page.getPropertySetInput("sonar.autogenerated") | |||||
.setFieldValue(0, "value", "FIRST") | |||||
.setFieldValue(1, "value", "SECOND") | |||||
.setFieldValue(2, "value", "THIRD") | |||||
.save(); | |||||
assertPropertySet("sonar.autogenerated", | |||||
asList(entry("value", "FIRST")), | |||||
asList(entry("value", "SECOND")), | |||||
asList(entry("value", "THIRD"))); | |||||
} | } | ||||
@Test | @Test | ||||
assertThat(setting.getFieldValues().getFieldValuesList()).hasSize(fieldsValues.length); | assertThat(setting.getFieldValues().getFieldValuesList()).hasSize(fieldsValues.length); | ||||
int index = 0; | int index = 0; | ||||
for (Settings.FieldValues.Value fieldsValue : setting.getFieldValues().getFieldValuesList()) { | for (Settings.FieldValues.Value fieldsValue : setting.getFieldValues().getFieldValuesList()) { | ||||
assertThat(fieldsValue.getValue()).containsOnly(fieldsValues[index].toArray(new Map.Entry[] {})); | |||||
assertThat(fieldsValue.getValue()).containsOnly(fieldsValues[index].toArray(new Map.Entry[]{})); | |||||
index++; | index++; | ||||
} | } | ||||
} | } |
import com.sonar.orchestrator.Orchestrator; | import com.sonar.orchestrator.Orchestrator; | ||||
import com.sonar.orchestrator.build.SonarScanner; | import com.sonar.orchestrator.build.SonarScanner; | ||||
import com.sonar.orchestrator.selenium.Selenese; | import com.sonar.orchestrator.selenium.Selenese; | ||||
import java.io.UnsupportedEncodingException; | |||||
import java.net.URL; | import java.net.URL; | ||||
import org.junit.After; | import org.junit.After; | ||||
import org.junit.Rule; | import org.junit.Rule; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
import org.junit.rules.ExpectedException; | import org.junit.rules.ExpectedException; | ||||
import pageobjects.Navigation; | |||||
import util.selenium.SeleneseTest; | import util.selenium.SeleneseTest; | ||||
import static util.ItUtils.pluginArtifact; | import static util.ItUtils.pluginArtifact; | ||||
} | } | ||||
@Test | @Test | ||||
public void test_settings() { | |||||
public void test_settings() throws UnsupportedEncodingException { | |||||
URL secretKeyUrl = getClass().getResource("/settings/SettingsTest/sonar-secret.txt"); | URL secretKeyUrl = getClass().getResource("/settings/SettingsTest/sonar-secret.txt"); | ||||
orchestrator = Orchestrator.builderEnv() | orchestrator = Orchestrator.builderEnv() | ||||
.addPlugin(pluginArtifact("settings-plugin")) | .addPlugin(pluginArtifact("settings-plugin")) | ||||
.build(); | .build(); | ||||
orchestrator.start(); | orchestrator.start(); | ||||
Selenese selenese = Selenese.builder().setHtmlTestsInClasspath("test_settings", | |||||
"/settings/SettingsTest/general-settings.html", | |||||
// SONAR-2869 the annotation @Properties can be used on extensions and not only on plugin entry points | |||||
"/settings/SettingsTest/hidden-extension-property.html", | |||||
"/settings/SettingsTest/global-extension-property.html", | |||||
Navigation.get(orchestrator).openHomepage().logIn().asAdmin().openSettings(null) | |||||
.assertMenuContains("General") | |||||
.assertSettingDisplayed("sonar.dbcleaner.cleanDirectory") | |||||
.assertSettingNotDisplayed("settings.extension.hidden") | |||||
.assertSettingNotDisplayed("settings.extension.global"); | |||||
// SONAR-3344 - licenses | |||||
"/settings/SettingsTest/ignore-corrupted-license.html", | |||||
"/settings/SettingsTest/display-license.html", | |||||
"/settings/SettingsTest/display-untyped-license.html", | |||||
// SONAR-2084 - encryption | |||||
Selenese selenese = Selenese.builder().setHtmlTestsInClasspath("test_settings", | |||||
// test encryption | |||||
"/settings/SettingsTest/generate-secret-key.html", | "/settings/SettingsTest/generate-secret-key.html", | ||||
"/settings/SettingsTest/encrypt-text.html", | |||||
// SONAR-1378 - property types | |||||
"/settings/SettingsTest/validate-property-type.html", | |||||
// SONAR-3127 - hide passwords | |||||
"/settings/SettingsTest/hide-passwords.html" | |||||
).build(); | |||||
"/settings/SettingsTest/encrypt-text.html" | |||||
// test licenses | |||||
// TODO enable when license page will be rewritten | |||||
// "/settings/SettingsTest/ignore-corrupted-license.html", | |||||
// "/settings/SettingsTest/display-license.html", | |||||
// "/settings/SettingsTest/display-untyped-license.html" | |||||
).build(); | |||||
new SeleneseTest(selenese).runOn(orchestrator); | new SeleneseTest(selenese).runOn(orchestrator); | ||||
} | } | ||||
@Test | @Test | ||||
public void property_relocation() { | |||||
public void property_relocation() throws UnsupportedEncodingException { | |||||
orchestrator = Orchestrator.builderEnv() | orchestrator = Orchestrator.builderEnv() | ||||
.addPlugin(pluginArtifact("property-relocation-plugin")) | .addPlugin(pluginArtifact("property-relocation-plugin")) | ||||
.addPlugin(xooPlugin()) | .addPlugin(xooPlugin()) | ||||
// should not fail | // should not fail | ||||
orchestrator.executeBuilds(withDeprecatedKey, withNewKey); | orchestrator.executeBuilds(withDeprecatedKey, withNewKey); | ||||
Selenese selenese = Selenese.builder().setHtmlTestsInClasspath("property_relocation", | |||||
"/settings/SettingsTest/property_relocation.html" | |||||
).build(); | |||||
new SeleneseTest(selenese).runOn(orchestrator); | |||||
Navigation.get(orchestrator).openHomepage().logIn().asAdmin().openSettings(null) | |||||
.assertMenuContains("General") | |||||
.assertSettingDisplayed("sonar.newKey") | |||||
.assertSettingNotDisplayed("sonar.deprecatedKey"); | |||||
} | } | ||||
} | } |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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. | |||||
*/ | |||||
package it.settings; | |||||
import com.sonar.orchestrator.Orchestrator; | |||||
import com.sonar.orchestrator.build.SonarScanner; | |||||
import com.sonar.orchestrator.selenium.Selenese; | |||||
import it.Category1Suite; | |||||
import org.junit.ClassRule; | |||||
import org.junit.Test; | |||||
import org.sonar.wsclient.services.PropertyQuery; | |||||
import util.selenium.SeleneseTest; | |||||
import static org.assertj.core.api.Assertions.assertThat; | |||||
import static util.ItUtils.projectDir; | |||||
public class SubCategoriesTest { | |||||
@ClassRule | |||||
public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; | |||||
/** | |||||
* SONAR-3159 | |||||
*/ | |||||
@Test | |||||
public void should_support_global_subcategories() { | |||||
Selenese selenese = Selenese.builder().setHtmlTestsInClasspath("subcategories", | |||||
"/settings/subcategories/global-subcategories.html", | |||||
// SONAR-4495 | |||||
"/settings/subcategories/global-subcategories-no-default.html" | |||||
).build(); | |||||
new SeleneseTest(selenese).runOn(orchestrator); | |||||
assertThat(getProperty("prop3", null)).isEqualTo("myValue"); | |||||
} | |||||
/** | |||||
* SONAR-3159 | |||||
*/ | |||||
@Test | |||||
public void should_support_project_subcategories() { | |||||
orchestrator.executeBuild(SonarScanner.create(projectDir("shared/xoo-sample"))); | |||||
Selenese selenese = Selenese.builder().setHtmlTestsInClasspath("subcategories", | |||||
"/settings/subcategories/project-subcategories.html", | |||||
// SONAR-4495 | |||||
"/settings/subcategories/project-subcategories-no-default.html" | |||||
).build(); | |||||
new SeleneseTest(selenese).runOn(orchestrator); | |||||
assertThat(getProperty("prop3", "sample")).isEqualTo("myValue2"); | |||||
} | |||||
static String getProperty(String key, String resourceKeyOrId) { | |||||
return orchestrator.getServer().getAdminWsClient().find(new PropertyQuery().setKey(key).setResourceKeyOrId(resourceKeyOrId)).getValue(); | |||||
} | |||||
} |
return submitCredentials(login, password, Navigation.class); | return submitCredentials(login, password, Navigation.class); | ||||
} | } | ||||
public Navigation asAdmin() { | |||||
return submitCredentials("admin", "admin"); | |||||
} | |||||
public LoginPage submitWrongCredentials(String login, String password) { | public LoginPage submitWrongCredentials(String login, String password) { | ||||
$("#login").val(login); | $("#login").val(login); | ||||
$("#password").val(password); | $("#password").val(password); |
import com.codeborne.selenide.SelenideElement; | import com.codeborne.selenide.SelenideElement; | ||||
import com.codeborne.selenide.WebDriverRunner; | import com.codeborne.selenide.WebDriverRunner; | ||||
import com.sonar.orchestrator.Orchestrator; | import com.sonar.orchestrator.Orchestrator; | ||||
import java.io.UnsupportedEncodingException; | |||||
import java.net.URLEncoder; | |||||
import javax.annotation.Nullable; | |||||
import org.junit.rules.ExternalResource; | import org.junit.rules.ExternalResource; | ||||
import org.openqa.selenium.By; | import org.openqa.selenium.By; | ||||
import pageobjects.settings.SettingsPage; | |||||
import static com.codeborne.selenide.Selenide.$; | import static com.codeborne.selenide.Selenide.$; | ||||
import static com.codeborne.selenide.Selenide.page; | import static com.codeborne.selenide.Selenide.page; | ||||
return open("/background_tasks", BackgroundTasksPage.class); | return open("/background_tasks", BackgroundTasksPage.class); | ||||
} | } | ||||
public SettingsPage openSettings(@Nullable String projectKey) throws UnsupportedEncodingException { | |||||
String url = projectKey != null ? | |||||
"/project/settings?id=" + URLEncoder.encode(projectKey, "UTF-8") : | |||||
"/settings"; | |||||
return open(url, SettingsPage.class); | |||||
} | |||||
public void open(String relativeUrl) { | public void open(String relativeUrl) { | ||||
Selenide.open(relativeUrl); | Selenide.open(relativeUrl); | ||||
} | } |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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. | |||||
*/ | |||||
package pageobjects.settings; | |||||
import com.codeborne.selenide.SelenideElement; | |||||
import static com.codeborne.selenide.Condition.exist; | |||||
public class PropertySetInput { | |||||
private final SelenideElement elt; | |||||
public PropertySetInput(SelenideElement elt) { | |||||
this.elt = elt; | |||||
} | |||||
public PropertySetInput setFieldValue(int index, String fieldKey, String value) { | |||||
elt.findAll("input[name$=\"[" + fieldKey + "]\"]").get(index).val(value); | |||||
return this; | |||||
} | |||||
public PropertySetInput setFieldValue(String fieldKey, String value) { | |||||
return setFieldValue(0, fieldKey, value); | |||||
} | |||||
public PropertySetInput save() { | |||||
elt.find(".js-save-changes").click(); | |||||
elt.find(".js-save-changes").shouldNot(exist); | |||||
return this; | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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. | |||||
*/ | |||||
package pageobjects.settings; | |||||
import com.codeborne.selenide.SelenideElement; | |||||
import org.openqa.selenium.By; | |||||
import static com.codeborne.selenide.Condition.cssClass; | |||||
import static com.codeborne.selenide.Condition.exactValue; | |||||
import static com.codeborne.selenide.Condition.exist; | |||||
import static com.codeborne.selenide.Condition.visible; | |||||
import static com.codeborne.selenide.Selenide.$; | |||||
public class SettingsPage { | |||||
public SettingsPage() { | |||||
$("#settings-page").shouldBe(visible); | |||||
} | |||||
public SettingsPage assertMenuContains(String categoryName) { | |||||
$(".settings-menu").$(By.linkText(categoryName)).shouldBe(visible); | |||||
return this; | |||||
} | |||||
public SettingsPage assertSettingDisplayed(String settingKey) { | |||||
$(".settings-definition[data-key='" + settingKey + "']").shouldBe(visible); | |||||
return this; | |||||
} | |||||
public SettingsPage assertSettingNotDisplayed(String settingKey) { | |||||
$(".settings-definition[data-key='" + settingKey + "']").shouldNotBe(visible); | |||||
return this; | |||||
} | |||||
public SettingsPage openCategory(String categoryName) { | |||||
$(".settings-menu").$(By.linkText(categoryName)).click(); | |||||
return this; | |||||
} | |||||
public SettingsPage assertStringSettingValue(String settingKey, String value) { | |||||
$("input[name=\"settings[" + settingKey + "]\"]").shouldHave(exactValue(value)); | |||||
return this; | |||||
} | |||||
public SettingsPage assertBooleanSettingValue(String settingKey, boolean value) { | |||||
SelenideElement toggle = $("button[name=\"settings[" + settingKey + "]\"]"); | |||||
if (value) { | |||||
toggle.shouldHave(cssClass("boolean-toggle-on")); | |||||
} else { | |||||
toggle.shouldNotHave(cssClass("boolean-toggle-on")); | |||||
} | |||||
return this; | |||||
} | |||||
public SettingsPage setStringValue(String settingKey, String value) { | |||||
SelenideElement setting = $(".settings-definition[data-key=\"" + settingKey + "\"]"); | |||||
setting.find("input").val(value); | |||||
setting.find(".js-save-changes").click(); | |||||
setting.find(".js-save-changes").shouldNot(exist); | |||||
return this; | |||||
} | |||||
public PropertySetInput getPropertySetInput(String settingKey) { | |||||
SelenideElement setting = $(".settings-definition[data-key=\"" + settingKey + "\"]"); | |||||
return new PropertySetInput(setting); | |||||
} | |||||
} |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>global-admin-dashboards</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<thead> | |||||
<tr> | |||||
<td rowspan="1" colspan="3">global-admin-dashboards</td> | |||||
</tr> | |||||
</thead> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/login</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>link=Home</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Home</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Configure widgets</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Back to dashboard</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/dashboards</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings/index</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>link=Configuration</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>link=Configuration</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Default Dashboards</td> | |||||
<td></td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>display-added-files</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<thead> | |||||
<tr> | |||||
<td rowspan="1" colspan="3">should_display_added_files_in_differential_drilldown</td> | |||||
</tr> | |||||
</thead> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/logout</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/project/settings?id=sample&category=general&subcategory=differentialviews</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>name=commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForText</td> | |||||
<td>properties</td> | |||||
<td>*Leak Period*</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>override-global-settings</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<thead> | |||||
<tr> | |||||
<td rowspan="1" colspan="3">override-global-settings</td> | |||||
</tr> | |||||
</thead> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/logout</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/project/settings/com.sonarsource.it.samples%3Amulti-modules-sample%3Amodule_a</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>name=commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForText</td> | |||||
<td>plugins</td> | |||||
<td>*Settings*</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>override-global-settings</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<thead> | |||||
<tr> | |||||
<td rowspan="1" colspan="3">override-global-settings</td> | |||||
</tr> | |||||
</thead> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/logout</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/project/settings/sample?category=project-only</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>name=commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_prop_only_on_project</td> | |||||
<td>foo</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>id=submit_settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>id=input_prop_only_on_project</td> | |||||
<td>foo</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>override-global-settings</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<thead> | |||||
<tr> | |||||
<td rowspan="1" colspan="3">override-global-settings</td> | |||||
</tr> | |||||
</thead> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/logout</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/project/settings/sample?category=exclusions&subcategory=files</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>name=commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_sonar.exclusions</td> | |||||
<td>my-exclusions</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>id=submit_settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>id=input_sonar.exclusions</td> | |||||
<td>my-exclusions</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td>open</td> | <td>open</td> | ||||
<td>/settings/index</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Licenses</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Server ID</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>selectFrame</td> | |||||
<td>settings_iframe</td> | |||||
<td>/server_id_configuration</td> | |||||
<td></td> | <td></td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> |
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td>open</td> | <td>open</td> | ||||
<td>/settings/index</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Licenses</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Server ID</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>selectFrame</td> | |||||
<td>settings_iframe</td> | |||||
<td>/server_id_configuration</td> | |||||
<td></td> | <td></td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> |
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td>open</td> | <td>open</td> | ||||
<td>/settings/index</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Licenses</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Server ID</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>settings_iframe</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>selectFrame</td> | |||||
<td>settings_iframe</td> | |||||
<td>/server_id_configuration</td> | |||||
<td></td> | <td></td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>create</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/new</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings?category=DEV</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>1</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_value</td> | |||||
<td>FIRST</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>css=button.add_value</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>xpath=(//input[@id='input_value'])[2]</td> | |||||
<td>SECOND</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>css=button.add_value</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>xpath=(//input[@id='input_value'])[3]</td> | |||||
<td>THIRD</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>id=submit_settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>2</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>update</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/new</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings?category=DEV</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>1</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>link=Delete</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForVisible</td> | |||||
<td>id=submit_settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>id=submit_settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>2</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>all_types</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/new</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings?category=DEV</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>1</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_text</td> | |||||
<td>text</td> | |||||
</tr> | |||||
<tr> | |||||
<td>select</td> | |||||
<td>id=input_boolean</td> | |||||
<td>label=True</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_float</td> | |||||
<td>42.0</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_license</td> | |||||
<td>abc</td> | |||||
</tr> | |||||
<tr> | |||||
<td>select</td> | |||||
<td>id=input_metric</td> | |||||
<td>label=Overall Condition Coverage</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_password</td> | |||||
<td>abcde</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_regexp</td> | |||||
<td>.*</td> | |||||
</tr> | |||||
<tr> | |||||
<td>select</td> | |||||
<td>id=input_list</td> | |||||
<td>label=AAA</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>id=submit_settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>2</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>id=input_text</td> | |||||
<td>text</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>id=input_boolean</td> | |||||
<td>true</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>id=input_float</td> | |||||
<td>42.0</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>id=input_license</td> | |||||
<td>abc</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>id=input_metric</td> | |||||
<td>overall_branch_coverage</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>id=input_password</td> | |||||
<td>{{*******************}}</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>id=input_regexp</td> | |||||
<td>exact:.*</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>id=input_list</td> | |||||
<td>AAA</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>create</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/new</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings?category=DEV</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>1</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_key</td> | |||||
<td>jira1</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_url</td> | |||||
<td>http://jira</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_port</td> | |||||
<td>12345</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>id=submit_settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>2</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>id=input_key</td> | |||||
<td>jira1</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>id=input_url</td> | |||||
<td>exact:http://jira</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>id=input_port</td> | |||||
<td>12345</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>delete</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/new</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings?category=DEV</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>1</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_key</td> | |||||
<td>jira1</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_url</td> | |||||
<td>http://jira1</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>css=#block_sonar\.test\.jira\.servers .add_value</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>xpath=(//input[@id='input_key'])[2]</td> | |||||
<td>jira2</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>xpath=(//input[@id='input_url'])[2]</td> | |||||
<td>http://jira2</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>id=submit_settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>2</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>xpath=(//input[@id='input_key'])[1]</td> | |||||
<td>jira1</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>xpath=(//input[@id='input_key'])[2]</td> | |||||
<td>jira2</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>xpath=(//a[contains(text(),'Delete')])[3]</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>id=submit_settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>3</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>xpath=(//input[@id='input_key'])[1]</td> | |||||
<td>jira1</td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForNotText</td> | |||||
<td>xpath=(//input[@id='input_key'])</td> | |||||
<td>*jira2*</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>reference</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/new</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings?category=DEV</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>1</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>xpath=(//input[@id='input_key'])[1]</td> | |||||
<td>jira1</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>css=#block_sonar\.test\.jira\.servers .add_value</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>xpath=(//input[@id='input_key'])[2]</td> | |||||
<td>jira2</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>id=submit_settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>2</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertSelectOptions</td> | |||||
<td>id=input_sonar.test.jira</td> | |||||
<td>Default,jira1,jira2</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>xpath=(//a[contains(text(),'Delete')])[2]</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>id=submit_settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>3</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td>open</td> | <td>open</td> | ||||
<td>/settings?category=security&subcategory=encryption</td> | |||||
<td>/encryption_configuration</td> | |||||
<td></td> | <td></td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td>waitForElementPresent</td> | <td>waitForElementPresent</td> | ||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>selectFrame</td> | |||||
<td>settings_iframe</td> | |||||
<td>css=#submit_encrypt</td> | |||||
<td></td> | <td></td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>settings_on_core_plugins</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<thead> | |||||
<tr> | |||||
<td rowspan="1" colspan="3">settings_on_core_plugins</td> | |||||
</tr> | |||||
</thead> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/logout</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/new</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings/index</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForText</td> | |||||
<td>plugins</td> | |||||
<td>*General*</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td>open</td> | <td>open</td> | ||||
<td>/settings?category=security&subcategory=encryption</td> | |||||
<td>/encryption_configuration</td> | |||||
<td></td> | <td></td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td>waitForElementPresent</td> | <td>waitForElementPresent</td> | ||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>selectFrame</td> | |||||
<td>settings_iframe</td> | |||||
<td>css=#submit_encrypt</td> | |||||
<td></td> | <td></td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>global-extension-property</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<thead> | |||||
<tr> | |||||
<td rowspan="1" colspan="3">global-extension-property</td> | |||||
</tr> | |||||
</thead> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/new</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings?category=Settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertNotText</td> | |||||
<td>plugins</td> | |||||
<td>glob:*Hidden*</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>hidden-extension-property</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<thead> | |||||
<tr> | |||||
<td rowspan="1" colspan="3">hidden-extension-property</td> | |||||
</tr> | |||||
</thead> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/new</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings?category=Settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertNotText</td> | |||||
<td>plugins</td> | |||||
<td>glob:*Hidden*</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>hide-passwords</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/logout</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings?category=Settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>name=commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForText</td> | |||||
<td>block_password</td> | |||||
<td>*Default*</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertNotText</td> | |||||
<td>block_password</td> | |||||
<td>*Default*sonar*</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>property-relocation</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/logout</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings/index?category=general</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>name=commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForText</td> | |||||
<td>properties</td> | |||||
<td>*sonar.newKey*</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertNotText</td> | |||||
<td>properties</td> | |||||
<td>*sonar.deprecatedKey*</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>validate-property-type</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/logout</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings?category=Settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>name=commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_float</td> | |||||
<td>abc</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_integer</td> | |||||
<td>123</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>id=submit_settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForText</td> | |||||
<td>properties</td> | |||||
<td>*Not a floating point number*</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>input_integer</td> | |||||
<td>123</td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings?category=Settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>input_float</td> | |||||
<td></td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>global-subcategories</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/new</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings?category=Category 2</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>1</td> | |||||
</tr> | |||||
<!-- First subcategory should be selected by default --> | |||||
<tr> | |||||
<td>assertElementPresent</td> | |||||
<td>id=input_prop2_1</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop2_2</td> | |||||
<td></td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>global-subcategories</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/new</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/settings?category=Category 1</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>1</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop1</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop2</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop3</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementPresent</td> | |||||
<td>id=input_prop4</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Sub category 1</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementPresent</td> | |||||
<td>id=input_prop1</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementPresent</td> | |||||
<td>id=input_prop2</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop3</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop4</td> | |||||
<td></td> | |||||
</tr> | |||||
<!-- Verify index attribute is taken into account --> | |||||
<tr> | |||||
<td>assertElementPresent</td> | |||||
<td>xpath=//.[@id='input_prop2']/following::input[@id='input_prop1']</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Sub category 2</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_prop3</td> | |||||
<td>myValue</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>id=submit_settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>2</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop1</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop2</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementPresent</td> | |||||
<td>id=input_prop3</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop4</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>id=input_prop3</td> | |||||
<td>myValue</td> | |||||
</tr> | |||||
<!-- SONAR-4473 --> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Sub category 1</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementPresent</td> | |||||
<td>id=input_prop1</td> | |||||
<td></td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>create</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/new</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/project/settings/sample?category=Category 2</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>1</td> | |||||
</tr> | |||||
<!-- First subcategory should be selected by default --> | |||||
<tr> | |||||
<td>assertElementPresent</td> | |||||
<td>id=input_prop2_1</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop2_2</td> | |||||
<td></td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||||
<title>create</title> | |||||
</head> | |||||
<body> | |||||
<table cellpadding="1" cellspacing="1" border="1"> | |||||
<tbody> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/sessions/new</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>login</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>password</td> | |||||
<td>admin</td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>commit</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForElementPresent</td> | |||||
<td>css=.js-user-authenticated</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>open</td> | |||||
<td>/project/settings/sample?category=Category 1</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>1</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop1</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop2</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop3</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementPresent</td> | |||||
<td>id=input_prop4</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Sub category 1</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementPresent</td> | |||||
<td>id=input_prop1</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementPresent</td> | |||||
<td>id=input_prop2</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop3</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop4</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Sub category 2</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>type</td> | |||||
<td>id=input_prop3</td> | |||||
<td>myValue2</td> | |||||
</tr> | |||||
<tr> | |||||
<td>click</td> | |||||
<td>id=submit_settings</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>waitForValue</td> | |||||
<td>name=page_version</td> | |||||
<td>2</td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop1</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop2</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementPresent</td> | |||||
<td>id=input_prop3</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementNotPresent</td> | |||||
<td>id=input_prop4</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertValue</td> | |||||
<td>id=input_prop3</td> | |||||
<td>myValue2</td> | |||||
</tr> | |||||
<!-- SONAR-4473 --> | |||||
<tr> | |||||
<td>clickAndWait</td> | |||||
<td>link=Sub category 1</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementPresent</td> | |||||
<td>id=input_prop1</td> | |||||
<td></td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</body> | |||||
</html> |
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td>open</td> | <td>open</td> | ||||
<td>/settings</td> | |||||
<td>/updatecenter</td> | |||||
<td></td> | <td></td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td>css=.js-user-authenticated</td> | <td>css=.js-user-authenticated</td> | ||||
<td></td> | <td></td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td>open</td> | |||||
<td>/updatecenter</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | <tr> | ||||
<td>waitForText</td> | <td>waitForText</td> | ||||
<td>content</td> | <td>content</td> |
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td>open</td> | <td>open</td> | ||||
<td>/settings/index</td> | |||||
<td>/settings</td> | |||||
<td></td> | <td></td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td>assertLocation</td> | <td>assertLocation</td> | ||||
<td>*/settings/index</td> | |||||
<td></td> | |||||
</tr> | |||||
<tr> | |||||
<td>assertElementPresent</td> | |||||
<td>plugins</td> | |||||
<td>*/settings</td> | |||||
<td></td> | <td></td> | ||||
</tr> | </tr> | ||||
</tbody> | </tbody> |
'projects': './src/main/js/apps/projects/app.js', | 'projects': './src/main/js/apps/projects/app.js', | ||||
'quality-gates': './src/main/js/apps/quality-gates/app.js', | 'quality-gates': './src/main/js/apps/quality-gates/app.js', | ||||
'quality-profiles': './src/main/js/apps/quality-profiles/app.js', | 'quality-profiles': './src/main/js/apps/quality-profiles/app.js', | ||||
'settings': './src/main/js/apps/settings/app.js', | |||||
'source-viewer': './src/main/js/apps/source-viewer/app.js', | 'source-viewer': './src/main/js/apps/source-viewer/app.js', | ||||
'system': './src/main/js/apps/system/app.js', | 'system': './src/main/js/apps/system/app.js', | ||||
'update-center': './src/main/js/apps/update-center/app.js', | 'update-center': './src/main/js/apps/update-center/app.js', |
function runDevServer (port) { | function runDevServer (port) { | ||||
app.use(require('webpack-dev-middleware')(compiler, { | app.use(require('webpack-dev-middleware')(compiler, { | ||||
noInfo: true, | noInfo: true, | ||||
quiet: true, | |||||
publicPath: config.output.publicPath | publicPath: config.output.publicPath | ||||
})); | })); | ||||
app.use(require('webpack-hot-middleware')(compiler, { | |||||
noInfo: true, | |||||
quiet: true | |||||
})); | |||||
app.use(require('webpack-hot-middleware')(compiler)); | |||||
app.all('*', proxy(API_HOST, { | app.all('*', proxy(API_HOST, { | ||||
forwardPath: function (req) { | forwardPath: function (req) { |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 omitBy from 'lodash/omitBy'; | |||||
import { getJSON, post } from '../helpers/request'; | |||||
import { TYPE_PROPERTY_SET } from '../apps/settings/constants'; | |||||
export function getDefinitions (componentKey) { | |||||
const url = '/api/settings/list_definitions'; | |||||
const data = componentKey ? { componentKey } : {}; | |||||
return getJSON(url, data).then(r => r.definitions); | |||||
} | |||||
export function getValues (keys, componentKey) { | |||||
const url = '/api/settings/values'; | |||||
const data = { keys }; | |||||
if (componentKey) { | |||||
data.componentKey = componentKey; | |||||
} | |||||
return getJSON(url, data).then(r => r.settings); | |||||
} | |||||
export function setSettingValue (definition, value, componentKey) { | |||||
const url = '/api/settings/set'; | |||||
const { key } = definition; | |||||
const data = { key }; | |||||
if (definition.multiValues) { | |||||
data.values = value; | |||||
} else if (definition.type === TYPE_PROPERTY_SET) { | |||||
data.fieldValues = value | |||||
.map(fields => omitBy(fields, value => value == null)) | |||||
.map(JSON.stringify); | |||||
} else { | |||||
data.value = value; | |||||
} | |||||
if (componentKey) { | |||||
data.componentKey = componentKey; | |||||
} | |||||
return post(url, data); | |||||
} | |||||
export function resetSettingValue (key, componentKey) { | |||||
const url = '/api/settings/reset'; | |||||
const data = { key }; | |||||
if (componentKey) { | |||||
data.componentKey = componentKey; | |||||
} | |||||
return post(url, data); | |||||
} |
const url = '/api/users/identity_providers'; | const url = '/api/users/identity_providers'; | ||||
return getJSON(url); | return getJSON(url); | ||||
} | } | ||||
export function searchUsers (query) { | |||||
const url = '/api/users/search'; | |||||
const data = { q: query }; | |||||
return getJSON(url, data); | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { expect } from 'chai'; | |||||
import { getEmptyValue } from '../utils'; | |||||
import { TYPE_PROPERTY_SET, TYPE_STRING, TYPE_SINGLE_SELECT_LIST, TYPE_BOOLEAN } from '../constants'; | |||||
const fields = [ | |||||
{ key: 'foo', type: TYPE_STRING }, | |||||
{ key: 'bar', type: TYPE_SINGLE_SELECT_LIST } | |||||
]; | |||||
describe('Settings :: Utils', () => { | |||||
describe('#getEmptyValue()', () => { | |||||
it('should work for property sets', () => { | |||||
const setting = { type: TYPE_PROPERTY_SET, fields }; | |||||
expect(getEmptyValue(setting)).to.deep.equal([{ foo: '', bar: null }]); | |||||
}); | |||||
it('should work for multi values string', () => { | |||||
const setting = { type: TYPE_STRING, multiValues: true }; | |||||
expect(getEmptyValue(setting)).to.deep.equal(['']); | |||||
}); | |||||
it('should work for multi values boolean', () => { | |||||
const setting = { type: TYPE_BOOLEAN, multiValues: true }; | |||||
expect(getEmptyValue(setting)).to.deep.equal([null]); | |||||
}); | |||||
}); | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { render } from 'react-dom'; | |||||
import { Provider } from 'react-redux'; | |||||
import { Router, Route, Redirect, useRouterHistory } from 'react-router'; | |||||
import { createHistory } from 'history'; | |||||
import App from './components/App'; | |||||
import rootReducer from './store/rootReducer'; | |||||
import configureStore from '../../components/store/configureStore'; | |||||
window.sonarqube.appStarted.then(options => { | |||||
const el = document.querySelector(options.el); | |||||
const controller = options.component ? '/project/settings' : '/settings'; | |||||
const history = useRouterHistory(createHistory)({ | |||||
basename: window.baseUrl + controller | |||||
}); | |||||
const store = configureStore(rootReducer); | |||||
const withComponent = ComposedComponent => props => | |||||
<ComposedComponent {...props} component={options.component}/>; | |||||
render(( | |||||
<Provider store={store}> | |||||
<Router history={history}> | |||||
<Redirect from="/index" to="/"/> | |||||
<Route path="/" component={withComponent(App)}/> | |||||
</Router> | |||||
</Provider> | |||||
), el); | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { connect } from 'react-redux'; | |||||
import CategoriesList from './CategoriesList'; | |||||
import { getAllCategories } from '../store/rootReducer'; | |||||
class AllCategoriesList extends React.Component { | |||||
render () { | |||||
return <CategoriesList {...this.props}/>; | |||||
} | |||||
} | |||||
const mapStateToProps = state => ({ | |||||
categories: getAllCategories(state) | |||||
}); | |||||
export default connect( | |||||
mapStateToProps | |||||
)(AllCategoriesList); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 shallowCompare from 'react-addons-shallow-compare'; | |||||
import { connect } from 'react-redux'; | |||||
import PageHeader from './PageHeader'; | |||||
import CategoryDefinitionsList from './CategoryDefinitionsList'; | |||||
import AllCategoriesList from './AllCategoriesList'; | |||||
import GlobalMessagesContainer from './GlobalMessagesContainer'; | |||||
import { fetchSettings } from '../store/actions'; | |||||
import { getDefaultCategory } from '../store/rootReducer'; | |||||
import '../styles.css'; | |||||
class App extends React.Component { | |||||
static propTypes = { | |||||
component: React.PropTypes.object, | |||||
fetchSettings: React.PropTypes.func.isRequired, | |||||
defaultCategory: React.PropTypes.string | |||||
}; | |||||
state = { loaded: false }; | |||||
componentDidMount () { | |||||
document.querySelector('html').classList.add('dashboard-page'); | |||||
const componentKey = this.props.component ? this.props.component.key : null; | |||||
this.props.fetchSettings(componentKey).then(() => { | |||||
this.setState({ loaded: true }); | |||||
}); | |||||
} | |||||
shouldComponentUpdate (nextProps, nextState) { | |||||
return shallowCompare(this, nextProps, nextState); | |||||
} | |||||
componentDidUpdate (prevProps) { | |||||
if (prevProps.component !== this.props.component) { | |||||
const componentKey = this.props.component ? this.props.component.key : null; | |||||
this.props.fetchSettings(componentKey); | |||||
} | |||||
} | |||||
componentWillUnmount () { | |||||
document.querySelector('html').classList.remove('dashboard-page'); | |||||
} | |||||
render () { | |||||
if (!this.state.loaded) { | |||||
return null; | |||||
} | |||||
const { query } = this.props.location; | |||||
const selectedCategory = query.category || this.props.defaultCategory; | |||||
return ( | |||||
<div id="settings-page" className="page page-limited"> | |||||
<PageHeader component={this.props.component}/> | |||||
<GlobalMessagesContainer/> | |||||
<div className="settings-layout"> | |||||
<div className="settings-side"> | |||||
<AllCategoriesList | |||||
component={this.props.component} | |||||
selectedCategory={selectedCategory} | |||||
defaultCategory={this.props.defaultCategory}/> | |||||
</div> | |||||
<div className="settings-main"> | |||||
<CategoryDefinitionsList | |||||
component={this.props.component} | |||||
category={selectedCategory}/> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
); | |||||
} | |||||
} | |||||
const mapStateToProps = state => ({ | |||||
defaultCategory: getDefaultCategory(state) | |||||
}); | |||||
export default connect( | |||||
mapStateToProps, | |||||
{ fetchSettings } | |||||
)(App); | |||||
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 shallowCompare from 'react-addons-shallow-compare'; | |||||
import sortBy from 'lodash/sortBy'; | |||||
import { IndexLink } from 'react-router'; | |||||
import { getCategoryName } from '../utils'; | |||||
export default class CategoriesList extends React.Component { | |||||
static propTypes = { | |||||
categories: React.PropTypes.array.isRequired, | |||||
selectedCategory: React.PropTypes.string.isRequired, | |||||
defaultCategory: React.PropTypes.string.isRequired | |||||
}; | |||||
shouldComponentUpdate (nextProps, nextState) { | |||||
return shallowCompare(this, nextProps, nextState); | |||||
} | |||||
renderLink (category) { | |||||
const query = {}; | |||||
if (category.key !== this.props.defaultCategory) { | |||||
query.category = category.key.toLowerCase(); | |||||
} | |||||
if (this.props.component) { | |||||
query.id = this.props.component.key; | |||||
} | |||||
const className = category.key.toLowerCase() === this.props.selectedCategory.toLowerCase() ? 'active' : ''; | |||||
return ( | |||||
<IndexLink to={{ pathname: '/', query }} className={className} title={category.name}> | |||||
{category.name} | |||||
</IndexLink> | |||||
); | |||||
} | |||||
render () { | |||||
const categoriesWithName = this.props.categories.map(key => ({ key, name: getCategoryName(key) })); | |||||
const sortedCategories = sortBy(categoriesWithName, category => category.name.toLowerCase()); | |||||
return ( | |||||
<ul className="settings-menu"> | |||||
{sortedCategories.map(category => ( | |||||
<li key={category.key}> | |||||
{this.renderLink(category)} | |||||
</li> | |||||
))} | |||||
</ul> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { connect } from 'react-redux'; | |||||
import SubCategoryDefinitionsList from './SubCategoryDefinitionsList'; | |||||
import { getSettingsForCategory } from '../store/rootReducer'; | |||||
class CategoryDefinitionsList extends React.Component { | |||||
render () { | |||||
return <SubCategoryDefinitionsList {...this.props}/>; | |||||
} | |||||
} | |||||
const mapStateToProps = (state, ownProps) => ({ | |||||
settings: getSettingsForCategory(state, ownProps.category) | |||||
}); | |||||
export default connect( | |||||
mapStateToProps | |||||
)(CategoryDefinitionsList); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { connect } from 'react-redux'; | |||||
import shallowCompare from 'react-addons-shallow-compare'; | |||||
import classNames from 'classnames'; | |||||
import Input from './inputs/Input'; | |||||
import DefinitionDefaults from './DefinitionDefaults'; | |||||
import DefinitionChanges from './DefinitionChanges'; | |||||
import { getPropertyName, getPropertyDescription, isEmptyValue, getSettingValue, isDefaultOrInherited } from '../utils'; | |||||
import { translateWithParameters, translate } from '../../../helpers/l10n'; | |||||
import { resetValue, saveValue } from '../store/actions'; | |||||
import { isLoading, getValidationMessage, getChangedValue } from '../store/rootReducer'; | |||||
import { failValidation, passValidation } from '../store/settingsPage/validationMessages/actions'; | |||||
import { cancelChange, changeValue } from '../store/settingsPage/changedValues/actions'; | |||||
class Definition extends React.Component { | |||||
static propTypes = { | |||||
component: React.PropTypes.object, | |||||
setting: React.PropTypes.object.isRequired, | |||||
changedValue: React.PropTypes.any, | |||||
loading: React.PropTypes.bool.isRequired, | |||||
validationMessage: React.PropTypes.string, | |||||
changeValue: React.PropTypes.func.isRequired, | |||||
cancelChange: React.PropTypes.func.isRequired, | |||||
saveValue: React.PropTypes.func.isRequired, | |||||
resetValue: React.PropTypes.func.isRequired, | |||||
failValidation: React.PropTypes.func.isRequired, | |||||
passValidation: React.PropTypes.func.isRequired | |||||
}; | |||||
state = { | |||||
success: false | |||||
}; | |||||
componentDidMount () { | |||||
this.mounted = true; | |||||
} | |||||
shouldComponentUpdate (nextProps, nextState) { | |||||
return shallowCompare(this, nextProps, nextState); | |||||
} | |||||
componentWillUnmount () { | |||||
this.mounted = false; | |||||
} | |||||
safeSetState (changes) { | |||||
if (this.mounted) { | |||||
this.setState(changes); | |||||
} | |||||
} | |||||
handleChange (value) { | |||||
clearTimeout(this.timeout); | |||||
return this.props.changeValue(this.props.setting.definition.key, value); | |||||
} | |||||
handleReset () { | |||||
const componentKey = this.props.component ? this.props.component.key : null; | |||||
const { definition } = this.props.setting; | |||||
return this.props.resetValue(definition.key, componentKey).then(() => { | |||||
this.safeSetState({ success: true }); | |||||
this.timeout = setTimeout(() => this.safeSetState({ success: false }), 3000); | |||||
}).catch(() => { /* do nothing */ }); | |||||
} | |||||
handleCancel () { | |||||
this.props.cancelChange(this.props.setting.definition.key); | |||||
this.props.passValidation(this.props.setting.definition.key); | |||||
} | |||||
handleSave () { | |||||
this.safeSetState({ success: false }); | |||||
const { definition } = this.props.setting; | |||||
if (isEmptyValue(definition, this.props.changedValue)) { | |||||
this.props.failValidation(definition.key, translate('settings.state.value_cant_be_empty')); | |||||
return; | |||||
} | |||||
const componentKey = this.props.component ? this.props.component.key : null; | |||||
this.props.saveValue(this.props.setting.definition.key, componentKey).then(() => { | |||||
this.safeSetState({ success: true }); | |||||
this.timeout = setTimeout(() => this.safeSetState({ success: false }), 3000); | |||||
}).catch(() => { /* do nothing */ }); | |||||
} | |||||
render () { | |||||
const { setting, changedValue, loading } = this.props; | |||||
const { definition } = setting; | |||||
const propertyName = getPropertyName(definition); | |||||
const hasValueChanged = changedValue != null; | |||||
const className = classNames('settings-definition', { | |||||
'settings-definition-changed': hasValueChanged | |||||
}); | |||||
const effectiveValue = hasValueChanged ? changedValue : getSettingValue(setting); | |||||
const isDefault = isDefaultOrInherited(setting) && !hasValueChanged; | |||||
return ( | |||||
<div className={className} data-key={definition.key}> | |||||
<div className="settings-definition-left"> | |||||
<h3 className="settings-definition-name" title={propertyName}> | |||||
{propertyName} | |||||
</h3> | |||||
<div className="settings-definition-description markdown small spacer-top" | |||||
dangerouslySetInnerHTML={{ __html: getPropertyDescription(definition) }}/> | |||||
<div className="settings-definition-key note little-spacer-top"> | |||||
{translateWithParameters('settings.key_x', definition.key)} | |||||
</div> | |||||
</div> | |||||
<div className="settings-definition-right"> | |||||
<Input setting={setting} value={effectiveValue} onChange={this.handleChange.bind(this)}/> | |||||
{!hasValueChanged && ( | |||||
<DefinitionDefaults | |||||
setting={setting} | |||||
isDefault={isDefault} | |||||
onReset={() => this.handleReset()}/> | |||||
)} | |||||
{hasValueChanged && ( | |||||
<DefinitionChanges | |||||
onSave={this.handleSave.bind(this)} | |||||
onCancel={this.handleCancel.bind(this)}/> | |||||
)} | |||||
<div className="settings-definition-state"> | |||||
{loading && ( | |||||
<span className="text-info"> | |||||
<span className="settings-definition-state-icon"> | |||||
<i className="spinner"/> | |||||
</span> | |||||
{translate('settings.state.saving')} | |||||
</span> | |||||
)} | |||||
{!loading && (this.props.validationMessage != null) && ( | |||||
<span className="text-danger"> | |||||
<span className="settings-definition-state-icon"> | |||||
<i className="icon-alert-error"/> | |||||
</span> | |||||
{translateWithParameters('settings.state.validation_failed', this.props.validationMessage)} | |||||
</span> | |||||
)} | |||||
{!loading && this.state.success && ( | |||||
<span className="text-success"> | |||||
<span className="settings-definition-state-icon"> | |||||
<i className="icon-check"/> | |||||
</span> | |||||
{translate('settings.state.saved')} | |||||
</span> | |||||
)} | |||||
</div> | |||||
</div> | |||||
</div> | |||||
); | |||||
} | |||||
} | |||||
const mapStateToProps = (state, ownProps) => ({ | |||||
changedValue: getChangedValue(state, ownProps.setting.definition.key), | |||||
loading: isLoading(state, ownProps.setting.definition.key), | |||||
validationMessage: getValidationMessage(state, ownProps.setting.definition.key) | |||||
}); | |||||
export default connect( | |||||
mapStateToProps, | |||||
{ changeValue, saveValue, resetValue, failValidation, passValidation, cancelChange } | |||||
)(Definition); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 shallowCompare from 'react-addons-shallow-compare'; | |||||
import { translate } from '../../../helpers/l10n'; | |||||
export default class DefinitionChanges extends React.Component { | |||||
static propTypes = { | |||||
onSave: React.PropTypes.func.isRequired, | |||||
onCancel: React.PropTypes.func.isRequired | |||||
}; | |||||
shouldComponentUpdate (nextProps, nextState) { | |||||
return shallowCompare(this, nextProps, nextState); | |||||
} | |||||
handleSaveClick (e) { | |||||
e.preventDefault(); | |||||
e.target.blur(); | |||||
this.props.onSave(); | |||||
} | |||||
handleCancelChange (e) { | |||||
e.preventDefault(); | |||||
e.target.blur(); | |||||
this.props.onCancel(); | |||||
} | |||||
render () { | |||||
return ( | |||||
<div className="settings-definition-changes"> | |||||
<button className="js-save-changes button-success" onClick={e => this.handleSaveClick(e)}> | |||||
{translate('save')} | |||||
</button> | |||||
<button className="js-cancel-changes big-spacer-left button-link" onClick={e => this.handleCancelChange(e)}> | |||||
{translate('cancel')} | |||||
</button> | |||||
</div> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { getSettingValue, isEmptyValue, getDefaultValue } from '../utils'; | |||||
import { translate } from '../../../helpers/l10n'; | |||||
export default class DefinitionDefaults extends React.Component { | |||||
static propTypes = { | |||||
setting: React.PropTypes.object.isRequired, | |||||
isDefault: React.PropTypes.bool.isRequired, | |||||
onReset: React.PropTypes.func.isRequired | |||||
}; | |||||
handleReset (e) { | |||||
e.preventDefault(); | |||||
e.target.blur(); | |||||
this.props.onReset(); | |||||
} | |||||
render () { | |||||
const { setting, isDefault } = this.props; | |||||
const { definition } = setting; | |||||
const isExplicitlySet = !isDefault && !isEmptyValue(definition, getSettingValue(setting)); | |||||
return ( | |||||
<div> | |||||
{isDefault && ( | |||||
<div className="spacer-top note" style={{ lineHeight: '24px' }}> | |||||
{translate('settings._default')} | |||||
</div> | |||||
)} | |||||
{isExplicitlySet && ( | |||||
<div className="spacer-top nowrap"> | |||||
<button onClick={e => this.handleReset(e)}>{translate('reset_verb')}</button> | |||||
<span className="spacer-left note">{translate('default')}{': '}{getDefaultValue(setting)}</span> | |||||
</div> | |||||
)} | |||||
</div> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 shallowCompare from 'react-addons-shallow-compare'; | |||||
import Definition from './Definition'; | |||||
export default class DefinitionsList extends React.Component { | |||||
static propTypes = { | |||||
component: React.PropTypes.object, | |||||
settings: React.PropTypes.array.isRequired | |||||
}; | |||||
shouldComponentUpdate (nextProps, nextState) { | |||||
return shallowCompare(this, nextProps, nextState); | |||||
} | |||||
render () { | |||||
return ( | |||||
<ul className="settings-definitions-list"> | |||||
{this.props.settings.map(setting => ( | |||||
<li key={setting.definition.key}> | |||||
<Definition component={this.props.component} setting={setting}/> | |||||
</li> | |||||
))} | |||||
</ul> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { connect } from 'react-redux'; | |||||
import GlobalMessages from '../../../components/controls/GlobalMessages'; | |||||
import { getGlobalMessages } from '../store/rootReducer'; | |||||
const mapStateToProps = state => ({ | |||||
messages: getGlobalMessages(state) | |||||
}); | |||||
export default connect(mapStateToProps)(GlobalMessages); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { translate } from '../../../helpers/l10n'; | |||||
export default class PageHeader extends React.Component { | |||||
static propTypes = { | |||||
component: React.PropTypes.object | |||||
}; | |||||
render () { | |||||
const title = this.props.component != null ? | |||||
translate('project_settings.page') : | |||||
translate('settings.page'); | |||||
const description = this.props.component != null ? | |||||
translate('project_settings.page.description') : | |||||
translate('settings.page.description'); | |||||
return ( | |||||
<header className="page-header"> | |||||
<h1 className="page-title">{title}</h1> | |||||
<div className="page-description">{description}</div> | |||||
</header> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 shallowCompare from 'react-addons-shallow-compare'; | |||||
import groupBy from 'lodash/groupBy'; | |||||
import sortBy from 'lodash/sortBy'; | |||||
import DefinitionsList from './DefinitionsList'; | |||||
import { getSubCategoryName, getSubCategoryDescription } from '../utils'; | |||||
export default class SubCategoryDefinitionsList extends React.Component { | |||||
static propTypes = { | |||||
component: React.PropTypes.object, | |||||
settings: React.PropTypes.array.isRequired | |||||
}; | |||||
shouldComponentUpdate (nextProps, nextState) { | |||||
return shallowCompare(this, nextProps, nextState); | |||||
} | |||||
render () { | |||||
const bySubCategory = groupBy(this.props.settings, setting => setting.definition.subCategory); | |||||
const subCategories = Object.keys(bySubCategory).map(key => ({ | |||||
key, | |||||
name: getSubCategoryName(bySubCategory[key][0].definition.category, key), | |||||
description: getSubCategoryDescription(bySubCategory[key][0].definition.category, key) | |||||
})); | |||||
const sortedSubCategories = sortBy(subCategories, subCategory => subCategory.name.toLowerCase()); | |||||
return ( | |||||
<ul className="settings-sub-categories-list"> | |||||
{sortedSubCategories.map(subCategory => ( | |||||
<li key={subCategory.key}> | |||||
<h2 className="settings-sub-category-name">{subCategory.name}</h2> | |||||
{subCategory.description != null && ( | |||||
<div className="settings-sub-category-description markdown"> | |||||
{subCategory.description} | |||||
</div> | |||||
)} | |||||
<DefinitionsList settings={bySubCategory[subCategory.key]} component={this.props.component}/> | |||||
</li> | |||||
))} | |||||
</ul> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 shallowCompare from 'react-addons-shallow-compare'; | |||||
import PropertySetInput from './PropertySetInput'; | |||||
import MultiValueInput from './MultiValueInput'; | |||||
import PrimitiveInput from './PrimitiveInput'; | |||||
import { TYPE_PROPERTY_SET } from '../../constants'; | |||||
export default class Input extends React.Component { | |||||
static propTypes = { | |||||
setting: React.PropTypes.object.isRequired, | |||||
value: React.PropTypes.any, | |||||
onChange: React.PropTypes.func.isRequired | |||||
}; | |||||
shouldComponentUpdate (nextProps, nextState) { | |||||
return shallowCompare(this, nextProps, nextState); | |||||
} | |||||
render () { | |||||
const { definition } = this.props.setting; | |||||
if (definition.multiValues) { | |||||
return <MultiValueInput {...this.props}/>; | |||||
} | |||||
if (definition.type === TYPE_PROPERTY_SET) { | |||||
return <PropertySetInput {...this.props}/>; | |||||
} | |||||
return <PrimitiveInput {...this.props}/>; | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 Toggle from '../../../../components/controls/Toggle'; | |||||
import { defaultInputPropTypes } from '../../propTypes'; | |||||
import { translate } from '../../../../helpers/l10n'; | |||||
export default class InputForBoolean extends React.Component { | |||||
static propTypes = { | |||||
...defaultInputPropTypes, | |||||
value: React.PropTypes.oneOfType([React.PropTypes.bool, React.PropTypes.string]) | |||||
}; | |||||
render () { | |||||
const hasValue = this.props.value != null; | |||||
const displayedValue = hasValue ? this.props.value : false; | |||||
return ( | |||||
<div className="display-inline-block text-top"> | |||||
<Toggle | |||||
name={this.props.name} | |||||
value={displayedValue} | |||||
onChange={this.props.onChange}/> | |||||
{!hasValue && ( | |||||
<span className="spacer-left note">{translate('settings.not_set')}</span> | |||||
)} | |||||
</div> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 SimpleInput from './SimpleInput'; | |||||
export default class InputForNumber extends React.Component { | |||||
render () { | |||||
return ( | |||||
<SimpleInput {...this.props} className="input-small" type="text"/> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { translate } from '../../../../helpers/l10n'; | |||||
import { defaultInputPropTypes } from '../../propTypes'; | |||||
export default class InputForPassword extends React.Component { | |||||
static propTypes = defaultInputPropTypes; | |||||
state = { | |||||
changing: false | |||||
}; | |||||
handleChangeClick (e) { | |||||
e.preventDefault(); | |||||
e.target.blur(); | |||||
this.setState({ changing: true }); | |||||
} | |||||
handleCancelChangeClick (e) { | |||||
e.preventDefault(); | |||||
e.target.blur(); | |||||
this.setState({ changing: false }); | |||||
} | |||||
handleFormSubmit (e) { | |||||
e.preventDefault(); | |||||
this.props.onChange(this.refs.input.value); | |||||
this.setState({ changing: false }); | |||||
} | |||||
renderInput () { | |||||
return ( | |||||
<div> | |||||
<form onSubmit={e => this.handleFormSubmit(e)}> | |||||
<input className="hidden" type="password"/> | |||||
<input | |||||
ref="input" | |||||
name={this.props.name} | |||||
className="input-large text-top" | |||||
type="password" | |||||
autoFocus={true} | |||||
autoComplete={false}/> | |||||
<button className="spacer-left">{translate('set')}</button> | |||||
<a className="spacer-left" href="#" onClick={e => this.handleCancelChangeClick(e)}> | |||||
{translate('cancel')} | |||||
</a> | |||||
</form> | |||||
</div> | |||||
); | |||||
} | |||||
render () { | |||||
if (this.state.changing) { | |||||
return this.renderInput(); | |||||
} | |||||
const hasValue = !!this.props.value; | |||||
return ( | |||||
<div> | |||||
{hasValue && ( | |||||
<i className="big-spacer-right icon-lock icon-gray"/> | |||||
)} | |||||
<button onClick={e => this.handleChangeClick(e)}> | |||||
{hasValue ? translate('change_verb') : translate('set')} | |||||
</button> | |||||
</div> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 Select from 'react-select'; | |||||
import { defaultInputPropTypes } from '../../propTypes'; | |||||
export default class InputForSingleSelectList extends React.Component { | |||||
static propTypes = { | |||||
...defaultInputPropTypes, | |||||
options: React.PropTypes.arrayOf(React.PropTypes.string).isRequired | |||||
}; | |||||
handleInputChange (option) { | |||||
this.props.onChange(option.value); | |||||
} | |||||
render () { | |||||
const options = this.props.options.map(option => ({ | |||||
label: option, | |||||
value: option | |||||
})); | |||||
return ( | |||||
<Select | |||||
name={this.props.name} | |||||
className="input-large" | |||||
options={options} | |||||
clearable={false} | |||||
value={this.props.value} | |||||
onChange={option => this.handleInputChange(option)}/> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 SimpleInput from './SimpleInput'; | |||||
export default class InputForString extends React.Component { | |||||
render () { | |||||
return ( | |||||
<SimpleInput {...this.props} className="input-large" type="text"/> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { defaultInputPropTypes } from '../../propTypes'; | |||||
export default class InputForText extends React.Component { | |||||
static propTypes = defaultInputPropTypes; | |||||
handleInputChange (e) { | |||||
this.props.onChange(e.target.value); | |||||
} | |||||
render () { | |||||
return ( | |||||
<textarea | |||||
name={this.props.name} | |||||
className="input-super-large text-top" | |||||
rows="5" | |||||
value={this.props.value} | |||||
onChange={e => this.handleInputChange(e)}/> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 PrimitiveInput from './PrimitiveInput'; | |||||
import { getEmptyValue } from '../../utils'; | |||||
export default class MultiValueInput extends React.Component { | |||||
static propTypes = { | |||||
setting: React.PropTypes.object.isRequired, | |||||
value: React.PropTypes.array, | |||||
onChange: React.PropTypes.func.isRequired | |||||
}; | |||||
ensureValue () { | |||||
return this.props.value || []; | |||||
} | |||||
handleSingleInputChange (index, value) { | |||||
const newValue = [...this.ensureValue()]; | |||||
newValue.splice(index, 1, value); | |||||
this.props.onChange(newValue); | |||||
} | |||||
handleDeleteValue (e, index) { | |||||
e.preventDefault(); | |||||
e.target.blur(); | |||||
const newValue = [...this.ensureValue()]; | |||||
newValue.splice(index, 1); | |||||
this.props.onChange(newValue); | |||||
} | |||||
prepareSetting () { | |||||
const { setting } = this.props; | |||||
const newDefinition = { ...setting.definition, multiValues: false }; | |||||
return { | |||||
...setting, | |||||
definition: newDefinition, | |||||
values: undefined | |||||
}; | |||||
} | |||||
renderInput (value, index, isLast) { | |||||
return ( | |||||
<li key={index} className="spacer-bottom"> | |||||
<PrimitiveInput | |||||
setting={this.prepareSetting()} | |||||
value={value} | |||||
onChange={this.handleSingleInputChange.bind(this, index)}/> | |||||
{!isLast && ( | |||||
<div className="display-inline-block spacer-left"> | |||||
<button className="js-remove-value button-clean" onClick={e => this.handleDeleteValue(e, index)}> | |||||
<i className="icon-delete"/> | |||||
</button> | |||||
</div> | |||||
)} | |||||
</li> | |||||
); | |||||
} | |||||
render () { | |||||
const displayedValue = [...this.ensureValue(), ...getEmptyValue(this.props.setting.definition)]; | |||||
return ( | |||||
<div> | |||||
<ul> | |||||
{displayedValue.map((value, index) => this.renderInput(value, index, index === displayedValue.length - 1))} | |||||
</ul> | |||||
</div> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 InputForString from './InputForString'; | |||||
import InputForText from './InputForText'; | |||||
import InputForPassword from './InputForPassword'; | |||||
import InputForBoolean from './InputForBoolean'; | |||||
import InputForNumber from './InputForNumber'; | |||||
import InputForSingleSelectList from './InputForSingleSelectList'; | |||||
import { getUniqueName, isDefaultOrInherited } from '../../utils'; | |||||
import * as types from '../../constants'; | |||||
const typeMapping = { | |||||
[types.TYPE_STRING]: InputForString, | |||||
[types.TYPE_TEXT]: InputForText, | |||||
[types.TYPE_PASSWORD]: InputForPassword, | |||||
[types.TYPE_BOOLEAN]: InputForBoolean, | |||||
[types.TYPE_INTEGER]: InputForNumber, | |||||
[types.TYPE_LONG]: InputForNumber, | |||||
[types.TYPE_FLOAT]: InputForNumber | |||||
}; | |||||
export default class PrimitiveInput extends React.Component { | |||||
static propTypes = { | |||||
setting: React.PropTypes.object.isRequired, | |||||
value: React.PropTypes.any, | |||||
onChange: React.PropTypes.func.isRequired | |||||
}; | |||||
render () { | |||||
const { setting, value, onChange, ...other } = this.props; | |||||
const { definition } = setting; | |||||
const name = getUniqueName(definition); | |||||
if (definition.type === types.TYPE_SINGLE_SELECT_LIST) { | |||||
return ( | |||||
<InputForSingleSelectList | |||||
name={name} | |||||
value={value} | |||||
isDefault={isDefaultOrInherited(setting)} | |||||
options={definition.options} | |||||
onChange={onChange} | |||||
{...other}/> | |||||
); | |||||
} | |||||
const InputComponent = typeMapping[definition.type] || InputForString; | |||||
return ( | |||||
<InputComponent | |||||
name={name} | |||||
value={value} | |||||
isDefault={isDefaultOrInherited(setting)} | |||||
onChange={onChange} | |||||
{...other}/> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 PrimitiveInput from './PrimitiveInput'; | |||||
import { getEmptyValue, getUniqueName } from '../../utils'; | |||||
export default class PropertySetInput extends React.Component { | |||||
static propTypes = { | |||||
setting: React.PropTypes.object.isRequired, | |||||
value: React.PropTypes.array, | |||||
onChange: React.PropTypes.func.isRequired | |||||
}; | |||||
ensureValue () { | |||||
return this.props.value || []; | |||||
} | |||||
getFieldName (field) { | |||||
return getUniqueName(this.props.setting.definition, field.key); | |||||
} | |||||
handleDeleteValue (e, index) { | |||||
e.preventDefault(); | |||||
e.target.blur(); | |||||
const newValue = [...this.ensureValue()]; | |||||
newValue.splice(index, 1); | |||||
this.props.onChange(newValue); | |||||
} | |||||
handleInputChange (index, fieldKey, value) { | |||||
const emptyValue = getEmptyValue(this.props.setting.definition)[0]; | |||||
const newValue = [...this.ensureValue()]; | |||||
const newFields = { ...emptyValue, ...newValue[index], [fieldKey]: value }; | |||||
newValue.splice(index, 1, newFields); | |||||
return this.props.onChange(newValue); | |||||
} | |||||
renderFields (fieldValues, index, isLast) { | |||||
const { setting } = this.props; | |||||
return ( | |||||
<tr key={index}> | |||||
{setting.definition.fields.map(field => ( | |||||
<td key={field.key}> | |||||
<PrimitiveInput | |||||
name={this.getFieldName(field)} | |||||
setting={{ definition: field, value: fieldValues[field.key] }} | |||||
value={fieldValues[field.key]} | |||||
onChange={this.handleInputChange.bind(this, index, field.key)}/> | |||||
</td> | |||||
))} | |||||
<td className="thin nowrap"> | |||||
{!isLast && ( | |||||
<button className="js-remove-value button-link" onClick={e => this.handleDeleteValue(e, index)}> | |||||
<i className="icon-delete"/> | |||||
</button> | |||||
)} | |||||
</td> | |||||
</tr> | |||||
); | |||||
} | |||||
render () { | |||||
const { setting } = this.props; | |||||
const displayedValue = [...this.ensureValue(), ...getEmptyValue(this.props.setting.definition)]; | |||||
return ( | |||||
<div> | |||||
<table className="data zebra-hover no-outer-padding" style={{ width: 'auto', minWidth: 480, marginTop: -12 }}> | |||||
<thead> | |||||
<tr> | |||||
{setting.definition.fields.map(field => ( | |||||
<th key={field.key}> | |||||
{field.name} | |||||
{field.description != null && ( | |||||
<span className="spacer-top small">{field.description}</span> | |||||
)} | |||||
</th> | |||||
))} | |||||
<th> </th> | |||||
</tr> | |||||
</thead> | |||||
<tbody> | |||||
{displayedValue.map((fieldValues, index) => | |||||
this.renderFields(fieldValues, index, index === displayedValue.length - 1))} | |||||
</tbody> | |||||
</table> | |||||
</div> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { defaultInputPropTypes } from '../../propTypes'; | |||||
export default class SimpleInput extends React.Component { | |||||
static propTypes = { | |||||
...defaultInputPropTypes, | |||||
value: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]), | |||||
type: React.PropTypes.string.isRequired, | |||||
className: React.PropTypes.string.isRequired | |||||
}; | |||||
handleInputChange (e) { | |||||
this.props.onChange(e.target.value); | |||||
} | |||||
render () { | |||||
return ( | |||||
<input | |||||
name={this.props.name} | |||||
className={this.props.className + ' text-top'} | |||||
type={this.props.type} | |||||
value={this.props.value} | |||||
onChange={e => this.handleInputChange(e)}/> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { expect } from 'chai'; | |||||
import { shallow } from 'enzyme'; | |||||
import sinon from 'sinon'; | |||||
import Input from '../Input'; | |||||
import PrimitiveInput from '../PrimitiveInput'; | |||||
import MultiValueInput from '../MultiValueInput'; | |||||
import PropertySetInput from '../PropertySetInput'; | |||||
import { TYPE_STRING, TYPE_PROPERTY_SET } from '../../../constants'; | |||||
describe('Settings :: Inputs :: Input', () => { | |||||
it('should render PrimitiveInput', () => { | |||||
const setting = { definition: { key: 'example', type: TYPE_STRING } }; | |||||
const onChange = sinon.spy(); | |||||
const input = shallow(<Input setting={setting} value="foo" onChange={onChange}/>).find(PrimitiveInput); | |||||
expect(input).to.have.length(1); | |||||
expect(input.prop('setting')).to.equal(setting); | |||||
expect(input.prop('value')).to.equal('foo'); | |||||
expect(input.prop('onChange')).to.equal(onChange); | |||||
}); | |||||
it('should render MultiValueInput', () => { | |||||
const setting = { definition: { key: 'example', type: TYPE_STRING, multiValues: true } }; | |||||
const onChange = sinon.spy(); | |||||
const input = shallow(<Input setting={setting} value="foo" onChange={onChange}/>).find(MultiValueInput); | |||||
expect(input).to.have.length(1); | |||||
expect(input.prop('setting')).to.equal(setting); | |||||
expect(input.prop('value')).to.equal('foo'); | |||||
expect(input.prop('onChange')).to.equal(onChange); | |||||
}); | |||||
it('should render PropertySetInput', () => { | |||||
const setting = { definition: { key: 'example', type: TYPE_PROPERTY_SET, fields: [] } }; | |||||
const onChange = sinon.spy(); | |||||
const input = shallow(<Input setting={setting} value="foo" onChange={onChange}/>).find(PropertySetInput); | |||||
expect(input).to.have.length(1); | |||||
expect(input.prop('setting')).to.equal(setting); | |||||
expect(input.prop('value')).to.equal('foo'); | |||||
expect(input.prop('onChange')).to.equal(onChange); | |||||
}); | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { expect } from 'chai'; | |||||
import { shallow } from 'enzyme'; | |||||
import sinon from 'sinon'; | |||||
import InputForBoolean from '../InputForBoolean'; | |||||
import Toggle from '../../../../../components/controls/Toggle'; | |||||
describe('Settings :: Inputs :: InputForBoolean', () => { | |||||
it('should render Toggle', () => { | |||||
const onChange = sinon.spy(); | |||||
const toggle = shallow( | |||||
<InputForBoolean | |||||
name="foo" | |||||
value={true} | |||||
isDefault={false} | |||||
onChange={onChange}/> | |||||
).find(Toggle); | |||||
expect(toggle).to.have.length(1); | |||||
expect(toggle.prop('name')).to.equal('foo'); | |||||
expect(toggle.prop('value')).to.equal(true); | |||||
expect(toggle.prop('onChange')).to.be.a('function'); | |||||
}); | |||||
it('should render Toggle without value', () => { | |||||
const onChange = sinon.spy(); | |||||
const input = shallow( | |||||
<InputForBoolean | |||||
name="foo" | |||||
isDefault={false} | |||||
onChange={onChange}/> | |||||
); | |||||
const toggle = input.find(Toggle); | |||||
expect(toggle).to.have.length(1); | |||||
expect(toggle.prop('name')).to.equal('foo'); | |||||
expect(toggle.prop('value')).to.equal(false); | |||||
expect(toggle.prop('onChange')).to.be.a('function'); | |||||
expect(input.find('.note')).to.have.length(1); | |||||
}); | |||||
it('should call onChange', () => { | |||||
const onChange = sinon.spy(); | |||||
const input = shallow( | |||||
<InputForBoolean | |||||
name="foo" | |||||
value={true} | |||||
isDefault={false} | |||||
onChange={onChange}/> | |||||
); | |||||
const toggle = input.find(Toggle); | |||||
expect(toggle).to.have.length(1); | |||||
expect(toggle.prop('onChange')).to.be.a('function'); | |||||
toggle.prop('onChange')(false); | |||||
expect(onChange.called).to.equal(true); | |||||
expect(onChange.lastCall.args).to.deep.equal([false]); | |||||
}); | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { expect } from 'chai'; | |||||
import { shallow } from 'enzyme'; | |||||
import sinon from 'sinon'; | |||||
import InputForNumber from '../InputForNumber'; | |||||
import SimpleInput from '../SimpleInput'; | |||||
describe('Settings :: Inputs :: InputForNumber', () => { | |||||
it('should render SimpleInput', () => { | |||||
const onChange = sinon.spy(); | |||||
const simpleInput = shallow( | |||||
<InputForNumber | |||||
name="foo" | |||||
value={17} | |||||
isDefault={false} | |||||
onChange={onChange}/> | |||||
).find(SimpleInput); | |||||
expect(simpleInput).to.have.length(1); | |||||
expect(simpleInput.prop('name')).to.equal('foo'); | |||||
expect(simpleInput.prop('value')).to.equal(17); | |||||
expect(simpleInput.prop('type')).to.equal('text'); | |||||
expect(simpleInput.prop('onChange')).to.be.a('function'); | |||||
}); | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { expect } from 'chai'; | |||||
import { shallow, mount } from 'enzyme'; | |||||
import sinon from 'sinon'; | |||||
import InputForPassword from '../InputForPassword'; | |||||
import { click, submit } from '../../../../../../../../tests/utils'; | |||||
describe('Settings :: Inputs :: InputForPassword', () => { | |||||
it('should render lock icon, but no form', () => { | |||||
const onChange = sinon.spy(); | |||||
const input = shallow( | |||||
<InputForPassword | |||||
name="foo" | |||||
value="bar" | |||||
isDefault={false} | |||||
onChange={onChange}/> | |||||
); | |||||
expect(input.find('.icon-lock')).to.have.length(1); | |||||
expect(input.find('form')).to.have.length(0); | |||||
}); | |||||
it('should open form', () => { | |||||
const onChange = sinon.spy(); | |||||
const input = shallow( | |||||
<InputForPassword | |||||
name="foo" | |||||
value="bar" | |||||
isDefault={false} | |||||
onChange={onChange}/> | |||||
); | |||||
const button = input.find('button'); | |||||
expect(button).to.have.length(1); | |||||
click(button); | |||||
expect(input.find('form')).to.have.length(1); | |||||
}); | |||||
it('should close form', () => { | |||||
const onChange = sinon.spy(); | |||||
const input = shallow( | |||||
<InputForPassword | |||||
name="foo" | |||||
value="bar" | |||||
isDefault={false} | |||||
onChange={onChange}/> | |||||
); | |||||
const button = input.find('button'); | |||||
expect(button).to.have.length(1); | |||||
click(button); | |||||
expect(input.find('form')).to.have.length(1); | |||||
click(input.find('form').find('a')); | |||||
expect(input.find('form')).to.have.length(0); | |||||
}); | |||||
it('should set value', () => { | |||||
const onChange = sinon.stub().returns(Promise.resolve()); | |||||
const input = mount( | |||||
<InputForPassword | |||||
name="foo" | |||||
value="bar" | |||||
isDefault={false} | |||||
onChange={onChange}/> | |||||
); | |||||
const button = input.find('button'); | |||||
expect(button).to.have.length(1); | |||||
click(button); | |||||
const form = input.find('form'); | |||||
expect(form).to.have.length(1); | |||||
input.ref('input').value = 'secret'; | |||||
submit(form); | |||||
expect(onChange.called).to.equal(true); | |||||
}); | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { expect } from 'chai'; | |||||
import { shallow } from 'enzyme'; | |||||
import sinon from 'sinon'; | |||||
import Select from 'react-select'; | |||||
import InputForSingleSelectList from '../InputForSingleSelectList'; | |||||
describe('Settings :: Inputs :: InputForSingleSelectList', () => { | |||||
it('should render Select', () => { | |||||
const onChange = sinon.spy(); | |||||
const select = shallow( | |||||
<InputForSingleSelectList | |||||
name="foo" | |||||
value="bar" | |||||
options={['foo', 'bar', 'baz']} | |||||
isDefault={false} | |||||
onChange={onChange}/> | |||||
).find(Select); | |||||
expect(select).to.have.length(1); | |||||
expect(select.prop('name')).to.equal('foo'); | |||||
expect(select.prop('value')).to.equal('bar'); | |||||
expect(select.prop('options')).to.deep.equal([ | |||||
{ value: 'foo', label: 'foo' }, | |||||
{ value: 'bar', label: 'bar' }, | |||||
{ value: 'baz', label: 'baz' } | |||||
]); | |||||
expect(select.prop('onChange')).to.be.a('function'); | |||||
}); | |||||
it('should call onChange', () => { | |||||
const onChange = sinon.spy(); | |||||
const select = shallow( | |||||
<InputForSingleSelectList | |||||
name="foo" | |||||
value="bar" | |||||
options={['foo', 'bar', 'baz']} | |||||
isDefault={false} | |||||
onChange={onChange}/> | |||||
).find(Select); | |||||
expect(select).to.have.length(1); | |||||
expect(select.prop('onChange')).to.be.a('function'); | |||||
select.prop('onChange')({ value: 'baz', label: 'baz' }); | |||||
expect(onChange.called).to.equal(true); | |||||
expect(onChange.lastCall.args).to.deep.equal(['baz']); | |||||
}); | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { expect } from 'chai'; | |||||
import { shallow } from 'enzyme'; | |||||
import sinon from 'sinon'; | |||||
import InputForString from '../InputForString'; | |||||
import SimpleInput from '../SimpleInput'; | |||||
describe('Settings :: Inputs :: InputForString', () => { | |||||
it('should render SimpleInput', () => { | |||||
const onChange = sinon.spy(); | |||||
const simpleInput = shallow( | |||||
<InputForString | |||||
name="foo" | |||||
value="bar" | |||||
isDefault={false} | |||||
onChange={onChange}/> | |||||
).find(SimpleInput); | |||||
expect(simpleInput).to.have.length(1); | |||||
expect(simpleInput.prop('name')).to.equal('foo'); | |||||
expect(simpleInput.prop('value')).to.equal('bar'); | |||||
expect(simpleInput.prop('type')).to.equal('text'); | |||||
expect(simpleInput.prop('onChange')).to.be.a('function'); | |||||
}); | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { expect } from 'chai'; | |||||
import { shallow } from 'enzyme'; | |||||
import sinon from 'sinon'; | |||||
import InputForText from '../InputForText'; | |||||
import { change } from '../../../../../../../../tests/utils'; | |||||
describe('Settings :: Inputs :: InputForText', () => { | |||||
it('should render textarea', () => { | |||||
const onChange = sinon.spy(); | |||||
const textarea = shallow( | |||||
<InputForText | |||||
name="foo" | |||||
value="bar" | |||||
isDefault={false} | |||||
onChange={onChange}/> | |||||
).find('textarea'); | |||||
expect(textarea).to.have.length(1); | |||||
expect(textarea.prop('name')).to.equal('foo'); | |||||
expect(textarea.prop('value')).to.equal('bar'); | |||||
expect(textarea.prop('onChange')).to.be.a('function'); | |||||
}); | |||||
it('should call onChange', () => { | |||||
const onChange = sinon.spy(); | |||||
const textarea = shallow( | |||||
<InputForText | |||||
name="foo" | |||||
value="bar" | |||||
isDefault={false} | |||||
onChange={onChange}/> | |||||
).find('textarea'); | |||||
expect(textarea).to.have.length(1); | |||||
expect(textarea.prop('onChange')).to.be.a('function'); | |||||
change(textarea, 'qux'); | |||||
expect(onChange.called).to.equal(true); | |||||
expect(onChange.lastCall.args).to.deep.equal(['qux']); | |||||
}); | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { expect } from 'chai'; | |||||
import { shallow, mount } from 'enzyme'; | |||||
import sinon from 'sinon'; | |||||
import MultiValueInput from '../MultiValueInput'; | |||||
import InputForString from '../InputForString'; | |||||
import { click, change } from '../../../../../../../../tests/utils'; | |||||
const definition = { multiValues: true }; | |||||
const assertValues = (inputs, values) => { | |||||
values.forEach((value, index) => { | |||||
const input = inputs.at(index); | |||||
expect(input.prop('value')).to.equal(value); | |||||
}); | |||||
}; | |||||
describe('Settings :: Inputs :: MultiValueInput', () => { | |||||
it('should render one value', () => { | |||||
const multiValueInput = mount( | |||||
<MultiValueInput | |||||
setting={{ definition }} | |||||
value={['foo']} | |||||
onChange={sinon.stub()}/> | |||||
); | |||||
const stringInputs = multiValueInput.find(InputForString); | |||||
expect(stringInputs).to.have.length(1 + 1); | |||||
assertValues(stringInputs, ['foo', '']); | |||||
}); | |||||
it('should render several values', () => { | |||||
const multiValueInput = mount( | |||||
<MultiValueInput | |||||
setting={{ definition }} | |||||
value={['foo', 'bar', 'baz']} | |||||
onChange={sinon.stub()}/> | |||||
); | |||||
const stringInputs = multiValueInput.find(InputForString); | |||||
expect(stringInputs).to.have.length(3 + 1); | |||||
assertValues(stringInputs, ['foo', 'bar', 'baz', '']); | |||||
}); | |||||
it('should remove value', () => { | |||||
const onChange = sinon.spy(); | |||||
const multiValueInput = mount( | |||||
<MultiValueInput | |||||
setting={{ definition }} | |||||
value={['foo', 'bar', 'baz']} | |||||
onChange={onChange}/> | |||||
); | |||||
click(multiValueInput.find('.js-remove-value').at(1)); | |||||
expect(onChange.called).to.equal(true); | |||||
expect(onChange.lastCall.args).to.deep.equal([['foo', 'baz']]); | |||||
}); | |||||
it('should change existing value', () => { | |||||
const onChange = sinon.spy(); | |||||
const multiValueInput = mount( | |||||
<MultiValueInput | |||||
setting={{ definition }} | |||||
value={['foo', 'bar', 'baz']} | |||||
onChange={onChange}/> | |||||
); | |||||
change(multiValueInput.find(InputForString).at(1).find('input'), 'qux'); | |||||
expect(onChange.called).to.equal(true); | |||||
expect(onChange.lastCall.args).to.deep.equal([['foo', 'qux', 'baz']]); | |||||
}); | |||||
it('should add new value', () => { | |||||
const onChange = sinon.spy(); | |||||
const multiValueInput = mount( | |||||
<MultiValueInput | |||||
setting={{ definition }} | |||||
value={['foo']} | |||||
onChange={onChange}/> | |||||
); | |||||
change(multiValueInput.find(InputForString).at(1).find('input'), 'bar'); | |||||
expect(onChange.called).to.equal(true); | |||||
expect(onChange.lastCall.args).to.deep.equal([['foo', 'bar']]); | |||||
}); | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { expect } from 'chai'; | |||||
import { shallow } from 'enzyme'; | |||||
import sinon from 'sinon'; | |||||
import SimpleInput from '../SimpleInput'; | |||||
import { change } from '../../../../../../../../tests/utils'; | |||||
describe('Settings :: Inputs :: SimpleInput', () => { | |||||
it('should render input', () => { | |||||
const onChange = sinon.spy(); | |||||
const input = shallow( | |||||
<SimpleInput | |||||
type="text" | |||||
className="input-large" | |||||
name="foo" | |||||
value="bar" | |||||
isDefault={false} | |||||
onChange={onChange}/> | |||||
).find('input'); | |||||
expect(input).to.have.length(1); | |||||
expect(input.prop('type')).to.equal('text'); | |||||
expect(input.prop('className')).to.include('input-large'); | |||||
expect(input.prop('name')).to.equal('foo'); | |||||
expect(input.prop('value')).to.equal('bar'); | |||||
expect(input.prop('onChange')).to.be.a('function'); | |||||
}); | |||||
it('should call onChange', () => { | |||||
const onChange = sinon.spy(); | |||||
const input = shallow( | |||||
<SimpleInput | |||||
type="text" | |||||
className="input-large" | |||||
name="foo" | |||||
value="bar" | |||||
isDefault={false} | |||||
onChange={onChange}/> | |||||
).find('input'); | |||||
expect(input).to.have.length(1); | |||||
expect(input.prop('onChange')).to.be.a('function'); | |||||
change(input, 'qux'); | |||||
expect(onChange.called).to.equal(true); | |||||
expect(onChange.lastCall.args).to.deep.equal(['qux']); | |||||
}); | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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. | |||||
*/ | |||||
export const TYPE_STRING = 'STRING'; | |||||
export const TYPE_TEXT = 'TEXT'; | |||||
export const TYPE_PASSWORD = 'PASSWORD'; | |||||
export const TYPE_BOOLEAN = 'BOOLEAN'; | |||||
export const TYPE_FLOAT = 'FLOAT'; | |||||
export const TYPE_INTEGER = 'INTEGER'; | |||||
export const TYPE_LONG = 'LONG'; | |||||
export const TYPE_SINGLE_SELECT_LIST = 'SINGLE_SELECT_LIST'; | |||||
export const TYPE_PROPERTY_SET = 'PROPERTY_SET'; |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { PropTypes } from 'react'; | |||||
export const defaultInputPropTypes = { | |||||
name: PropTypes.string.isRequired, | |||||
value: PropTypes.any, | |||||
isDefault: PropTypes.bool.isRequired, | |||||
onChange: PropTypes.func.isRequired | |||||
}; |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { getDefinitions, getValues, setSettingValue, resetSettingValue } from '../../../api/settings'; | |||||
import { receiveValues } from './values/actions'; | |||||
import { receiveDefinitions } from './definitions/actions'; | |||||
import { startLoading, stopLoading } from './settingsPage/loading/actions'; | |||||
import { parseError } from '../../code/utils'; | |||||
import { addGlobalErrorMessage, closeAllGlobalMessages } from '../../../components/store/globalMessages'; | |||||
import { passValidation, failValidation } from './settingsPage/validationMessages/actions'; | |||||
import { cancelChange } from './settingsPage/changedValues/actions'; | |||||
import { getDefinition, getChangedValue } from './rootReducer'; | |||||
export const fetchSettings = componentKey => dispatch => { | |||||
return getDefinitions(componentKey) | |||||
.then(definitions => { | |||||
dispatch(receiveDefinitions(definitions)); | |||||
const keys = definitions.map(definition => definition.key).join(); | |||||
return getValues(keys, componentKey); | |||||
}) | |||||
.then(settings => { | |||||
dispatch(receiveValues(settings)); | |||||
dispatch(closeAllGlobalMessages()); | |||||
}) | |||||
.catch(e => parseError(e).then(message => dispatch(addGlobalErrorMessage(message)))); | |||||
}; | |||||
export const saveValue = (key, componentKey) => (dispatch, getState) => { | |||||
dispatch(startLoading(key)); | |||||
const state = getState(); | |||||
const definition = getDefinition(state, key); | |||||
const value = getChangedValue(state, key); | |||||
return setSettingValue(definition, value, componentKey) | |||||
.then(() => getValues(key, componentKey)) | |||||
.then(values => { | |||||
dispatch(receiveValues(values)); | |||||
dispatch(cancelChange(key)); | |||||
dispatch(passValidation(key)); | |||||
dispatch(stopLoading(key)); | |||||
}) | |||||
.catch(e => { | |||||
dispatch(stopLoading(key)); | |||||
parseError(e).then(message => dispatch(failValidation(key, message))); | |||||
return Promise.reject(); | |||||
}); | |||||
}; | |||||
export const resetValue = (key, componentKey) => dispatch => { | |||||
dispatch(startLoading(key)); | |||||
return resetSettingValue(key, componentKey) | |||||
.then(() => getValues(key, componentKey)) | |||||
.then(values => { | |||||
if (values.length > 0) { | |||||
dispatch(receiveValues(values)); | |||||
} else { | |||||
dispatch(receiveValues([{ key }])); | |||||
} | |||||
dispatch(passValidation(key)); | |||||
dispatch(stopLoading(key)); | |||||
}) | |||||
.catch(e => { | |||||
dispatch(stopLoading(key)); | |||||
parseError(e).then(message => dispatch(failValidation(key, message))); | |||||
return Promise.reject(); | |||||
}); | |||||
}; |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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. | |||||
*/ | |||||
export const RECEIVE_DEFINITIONS = 'RECEIVE_DEFINITIONS'; | |||||
/** | |||||
* Receive definitions action creator | |||||
* @param {Array} definitions | |||||
* @returns {Object} | |||||
*/ | |||||
export const receiveDefinitions = definitions => ({ | |||||
type: RECEIVE_DEFINITIONS, | |||||
definitions | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 keyBy from 'lodash/keyBy'; | |||||
import sortBy from 'lodash/sortBy'; | |||||
import uniqBy from 'lodash/uniqBy'; | |||||
import { RECEIVE_DEFINITIONS } from './actions'; | |||||
import { DEFAULT_CATEGORY, getCategoryName } from '../../utils'; | |||||
const reducer = (state = {}, action = {}) => { | |||||
if (action.type === RECEIVE_DEFINITIONS) { | |||||
const definitionsByKey = keyBy(action.definitions, 'key'); | |||||
return { ...state, ...definitionsByKey }; | |||||
} | |||||
return state; | |||||
}; | |||||
export default reducer; | |||||
export const getDefinition = (state, key) => state[key]; | |||||
export const getAllDefinitions = state => Object.values(state); | |||||
export const getDefinitionsForCategory = (state, category) => | |||||
getAllDefinitions(state).filter(definition => definition.category.toLowerCase() === category.toLowerCase()); | |||||
export const getAllCategories = state => uniqBy( | |||||
getAllDefinitions(state).map(definition => definition.category), | |||||
category => category.toLowerCase()); | |||||
export const getDefaultCategory = state => { | |||||
const categories = getAllCategories(state); | |||||
if (categories.includes(DEFAULT_CATEGORY)) { | |||||
return DEFAULT_CATEGORY; | |||||
} else { | |||||
const sortedCategories = sortBy(categories, category => getCategoryName(category).toLowerCase()); | |||||
return sortedCategories[0]; | |||||
} | |||||
}; |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { combineReducers } from 'redux'; | |||||
import definitions, * as fromDefinitions from './definitions/reducer'; | |||||
import values, * as fromValues from './values/reducer'; | |||||
import settingsPage, * as fromSettingsPage from './settingsPage/reducer'; | |||||
import globalMessages, * as fromGlobalMessages from '../../../components/store/globalMessages'; | |||||
const rootReducer = combineReducers({ | |||||
definitions, | |||||
values, | |||||
settingsPage, | |||||
globalMessages | |||||
}); | |||||
export default rootReducer; | |||||
export const getDefinition = (state, key) => fromDefinitions.getDefinition(state.definitions, key); | |||||
export const getAllCategories = state => fromDefinitions.getAllCategories(state.definitions); | |||||
export const getDefaultCategory = state => fromDefinitions.getDefaultCategory(state.definitions); | |||||
export const getValue = (state, key) => fromValues.getValue(state.values, key); | |||||
export const getSettingsForCategory = (state, category) => | |||||
fromDefinitions.getDefinitionsForCategory(state.definitions, category).map(definition => ({ | |||||
...getValue(state, definition.key), | |||||
definition | |||||
})); | |||||
export const getChangedValue = (state, key) => fromSettingsPage.getChangedValue(state.settingsPage, key); | |||||
export const isLoading = (state, key) => fromSettingsPage.isLoading(state.settingsPage, key); | |||||
export const getValidationMessage = (state, key) => fromSettingsPage.getValidationMessage(state.settingsPage, key); | |||||
export const getGlobalMessages = state => fromGlobalMessages.getGlobalMessages(state.globalMessages); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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. | |||||
*/ | |||||
export const CHANGE_VALUE = 'settingsPage/CHANGE_VALUE'; | |||||
export const changeValue = (key, value) => ({ | |||||
type: CHANGE_VALUE, | |||||
key, | |||||
value | |||||
}); | |||||
export const CANCEL_CHANGE = 'settingsPage/CANCEL_CHANGE'; | |||||
export const cancelChange = key => ({ | |||||
type: CANCEL_CHANGE, | |||||
key | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 omit from 'lodash/omit'; | |||||
import { CHANGE_VALUE, CANCEL_CHANGE } from './actions'; | |||||
const reducer = (state = {}, action = {}) => { | |||||
if (action.type === CHANGE_VALUE) { | |||||
return { ...state, [action.key]: action.value }; | |||||
} | |||||
if (action.type === CANCEL_CHANGE) { | |||||
return omit(state, action.key); | |||||
} | |||||
return state; | |||||
}; | |||||
export default reducer; | |||||
export const getChangedValue = (state, key) => state[key]; |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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. | |||||
*/ | |||||
export const START_LOADING = 'settingsPage/START_LOADING'; | |||||
export const startLoading = key => ({ | |||||
type: START_LOADING, | |||||
key | |||||
}); | |||||
export const STOP_LOADING = 'settingsPage/STOP_LOADING'; | |||||
export const stopLoading = key => ({ | |||||
type: STOP_LOADING, | |||||
key | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { START_LOADING, STOP_LOADING } from './actions'; | |||||
const reducer = (state = {}, action = {}) => { | |||||
if (action.type === START_LOADING) { | |||||
return { ...state, [action.key]: true }; | |||||
} | |||||
if (action.type === STOP_LOADING) { | |||||
return { ...state, [action.key]: false }; | |||||
} | |||||
return state; | |||||
}; | |||||
export default reducer; | |||||
export const isLoading = (state, key) => !!state[key]; |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { combineReducers } from 'redux'; | |||||
import changedValues, * as fromChangedValues from './changedValues/reducer'; | |||||
import validationMessages, * as fromValidationMessages from './validationMessages/reducer'; | |||||
import loading, * as fromLoading from './loading/reducer'; | |||||
export default combineReducers({ | |||||
changedValues, | |||||
validationMessages, | |||||
loading | |||||
}); | |||||
export const getChangedValue = (state, key) => | |||||
fromChangedValues.getChangedValue(state.changedValues, key); | |||||
export const getValidationMessage = (state, key) => | |||||
fromValidationMessages.getValidationMessage(state.validationMessages, key); | |||||
export const isLoading = (state, key) => | |||||
fromLoading.isLoading(state.loading, key); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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. | |||||
*/ | |||||
export const FAIL_VALIDATION = 'settingsPage/FAIL_VALIDATION'; | |||||
export const failValidation = (key, message) => ({ | |||||
type: FAIL_VALIDATION, | |||||
key, | |||||
message | |||||
}); | |||||
export const PASS_VALIDATION = 'settingsPage/PASS_VALIDATION'; | |||||
export const passValidation = key => ({ | |||||
type: PASS_VALIDATION, | |||||
key | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { FAIL_VALIDATION, PASS_VALIDATION } from './actions'; | |||||
const reducer = (state = {}, action = {}) => { | |||||
if (action.type === FAIL_VALIDATION) { | |||||
return { ...state, [action.key]: action.message }; | |||||
} | |||||
if (action.type === PASS_VALIDATION) { | |||||
return { ...state, [action.key]: null }; | |||||
} | |||||
return state; | |||||
}; | |||||
export default reducer; | |||||
export const getValidationMessage = (state, key) => state[key]; |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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. | |||||
*/ | |||||
export const RECEIVE_VALUES = 'RECEIVE_VALUES'; | |||||
/** | |||||
* Receive settings action creator | |||||
* @param {Array} settings | |||||
* @returns {Object} | |||||
*/ | |||||
export const receiveValues = settings => ({ | |||||
type: RECEIVE_VALUES, | |||||
settings | |||||
}); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 keyBy from 'lodash/keyBy'; | |||||
import { RECEIVE_VALUES } from './actions'; | |||||
const reducer = (state = {}, action = {}) => { | |||||
if (action.type === RECEIVE_VALUES) { | |||||
const settingsByKey = keyBy(action.settings, 'key'); | |||||
return { ...state, ...settingsByKey }; | |||||
} | |||||
return state; | |||||
}; | |||||
export default reducer; | |||||
export const getValue = (state, key) => state[key]; |
.settings-layout { | |||||
display: flex; | |||||
justify-content: space-between; | |||||
align-items: stretch; | |||||
margin-bottom: 60px; | |||||
} | |||||
.settings-main { | |||||
position: relative; | |||||
z-index: 2; | |||||
flex-grow: 1; | |||||
padding: 15px 20px; | |||||
border: 1px solid #e6e6e6; | |||||
box-sizing: border-box; | |||||
background-color: #fff; | |||||
} | |||||
.settings-side { | |||||
position: relative; | |||||
z-index: 3; | |||||
width: 160px; | |||||
flex-shrink: 0; | |||||
padding: 10px 0; | |||||
box-sizing: border-box; | |||||
transform: translateX(1px); | |||||
} | |||||
.settings-menu { | |||||
} | |||||
.settings-menu > li { | |||||
margin-bottom: 4px; | |||||
} | |||||
.settings-menu > li > a { | |||||
display: block; | |||||
padding: 10px 10px; | |||||
line-height: 1.5; | |||||
border-top-left-radius: 3px; | |||||
border-bottom-left-radius: 3px; | |||||
border: 1px solid #e6e6e6; | |||||
border-right: none; | |||||
overflow: hidden; | |||||
text-overflow: ellipsis; | |||||
transition: color 0.3s ease, background-color 0.3s ease; | |||||
} | |||||
.settings-menu > li > a:hover, | |||||
.settings-menu > li > a:focus, | |||||
.settings-menu > li > a.active { | |||||
background-color: #fff; | |||||
} | |||||
.settings-menu > li > a.active { | |||||
color: #444; | |||||
cursor: default; | |||||
} | |||||
.settings-definitions-list > li + li { | |||||
margin-top: 30px; | |||||
} | |||||
.settings-definition { | |||||
display: flex; | |||||
align-items: stretch; | |||||
} | |||||
.settings-definition-changed { | |||||
margin: -10px -20px; | |||||
padding: 9px 20px; | |||||
border-top: 1px solid #faebcc; | |||||
border-bottom: 1px solid #faebcc; | |||||
background-color: #fcf8e3; | |||||
} | |||||
.settings-definition-left { | |||||
width: 330px; | |||||
padding-right: 30px; | |||||
box-sizing: border-box; | |||||
} | |||||
.settings-definition-right { | |||||
position: relative; | |||||
width: calc(100% - 330px); | |||||
padding-top: 35px; | |||||
box-sizing: border-box; | |||||
} | |||||
.settings-definition-name { | |||||
text-overflow: ellipsis; | |||||
} | |||||
.settings-definition-key { | |||||
line-height: 1.5; | |||||
overflow: hidden; | |||||
text-overflow: ellipsis; | |||||
white-space: nowrap; | |||||
} | |||||
.settings-definition-key:hover { | |||||
overflow: visible; | |||||
} | |||||
.settings-definition-state { | |||||
position: absolute; | |||||
top: 0; | |||||
left: 0; | |||||
right: 0; | |||||
line-height: 24px; | |||||
overflow: hidden; | |||||
text-overflow: ellipsis; | |||||
white-space: nowrap; | |||||
} | |||||
.settings-definition-state-icon { | |||||
display: inline-block; | |||||
vertical-align: middle; | |||||
width: 24px; | |||||
height: 24px; | |||||
margin-right: 8px; | |||||
text-align: center; | |||||
} | |||||
.settings-definition-state-icon > .icon-alert-error, | |||||
.settings-definition-state-icon > .spinner { | |||||
position: relative; | |||||
top: -2px; | |||||
} | |||||
.settings-definition-changes { | |||||
margin-top: 20px; | |||||
padding-top: 20px; | |||||
border-top: 1px dotted #e6e6e6; | |||||
} | |||||
.settings-sub-categories-list { | |||||
} | |||||
.settings-sub-categories-list > li { | |||||
} | |||||
.settings-sub-categories-list > li + li { | |||||
margin: 30px -20px 0; | |||||
padding: 30px 20px; | |||||
border-top: 1px solid #e6e6e6; | |||||
} | |||||
.settings-sub-category-name { | |||||
margin-bottom: 20px; | |||||
font-size: 16px; | |||||
} | |||||
.settings-sub-category-description { | |||||
margin-top: -15px; | |||||
margin-bottom: 20px; | |||||
color: #777; | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 { translate, hasMessage } from '../../helpers/l10n'; | |||||
import { TYPE_PROPERTY_SET, TYPE_BOOLEAN, TYPE_SINGLE_SELECT_LIST, TYPE_PASSWORD } from './constants'; | |||||
export const DEFAULT_CATEGORY = 'general'; | |||||
export function getPropertyName (definition) { | |||||
const key = `property.${definition.key}.name`; | |||||
return hasMessage(key) ? translate(key) : definition.name; | |||||
} | |||||
export function getPropertyDescription (definition) { | |||||
const key = `property.${definition.key}.description`; | |||||
return hasMessage(key) ? translate(key) : definition.description; | |||||
} | |||||
export function getCategoryName (category) { | |||||
const key = `property.category.${category}`; | |||||
return hasMessage(key) ? translate(key) : category; | |||||
} | |||||
export function getSubCategoryName (category, subCategory) { | |||||
const key = `property.category.${category}.${subCategory}`; | |||||
return hasMessage(key) ? translate(key) : getCategoryName(subCategory); | |||||
} | |||||
export function getSubCategoryDescription (category, subCategory) { | |||||
const key = `property.category.${category}.${subCategory}.description`; | |||||
return hasMessage(key) ? translate(key) : null; | |||||
} | |||||
export function getUniqueName (definition, index = null) { | |||||
const indexSuffix = index != null ? `[${index}]` : ''; | |||||
return `settings[${definition.key}]${indexSuffix}`; | |||||
} | |||||
export function getSettingValue (setting) { | |||||
if (setting.definition.multiValues) { | |||||
return setting.values; | |||||
} else if (setting.definition.type === TYPE_PROPERTY_SET) { | |||||
return setting.fieldValues; | |||||
} else { | |||||
return setting.value; | |||||
} | |||||
} | |||||
export function isEmptyValue (definition, value) { | |||||
if (value == null) { | |||||
return true; | |||||
} else if (definition.type === TYPE_BOOLEAN) { | |||||
return false; | |||||
} else { | |||||
return value.length === 0; | |||||
} | |||||
} | |||||
export function getEmptyValue (definition) { | |||||
if (definition.multiValues) { | |||||
return [getEmptyValue({ ...definition, multiValues: false })]; | |||||
} | |||||
if (definition.type === TYPE_PROPERTY_SET) { | |||||
const value = {}; | |||||
definition.fields.forEach(field => value[field.key] = getEmptyValue(field)); | |||||
return [value]; | |||||
} | |||||
if (definition.type === TYPE_BOOLEAN || definition.type === TYPE_SINGLE_SELECT_LIST) { | |||||
return null; | |||||
} | |||||
return ''; | |||||
} | |||||
export function isDefaultOrInherited (setting) { | |||||
return !!setting.default || !!setting.inherited; | |||||
} | |||||
function getParentValue (setting) { | |||||
if (setting.definition.multiValues) { | |||||
return setting.parentValues; | |||||
} else if (setting.definition.type === TYPE_PROPERTY_SET) { | |||||
return setting.parentFieldValues; | |||||
} else { | |||||
return setting.parentValue; | |||||
} | |||||
} | |||||
/** | |||||
* Get and format the default value | |||||
* @param setting | |||||
* @returns {string} | |||||
*/ | |||||
export function getDefaultValue (setting) { | |||||
const parentValue = getParentValue(setting); | |||||
if (parentValue == null) { | |||||
return translate('settings.default.no_value'); | |||||
} | |||||
if (setting.definition.multiValues) { | |||||
return parentValue.length > 0 ? | |||||
parentValue.join(', ') : | |||||
translate('settings.default.no_value'); | |||||
} | |||||
if (setting.definition.type === TYPE_PROPERTY_SET) { | |||||
return parentValue.length > 0 ? | |||||
translate('settings.default.complex_value') : | |||||
translate('settings.default.no_value'); | |||||
} | |||||
if (setting.definition.type === TYPE_PASSWORD) { | |||||
return translate('settings.default.password'); | |||||
} | |||||
if (setting.definition.type === TYPE_BOOLEAN) { | |||||
return parentValue ? translate('settings.boolean.true') : translate('settings.boolean.false'); | |||||
} | |||||
return parentValue; | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 classNames from 'classnames'; | |||||
import './styles.css'; | |||||
export default class Toggle extends React.Component { | |||||
static propTypes = { | |||||
value: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.bool]).isRequired, | |||||
name: React.PropTypes.string, | |||||
onChange: React.PropTypes.func | |||||
}; | |||||
handleClick (e, value) { | |||||
e.preventDefault(); | |||||
e.currentTarget.blur(); | |||||
if (this.props.onChange) { | |||||
this.props.onChange(!value); | |||||
} | |||||
} | |||||
render () { | |||||
const { value } = this.props; | |||||
const booleanValue = typeof value === 'string' ? value === 'true' : value; | |||||
const className = classNames('boolean-toggle', { 'boolean-toggle-on': booleanValue }); | |||||
return ( | |||||
<button className={className} name={this.props.name} onClick={e => this.handleClick(e, booleanValue)}> | |||||
<div className="boolean-toggle-handle"/> | |||||
</button> | |||||
); | |||||
} | |||||
} |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2016 SonarSource SA | |||||
* mailto:contact 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 chai, { expect } from 'chai'; | |||||
import { shallow } from 'enzyme'; | |||||
import sinon from 'sinon'; | |||||
import sinonChai from 'sinon-chai'; | |||||
import React from 'react'; | |||||
import Toggle from '../Toggle'; | |||||
chai.use(sinonChai); | |||||
function getSample (props) { | |||||
return ( | |||||
<Toggle value={true} onChange={() => true} {...props}/>); | |||||
} | |||||
function click (element) { | |||||
return element.simulate('click', { | |||||
currentTarget: { blur () {} }, | |||||
preventDefault () {} | |||||
}); | |||||
} | |||||
describe('Components :: Controls :: Toggle', () => { | |||||
it('should render', () => { | |||||
const Toggle = shallow(getSample()); | |||||
expect(Toggle.is('button')).to.equal(true); | |||||
}); | |||||
it('should call onChange', () => { | |||||
const onChange = sinon.spy(); | |||||
const Toggle = shallow(getSample({ onChange })); | |||||
click(Toggle); | |||||
expect(onChange).to.have.been.calledWith(false); | |||||
}); | |||||
}); |
.date-input-control-input:focus + .date-input-control-icon path { | .date-input-control-input:focus + .date-input-control-icon path { | ||||
fill: #4b9fd5; | fill: #4b9fd5; | ||||
} | } | ||||
.boolean-toggle { | |||||
display: inline-block; | |||||
vertical-align: middle; | |||||
width: 48px; | |||||
height: 24px; | |||||
padding: 1px; | |||||
border: 1px solid #cdcdcd; | |||||
border-radius: 24px; | |||||
box-sizing: border-box; | |||||
background-color: #fff; | |||||
cursor: pointer; | |||||
transition: all 0.3s ease; | |||||
} | |||||
.boolean-toggle:hover { | |||||
background-color: #fff; | |||||
} | |||||
.boolean-toggle:focus { | |||||
border-color: #4b9fd5; | |||||
background-color: #f6f6f6; | |||||
} | |||||
.boolean-toggle-handle { | |||||
width: 20px; | |||||
height: 20px; | |||||
border: 1px solid #cdcdcd; | |||||
border-radius: 22px; | |||||
box-sizing: border-box; | |||||
background-color: #f6f6f6; | |||||
transition: transform 0.3s cubic-bezier(.87,-.41,.19,1.44), border 0.3s ease; | |||||
} | |||||
.boolean-toggle-on { | |||||
border-color: #236a97; | |||||
background-color: #236a97; | |||||
} | |||||
.boolean-toggle-on:hover { | |||||
background-color: #236a97; | |||||
} | |||||
.boolean-toggle-on:focus { | |||||
background-color: #236a97; | |||||
} | |||||
.boolean-toggle-on .boolean-toggle-handle { | |||||
border-color: #f6f6f6; | |||||
transform: translateX(24px); | |||||
} |
} | } | ||||
} | } | ||||
export function hasMessage (...keys) { | |||||
const messageKey = keys.join('.'); | |||||
return messages[messageKey] != null; | |||||
} | |||||
function getCurrentLocale () { | function getCurrentLocale () { | ||||
return window.navigator.languages ? window.navigator.languages[0] : window.navigator.language; | return window.navigator.languages ? window.navigator.languages[0] : window.navigator.language; | ||||
} | } |
* @returns {Promise} | * @returns {Promise} | ||||
*/ | */ | ||||
export function delay (response) { | export function delay (response) { | ||||
return new Promise(resolve => setTimeout(() => resolve(response), 3000)); | |||||
return new Promise(resolve => setTimeout(() => resolve(response), 500)); | |||||
} | } |
left: 0; | left: 0; | ||||
line-height: @formControlHeight; | line-height: @formControlHeight; | ||||
padding-left: 8px; | padding-left: 8px; | ||||
padding-right: 8px; | |||||
padding-right: 24px; | |||||
position: absolute; | position: absolute; | ||||
right: 0; | right: 0; | ||||
top: 0; | top: 0; |