Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selenium + Chrome can't load ESModule code due to CORS policy violation #128

Open
xerial opened this issue Jul 2, 2023 · 2 comments
Open

Comments

@xerial
Copy link

xerial commented Jul 2, 2023

If ESModule is enabled, Scala.js + Selenium can't complete tests because loading main.js failed due to CORS policy violation:

image

Access to script at 'file:///Users/leo/work/git/scalajs-selenium/target/scala-3.1.2/test-selenium-test-fastopt/main.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted.

My current guess of the cause is that ES modules are loaded using relative paths (e.g., ./java.lang.-Object.js), but browser can't allow such accesses:

main.js compiled with Scala.js (from empty source code):

'use strict';
import * as $j_java$002elang$002e$002dObject from "./java.lang.-Object.js";
import * as $j_org$002escalajs$002etesting$002ebridge$002e$002dBridge from "./org.scalajs.testing.bridge.-Bridge.js";
$j_org$002escalajs$002etesting$002ebridge$002e$002dBridge.$s_Lorg_scalajs_testing_bridge_Bridge__start__V();
//# sourceMappingURL=main.js.map

Library versions

  • Scala 3.x. The same problem happens in Scala 3.2.x, 3.3.0 as wel.
  • sbt 1.9.1
  • scalajs-env-selenium: 1.1.1
  • scala.js 1.13.2

How to reproduce

Reproduction repo: https://github.com/xerial/scalajs-selenium/tree/selenium-esmodule

Install Selenium Chrome driver

Run Selenium + Scala.js test

$ git clone -b selenium-esmodule [email protected]:xerial/scalajs-selenium
$ cd scalajs-selenium
$ ./sbt
sbt:test-selenium> test
Jul 02, 2023 12:29:54 PM org.openqa.selenium.remote.server.DefaultDriverFactory registerDriverProvider
INFO: Driver provider class org.openqa.selenium.ie.InternetExplorerDriver registration is skipped:
 registration capabilities Capabilities {browserName: internet explorer, platformName: WINDOWS} does not match the current platform MAC
Jul 02, 2023 12:29:54 PM org.openqa.selenium.remote.server.DefaultDriverFactory registerDriverProvider
INFO: Driver provider class org.openqa.selenium.edge.EdgeDriver registration is skipped:
 registration capabilities Capabilities {browserName: MicrosoftEdge, platformName: WINDOWS} does not match the current platform MAC
[info] Fast optimizing /Users/leo/work/git/scalajs-selenium/target/scala-3.1.2/test-selenium-test-fastopt
Jul 02, 2023 12:29:54 PM org.openqa.selenium.remote.server.DefaultDriverProvider newInstance
INFO: Creating a new session for Capabilities {browserName: chrome, goog:chromeOptions: {args: [], extensions: []}, javascriptEnabled: true}
Starting ChromeDriver 114.0.5735.90 (386bc09e8f4f2e025eddae123f36f6263096ae49-refs/branch-heads/5735@{#1052}) on port 20983
Only local connections are allowed.dTestFrameworks 0s
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
Jul 02, 2023 12:29:56 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C / loadedTestFrameworks 0s

// Test execution blocked here because of the load error of main.js 

Where it's blocked?

I used jstack command to see which thread was blocked. TestAdaptor.loadFrameworks can't load the test completion result because main.js doesn't work properly in the browser (Selenium):

"pool-48-thread-4" #475 prio=5 os_prio=31 cpu=48.95ms elapsed=427.68s tid=0x00000002a7c4a800 nid=0x18f0b waiting on condition  [0x00000002924650
00]
   java.lang.Thread.State: WAITING (parking)
        at jdk.internal.misc.Unsafe.park([email protected]/Native Method)
        - parking to wait for  <0x00000007a22dcb98> (a scala.concurrent.impl.Promise$CompletionLatch)
        at java.util.concurrent.locks.LockSupport.park([email protected]/LockSupport.java:194)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt([email protected]/AbstractQueuedSynchronizer.java:885)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly([email protected]/AbstractQueuedSynchronizer.java
:1039)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly([email protected]/AbstractQueuedSynchronizer.java:1
345)
        at scala.concurrent.impl.Promise$DefaultPromise.tryAwait(Promise.scala:242)
        at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:258)
        at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:263)
        at scala.concurrent.Await$.$anonfun$result$1(package.scala:223)
        at scala.concurrent.Await$$$Lambda$5571/0x0000000801824440.apply(Unknown Source)
        at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:57)
        at scala.concurrent.Await$.result(package.scala:146)
        at org.scalajs.testing.adapter.package$AwaitFuture$.await$extension(package.scala:20)
        at org.scalajs.testing.adapter.TestAdapter.loadFrameworks(TestAdapter.scala:58)
        at org.scalajs.sbtplugin.ScalaJSPluginInternal$.$anonfun$scalaJSTestSettings$6(ScalaJSPluginInternal.scala:707)
        at org.scalajs.sbtplugin.ScalaJSPluginInternal$$$Lambda$10804/0x0000000802991c40.apply(Unknown Source)
        at org.scalajs.sbtplugin.ScalaJSPluginInternal$.enhanceNotInstalledException(ScalaJSPluginInternal.scala:104)
        at org.scalajs.sbtplugin.ScalaJSPluginInternal$.$anonfun$scalaJSTestSettings$4(ScalaJSPluginInternal.scala:707)
        at org.scalajs.sbtplugin.ScalaJSPluginInternal$$$Lambda$8949/0x00000008023ec040.apply(Unknown Source)

What is the issue?

HTML file generated by scala.js runner:
image

main.js code compiled with Scala.js. Even no application code is compiled, loading java.lang.Object fails probably because its use of relative paths:
image

Expectation

sbt test passes

Sucess Path

If ESModule is not used here (comment out this setting), the test passes with Selenium:
https://github.com/xerial/scalajs-selenium/blob/7078b3eee741560469c9cc19d8503962c4d650de/build.sbt#L18-L22

But without using ESModule, ScalablyTyped can't load other JS modules in package.json.

Background

For writing tests with Scala.js with jsdom, ECMAScript modules can't be used becuase jsdom doesn't suppot module type yet scala-js/scala-js-env-jsdom-nodejs#56 jsdom/jsdom#2475, so I've tried Selenium so that DOM document can be accessed from Scala.js tests.

I haven't tested other Selenium drivers (e.g., Safari) because I hit another issue for launching Safari in Mac with Scala.js.

@xerial
Copy link
Author

xerial commented Jul 2, 2023

Workaround

ok. I found a workaround: We need to add a setting --disable-web-security to Chrome to disable CORS check only for testing:

    Test / jsEnv := {
      val options = new ChromeOptions()
      options.addArguments("--disable-web-security")
      options.setHeadless(true)
      new SeleniumJSEnv(options, SeleniumJSEnv.Config())
    }

@faveoled
Copy link

@xerial Thanks. It works. Just added some imports:

import org.scalajs.jsenv.selenium.SeleniumJSEnv
import org.openqa.selenium.chrome.ChromeOptions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants