Unit Testing a cloudflare worker with HTMLRewriter fails as its undefined

I have a test to test my cloudflare worker that looks like this:

const workerScript = fs.readFileSync(
    path.resolve(__dirname, '../pkg-prd/worker.js'),
    'utf8'
);

describe('worker unit test', function () {
    // this.timeout(60000);
    let worker;

    beforeEach(() => {
        worker = new Cloudworker(workerScript, {
            bindings: {
                HTMLRewriter
            },
        });
    });

    it('tests requests and responses', async () => {
        const request = new Cloudworker.Request('https://www.example.com/pathname')
        const response = await worker.dispatch(request);
        console.log(response);
        // const body = await response.json();
        expect(response.status).to.eql(200);
        // expect(body).to.eql({message: 'Hello mocha!'});
    });
});

In my worker I do something like this:

 const response = await fetch(BASE_URL, request);
        const modifiedResponse = new Response(response.body, response);

        // Remove the webflow badge
        class ElementHandler {
            element(element) {
                element.append('<style type="text/css">body .w-webflow-badge {display: none!important}</style>', {html: true})
            }
        }
        console.log(3);

        return new HTMLRewriter()
            .on('head', new ElementHandler()).transform(modifiedResponse);

Now when i run my test I get this error message:

  ● worker unit test › tests requests and responses

TypeError: Cannot read property 'transform' of undefined

  at evalmachine.<anonymous>:1:1364
  at FetchEvent.respondWith (node_modules/@dollarshaveclub/cloudworker/lib/cloudworker.js:39:17)

What seems to be wrong?

HTMLRewriter i created looks like this:

function HTMLRewriter() {
    const elementHandler = {};

    const on = (selector, handler) => {
        if (handler && handler.element) {
            if (!elementHandler[selector]) {
                elementHandler[selector] = [];
            }
            elementHandler[selector].push(handler.element.bind(handler));
        }
    };

    const transform = async response => {
        const tempResponse = response.clone();

        const doc = HTMLParser.parse(await tempResponse.text());
        Object.keys(elementHandler).forEach(selector => {
            const el = doc.querySelector(selector);
            if (el) {
                elementHandler[selector].map(callback => {
                    callback(new _Element(el));
                });
            }
        });

        return new Response(doc.toString(), response);
    };

    return {
        on,
        transform
    };
}

Cloudworker is unfortunately not actively maintained at the moment and is lacking support for the HTMLRewriter, as can be seen here.

Are there any other alternatives?

Why don’t you use the new wrangler dev command? It should work just as if it was deployed but it’s tunneled only to your localhost.

2 Likes