#Mocking for JS

1 messages · Page 1 of 1 (latest)

frosty barn
#

To test my JS FFI, I want to mock the "World" object that I FFI against.

I have seen mocking libraries for the erlang backend, but none for the JS one.

Has anyone explored mocking JS already?

sacred frigate
#

We strongly discourage magic mocking in favour of the functional core pattern and dependency injection

frosty barn
#

Which I totally understand. Though sadly I have to somehow deal with this opaque and not open source object from a plugin API, that I can not get any hold on outside of a running obsidian instance, in which I obviously can't run test.

sacred frigate
#

You could use functional core or dependency injection there

frosty barn
#

I need to wrap my head around it. Maybe I have to take another nap over it.

sacred frigate
#

We could really do with some documentation on these patterns

frosty barn
#

Goal is a talk about my adventures, learning gleam as I implement some obsidian plugin (and the ffi).

frosty barn
#

I wanted to play with it, though as soon as I import anything into my tests that imports the FFI modules, I get an error that it wasn't foudn in node_modules… The "module" from npm is just a bunch of d.ts files and no actual JS sources, what would be my best bet here to get past that?

sacred frigate
#

Play with what sorry?

#

What gives you an error?

frosty barn
#

So far I only wanted to import my main module, and test a helper function from it, which is pure gleam, though that already fails, as I import my FFI modules there for something else.

The error I get is "Error: Cannot find package '/home/nmelzer/Projects/obsidian-work-tracker/node_modules/obsidian' imported from /home/nmelzer/Projects/obsidian-work-tracker/build/dev/javascript/work_tracker/obsidian_app.ts", as I have import … from 'obsidian', in a couple of the gluecode modules. Which are imported into that module my SUT is on.

So I would be able to move the helper out into another module, and test that, but this would also mean, that there is no way for me to actually test anything that refers to the obsidian JS?

sacred frigate
#

This is where functional core comes in

#

You write code not to directly depend on this external service and hook it up at a higher level

frosty barn
#

How does that avoid having the import?

sacred frigate
#

If it doesn't depend on obsidian it doesn't import it

frosty barn
#

but something ultimatively will?

sacred frigate
#

Yup, the imperative shell part of "functional core, imperative shell" that you would not be importing into your tests

frosty barn
#

Wait… I think I can get rid of it…

I currently use TS files for the glue, which require the imports for the types… If I though would just use MJS without type annotations, there would be no need for the imports…

I do not like that…

#

Sadly I do not see much I could do in a functional core, as the API heavily relies on mutation of internal state for nearly everything 😦

sacred frigate
#

That's exactly what functional core is intended for

#

Consider how react provides a pure abstraction over the DOM

frosty barn
#

I do not do react.

sacred frigate
#

You can split what should happen from how it is done by modeling actions as a data structure

sacred frigate
#

Another approach to it is to use dependency injection and provide those side effecting functions as arguments

frosty barn
#

I seem to have a fundamental misunderstanding what functional core means here… I have a god object from a third party that I want to integrate via FFI. And I have to somehow deal with that. This God object is the core of the FFI, there is no way to make it functional all of a sudden. Dealing with this object is inherently not functional.

Sure I can use DI for the consumers of the FFI, but that wouldn't that require me to implement half of the FFI twice?

And besides LiveView I have never worked with any of these, and as I do not know how the DOM works on the client, I do not really see LV as a help here, as I do not know what it abstracts away from me nor how.

sacred frigate
#

If you want to test this code you're going to need to either determine a way to incorporate obsidian into your tests, or build an abstraction in front of obsidian that your business logic will interact with

#

Both paths will be additional work