/*
 * Copyright 2013, Red Hat, Inc. and individual contributors as indicated by the
 * @author tags. See the copyright.txt file in the distribution for a full
 * listing of individual contributors.
 *
 * This 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 2.1 of the License, or (at your option)
 * any later version.
 *
 * This software 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 software; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
 * site: http://www.fsf.org.
 */
package org.zanata.feature.security;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

import java.util.ArrayList;
import java.util.List;

import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.zanata.feature.BasicAcceptanceTest;
import org.zanata.feature.DetailedTest;
import org.zanata.page.account.ResetPasswordPage;
import org.zanata.page.account.SignInPage;
import org.zanata.page.utility.DashboardPage;
import org.zanata.util.ResetDatabaseRule;
import org.zanata.workflow.BasicWorkFlow;
import org.zanata.workflow.LoginWorkFlow;

/**
 * @author Damian Jansen <a href="mailto:djansen@redhat.com">djansen@redhat.com</a>
 */
@Category(DetailedTest.class)
public class SecurityFullTest
{
   @ClassRule
   public static ResetDatabaseRule resetDatabaseRule = new ResetDatabaseRule();

   @Before
   public void before()
   {
      // Remove all cookies, no previous login is allowed
      new BasicWorkFlow().goToHome().deleteCookiesAndRefresh();
   }

   @Test
   @Category(BasicAcceptanceTest.class)
   public void signInSuccessful()
   {
      DashboardPage dashboardPage = new LoginWorkFlow().signIn("admin", "admin");
      assertThat("User is logged in", dashboardPage.loggedInAs(), equalTo("admin"));
   }

   @Test
   public void signInFailure()
   {
      SignInPage signInPage = new BasicWorkFlow().goToHome().clickSignInLink();
      signInPage = signInPage.signInFailure("nosuchuser", "password");
      assertThat("Error message is shown", signInPage.getNotificationMessage(), equalTo("Login failed"));
      assertThat("User has failed to log in", !signInPage.hasLoggedIn());
   }

   @Test
   @Ignore("RHBZ-987707 | Cannot intercept email yet")
   public void resetPasswordSuccessful()
   {
      SignInPage signInPage = new BasicWorkFlow().goToHome().clickSignInLink();
      ResetPasswordPage resetPasswordPage = signInPage.gotToResetPassword();
      resetPasswordPage = resetPasswordPage.enterUserName("nosuchuser").enterEmail("nosuchuser@nosuchdomain.com");
      resetPasswordPage = resetPasswordPage.resetPassword();
      //TODO: Reset Success page
   }

   @Test
   public void resetPasswordFailureForInvalidAccount()
   {
      SignInPage signInPage = new BasicWorkFlow().goToHome().clickSignInLink();
      ResetPasswordPage resetPasswordPage = signInPage.gotToResetPassword();
      resetPasswordPage = resetPasswordPage.enterUserName("nosuchuser").enterEmail("nosuchuser@nosuchdomain.com");
      resetPasswordPage = resetPasswordPage.resetFailure();
      assertThat("A no such account message is displayed", resetPasswordPage.getNotificationMessage(),
            equalTo("No such account found"));
   }

   @Test
   public void invalidResetPasswordFieldEntries()
   {
      SignInPage signInPage = new BasicWorkFlow().goToHome().clickSignInLink();
      ResetPasswordPage resetPasswordPage = signInPage.gotToResetPassword();
      resetPasswordPage = resetPasswordPage.enterUserName("b").enterEmail("b");
      resetPasswordPage = resetPasswordPage.resetFailure();

      assertThat("Invalid email error is displayed", resetPasswordPage.waitForErrors(),
            hasItem("not a well-formed email address"));

      // Both are valid, but show seemingly at random
      assertThat(resetPasswordPage.getErrors().get(0),
            either(equalTo("size must be between 3 and 20")).or(equalTo("must match ^[a-z\\d_]{3,20}$")));

   }

   @Test
   public void emptyResetPasswordFieldEntries()
   {
      // Both are valid, but show seemingly at random
      List<String> emptyUsernameErrors = new ArrayList<String>();
      emptyUsernameErrors.add("size must be between 3 and 20");
      emptyUsernameErrors.add("must match ^[a-z\\d_]{3,20}$");

      SignInPage signInPage = new BasicWorkFlow().goToHome().clickSignInLink();
      ResetPasswordPage resetPasswordPage = signInPage.gotToResetPassword();
      resetPasswordPage = resetPasswordPage.clearFields();
      resetPasswordPage = resetPasswordPage.resetFailure();

      assertThat("Empty email error is displayed", resetPasswordPage.waitForErrors(),
            hasItem("may not be empty"));


      assertThat(resetPasswordPage.getErrors().get(0), equalTo("may not be empty"));

   }

}

@@ -4585,256 +4585,8 @@
   %7B%0A
-      // Both are valid, but show seemingly at random%0A      List%3CString%3E emptyUsernameErrors = new ArrayList%3CString%3E();%0A      emptyUsernameErrors.add(%22size must be between 3 and 20%22);%0A      emptyUsernameErrors.add(%22must match %5E%5Ba-z%5C%5Cd_%5D%7B3,20%7D$%22);%0A%0A
     
@@ -4987,16 +4987,62 @@
 ty%22));%0A%0A
+      // All are valid, but may show at random
 %0A      a
@@ -5092,35 +5092,182 @@
 (0),
- equalTo(%22may not be empty%22
+%0A            either(equalTo(%22size must be between 3 and 20%22))%0A                  .or(equalTo(%22may not be empty%22))%0A                  .or(equalTo(%22must match %5E%5Ba-z%5C%5Cd_%5D%7B3,20%7D$%22)
 ));%0A

test cater for randomly selected error message