Skip to content

Commit 76d2b57

Browse files
feat: add option to support animations (#555)
1 parent f49bda4 commit 76d2b57

File tree

4 files changed

+109
-3
lines changed

4 files changed

+109
-3
lines changed

packages/main/src/index.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ interface EvaluatorConfig {
2020
afterEach?: string;
2121
afterAll?: string;
2222
};
23+
allowAnimations?: boolean;
2324
loadEnzyme?: boolean;
2425
}
2526

@@ -53,7 +54,15 @@ export class FCCTestRunner {
5354
}
5455

5556
async createTestRunner(
56-
{ source, type, code, assetPath, hooks, loadEnzyme }: EvaluatorConfig,
57+
{
58+
source,
59+
type,
60+
code,
61+
assetPath,
62+
hooks,
63+
loadEnzyme,
64+
allowAnimations,
65+
}: EvaluatorConfig,
5766
{ timeout }: RunnerConfig = { timeout: 20000 },
5867
) {
5968
let testRunner: DOMTestRunner | WorkerTestRunner | null = null;
@@ -82,7 +91,10 @@ export class FCCTestRunner {
8291
break;
8392
}
8493

85-
await testRunner.init({ code, source, loadEnzyme, hooks }, timeout);
94+
await testRunner.init(
95+
{ code, source, loadEnzyme, hooks, allowAnimations },
96+
timeout,
97+
);
8698

8799
return testRunner;
88100
}

packages/main/src/test-runner.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,24 @@ const hideFrame = (iframe: HTMLIFrameElement) => {
9191
iframe.style.visibility = "hidden";
9292
};
9393

94+
const hideAllowingAnimations = (iframe: HTMLIFrameElement) => {
95+
iframe.style.width = "0px";
96+
iframe.style.height = "0px";
97+
iframe.style.opacity = "0";
98+
iframe.style.pointerEvents = "none";
99+
};
100+
101+
const resetCSS = (iframe: HTMLIFrameElement) => {
102+
iframe.style.position = "";
103+
iframe.style.left = "";
104+
iframe.style.top = "";
105+
iframe.style.visibility = "";
106+
iframe.style.width = "";
107+
iframe.style.height = "";
108+
iframe.style.opacity = "";
109+
iframe.style.pointerEvents = "";
110+
};
111+
94112
export class DOMTestRunner implements Runner {
95113
#testEvaluator: HTMLIFrameElement;
96114
#script: string;
@@ -101,7 +119,6 @@ export class DOMTestRunner implements Runner {
101119
iframe.sandbox.add("allow-scripts", "allow-forms");
102120
iframe.allow = "autoplay";
103121
iframe.id = "test-frame";
104-
hideFrame(iframe);
105122

106123
const scriptUrl = getFullAssetPath(assetPath) + script;
107124
const scriptHTML = `<script id='${TEST_EVALUATOR_SCRIPT_ID}' src='${scriptUrl}'></script>`;
@@ -165,6 +182,17 @@ ${this.#script}
165182
${hooksScript}
166183
${opts.source}`;
167184

185+
resetCSS(this.#testEvaluator);
186+
// Whether or not animations will run depends on the browser. By default, at
187+
// time of writing, Firefox allows animations in offscreen iframes, while
188+
// Chrome does not. If this option is set, we try and allow animations by
189+
// making the frame tiny but visible.
190+
if (opts.allowAnimations) {
191+
hideAllowingAnimations(this.#testEvaluator);
192+
} else {
193+
hideFrame(this.#testEvaluator);
194+
}
195+
168196
document.body.appendChild(this.#testEvaluator);
169197
await isReady;
170198

packages/shared/src/interfaces/test-evaluator.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export interface InitTestFrameOptions {
4141
afterEach?: string;
4242
afterAll?: string;
4343
};
44+
allowAnimations?: boolean;
4445
}
4546

4647
export interface InitWorkerOptions {

packages/tests/integration-tests/index.test.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,35 @@ const getFive = () => 5;
849849
});
850850
});
851851

852+
it("should use a different approach to hide the iframe when using allowAnimations", async () => {
853+
await page.evaluate(async () => {
854+
await window.FCCTestRunner.createTestRunner({
855+
type: "dom",
856+
allowAnimations: true,
857+
});
858+
});
859+
860+
const iframe = await page.$("iframe");
861+
const style = await iframe?.evaluate((iframe) => {
862+
const style = window.getComputedStyle(iframe);
863+
return {
864+
width: style.width,
865+
height: style.height,
866+
opacity: style.opacity,
867+
pointerEvents: style.pointerEvents,
868+
visbility: style.visibility,
869+
};
870+
});
871+
872+
expect(style).toEqual({
873+
width: "0px",
874+
height: "0px",
875+
opacity: "0",
876+
pointerEvents: "none",
877+
visbility: "visible", // This confirms that the default style has been reverted
878+
});
879+
});
880+
852881
it("should layout the iframe correctly", async () => {
853882
const source = `<body>
854883
indented text
@@ -1264,6 +1293,42 @@ checkBtn.click();
12641293

12651294
expect(result).toEqual([{ pass: true }, { pass: true }]);
12661295
});
1296+
1297+
it("should be possible to test CSS transitions", async () => {
1298+
const source = `<style>
1299+
#box {
1300+
width: 100px;
1301+
transition: width 0.1s;
1302+
}
1303+
#box.expanded {
1304+
width: 200px;
1305+
}
1306+
</style>
1307+
<div id="box"></div>`;
1308+
1309+
const result = await page.evaluate(async (source) => {
1310+
const runner = await window.FCCTestRunner.createTestRunner({
1311+
source,
1312+
type: "dom",
1313+
allowAnimations: true,
1314+
});
1315+
1316+
return runner.runTest(`
1317+
const box = document.getElementById('box');
1318+
box.classList.add('expanded');
1319+
1320+
// Wait for the transition to complete
1321+
await new Promise((resolve) => {
1322+
box.addEventListener('transitionend', resolve, { once: true });
1323+
});
1324+
1325+
const computedStyle = window.getComputedStyle(box);
1326+
assert.equal(computedStyle.width, '200px');
1327+
`);
1328+
}, source);
1329+
1330+
expect(result).toEqual({ pass: true });
1331+
});
12671332
});
12681333

12691334
describe("Javascript evaluator", () => {

0 commit comments

Comments
 (0)