import unittest

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
import os
import sys
import time

class TestphpLDAPadminWeb(unittest.TestCase):

    def setUp(self):

        options = webdriver.ChromeOptions()
        options.add_argument('--headless')
        options.add_argument('--no-sandbox')
        options.add_argument('--headless')
        options.add_argument('--disable-gpu')
        options.add_argument('--disable-dev-shm-usage')
        service = Service(executable_path=r'/usr/bin/chromedriver')
        self.driver = webdriver.Chrome(service=service, options=options)

    def tearDown(self):
        self.driver.close()

    def do_login(self):
        self.driver.get("http://localhost:8888/phpldapadmin/")
        self.assertIn("phpLDAPadmin", self.driver.title)

        login_btn = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.XPATH, "//a[@title='Login to My LDAP Server']"))
        login_btn.click()

        # Anonymous checkbox on login page
        WebDriverWait(self.driver, 60).until(lambda x: x.find_element(By.NAME, "anonymous_bind"))

        title = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.CLASS_NAME, "title"))
        self.assertIn("Authenticate to server My LDAP Server", title.text)

        user = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "login"))
        user.send_keys("cn=admin,dc=testing,dc=local")

        password = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "password"))
        password.send_keys("public")

        password.submit()

        tree_menu = WebDriverWait(self.driver, 60).until(lambda x: x.find_element(By.CLASS_NAME, "treemenudiv"))

    def do_expand(self, img_name):
        expander = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.XPATH, f"//img[@src='images/default/{img_name}']"))
        expander.click()

    def test_title_and_footer(self):
        self.driver.get("http://localhost:8888/phpldapadmin/")
        self.assertIn("phpLDAPadmin", self.driver.title)

        version = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "ajFOOT"))
        self.assertIn("1.2.", version.text)

        login_btn = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.CLASS_NAME, "logged_in"))
        self.assertIn("login", login_btn.text)

    def test_login_and_export(self):
        self.do_login()

        tree_item = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.XPATH, "//a[@title='dc=testing,dc=local']"))
        tree_item.click()

        export_btn = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.XPATH, "//a[@title='Save a dump of this object']"))
        export_btn.click()

        export_form = WebDriverWait(self.driver, 60).until(lambda x: x.find_element(By.ID, "export_form"))
        export_form.submit()

        export_result = WebDriverWait(self.driver, 60).until(lambda x: x.find_element(By.ID, "ajBODY"))

        self.assertIn("# LDIF Export for dc=testing,dc=local", export_result.text)
        self.assertIn("# Server: My LDAP Server (127.0.0.1)", export_result.text)
        self.assertIn("# Search Scope: base", export_result.text)
        self.assertIn("# Search Filter: (objectClass=*)", export_result.text)
        self.assertIn("# Total Entries: 1", export_result.text)
        self.assertIn("# Generated by phpLDAPadmin", export_result.text)
        self.assertIn("# Version: 1.2.", export_result.text)
        self.assertIn("version: 1", export_result.text)
        self.assertIn("# Entry 1: dc=testing,dc=local", export_result.text)
        self.assertIn("dn: dc=testing,dc=local", export_result.text)
        self.assertIn("dc: testing", export_result.text)
        self.assertIn("o: Debian Testing", export_result.text)
        self.assertIn("objectclass: top", export_result.text)
        self.assertIn("objectclass: dcObject", export_result.text)
        self.assertIn("objectclass: organization", export_result.text)

    def test_login_and_import(self):

        Simpsons = open("/usr/share/doc/phpldapadmin/Simpsons.ldif", "r")
        Simpsons = Simpsons.read()
        self.assertIn("o=Simpsons", Simpsons)
        Simpsons = Simpsons.replace("o=Simpsons", "o=Simpsons,dc=testing,dc=local")

        self.do_login()

        import_btn = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.XPATH, "//a[@title='Import My LDAP Server']"))
        import_btn.click()

        import_form = WebDriverWait(self.driver, 60).until(lambda x: x.find_element(By.CLASS_NAME, "new_value"))

        import_area = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.XPATH, "//textarea[@name='ldif']"))

        for line in Simpsons.split('\n'):
            import_area.send_keys(line + "\n")

        import_form.submit()

        import_result = WebDriverWait(self.driver, 60).until(lambda x: x.find_element(By.ID, "ajBODY"))

        self.assertIn("STDIN 30,367 bytes (LDIF Import)", import_result.text)
        self.assertIn("Adding", import_result.text)
        self.assertIn("Success", import_result.text)
        self.assertIn("o=Simpsons,dc=testing,dc=local", import_result.text)
        self.assertIn("cn=simpsons-goun,o=Simpsons,dc=testing,dc=local", import_result.text)
        self.assertIn("cn=simpsons-pg,o=Simpsons,dc=testing,dc=local", import_result.text)
        self.assertIn("ou=People,o=Simpsons,dc=testing,dc=local", import_result.text)
        self.assertIn("cn=Bart Simpson,ou=People,o=Simpsons,dc=testing,dc=local", import_result.text)
        self.assertIn("cn=Homer Simpson,ou=People,o=Simpsons,dc=testing,dc=local", import_result.text)
        self.assertIn("cn=Lisa Simpson,ou=People,o=Simpsons,dc=testing,dc=local", import_result.text)
        self.assertIn("cn=Maggie Simpson,ou=People,o=Simpsons,dc=testing,dc=local", import_result.text)
        self.assertIn("cn=Marge Simpson,ou=People,o=Simpsons,dc=testing,dc=local", import_result.text)
        self.assertIn("ou=Pets,o=Simpsons,dc=testing,dc=local", import_result.text)
        self.assertIn("cn=Santas Little Helper,ou=Pets,o=Simpsons,dc=testing,dc=local", import_result.text)

        WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.XPATH, "//a[@title='Refresh My LDAP Server']")).click()

        # Expand dc=testing,dc=local
        self.do_expand("tree_expand_corner_first.png")
        # Expand o=Simpsons
        self.do_expand("tree_expand.png")
        # Expand ou=People
        self.do_expand("tree_expand.png")
        # Expand ou=Pets
        self.do_expand("tree_expand.png")


        WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.XPATH, "//a[@title='cn=Santas Little Helper,ou=Pets,o=Simpsons,dc=testing,dc=local']")).click()

        title = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.XPATH, "//h3[@class='title']"))
        self.assertIn("cn=Santas Little Helper", title.text)

        object_class = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "new_values_objectclass_0"))
        self.assertIn("inetOrgPerson", object_class.get_attribute("value"))

        WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.XPATH, "//a[@title='cn=Marge Simpson,ou=People,o=Simpsons,dc=testing,dc=local']")).click()

        title = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.XPATH, "//h3[@class='title']"))
        self.assertIn("cn=Marge Simpson", title.text)

        object_class = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "new_values_objectclass_0"))
        self.assertIn("inetOrgPerson", object_class.get_attribute("value"))

        object_class = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "new_values_objectclass_3"))
        self.assertIn("shadowAccount", object_class.get_attribute("value"))

        # Check cn=simpsons-pg
        WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.XPATH, "//a[@title='cn=simpsons-pg,o=Simpsons,dc=testing,dc=local']")).click()

        object_class = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "new_values_memberuid_0"))
        self.assertIn("maggie", object_class.get_attribute("value"))
        object_class = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "new_values_memberuid_1"))
        self.assertIn("marg", object_class.get_attribute("value"))
        object_class = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "new_values_memberuid_2"))
        self.assertIn("lisa", object_class.get_attribute("value"))
        object_class = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "new_values_memberuid_3"))
        self.assertIn("homer", object_class.get_attribute("value"))
        object_class = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "new_values_memberuid_4"))
        self.assertIn("bart", object_class.get_attribute("value"))

        # Check cn=simpsons-goun
        WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.XPATH, "//a[@title='cn=simpsons-goun,o=Simpsons,dc=testing,dc=local']")).click()

        object_class = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "new_values_uniquemember_0"))
        self.assertIn("cn=Bart Simpson,ou=People,o=Simpsons,dc=testing,dc=local", object_class.get_attribute("value"))
        object_class = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "new_values_uniquemember_1"))
        self.assertIn("cn=Homer Simpson,ou=People,o=Simpsons,dc=testing,dc=local", object_class.get_attribute("value"))
        object_class = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "new_values_uniquemember_2"))
        self.assertIn("cn=Lisa Simpson,ou=People,o=Simpsons,dc=testing,dc=local", object_class.get_attribute("value"))
        object_class = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "new_values_uniquemember_3"))
        self.assertIn("cn=Maggie Simpson,ou=People,o=Simpsons,dc=testing,dc=local", object_class.get_attribute("value"))
        object_class = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.ID, "new_values_uniquemember_4"))
        self.assertIn("cn=Marge Simpson,ou=People,o=Simpsons,dc=testing,dc=local", object_class.get_attribute("value"))

        #print(self.driver.page_source)


if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(TestphpLDAPadminWeb)
    result = unittest.TextTestRunner(verbosity=2).run(suite)

    if not result.wasSuccessful():
        sys.exit(1)
