package com.codeborne.selenide.impl;

import org.apache.commons.io.IOUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.By.ByCssSelector;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;

import static com.codeborne.selenide.Configuration.SelectorMode.CSS;
import static com.codeborne.selenide.Configuration.selectorMode;
import static com.codeborne.selenide.Selenide.executeJavaScript;
import static java.lang.Thread.currentThread;

/**
 * Thanks to http://selenium.polteq.com/en/injecting-the-sizzle-css-selector-library/
 */
public class WebElementSelector {
  public static WebElementSelector instance = new WebElementSelector();

  protected String sizzleSource;

  public WebElement findElement(SearchContext context, By selector) {
    if (selectorMode == CSS || !(selector instanceof ByCssSelector)) {
      return context.findElement(selector);
    }

    List<WebElement> webElements = evaluateSizzleSelector(context, (ByCssSelector) selector);
    return webElements.isEmpty() ? null : webElements.get(0);
  }

  public List<WebElement> findElements(SearchContext context, By selector) {
    if (selectorMode == CSS || !(selector instanceof ByCssSelector)) {
      return context.findElements(selector);
    }

    return evaluateSizzleSelector(context, (ByCssSelector) selector);
  }

  protected List<WebElement> evaluateSizzleSelector(SearchContext context, ByCssSelector sizzleCssSelector) {
    injectSizzleIfNeeded();

    String sizzleSelector = sizzleCssSelector.toString()
        .replace("By.selector: ", "")
        .replace("By.cssSelector: ", "");

    if (context instanceof WebElement)
      return executeJavaScript("return Sizzle(arguments[0], arguments[1])", sizzleSelector, context);
    else
      return executeJavaScript("return Sizzle(arguments[0])", sizzleSelector);
  }

  protected void injectSizzleIfNeeded() {
    if (!sizzleLoaded()) {
      injectSizzle();
    }
  }

  protected Boolean sizzleLoaded() {
    try {
      return executeJavaScript("return typeof Sizzle != 'undefined'");
    } catch (WebDriverException e) {
      return false;
    }
  }

  protected synchronized void injectSizzle() {
    if (sizzleSource == null) {
      try {
        sizzleSource = IOUtils.toString(currentThread().getContextClassLoader().getResource("sizzle.js"), Charset.defaultCharset());
      } catch (IOException e) {
        throw new RuntimeException("Cannot load sizzle.js from classpath", e);
      }
    }
    executeJavaScript(sizzleSource);
  }
}

@@ -335,16 +335,58 @@
 harset;%0A
+import java.nio.charset.StandardCharsets;%0A
 import j
@@ -2510,32 +2510,30 @@
 %22), 
-Charset.defaultCharset()
+StandardCharsets.UTF_8
 );%0A 

Set charset to UTF_8 for injectSizzle method.