-
Notifications
You must be signed in to change notification settings - Fork 1
π§ͺ test(font-fidelity): add unit tests for FontFidelity module #142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,3 +53,123 @@ test("splitCssFontFamilies", async () => { | |
| assert.deepEqual(splitCssFontFamilies(""), []); | ||
| assert.deepEqual(splitCssFontFamilies(" "), []); | ||
| }); | ||
|
|
||
| test("FontFidelity constructor options", async () => { | ||
| const { FontFidelity, POWERPOINT_FONT_FALLBACKS } = await loadFontFidelityModule(); | ||
|
|
||
| const customFallbacks = { 'Custom Font': ['Fallback1', 'sans-serif'] }; | ||
| const fidelity = new FontFidelity({ fontFallbacks: customFallbacks }); | ||
|
|
||
| const fallbacks = fidelity.getRendererFallbacks(); | ||
| assert.deepEqual(fallbacks['Custom Font'], ['Fallback1', 'sans-serif']); | ||
| assert.deepEqual(fallbacks['Aptos'], POWERPOINT_FONT_FALLBACKS['Aptos']); | ||
| }); | ||
|
|
||
| test("FontFidelity.prototype.measureText delegates to measureTextFn and safely fallbacks", async () => { | ||
| const { FontFidelity } = await loadFontFidelityModule(); | ||
|
|
||
| const mockMeasureText = (text, fontFamily, fontSizePx) => { | ||
| if (text === "invalid") return NaN; | ||
| if (text === "negative") return -1; | ||
| return text.length * fontSizePx; | ||
| }; | ||
|
|
||
| const fidelity = new FontFidelity({ | ||
| measureText: mockMeasureText, | ||
| isFontAvailable: () => true | ||
| }); | ||
|
|
||
| // Delegates properly | ||
| assert.equal(fidelity.measureText("hello", "Arial", 10), 50); | ||
|
|
||
| // Safely falls back on NaN | ||
| assert.equal(fidelity.measureText("invalid", "Arial", 10), 7 * 10 * 0.6); | ||
|
|
||
| // Safely falls back on negative | ||
| assert.equal(fidelity.measureText("negative", "Arial", 10), 8 * 10 * 0.6); | ||
| }); | ||
|
|
||
| class MockElement { | ||
| constructor(tagName) { | ||
| this.tagName = tagName; | ||
| this.attributes = new Map(); | ||
| this.children = []; | ||
| } | ||
| getAttribute(name) { | ||
| return this.attributes.get(name) || null; | ||
| } | ||
| setAttribute(name, value) { | ||
| this.attributes.set(name, value); | ||
| } | ||
| getElementsByTagName(name) { | ||
| let results = []; | ||
| for (const child of this.children) { | ||
| if (name === '*' || child.tagName === name) { | ||
| results.push(child); | ||
| } | ||
| results.push(...child.getElementsByTagName(name)); | ||
| } | ||
| return results; | ||
| } | ||
| } | ||
|
|
||
| test("FontFidelity.prototype.applySvgSubstitutions substitutes fonts and styles", async () => { | ||
| const { FontFidelity } = await loadFontFidelityModule(); | ||
|
|
||
| const fidelity = new FontFidelity({ | ||
| isFontAvailable: (font) => font.toLowerCase() === "arial" || font.toLowerCase() === "sans-serif" | ||
| }); | ||
|
|
||
| const svg = new MockElement("svg"); | ||
| svg.setAttribute("font-family", "Unknown Font"); | ||
|
|
||
| const textElement = new MockElement("text"); | ||
| textElement.setAttribute("style", "font-family: 'Another Unknown'; color: red;"); | ||
| svg.children.push(textElement); | ||
|
|
||
| const substitutions = fidelity.applySvgSubstitutions(svg); | ||
|
|
||
| // Check svg attributes | ||
| assert.equal(svg.getAttribute("data-native-powerpoint-requested-font"), "Unknown Font"); | ||
| assert.equal(svg.getAttribute("data-native-powerpoint-font-substitution"), "Arial"); | ||
| assert.ok(svg.getAttribute("font-family").includes("Arial")); | ||
|
|
||
| // Check text element style | ||
| assert.equal(textElement.getAttribute("data-native-powerpoint-requested-font"), "Another Unknown"); | ||
| assert.equal(textElement.getAttribute("data-native-powerpoint-font-substitution"), "Arial"); | ||
| assert.ok(textElement.getAttribute("style").includes("font-family:")); | ||
| assert.ok(textElement.getAttribute("style").includes("color: red;")); | ||
|
|
||
| // Check substitutions array | ||
| assert.equal(substitutions.length, 2); | ||
| // Sorted by requested font string | ||
| assert.equal(substitutions[0].requested, "Another Unknown"); | ||
| assert.equal(substitutions[0].substitute, "Arial"); | ||
| assert.equal(substitutions[1].requested, "Unknown Font"); | ||
| assert.equal(substitutions[1].substitute, "Arial"); | ||
| }); | ||
|
|
||
| test("FontFidelity caches isFontAvailableFn results", async () => { | ||
| const { FontFidelity } = await loadFontFidelityModule(); | ||
|
|
||
| let callCount = 0; | ||
| const mockIsFontAvailable = (font) => { | ||
| callCount++; | ||
| return true; | ||
| }; | ||
|
|
||
| const fidelity = new FontFidelity({ | ||
| isFontAvailable: mockIsFontAvailable | ||
| }); | ||
|
|
||
| fidelity.measureText("hello", "CustomCacheFont", 10); | ||
| const callsAfterFirst = callCount; | ||
|
|
||
| // Should not trigger again | ||
| fidelity.measureText("hello", "CustomCacheFont", 10); | ||
| assert.equal(callCount, callsAfterFirst); | ||
|
|
||
| // Same font with quotes and mixed casing should hit cache | ||
| fidelity.measureText("hello", "'customcachefont'", 10); | ||
| assert.equal(callCount, callsAfterFirst); | ||
|
Comment on lines
+168
to
+174
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
These repeated calls only exercise Useful? React with πΒ / π. |
||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The input style already contains both
font-family:andcolor: red;, so these assertions still pass ifapplySvgSubstitutions()stops rewriting inline font families altogether. Assert that the resulting style contains the resolvedArialstack (or the exact expected style) so this test detects the regression it is intended to cover.Useful? React with πΒ / π.