https://kotlinlang.org logo
#javascript
Title
# javascript
e

Edoardo Luppi

02/22/2024, 9:27 PM
Good news is I've managed to setup Mocha test suites using Mocha externals. This was a prerequisite for VS Code, since it uses Mocha by default. So you end up with an entry point for VS Code:
Copy code
@JsExport
fun run(): Promise<Void>? {
  val mocha = Mocha(jso {
    ui = Interface.tdd
    color = true
  })

  val testsRoot = path.resolve(js("__dirname") as String)
  mocha.addFile(path.resolve(testsRoot, "tests.mjs"))

  try {
    return Promise { c, e ->
      mocha.run { ... }
    }
  } catch (e: Throwable) {
    console.error(e)
    return null
  }
}
And your actual tests:
Copy code
@Suppress("DEPRECATION")
@EagerInitialization
val e = {
  suite("Extension Test Suite") {
    test("Sample test") {
      println("OK!")
    }
  }
}
The
@EagerInitialization
bit is required so that the function gets executed immediately. It's a bit messy to look at, but I haven't found other solutions
a

Artem Kobzar

02/23/2024, 9:51 AM
@Ilya Goncharov [JB], but we use
Mocha
in kotlin.test by default, am I right?
i

Ilya Goncharov [JB]

02/23/2024, 9:52 AM
Yes, when you use our Gradle plugin, Mocha is already used both in nodejs and in browser (via Karma)
a

Artem Kobzar

02/23/2024, 9:57 AM
So, @Edoardo Luppi we generate such a code with a compiler when you use the plain-old `kotlin.test`:
Copy code
val e = {
  suite("Extension Test Suite") {
    test("Sample test") {
      println("OK!")
    }
  }
}
e

Edoardo Luppi

02/23/2024, 10:44 AM
It's a bit different in VS Code world tho. When you want to execute VS Code tests (which are based on Mocha), you have to invoke them through the VS Code executable:
Copy code
code --extensionDevelopmentPath=... --extensionTestsPath=.../src/test/suite/index
Where
index
is the compiled
index.kt
file that contains
Copy code
@JsExport
fun run(): Promise<Void>? { ...
I couldn't find a solution to do this using the standard way of starting tests
Open to suggestions tho!
I suppose the K/JS way of doing it would be to offer customization of the entry point for tests. So that the .js/.mjs test entry point can be invoked directly by VS Code
a

Artem Kobzar

02/23/2024, 10:48 AM
@Ilya Goncharov [JB] ^^
i

Ilya Goncharov [JB]

02/23/2024, 7:12 PM
So do you mean that VS code run specific method in js script? Or it can just execute full script with all its side effects?
e

Edoardo Luppi

02/23/2024, 7:18 PM
@Ilya Goncharov [JB] it looks for a specific
run
method in the JS script, as its entry point.
i

Ilya Goncharov [JB]

02/23/2024, 7:28 PM
Hm, its interesting, but before it find run method, it should initialize module and execute all side effects as I understand, but I need to check this specific case
e

Edoardo Luppi

02/23/2024, 7:29 PM
Would it be better if I prepare an example and you can just clone it and try it?
i

Ilya Goncharov [JB]

02/23/2024, 7:29 PM
I mean, yes, your
run
method is okay, but why do you need the second part, when you are using
EagerInitialization
? I mean kotlin compiler generates side effects for kotlin test
If it is not a problem for you, I would rather get some reproducer
e

Edoardo Luppi

02/23/2024, 7:31 PM
Sure. I already have a working extension set up. I will push it later with a readme explaining what to do.
I think I don't have the full picture of how the compilation of tests work, so if you look at it you might find it's easier than what I made it look like
👍 1
@Ilya Goncharov [JB] see https://github.com/lppedd/kotlin-externals/tree/master/examples/vscode-extension You need to clone the entire repository
i

Ilya Goncharov [JB]

02/26/2024, 11:02 AM
I have taken a look, and what I can see now. If you want to write your own test runner script (https://code.visualstudio.com/api/working-with-extensions/testing-extension#the-test-runner-script), so you can do it via Kotlin/JS. The only what you need to do is to point it onto your test file which was compiled for test compilation. But as I understand, you can write tests just with
kotlin-test
library Because for example this
Copy code
class Foo {
    @Test
    fun foo() {
         println("OK")
    }
}
will be compiled to
Copy code
suite('Foo', () => {

  test('foo', () => {
    println("OK")
  });
});
It looks like what VS code expects from tests So, ``--extensionDevelopmentPath` has to point onto your extension executable file, and
--extensionTestsPath
has to point onto your runner, and inside your runner, you should point your test file. But as I understand you can use easier way with
@vscode/test-electron
package (https://code.visualstudio.com/api/working-with-extensions/testing-extension#advanced-setup-your-own-runner) It does not require to operate with
Mocha
instance
👍 1
e

Edoardo Luppi

02/26/2024, 11:10 AM
But as I understand, you can write tests just with
kotlin-test
library
It is true that kotlin-test compiles down to a Mocha test suite. However, currently I see no way of communicating the test results to the VS Code instance. The runner script returns a Promise with test results from a
run
function:
Copy code
return new Promise((resolve, reject) => {
  try {
    mocha.run(failures => {
      if (failures > 0) {
        reject(new Error(`${failures} tests failed.`));
      } else {
        resolve();
      }
    });
  } catch (err) {
    reject(err);
  }
});
That's the part I'm missing. Since the outputted JS test file doesn't have a
run
entry point, I don't see how VS Code can be made aware of those test suites
i

Ilya Goncharov [JB]

02/26/2024, 11:25 AM
As I can see, this test runner just run tests, I can’t see any relation with communicating with VS code. This promise in js in fact returns
void
, because from lambda under
run
there is no
return
statement. As I understand just running mocha via cli, just returns the same
mocha.run
I’d say I don’t understand how VS code now may know results because returning Promise is void.
e

Edoardo Luppi

02/26/2024, 11:27 AM
Mmm it sounds reasonable, yeah. I need to try out, looks like the only way to be sure!
👍 1
@Ilya Goncharov [JB] pointing to the outputted
*-test.js
files doesn't work unfortunately.
Copy code
Error: Path file:///c%3A/Users/edoardo.luppi/IdeaProjects/client-vscode/build/js/packages/client-vscode-extension-kotlin-test/kotlin/client-vscode-extension-kotlin-test does not point to a valid extension test runner.
	at g.qb (c:\Users\edoardo.luppi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\api\node\extensionHostProcess.js:156:15485)
	at async g.$extensionTestsExecute (c:\Users\edoardo.luppi\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\api\node\extensionHostProcess.js:156:15203) {stack: 'Error: Path file:///c%3A/Users/edoardo.luppi/…h\api\node\extensionHostProcess.js:156:15203)', message: 'Path file:///c%3A/Users/edoardo.luppi/IdeaPr… not point to a valid extension test runner.'}
When you use the VS Code launch configuration for tests, as said it uses
--extensionTestsPath
which internally uses the same approach as
vscode-test
, see https://github.com/microsoft/vscode-test/blob/bc400a29fbd3d54496bbcc7e9cbe5f687880471f/lib/runTest.ts#L78 So the entry point with a
Promise<void>
is mandatory.
In the meantime I'm building my own KSP processor that will generate an appropriate file starting from custom annotations like
@MochaTest
. Almost got it to work
t

turansky

03/01/2024, 7:16 PM
> So the entry point with a
Promise<void>
is mandatory. It's already solved by
coroutines-test
. For async tests you can use
runTest
. Modified call
runTest
call example is here. But you can use
runTest
directly.
e

Edoardo Luppi

03/01/2024, 7:17 PM
But does it generate a
run
function? Because the name of the function is important
t

turansky

03/01/2024, 7:19 PM
Copy code
external interface MochaTestBase {
    fun run(): Promise<Void>
}
?
e

Edoardo Luppi

03/01/2024, 7:22 PM
I'm getting lost here. Is that interface going to be implemented by each test class?
t

turansky

03/01/2024, 7:23 PM
Yes
e

Edoardo Luppi

03/01/2024, 7:34 PM
But there should be only one top level
run
function. See the screenshot above
t

turansky

03/01/2024, 7:44 PM
OK, now I see 😞