Skip to content
This repository was archived by the owner on Jun 14, 2024. It is now read-only.
This repository was archived by the owner on Jun 14, 2024. It is now read-only.

web-test-runner integration with vite 3.0 #22

@diervo

Description

@diervo

Hi, I found this repo through a link on vitest and on google.

I was looking for the latest vite support (currently 3.x), but quickly realized the code was for the old version.
After hitting myself against the wall for some time, I develop an integration that works with the latest version.

In the spirit of OSS, rather than creating another npm package, I would love to help the maintainer in this repo with the package update if there is the willingness to do so.

For the record, if anyone wants to do the integration in the meantime, here is the code:

// vite-web-test-runner-plugin.js
import { createServer } from 'vite';
import { join, relative } from 'node:path';
import koaConnect from 'koa-connect';
import minimatch from 'minimatch';


/** @typedef { import('@web/test-runner').TestRunnerPlugin } RunnerPlugin */

/**
 * @return { RunnerPlugin }
*/
export default function viteWebTestRunnerPlugin({ testMatch, testRoot = process.cwd(), viteConfigFile } = {}) {
    let viteServer;
    let viteRoot;
    let relativeRoot;

    return {
        name: 'vite-wtr-plugin',
        async serverStart({ app, fileWatcher }) {
            viteServer = await createServer({
                clearScreen: true,
                server: { middlewareMode: true, hmr: false },
                appType: 'custom',
                configFile: viteConfigFile || join(testRoot, 'vite.config.ts')
            });

            viteRoot = viteServer.config.root;

            // This path represents the diff beween the test root and the vite root
            // viteRoot should always be a relative path from the root (ex. testRoot: /root/test vs viteRoot: /root/test/src/module)
            relativeRoot = `/${relative(testRoot, viteRoot)}`;

            // Allow vite to take over most requests
            app.use(koaConnect(viteServer.middlewares));

            // Vite is taking over the handling of URLs, hence we need to forward the watching to the runner
            viteServer.watcher.on('change', (...args) => fileWatcher.emit('change', ...args));

        },
        async transformImport({ source }) {
            const [absSource, ] = source.split('?'); // Remove the queryString otherwise vite will fail resolving
            const relativeSource = absSource.at(0) === '/' ? absSource.substring(1) : absSource;
            for (const match of testMatch) {
                if (minimatch(relativeSource, match)) {
                    const newPath = absSource.replace(relativeRoot, '');
                    return newPath;
                }
            }
        },
        async serverStop() {
            return viteServer.close();
        },
    }
}

Example usage:

// web-test-runner-config.js
import { jasmineTestRunnerConfig } from 'web-test-runner-jasmine';
import viteWebTestRunnerPlugin from './scripts/testing/vite-web-test-runner-plugin.mjs';

const testMatch = ['src/**/*.test.ts'];

export default {
    ...jasmineTestRunnerConfig(),
    files: testMatch,
    nodeResolve: true,
    plugins: [
        viteWebTestRunnerPlugin({ testMatch })
    ],
};

Also, if you want to use commands in WTR you have to tell vite to ignore that endpoint

//vite.config.ts
const webTestRunnerIgnore = (): Plugin => {
    return {
        name: 'web-dev-server',
        resolveId: (id): { external: boolean; id: string } | void => {
            // Vite should not transform the WebSocket route to allow WTR commands to function correctly
            if (id === '/__web-dev-server__web-socket.js') {
                return { external: true, id };
            }
        },
    };
};

export default defineConfig({
  plugins: [webTestRunnerIgnore()]
});

My 2cents: If you are using vite and a web-component framework like lit, using web-test-runner is a superior testing approach rather than using any synthetic DOM implementation like JSDOM or HappyDOM.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions