I'm a bit new to JS... I'm trying to unit test a f...
# javascript
c
I'm a bit new to JS... I'm trying to unit test a function that takes a
org.w3c.files.File
as argument, but I don't know how to build one from JS (on JVM I could just
new java.io.File("path")
but I've heard that's not possible on JS?)
n
In js, just take a File argument. Note that the w3c File isn't the same thing as the java io File object, so this isn't a multiplatform thing. You can't construct the js File object, you have to get it from a file input.
c
How can I get it from a file input in a unit test? I guess the ‘normal' way would be via a form, but a unit test can't have human interaction
n
Good question 😊, I have no idea. Let me know if you find a way to mock it out. Perhaps there's a library for that purpose
c
Right now I have:
Copy code
val promise = fetch("some PNG I found").await()
val blob = promise.asDynamic().blob() as Promise<Blob>
val data = blob.await()

js("new File([data], \"filename.png\", {type: \"image/png\"})")
But that fails with
ReferenceError: File is not defined
Which is surprising, because according to MDN, it should be available everywhere (I only run tests in Chromium & NodeJS so far) https://developer.mozilla.org/en-US/docs/Web/API/File/File
n
Yeah but file has no constructor, it only comes from user ops. iirc a file is a blob, can you just change your api to accept blob?
Oh, I guess it does have a constructor.
c
I use
FileReader.readAsArrayBuffer(Blob)
, so I guess that's an option, yes
Also, this seems to explain the error for NodeJS, but not for browser… SO
n
Aha. Run your tests in browser then 🙂. (Although I've had trouble getting that to work in CI)
c
Well I call
jsBrowserTest
, so I think that's what I'm doing already? xD
For this project I'd like to have it working on browser and node though 😕
n
I switched to my laptop to try it. If I do:
Copy code
@Test
fun testFile() {
   val f = File(arrayOf(Blob(arrayOf(1, 2, 3))), "Test")
   println(f)
}
this works when I run browserTest
c
Very interesting, it doesn't work for me
n
My gradle:
Copy code
kotlin {
	js {

		browser {
			testTask {
				
				useKarma {
					useChromeHeadless()
				}
			}
		}
curious if your browserTest is still using Node
n
try changing mocha to
Copy code
useKarma {
   useChromeHeadless()
}
If you want it working in browser and node, it's a little tricky -- you'll probably need a common js source set then a node and browser source sets. I know it's possible, but don't have an example off hand. From my experience trying to npm depend on for example a File polyfill for Node is a rabbit hole, you'll get errors when you go back to browser. (Although if you figure that out I'd love to see)
c
Well, my knowledge about the JS ecosystem is incredibly thin, I probably won't attempt anything for now 🙂 Also, NodeJS support is interesting for the project, but not vital, so…
Do you know how to set the timeout in
useKarma
? The IDE doesn't want to autocomplete my gradle setup right now 😕
n
ha, there isn't a way afaik. >_<
c
I see
timeout.set(Duration?)
but I have no idea how to provide a
Duration
, and it won't import
java.time.Duration
xD
n
it's kotlin.Duration, and you'd do something like 3.seconds
sorry, kotlin.time.Duration
and I think you're looking at the wrong thing, I believe timeout is on AbstractTask, which is unrelated to the unit tests timeout
c
Oh, yes. Thanks.
It does work with Karma, good to know, however the timeout is too small for the other tests
Oh, the
File
constructor works, but the
fetch
now fails. I'm not convinced yet that adding Kotlin to JS solves its issues... Well, I'll keep searching, thanks a lot for the help ^^
n
you have to do window.fetch I think
but unfortunately I think relative paths in unit tests in kotlin MPP are difficult...
c
Yeah but again, that's not going to work on Node xD
Same error, anyway
n
you could try npm jsdom
it emulates window
but as I said before it's tricky having a node library just for node, I think you'd have to split your source sets
c
If I find no solutions, I'll probably do that, that's pretty much the only thing that I have that's not in
common
anyway, so it shouldn't take too much work
n
is the purpose of all this to have common code process images or something like that?
I think there are multiplatform buffer utils that you can use to turn a blob or a jvm filestream into
or better yet, the js file stream, process as it downloads
anyway, my point is that i wouldn't try to put something as specific as File in common, use a common buffer format