How can I make jest support importing HTML file inside TS files?
Asked Answered
F

1

6

I have a project that has some script to build typescript web-component in it (here). I use rollup and typescript to build my web-components and my web-component file is like this:

import HTML from './project-build-info.html';
import CSS from './project-build-info.scss';
export class ProjectBuildInfoWebComponent extends HTMLElement {
    elements:ElementsObject;
    constructor() {
        super();
        this.initWebComponent();
    }
    initWebComponent() {
        const shadowRoot = this.attachShadow({ mode: 'open' });     
        const html = `<style>${CSS}</style>` + '\n' + HTML;
        const element = document.createElement('template');
        element.innerHTML = html;
        shadowRoot.appendChild(element.content.cloneNode(true));
    }
}

As you can see I write my wc HTML in separated file and import it and put it in my dom tree and they are all worked perfectly. But when I try to write test in jest with ts-jest it stuck in HTML file import line and says you must enable jsx with babel, ... but they are not jsx and I just want to import them as pure string like what rollup-plugin-html package do in my official build process. The thing is I don't want to mock my HTML with some default value and I need real text value of my imported HTML.

Currently I try to many ways like using jest-transform-stub, jest-raw-loader as transform & moduleNameMapper. Transform does nothing and setting moduleNameMapper will pass the import line error but HTML is undefined in value in actual test. I also try to write custom transformer like this but still not work:

const fs = require('fs');

module.exports = {
  process(src, filename) {
    const content =  'module.exports = ' + JSON.stringify(fs.readFileSync(filename, 'utf8')) + ';';
    return content;
  },
};

Here is my jest config:

import path from "path";
import { jestAliasMaps } from "./config/path-aliases-config.js";
import { generalConfigServer } from "./config/general-config-server.js";
export default async () => {
    return {
        verbose: true,
        testEnvironment:'jsdom',
        transform: {
            //web component do not compile by babel so they must test with ts
            '^(?!.*web-components).*\.(js|jsx|tsx|ts)?$': ['babel-jest', { configFile: path.join(generalConfigServer.basePath, 'config', 'babel.config.json') }],
            '^.*web-components.*\.(js|jsx|tsx|ts)?$': ['ts-jest', { tsconfig: path.join(generalConfigServer.basePath, 'tsconfig-modules.json' ) ,useESM:true}],
            ".*\\.html$":path.join(generalConfigServer.basePath,'command','test','mocks','html-transform.cjs'),
        },
        moduleNameMapper: {
            // '.*\\.(css|less|styl|scss|sass)$': path.join(generalConfigServer.basePath, 'command', 'test', 'mocks', 'style-mocks.js'),
            '.*\\.(css|less|styl|scss|sass)$': ['babel-jest', { configFile: path.join(generalConfigServer.basePath, 'config', 'babel.config.json') }],
            '.*\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
            path.join(generalConfigServer.basePath, 'command', 'test', 'mocks', 'media-mocks.js'),
            ".*\\.html$": path.join(generalConfigServer.basePath,'command','test','mocks','html-transform.cjs'),
            // ".*\\.(htm|html)$": 'identity-obj-proxy',
            ...jestAliasMaps,
        },
        setupFiles: ['raf/polyfill'],
        globals: {
            NODE_ENV: "test"
        },
        injectGlobals: false
    };
};
Fizzy answered 23/3 at 2:8 Comment(0)
H
1

Please note here that the transformer should return an object with code property.

if you write your transformer like this:

import path from "path";
import fs from "fs";

function process(sourceText, sourcePath, options) {
  return {
    code: `module.exports = \`${fs.readFileSync(sourcePath)}\`;`,
  };
}

const transformer = {
  process,
};

export default transformer;

it should load the HTML file contents just fine.

Hearse answered 27/3 at 10:41 Comment(2)
thank you I learned a lot from your response but FYI first I need to move ".*\\.html$" transformer to the top, then I need to use npx jest --clearCache but after all imported HTML is still undefined. when I debug the transformer everything works fine and it returns a string value with the HTML code module.exports = `<div ...` but in my ts module the value of HTML is still undefinedFizzy
I even try this: kulshekhar.github.io/ts-jest/docs/getting-started/options/… but still did not workFizzy

© 2022 - 2024 — McMap. All rights reserved.