selfie icon indicating copy to clipboard operation
selfie copied to clipboard

[Enhancment] Calling `expectSelfie()` from another package

Open IzawGithub opened this issue 6 months ago • 1 comments

Hello, the library is pretty useful, but I'm stumbling into a problem that I'm not sure how to fix.

Using Kotest, I want to create a reusable Spec to snapshot tests my custom exceptions and their localization. It ends up looking kind of like this:

package mypackage.errors

abstract class ErrorSpec<T : Error>(
    private val clazz: KClass<T>,
    private val create: () -> T
) :
    FunSpec({
        context("Localisation") {
            forAll(Exhaustive.collection(SUPPORTED_LOCALES)) {

                expectSelfie(json.encodeToString(clazz.serializer(), create())).toMatchDisk()

            }
        }
    })

class ErrorTest : ErrorSpec<Error>(
    clazz = Error::class,
    create = { Error() }
)

This work perfectly, until I put ErrorSpec in another package. The main reason I want to do this is to use a testFixtures.

This then ends up failing at runtime with:

org.opentest4j.AssertionFailedError:
Couldn't find source file for CallLocation(
    clazz=mypackage.ErrorSpec$1$1,
    method=invokeSuspend,
    fileName=Specs.kt,
    line=36
),

looked in TypedPath(absolutePath=[...]/mypackage/src/test/kotlin/)
and [[...]/mypackage/src/test/resources],

maybe there are other source roots?

What I don't understand is that, if I use toMatchDisk_TODO() instead of toMatchDisk(), the snapshot files end up being written, but the tests fails on writeLine.

Manually changing the value of isTodo to true in SelfieImplementations/DiskSelfie.toMatchDisk():38, the tests pass successfully, with the snapshot file being written at the correct place (albeit being overwritten every run, which kind of defeat the point).

Is there a way to do what I want using the public API? If not, would it be possible to implement?

IzawGithub avatar Jun 18 '25 15:06 IzawGithub

Is there a way to do what I want using the public API?

I think so! The key part of the error message is this:

looked in TypedPath(absolutePath=[...]/mypackage/src/test/kotlin/) and [[...]/mypackage/src/test/resources],

If you are using text fixtures, then your code is not present in either of those two places, correct? You can add more places to look by overriding this:

https://github.com/diffplug/selfie/blob/75eaaec8cb097d255fde6f46addfa5146ca3a11f/jvm/selfie-runner-kotest/src/commonMain/kotlin/com/diffplug/selfie/kotest/SelfieSettingsAPI.kt#L77-L93

Selfie has the unusual requirement that it needs to find the actual source file to change the _TODO() calls...

nedtwigg avatar Jun 18 '25 19:06 nedtwigg