Embroider advice for static js addon inclusions for tests

Hi! We are currently trying to port our application over to using embroider as a build system.

Our first exercise is working on our addons to make them “embroider-safe”.

We have an addon that provides test support utilities, and one of the things it provides is a static javascript file that contains static fixtures for pretender. This javascript file is not imported by its callers, it rather is saved to a global variable at script evaluation and accessed that way.

currently we create this javascript file by conbining all the fixture files and apply babel using broccoli in the index file of the addon, and put the result in public/assets. Then other addons and our app just pull in the file via script tag in their test index.html, which triggers the script eval and saving to global.

Where this gets complicated is the static javascript file makes use of momentjs to format some date fields. The old addon format “figures this out” and is able to successfully reference moment when used by other addons and our app.

This approach seems to be less successful in embroider, as it has trouble resolving moment from the other addons and the app, even though moment is a dependency and is able to be referenced in local files.

I guess my question is, acknowledging this legacy approach might not be ideal, what is a preferred way to import static fixtures from a test support addon. Do I just move these fixtures into test-support and start importing them when used? That would be a heavy update since we have thousands of tests that use these fixtures. Just trying to figure out what my options are.

I’ll see if I can paste in some snippets for visuals, as my “wall of text” here might not be optimally digestible.

Here’s the code that currently packages the fixtures in the test-support addon

    treeForPublic: function (tree) {
        let fixtures = new Funnel(join(this.root, 'support/static-fixtures'), {
            include: ['**/*.js'],
            destDir: '/assets',
        });

        fixtures = babel(fixtures, {
            presets: [
                [
                    '@babel/preset-env',
                    {
                        targets: {
                            browsers: ['last 2 versions'],
                        },
                    },
                ],
            ],
        });

        fixtures = concat(fixtures, {
            inputFiles: ['**/*.js'],
            outputFile: '/assets/app-fixtures.js',
        });

        let trees = [fixtures];

        if (tree) {
            trees.push(tree);
        }

        return new MergeTrees(trees);
    },
    contentFor(type) {
        if (type === 'test-body-footer') {
            return '<script src="/assets/app-fixtures.js"></script>';
        }
    },

And each fixture just saves a mapping of url to payload:

TEST.FIXTURES['mobilews/accounts'] = {
...

That way tests in consuming addons/apps can just access them globally.

With this code today and auto-import we can even import moment and this will Just Work™️

import moment from 'moment';
TEST.FIXTURES['mobilews/transactionform/fundsTransfer'] = {
...

If you interested in what errors I see, when I run the addon’s own test suite with embroider compat, I get

when I run ember t -s, and when I run ember t. There’s more than 3 tests in my suite but that’s all it runs/fails with.

ok, I figured out how to keep my old broccoli code for the time being…

The “an unsupported module was defined” error seemed to me like moment was being babel processed when it wasn’t expecting to. I saw in another addon that babel was skipped for moment as follows:

//ember-cli-build.js
    const { maybeEmbroider } = require('@embroider/test-setup');
    return maybeEmbroider(app, {
        skipBabel: [
            {
                package: 'mocha',
            },
            {
                package: 'chai',
            },
            {
                package: 'loupe',
            },
            {
                package: 'moment',
            },
            {
                package: 'moment-timezone',
            },
            {
                package: 'type-detect',
            },
            {
                package: 'deep-eql',
            },
        ],
    });

The other skipped stuff was a result of fixing similar test errors for these other packages. I’m not completely sure of the why at this point, and I don’t have to do this special stuff for all my addons with moment, but maybe because this is a test-support addon and does make some chai/mocha calls available to its consumers.