@Test(
      description = "Verify the Downloads Tab contains the correct FOSS vs NETWORK links",
      groups = {"functional"})
  public void DownloadsTab_01() throws HarnessException {

    // Make sure common links are present
    for (String locator : CommonLocators) {
      ZAssert.assertTrue(
          app.zPageDownloads.sIsElementPresent(locator),
          "Verify the common locator exists: " + locator);
    }

    // If NETWORK, make sure NETWORK-only links appear and FOSS-only links do not appear
    // If FOSS, make sure FOSS-only links appear and NETWORK-only links do not appear
    if (ZimbraSeleniumProperties.zimbraGetVersionString().contains("NETWORK")) {

      for (String locator : NetworkOnlyLocators) {
        ZAssert.assertTrue(
            app.zPageDownloads.sIsElementPresent(locator),
            "Verify the network-only locator exists: " + locator);
      }

      for (String locator : FossOnlyLocators) {
        ZAssert.assertFalse(
            app.zPageDownloads.sIsElementPresent(locator),
            "Verify the foss-only locator does not exists: " + locator);
      }

    } else if (ZimbraSeleniumProperties.zimbraGetVersionString().contains("FOSS")) {

      for (String locator : NetworkOnlyLocators) {
        ZAssert.assertFalse(
            app.zPageDownloads.sIsElementPresent(locator),
            "Verify the network-only locator does not exists: " + locator);
      }

      for (String locator : FossOnlyLocators) {
        ZAssert.assertTrue(
            app.zPageDownloads.sIsElementPresent(locator),
            "Verify the foss-only locator exists: " + locator);
      }

    } else {
      throw new HarnessException(
          "Unable to find NETWORK or FOSS in version string: "
              + ZimbraSeleniumProperties.zimbraGetVersionString());
    }
  }
  @Test(
      description = "Verify the downloads links return 200 rather than 404",
      groups = {"functional"})
  public void DownloadsTab_02() throws HarnessException {

    // Determine which links should be present
    List<String> locators = new ArrayList<String>();

    if (ZimbraSeleniumProperties.zimbraGetVersionString().contains("NETWORK")) {

      locators.addAll(Arrays.asList(NetworkOnlyLocators));
      locators.addAll(Arrays.asList(CommonLocators));

    } else if (ZimbraSeleniumProperties.zimbraGetVersionString().contains("FOSS")) {

      locators.addAll(Arrays.asList(FossOnlyLocators));
      locators.addAll(Arrays.asList(CommonLocators));

    } else {
      throw new HarnessException(
          "Unable to find NETWORK or FOSS in version string: "
              + ZimbraSeleniumProperties.zimbraGetVersionString());
    }

    for (String locator : locators) {
      String href = app.zPageDownloads.sGetAttribute("xpath=" + locator + "@href");
      String page = ZimbraSeleniumProperties.getBaseURL() + href;

      HttpURLConnection connection = null;
      try {

        URL url = new URL(page);
        connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("HEAD");
        int code = connection.getResponseCode();

        // TODO: why is 400 returned for the PDF links?
        // 200 and 400 are acceptable
        ZAssert.assertStringContains(
            "200 400", "" + code, "Verify the download URL is valid: " + url.toString());

      } catch (MalformedURLException e) {
        throw new HarnessException(e);
      } catch (IOException e) {
        throw new HarnessException(e);
      } finally {
        if (connection != null) {
          connection.disconnect();
          connection = null;
        }
      }
    }
  }
  @Test(
      description = "Drag one folder and Drop into other",
      groups = {"smoke"})
  public void DragAndDropFeed_01() throws HarnessException, MalformedURLException {

    FolderItem inbox = FolderItem.importFromSOAP(app.zGetActiveAccount(), SystemFolder.Inbox);
    ZAssert.assertNotNull(inbox, "Verify the inbox is available");

    // Create a subfolder in Inbox
    String feedname = "feed" + ZimbraSeleniumProperties.getUniqueString();
    URL feedurl = new URL("http", "rss.news.yahoo.com", 80, "/rss/topstories");

    app.zGetActiveAccount()
        .soapSend(
            "<CreateFolderRequest xmlns='urn:zimbraMail'>"
                + "<folder name='"
                + feedname
                + "' l='"
                + inbox.getId()
                + "' url='"
                + feedurl.toString()
                + "'/>"
                + "</CreateFolderRequest>");

    FolderItem feed = FolderItem.importFromSOAP(app.zGetActiveAccount(), feedname);
    ZAssert.assertNotNull(feed, "Verify the subfolder is available");

    // Create two subfolders in the inbox
    // One folder to Drag
    // Another folder to drop into
    String name1 = "folder" + ZimbraSeleniumProperties.getUniqueString();

    app.zGetActiveAccount()
        .soapSend(
            "<CreateFolderRequest xmlns='urn:zimbraMail'>"
                + "<folder name='"
                + name1
                + "' l='"
                + inbox.getId()
                + "'/>"
                + "</CreateFolderRequest>");

    FolderItem subfolder1 = FolderItem.importFromSOAP(app.zGetActiveAccount(), name1);
    ZAssert.assertNotNull(subfolder1, "Verify the first subfolder is available");

    // Click on Get Mail to refresh the folder list
    app.zPageMail.zToolbarPressButton(Button.B_GETMAIL);

    // Bug 65234
    // Sometimes the folder tree is rendered slowly.  sleep a bit
    SleepUtil.sleepVerySmall();

    app.zPageMail.zDragAndDrop(
        "css=td[id='zti__main_Mail__" + feed.getId() + "_textCell']",
        "css=td[id='zti__main_Mail__" + subfolder1.getId() + "_textCell']");

    // Verify the folder is now in the other subfolder
    feed = FolderItem.importFromSOAP(app.zGetActiveAccount(), feedname);
    ZAssert.assertNotNull(feed, "Verify the subfolder is again available");
    ZAssert.assertEquals(
        subfolder1.getId(),
        feed.getParentId(),
        "Verify the subfolder's parent is now the other subfolder");
  }