# Licensed to the Software Freedom Conservancy (SFC) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The SFC licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

import pytest

from selenium.common.exceptions import WebDriverException
from selenium.webdriver.remote.webelement import WebElement

try:
    str = unicode
except NameError:
    pass


def testShouldBeAbleToExecuteSimpleJavascriptAndReturnAString(driver, pages):
    pages.load("xhtmlTest.html")

    result = driver.execute_script("return document.title")

    assert type(result) == str, "The type of the result is %s" % type(result)
    assert "XHTML Test Page" == result


def testShouldBeAbleToExecuteSimpleJavascriptAndReturnAnInteger(driver, pages):
    pages.load("nestedElements.html")
    result = driver.execute_script("return document.getElementsByName('checky').length")

    assert type(result) == int
    assert int(result) > 1


def testShouldBeAbleToExecuteSimpleJavascriptAndReturnAWebElement(driver, pages):
    pages.load("xhtmlTest.html")

    result = driver.execute_script("return document.getElementById('id1')")

    assert result is not None
    assert isinstance(result, WebElement)
    assert "a" == result.tag_name.lower()


def testShouldBeAbleToExecuteSimpleJavascriptAndReturnAListOfWebElements(driver, pages):
    pages.load("xhtmlTest.html")

    result = driver.execute_script("return document.querySelectorAll('div.navigation a')")

    assert result is not None
    assert isinstance(result, list)
    assert all(isinstance(item, WebElement) for item in result)
    assert all('a' == item.tag_name.lower() for item in result)


def testShouldBeAbleToExecuteSimpleJavascriptAndReturnWebElementsInsideAList(driver, pages):
    pages.load("xhtmlTest.html")

    result = driver.execute_script("return [document.body]")

    assert result is not None
    assert isinstance(result, list)
    assert isinstance(result[0], WebElement)


def testShouldBeAbleToExecuteSimpleJavascriptAndReturnWebElementsInsideANestedList(driver, pages):
    pages.load("xhtmlTest.html")

    result = driver.execute_script("return [document.body, [document.getElementById('id1')]]")

    assert result is not None
    assert isinstance(result, list)
    assert isinstance(result[0], WebElement)
    assert isinstance(result[1][0], WebElement)


def testShouldBeAbleToExecuteSimpleJavascriptAndReturnWebElementsInsideADict(driver, pages):
    pages.load("xhtmlTest.html")

    result = driver.execute_script("return {el1: document.body}")

    assert result is not None
    assert isinstance(result, dict)
    assert isinstance(result.get('el1'), WebElement)


def testShouldBeAbleToExecuteSimpleJavascriptAndReturnWebElementsInsideANestedDict(driver, pages):
    pages.load("xhtmlTest.html")

    result = driver.execute_script("return {el1: document.body, "
                                   "nested: {el2: document.getElementById('id1')}}")

    assert result is not None
    assert isinstance(result, dict)
    assert isinstance(result.get('el1'), WebElement)
    assert isinstance(result.get('nested').get('el2'), WebElement)


def testShouldBeAbleToExecuteSimpleJavascriptAndReturnWebElementsInsideAListInsideADict(driver, pages):
    pages.load("xhtmlTest.html")

    result = driver.execute_script("return {el1: [document.body]}")

    assert result is not None
    assert isinstance(result, dict)
    assert isinstance(result.get('el1'), list)
    assert isinstance(result.get('el1')[0], WebElement)


def testShouldBeAbleToExecuteSimpleJavascriptAndReturnABoolean(driver, pages):
    pages.load("xhtmlTest.html")

    result = driver.execute_script("return true")

    assert result is not None
    assert type(result) == bool
    assert bool(result)


def testShouldBeAbleToExecuteSimpleJavascriptAndAStringsArray(driver, pages):
    pages.load("javascriptPage.html")
    expectedResult = []
    expectedResult.append("zero")
    expectedResult.append("one")
    expectedResult.append("two")
    result = driver.execute_script(
        "return ['zero', 'one', 'two']")

    assert expectedResult == result


def testShouldBeAbleToExecuteSimpleJavascriptAndReturnAnArray(driver, pages):
    pages.load("javascriptPage.html")
    expectedResult = []
    expectedResult.append("zero")
    subList = []
    subList.append(True)
    subList.append(False)
    expectedResult.append(subList)
    result = driver.execute_script("return ['zero', [true, false]]")
    assert result is not None
    assert type(result) == list
    assert expectedResult == result


def testPassingAndReturningAnIntShouldReturnAWholeNumber(driver, pages):
    pages.load("javascriptPage.html")
    expectedResult = 1
    result = driver.execute_script("return arguments[0]", expectedResult)
    assert type(result) == int
    assert expectedResult == result


def testPassingAndReturningADoubleShouldReturnADecimal(driver, pages):
    pages.load("javascriptPage.html")
    expectedResult = 1.2
    result = driver.execute_script("return arguments[0]", expectedResult)
    assert type(result) == float
    assert expectedResult == result


def testShouldThrowAnExceptionWhenTheJavascriptIsBad(driver, pages):