Skip to content

Conversation

Smrtnyk
Copy link
Contributor

@Smrtnyk Smrtnyk commented Apr 21, 2025

How it works

  • "test:vitest" still runs tests in jsdom
  • "test:vitest:coverage" still runs tests in jsdom

new scripts added

  • "test:vitest:chromium" runs same set of tests but in chromium using vitest browser environment

There is no magic in here
just some small adaptations needed for tests to run in both environments now
I will comment those inline

Copy link

codesandbox bot commented Apr 21, 2025

Review or Edit in CodeSandbox

Open the branch in Web EditorVS CodeInsiders

Open Preview

@@ -25,3 +25,4 @@ e2e/test-report/
e2e/test-results/
**/.cache/
docs/
__screenshots__
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added this to gitignore because now if test fails there is a screenshot folder so you can see how page looked like at the time of failure
for example, if your test had canvas appended to the document, you can see how canvas looked like when it failed the test


describe('Pattern', () => {
const IMG_SRC = 'greyfloral.png';
const IMG_SRC = isJSDOM() ? 'greyfloral.png' : GrayFloralImage;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in old qunit these links had isNode and they fetched images differently

now in browser mode we need to import image directly that vite resolves internaly, where in jsdom it is as it was before

this change was made for few more test files

Copy link
Contributor

Build Stats

file / KB (diff) bundled minified
fabric 913.867 (0) 301.234 (0)

@@ -130,15 +132,15 @@ describe('Canvas', () => {
const canvas = new Canvas(undefined, {
allowTouchScrolling: false,
});
const touch = {
const touch = new Touch({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to add this polyfill for jsdom, because these plain objects passed to TouchEvent did not work in chromium

@@ -675,7 +675,8 @@ describe('fabric.Parser', () => {
it('getCssRule', () => {
expect(getCSSRules).toBeDefined();
const rules: Record<PropertyKey, any> = {};
const doc = getFabricDocument();
// NOTE: We need to use a new fresh document here because vitest in browser mode already adds some stylesheets which pollutes the test
const doc = getFabricDocument().implementation.createHTMLDocument('');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in vitest browser mode there are already some stylesheets imported to testing frame by vitest, so I had to get clean doc implementation here
works fine in both jsdom and chromium

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test i think is wrong.
The parser and getCSSRules is used for SVGdocuments, i think here to test the function we assumed that one document is like anohter.
getFabricDocument return the document that holds the javascript from fabricjs.
We need a generic document, if we have a generic api that works in both cases like new Document() or new XLMDocument() (since is svg) we should prefer that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is then something for a separate PR as a todo?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What i meant is, without having to create it from the fabric document itself.
Is there any global we can invoke that give us a new document, empty?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can do the same thing with document.implementation.createHTMLDocument('');

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes i just cheked document.implementation is just a normal browser thing, i just never used it.


describe('getRandomInt', () => {
beforeEach(() => {
global.Math.random = vi.fn(() => 0.1);
globalThis.Math.random = vi.fn(() => 0.1);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switched to globalThis for interop between jsdom and browser

@@ -0,0 +1,14 @@
declare module '*.gif' {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is needed for imports of images to be recognized when we import them for browser mode tests

@Smrtnyk
Copy link
Contributor Author

Smrtnyk commented Apr 21, 2025

if you end up wanting this @asturur you will need to write new workflow that executes "test:vitest:chromium" script
but will need to run npx playwright install before to fetch the chromium

additionally, if you adopt this and decide to have it, I can work on adding firefox and webkit as well

@Smrtnyk Smrtnyk closed this Apr 21, 2025
@Smrtnyk Smrtnyk reopened this Apr 21, 2025
@Smrtnyk Smrtnyk force-pushed the feat(tests)-browser-mode branch from dffcfbd to 46517f5 Compare April 21, 2025 19:36
@asturur
Copy link
Member

asturur commented Apr 21, 2025

For sure this is the natural extension of what we had before.
And i think is good to have, or at least to try if it maintainable.

In the long run this may seems unnecessary because if unit tests are written by the book, you mock most o the things and test only your own code.

Is a bit different for visual tests in which you really want to test the output of the drawing functions.

As a maintainer doing this extra loops of tests keep me informed of different rounding methods between browser and node, difference in api that may happen between node-canvas and browser, in general if not extreme added maintainance i prefer to keep doing it.

I left a bunch of notes that do not preclude a merge, please see what you think about them

@asturur
Copy link
Member

asturur commented Apr 21, 2025

An additional improvement that can be done another time is that we export from fixtures functions that return the URL instead of returning the different url each time we need the image in a different file.
This will be more evident with visual tests.

@Smrtnyk
Copy link
Contributor Author

Smrtnyk commented Apr 21, 2025

For sure this is the natural extension of what we had before. And i think is good to have, or at least to try if it maintainable.

In the long run this may seems unnecessary because if unit tests are written by the book, you mock most o the things and test only your own code.

Is a bit different for visual tests in which you really want to test the output of the drawing functions.

As a maintainer doing this extra loops of tests keep me informed of different rounding methods between browser and node, difference in api that may happen between node-canvas and browser, in general if not extreme added maintainance i prefer to keep doing it.

I left a bunch of notes that do not preclude a merge, please see what you think about them

I agree with you with the concept of unit tests.

I noticed when I ran these same tests in webkit I already saw some numeric misalignement in few snapshots due to some precision, which showed difference between jsdom/chromium/webkit, not a lot but few tests did appear.
Also in firefox kerning was 13 in one snapshot where in jsdom, webkit and chromium is 12.

This does add maintenance burden a bit, but on other hand I see chromium more valuable source of testing reliability than jsdom. Chromium is the most used browser, and I assume most users of fabric are using it in browser and not in node env.

My point of this PR was done to demonstrate that vitest has excellent capabilities to run tests in browser as well and very fast and in an easy way.

If you decide to only stick with jsdom we can keep this out for now, and revive in the future if you decide to actually incorporate it, but maybe we could give a try for jsdom and chromium for now?

@asturur
Copy link
Member

asturur commented Apr 22, 2025

We do want to run tests in browsers. this is good

@asturur
Copy link
Member

asturur commented Apr 22, 2025

i ll try to add it to an action now

@asturur asturur merged commit 85b7551 into fabricjs:master Apr 22, 2025
15 checks passed
@Smrtnyk
Copy link
Contributor Author

Smrtnyk commented Apr 22, 2025

pls also let me know if I should work on webkit and firefox tests next?
they have some discrepancies so will need some minor adjustments as well to have it all stable across all browsers

@Smrtnyk Smrtnyk deleted the feat(tests)-browser-mode branch April 22, 2025 07:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants