I'm building a small JS class that holds a <canvas> element and uses it to draw some images dynamically. Particularly those images have both background (fill) and text.
After doing this, I wanted to write some unit tests around this to ensure that, given some input, the generated output (as a base64 string) is always the same. That means that if I want to generate an image with a pink background and white text, the generated output is always a pink image with white text, and the dimensions are the same. In other words, the base64 encoded strings are equal.
I can run these tests locally and they pass (MacOS) but they fail on my Jenkins integration job (runs on Linux). That's because the image's font is slightly different. After reading a lot on this, I suspect this is because the fonts are implemented differently across different OSs.
See the images:
Expected, obtained locally in MacOS:
Actual, obtained in Linux:
You can see that the actual image I'm obtaining is a little bit taller than the expected (bottom padding below the text is smaller). Current font I'm using is "44px Arial"
See code:
Implementation
generateImage(backgroundColor, fontColor = "#000000") {
if (backgroundColor) {
this.drawBackgroundWithColor(backgroundColor);
}
this.drawTexOverBackground("Text to draw", X_POSITION, Y_POSITION, fontColor, "44px Arial");
return this.getCurrentCanvasAsBase64String();
}
drawBackgroundWithColor(backgroundColor){
if (backgroundColor) {
const context = this.getCanvasContext();
context.save();
context.fillStyle = backgroundColor;
context.fillRect(0, 0, this.width, this.height);
context.restore();
}
}
drawTexOverBackground(text, x, y, hexColor, font = this.font) {
const context = this.getCanvasContext();
context.save();
context.font = font;
context.textBaseline = "top";
context.fillStyle = hexColor;
context.fillText(text, x, y);
context.restore();
}
Unit test:
it('should create a basic pink background with black text', () => {
const backgroundGenerator = new ImageGenerator();
const createdBackground = backgroundGenerator.generateImage("#FFC0CB");
assert.equal(createdBackground, expectedTransparentImageWithText);
});
Being expectedTransparentImageWithText a global variable of the module that holds the string base64 value I expect and obtained in MacOS.
I must clarify that for unit testing this I'm using the canvas npm module which runs on a node and as the docs say it "implements that API as closely as possible" (referring to the Canvas browser API). I suspect that that's the reason why the fonts differ. I also got here and found that fonts DO differ between operating systems, and there's no 100% compatibility among them.
Is there any suggestion you can give me to unit test this better and take into account the fonts a well? Right now I'm only testing images without text, so I can avoid running into the explained scenario, but of course, not the best thing to do.

