/**
  * Test add configurable application to a nonexistent section.
  *
  * <p>This test depends on the "HopingThereIsNoSectionByThisName" section not existing.<br>
  * Tests: XWiki.ConfigurableClass
  */
 @Test
 public void testAddConfigurableApplicationInNonexistantSection() {
   String section = "HopingThereIsNoSectionByThisName";
   // Create the configurable for global admin.
   createConfigurableApplication("Main", "TestConfigurable", section, true);
   // Check it's available in global section.
   clickAdministerWiki();
   waitForElement(getAdminMenuItemLocator(section));
   clickLinkWithText(section);
   assertConfigurationPresent("Main", "TestConfigurable");
   // Check that it's not available in space section.
   open("Main", "WebPreferences", "admin");
   // Assert there is no menu item in the administration menu for our configurable application.
   assertElementNotPresent(getAdminMenuItemLocator(section));
 }
 /**
  * Will fail unless it detects a configuration of the type created by
  * createConfigurableApplication.<br>
  * Tests: XWiki.ConfigurableClass
  */
 public void assertConfigurationPresent(String space, String page) {
   assertElementPresent("//div[@id='admin-page-content']/h2[@id='HSomeHeading']/span");
   // Fields
   String fullName = space + "." + page;
   String form =
       "//div[@id='admin-page-content']/form[@action='/xwiki/bin/save/"
           + space
           + "/"
           + page
           + "']";
   assertElementPresent(form + "/fieldset/dl/dt[1]/label");
   assertElementPresent(form + "/fieldset/dl/dd[1]/input[@name='" + fullName + "_0_String']");
   assertElementPresent(form + "/fieldset/dl/dt[2]/label");
   assertElementPresent(form + "/fieldset/dl/dd[2]/select[@name='" + fullName + "_0_Boolean']");
   assertElementPresent(form + "/fieldset/dl/dt[3]/label");
   assertElementPresent(form + "/fieldset/dl/dd[3]/textarea[@name='" + fullName + "_0_TextArea']");
   assertElementPresent(form + "/fieldset/dl/dt[4]/label");
   assertElementPresent(form + "/fieldset/dl/dd[4]/select[@name='" + fullName + "_0_Select']");
   assertElementPresent(form + "/fieldset/input[@id='" + fullName + "_redirect']");
   assertElementPresent(
       form + "/fieldset/input[@value='" + getSelenium().getLocation() + "'][@name='xredirect']");
   // JavaScript injects a save button outside of the form and removes the default save button.
   waitForElement("//*[@class = 'admin-buttons']//input[@type = 'submit' and @value = 'Save']");
 }
  /*
   * Test Panel Wizard
   */
  @Test
  public void testPanelsAdmin() {
    open("XWiki", "XWikiPreferences", "admin");

    // test panel wizard at global level
    clickLinkWithLocator("//a[text()='Panel Wizard']");
    waitForBodyContains("Page Layout");
    clickLinkWithXPath("//a[@href='#PageLayoutSection']", false);
    waitForElement("//div[@id = 'rightcolumn']");
    clickLinkWithXPath("//div[@id='rightcolumn']", false);
    waitForBodyContains("Panel List");
    clickLinkWithXPath("//a[@href='#PanelListSection']", false);
    dragAndDrop(
        By.xpath("//div[@class='panel expanded CategoriesPanel']//h1"), By.id("rightPanels"));
    assertElementPresent("//div[@id = 'rightPanels']/div[contains(@class, 'CategoriesPanel')]");
    clickLinkWithXPath("//button[text()='Save the new layout']", false);
    waitForNotificationSuccessMessage("The layout has been saved properly.");
    open("Main", "WebHome");
    assertElementNotPresent("leftPanels");
    assertElementPresent("rightPanels");
    assertElementPresent("//div[@id = 'rightPanels']/div[contains(@class, 'CategoriesPanel')]");

    // Revert changes
    open("XWiki", "XWikiPreferences", "admin");
    clickLinkWithLocator("//a[text()='Panel Wizard']");
    waitForBodyContains("Page Layout");
    clickLinkWithXPath("//a[@href='#PageLayoutSection']", false);
    waitForCondition("selenium.isElementPresent(\"//div[@id='bothcolumns']\")!=false;");
    clickLinkWithXPath("//div[@id='bothcolumns']", false);
    waitForBodyContains("Panel List");
    clickLinkWithXPath("//a[@href='#PanelListSection']", false);
    dragAndDrop(
        By.xpath("//div[@id='rightPanels']//div[contains(@class, 'CategoriesPanel')]//h1"),
        By.xpath("//div[@id='allviewpanels']//div[@class='accordionTabContentBox']"));
    assertElementNotPresent("//div[@id = 'rightPanels']//div[contains(@class, 'CategoriesPanel')]");
    clickLinkWithXPath("//button[text()='Save the new layout']", false);
    waitForNotificationSuccessMessage("The layout has been saved properly.");
    open("Main", "WebHome");
    assertElementPresent("leftPanels");
    assertElementPresent("rightPanels");
    assertElementNotPresent("//div[@id = 'rightPanels']//div[contains(@class, 'CategoriesPanel')]");

    // test panel wizard at space level
    open("TestPanelsAdmin", "WebHome", "edit", "editor=wiki");
    setFieldValue("content", "aaa");
    clickEditSaveAndView();
    open("TestPanelsAdmin", "WebPreferences", "admin");
    clickLinkWithLocator("//a[text()='Panel Wizard']");
    waitForBodyContains("Page Layout");
    clickLinkWithXPath("//a[@href='#PageLayoutSection']", false);
    waitForCondition("selenium.isElementPresent(\"//div[@id='leftcolumn']\")!=false;");
    clickLinkWithXPath("//div[@id='leftcolumn']", false);
    waitForBodyContains("Panel List");
    clickLinkWithXPath("//a[@href='#PanelListSection']", false);
    dragAndDrop(
        By.xpath("//div[@class='panel expanded CategoriesPanel']//h1"), By.id("leftPanels"));
    clickLinkWithXPath("//button[text()='Save the new layout']", false);
    waitForNotificationSuccessMessage("The layout has been saved properly.");
    open("TestPanelsAdmin", "WebHome");
    assertElementPresent("leftPanels");
    assertElementPresent("//div[@id = 'leftPanels']//div[contains(@class, 'CategoriesPanel')]");
    open("XWiki", "WebHome");
    assertElementPresent("rightPanels");
    assertElementNotPresent("//div[@id = 'leftPanels']//div[contains(@class, 'CategoriesPanel')]");
  }
  /**
   * Creates a new page with a configuration class with some simple fields<br>
   * then adds an object of class configurable and one of it's own class.<br>
   * Tests: XWiki.ConfigurableClass
   */
  public void createConfigurableApplication(
      String space, String page, String section, boolean global) {
    // We have to use an existing space because the copy page form doesn't allow entering a new
    // space.
    String storageSpace = "Sandbox";
    String storagePage = "CreateConfigurableApplication";

    if (!tryToCopyPage(storageSpace, storagePage, space, page)) {
      // Create the page with a simple configuration class.
      createPage(space, page, "Test configurable application.", "xwiki/2.1");
      open(space, page, "edit", "editor=class");
      setFieldValue("propname", "String");
      setFieldValue("proptype", "String");
      clickButtonAndContinue("//input[@name='action_propadd']");
      setFieldValue("propname", "Boolean");
      setFieldValue("proptype", "Boolean");
      clickButtonAndContinue("//input[@name='action_propadd']");
      setFieldValue("propname", "TextArea");
      setFieldValue("proptype", "TextArea");
      clickButtonAndContinue("//input[@name='action_propadd']");
      // Expand the TextArea property we just added in order to set the "editor" meta property.
      getSelenium().click("xproperty_TextArea");
      getSelenium().select("TextArea_editor", "value=Text");
      clickEditSaveAndContinue();
      setFieldValue("propname", "Select");
      setFieldValue("proptype", "StaticList");
      clickButtonAndContinue("//input[@name='action_propadd']");

      // Go to the object section.
      open(space, page, "edit", "editor=object");

      // Add a configurable object which points to the new class as the configuration class.
      getSelenium().select("classname", "value=XWiki.ConfigurableClass");
      clickButtonAndContinue("//input[@name='action_objectadd']");
      clickEditSaveAndView();

      // Try to place it in the storage area.
      tryToCopyPage(space, page, storageSpace, storagePage);
    }

    // Go to the object section.
    open(space, page, "edit", "editor=object");

    // Add an object of the new class.
    waitForElement("classname");
    getSelenium().select("classname", "value=" + space + "." + page);
    // Scroll the page to the top because the edit menu can be activated when we hover over the add
    // button.
    getSelenium().runScript("window.scrollTo(0, 0)");
    clickButtonAndContinue("//input[@name='action_objectadd']");

    setFieldValue("XWiki.ConfigurableClass_0_displayInSection", section);
    setFieldValue("XWiki.ConfigurableClass_0_heading", "Some Heading");
    setFieldValue("XWiki.ConfigurableClass_0_configurationClass", space + "." + page);

    // Unfold the XWiki.ConfigurableClass object so that we can modify its properties
    WebElement configurableClassObj =
        getDriver().findElement(By.id("xobject_XWiki.ConfigurableClass_0"));
    if (configurableClassObj.getAttribute("class").contains("collapsed")) {
      configurableClassObj.click();
    }

    if (global) {
      getSelenium().check("XWiki.ConfigurableClass_0_configureGlobally");
    } else {
      getSelenium().uncheck("XWiki.ConfigurableClass_0_configureGlobally");
    }
    // We won't set linkPrefix, propertiesToShow, codeToExecute, or iconAttachment.

    clickEditSaveAndView();
  }
  /*
   * Creates a document with 2 configurable objects, one gets configured globally in one section and displays
   * 2 configuration fields, the other is configured in the space in another section and displays the other 2
   * fields. Fails if they are not displayed as they should be.
   *
   * Tests: XWiki.ConfigurableClass
   */
  @Test
  public void testApplicationConfiguredInMultipleSections() {
    String space = "Main";
    String page = "TestConfigurable";

    createConfigurableApplication(space, page, "TestSection1", true);
    open(space, page, "edit", "editor=object");
    // Add a second configurable object.
    getSelenium().select("classname", "value=XWiki.ConfigurableClass");
    clickButtonAndContinue("//input[@name='action_objectadd']");
    setFieldValue("XWiki.ConfigurableClass_1_displayInSection", "TestSection2");
    setFieldValue("XWiki.ConfigurableClass_1_heading", "Some Other Heading");
    setFieldValue("XWiki.ConfigurableClass_1_configurationClass", space + "." + page);
    getSelenium().uncheck("XWiki.ConfigurableClass_1_configureGlobally");
    // Set propertiesToShow so that each config only shows half of the properties.
    setFieldValue("XWiki.ConfigurableClass_1_propertiesToShow", "TextArea, Select");
    setFieldValue("XWiki.ConfigurableClass_0_propertiesToShow", "String, Boolean");
    clickEditSaveAndView();

    // Assert that half of the configuration shows up but not the other half.
    open("XWiki", "XWikiPreferences", "admin", "editor=globaladmin&section=TestSection1");
    assertElementPresent("//div[@id='admin-page-content']/h2[@id='HSomeHeading']/span");
    // Fields
    String fullName = space + "." + page;
    String form =
        "//div[@id='admin-page-content']/form[@action='/xwiki/bin/save/"
            + space
            + "/"
            + page
            + "']";
    assertElementPresent(form + "/fieldset//label['String']");
    assertElementPresent(form + "/fieldset//input[@name='" + fullName + "_0_String']");
    assertElementPresent(form + "/fieldset//label['Boolean']");
    assertElementPresent(form + "/fieldset//select[@name='" + fullName + "_0_Boolean']");
    assertElementPresent(form + "/fieldset/input[@id='" + fullName + "_redirect']");
    // xredirect
    assertElementPresent(
        form + "/fieldset/input[@value='" + getSelenium().getLocation() + "'][@name='xredirect']");
    // Save button
    // assertElementPresent(form + "/div/p/span/input[@type='submit']");
    // Javascript injects a save button outside of the form and removes the default save button.
    waitForElement("//div/div/p/span/input[@type='submit'][@value='Save']");
    // Should not be here
    assertElementNotPresent(form + "/fieldset//textarea[@name='" + fullName + "_0_TextArea']");
    assertElementNotPresent(form + "/fieldset//select[@name='" + fullName + "_0_Select']");

    // Now we go to where the other half of the configuration should be.
    open("Main", "WebPreferences", "admin", "editor=spaceadmin&section=TestSection2");
    assertElementPresent("//h2[@id='HSomeOtherHeading']/span");
    // Fields
    assertElementPresent(form + "/fieldset//label");
    assertElementPresent(form + "/fieldset//textarea[@name='" + fullName + "_0_TextArea']");
    assertElementPresent(form + "/fieldset//select[@name='" + fullName + "_0_Select']");
    assertElementPresent(form + "/fieldset/input[@id='" + fullName + "_redirect']");
    // xredirect
    assertElementPresent(
        form + "/fieldset/input[@value='" + getSelenium().getLocation() + "'][@name='xredirect']");
    // Save button
    // assertElementPresent(form + "/div/p/span/input[@type='submit']");
    // Javascript injects a save button outside of the form and removes the default save button.
    waitForElement("//div/div/p/span/input[@type='submit'][@value='Save']");
    // Should not be here
    assertElementNotPresent(form + "/fieldset//input[@name='" + fullName + "_0_String']");
    assertElementNotPresent(form + "/fieldset//select[@name='" + fullName + "_0_Boolean']");
  }