schultzcole / FVTT-Quench

Harden your Foundry module or system code with end-to-end UI tests directly within Foundry. Powered by Mocha
GNU General Public License v3.0
7 stars 2 forks source link

Foundry VTT 0.8.x #2

Open UFOMelkor opened 2 years ago

UFOMelkor commented 2 years ago

Hey,

first, thank you for this module. I run a lot of unit tests, but Quench looks like the missing part to test the things I could not test until now. Currently, my system still uses Foundry VTT 0.7.x, but I'd like to upgrade soon. Writing tests before upgrading is great, but only if the test runner works under the new version too ;-)

I know that the module.json says 0.7.9. I looked through your source code and could not find anything that prevents Quench from running with 0.8.8. Hence, I tried and got some really strange errors (with DnD5e as System and without running any tests). The errors occur even if I do not run the tests on startup or disable the Quench dialog on startup.

Do you have any idea what the origin of this problem might be?

TypeError: Failed initial data preparation for Actor [T2AU48DotVvKMavP]: e.prepareData is not a function
    at Actor5e.prepareEmbeddedEntities (foundry.js:9340)
    at Actor5e.prepareEmbeddedEntities (foundry.js:12277)
    at Actor5e.prepareData (foundry.js:9317)
    at Actor5e.prepareData (entity.js:54)
    at Actor5e._initialize (foundry.js:9130)
    at new Document (document.mjs:51)
    at new BaseActor (documents.mjs:61)
    at new <anonymous> (foundry.js:9103)
    at new Actor (foundry.js:12004)
    at new Actor5e (entity.js:12)
foundry.js:9133 TypeError: Failed initial data preparation for Scene [Wr9wnTV5otwMKAil]: e.prepareData is not a function
    at Scene.prepareEmbeddedEntities (foundry.js:9340)
    at Scene.prepareData (foundry.js:9317)
    at Scene._initialize (foundry.js:9130)
    at new Document (document.mjs:51)
    at new BaseScene (documents.mjs:850)
    at new <anonymous> (foundry.js:9103)
    at new Scene (foundry.js:15360)
    at Map._initialize (foundry.js:10064)
    at new WorldCollection (foundry.js:10050)
    at new Scenes (foundry.js:11298)
Foundry VTT | Prepared World Documents in 17ms
TypeError: Cannot read property 'draw' of undefined
    at foundry.js:19494
    at Map.map (collection.mjs:145)
    at DrawingsLayer.draw (foundry.js:19493)
    at async Canvas.draw (foundry.js:17503)
    at async Scene.view (foundry.js:15481)
    at async Game.initializeCanvas (foundry.js:4418)
    at async Game.setupGame (foundry.js:4297)
    at async Game._initializeGameView (foundry.js:5117)
    at async Game.initialize (foundry.js:4202)
foundry.js:17506 TypeError: Cannot read property 'draw' of undefined
    at foundry.js:19494
    at Map.map (collection.mjs:145)
    at WallsLayer.draw (foundry.js:19493)
    at async WallsLayer.draw (foundry.js:40409)
    at async Canvas.draw (foundry.js:17503)
    at async Scene.view (foundry.js:15481)
    at async Game.initializeCanvas (foundry.js:4418)
    at async Game.setupGame (foundry.js:4297)
    at async Game._initializeGameView (foundry.js:5117)
    at async Game.initialize (foundry.js:4202)
foundry.js:17506 TypeError: Cannot read property 'draw' of undefined
    at foundry.js:19494
    at Map.map (collection.mjs:145)
    at TemplateLayer.draw (foundry.js:19493)
    at async Canvas.draw (foundry.js:17503)
    at async Scene.view (foundry.js:15481)
    at async Game.initializeCanvas (foundry.js:4418)
    at async Game.setupGame (foundry.js:4297)
    at async Game._initializeGameView (foundry.js:5117)
    at async Game.initialize (foundry.js:4202)
foundry.js:17506 TypeError: Cannot read property 'draw' of undefined
    at foundry.js:19494
    at Map.map (collection.mjs:145)
    at TokenLayer.draw (foundry.js:19493)
    at async Canvas.draw (foundry.js:17503)
    at async Scene.view (foundry.js:15481)
    at async Game.initializeCanvas (foundry.js:4418)
    at async Game.setupGame (foundry.js:4297)
    at async Game._initializeGameView (foundry.js:5117)
    at async Game.initialize (foundry.js:4202)
schultzcole commented 2 years ago

Yeah, when 0.8 was back in alpha or beta I did a bit of investigation and ran into the same sort of things. I suspect it has to do with how I'm importing mocha and chai, but I didn't get the chance to fully figure out what the issue was or how to fix it. For the moment I can't really dedicate time to investigating it unfortunately, but I'm sure there is some sort of solution that could be reached.

UFOMelkor commented 2 years ago

I guess it is about the globalThis while importing, but still not sure. Will investigate and report :-)

UFOMelkor commented 2 years ago

I guess I could enclose the problem.

Hooks do not support async functions. Hence, while quenchInit is executed, other functions are also executed. They access CONFIG.DatabaseBackend and some classes like CONFIG.Combatant. I guess it are the classes whose objects are contained by objects of other classes (like Combatant is by Combat).

For me, it works when changing globalThis as follows. I might be missing some classes because not everything is used in my current world. Perhaps CONFIG: oldGlobal.CONFIG is a better variant.

I do not know whether this helps, because I don't know what mocha does with the globals.

globalThis = {
    Date: oldGlobal.Date,
    setTimeout: oldGlobal.setTimeout,
    setInterval: oldGlobal.setInterval,
    clearTimeout: oldGlobal.clearTimeout,
    clearInterval: oldGlobal.clearInterval,
    onerror: oldGlobal.onerror,
    location: oldGlobal.location,
    document: oldGlobal.document,
    CONFIG: {
        ActiveEffect: oldGlobal.CONFIG.ActiveEffect,
        AmbientLight: oldGlobal.CONFIG.AmbientLight,
        AmbientSound: oldGlobal.CONFIG.AmbientSound,
        Combatant: oldGlobal.CONFIG.Combatant,
        DatabaseBackend: oldGlobal.CONFIG.DatabaseBackend,
        Drawing: oldGlobal.CONFIG.Drawing,
        FogExploration: oldGlobal.CONFIG.FogExploration,
        JournalEntry: oldGlobal.CONFIG.JournalEntry,
        MeasuredTemplate: oldGlobal.CONFIG.MeasuredTemplate,
        Note: oldGlobal.CONFIG.Note,
        Playlist: oldGlobal.CONFIG.Playlist,
        PlaylistSound: oldGlobal.CONFIG.PlaylistSound,
        TableResult: oldGlobal.CONFIG.TableResult,
        Tile: oldGlobal.CONFIG.Tile,
        Token: oldGlobal.CONFIG.Token,
        Wall: oldGlobal.CONFIG.Wall,
    },
};
lupestro commented 2 years ago

Dancing with the definition of globalThis is a risky business, especially in an async environment.

I tried just loading mocha and chai at the top of the module, and the chief issue we encounter is that Foundry is injecting a ui member into globalThis.mocha, thereby overwriting mocha's own ui member. This then causes mocha to fail during startup when it starts running tests, as it expects ui to be a function it uses for delivering results. If there is some kind of exclude list for Foundry injecting ui into globals, that might let the straightforward approach work.

lupestro commented 2 years ago

I've found a way around this issue that doesn't involve messing with globalThis. It does involve bumping mocha to 9.x and applying a three line hack near the end of it:

    // Wicked hack for Quench - 
    // get ui property out of copy of global merged with mocha before merging 
    // so it doesn't clobber mocha's ui function
    var hackedCommonJsGlobal = Object.assign({}, commonjsGlobal);
    delete hackedCommonJsGlobal.ui;
    var browserEntry = Object.assign(mocha, hackedCommonJsGlobal);

    // Original implementation:
    //var browserEntry = Object.assign(mocha, commonjsGlobal);

This modified mocha can be used as you'd expect to be able to use it.