Repository navigation
Expand file tree
/
Copy pathpopupSandboxRichTextStyles.spec.ts
More file actions
107 lines (103 loc) · 5.48 KB
/
Copy pathpopupSandboxRichTextStyles.spec.ts
File metadata and controls
107 lines (103 loc) · 5.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import {expect} from '@playwright/test';
import {readFileSync} from 'fs';
import {resolve} from 'path';
import {test} from './workerContext';
// Roboto Serif and Merriweather are shipped only with `$serif-fonts` on (src/scss/variables.scss)
const SERIF_FONTS = /\$serif-fonts:\s*true\b/.test(
readFileSync(resolve(__dirname, '..', 'src', 'scss', 'variables.scss'), 'utf8')
);
const SERIF_FAMILIES = ['Roboto Serif', 'Merriweather'];
for(const options of [
{fontSize: 16, width: 400, rtl: false, legacyHeadings: false},
{fontSize: 20, width: 280, rtl: true, legacyHeadings: true}
]) test(`Instant View and rich messages use the editor content styles ${JSON.stringify(options)}`, async({page}) => {
const errors: string[] = [];
page.on('pageerror', error => errors.push(error.message));
page.on('console', message => {
if(message.type() === 'error' && message.text().startsWith('solid error')) errors.push(message.text());
});
await page.setViewportSize({width: 1440, height: 1000});
await page.goto('/?popups=1');
await page.waitForFunction(() => !!window.popupSandbox);
await page.evaluate(() => window.popupSandbox.ready());
await page.getByRole('button', {name: '◂ Hide', exact: true}).click();
const selectors = await page.evaluate(async options => {
const path = '/e2e/fixtures/richTextStyles.ts';
const {mountRichTextStyles} = await window.e2eImport(path);
return mountRichTextStyles(options).selectors as Record<string, string>;
}, options);
await expect.poll(() => page.evaluate(() => [...document.fonts]
.filter(font => font.status === 'loading')
.map(font => font.family))).toEqual([]);
await expect(page.locator('[data-rich-text-surface="message"] .code-code')).toHaveText('const value = 1;');
const snapshots = await page.evaluate(selectors => {
const properties = [
'font-family', 'font-size', 'font-weight', 'font-style', 'line-height', 'color',
'padding-top', 'padding-bottom', 'padding-left', 'padding-right',
'margin-top', 'margin-bottom', 'border-radius', 'border-top-width', 'border-top-color',
'text-align', 'background-color'
];
return Object.fromEntries(['editor', 'instant-view', 'message'].map(surface => {
const root = document.querySelector(`[data-rich-text-surface="${surface}"]`)!;
return [surface, Object.fromEntries(Object.entries(selectors).map(([name, selector]) => {
const element = root.querySelector(selector);
if(!element) return [name, null];
const style = getComputedStyle(element);
const bounds = element.getBoundingClientRect();
return [name, {
styles: Object.fromEntries(properties.map(property => [property, style.getPropertyValue(property)])),
width: bounds.width,
height: bounds.height
}];
}))];
}));
}, selectors);
await page.screenshot({path: test.info().outputPath('shared-rich-text-styles.png'), fullPage: true});
expect(errors).toEqual([]);
for(const surface of ['instant-view', 'message']) for(const name of Object.keys(selectors)) {
expect.soft(snapshots.editor[name], `editor: ${name}`).not.toBeNull();
expect.soft(snapshots[surface][name], `${surface}: ${name}`).not.toBeNull();
expect.soft(snapshots[surface][name]?.styles, `${surface}: ${name}`).toEqual(snapshots.editor[name]?.styles);
expect.soft(snapshots[surface][name]?.width, `${surface}: ${name} width`).toBeCloseTo(snapshots.editor[name]?.width, 0);
expect.soft(snapshots[surface][name]?.height, `${surface}: ${name} height`).toBeCloseTo(snapshots.editor[name]?.height, 0);
}
});
test('Roboto Serif retains language ranges in compiled CSS and loads Cyrillic', async({page}) => {
test.skip(!SERIF_FONTS, '$serif-fonts is off');
await page.goto('/?popups=1');
await page.waitForFunction(() => !!window.popupSandbox);
const result = await page.evaluate(async() => {
const faces = [...document.fonts].filter(font => font.family.replace(/"/g, '') === 'Roboto Serif');
await document.fonts.load('400 24px "Roboto Serif"', 'Привет');
return {ranges: faces.map(font => font.unicodeRange), loaded: faces.filter(font => font.status === 'loaded').map(font => font.unicodeRange)};
});
expect(result.ranges).toHaveLength(18);
expect(result.ranges).not.toContain('U+0-10FFFF');
expect(result.loaded.some(range => /U\+0?400-0?45F/i.test(range))).toBe(true);
});
test('with $serif-fonts off, neither serif web font is shipped', async({page}) => {
test.skip(SERIF_FONTS, '$serif-fonts is on');
await page.goto('/?popups=1');
await page.waitForFunction(() => !!window.popupSandbox);
expect(await page.evaluate((families) => [...document.fonts]
.map((font) => font.family.replace(/"/g, ''))
.filter((family) => families.includes(family)), SERIF_FAMILIES)).toEqual([]);
// and nothing stands in for them: italic text and headings are in the app's own font, as before
// the serif fonts, rather than in a system serif that reads as the fonts turned off
expect(await page.evaluate(() => {
const em = document.createElement('em');
em.textContent = 'italic';
document.body.append(em);
const style = getComputedStyle(document.documentElement);
const fonts = {
italic: getComputedStyle(em).fontFamily,
heading: style.getPropertyValue('--font-heading').trim(),
regular: style.getPropertyValue('--font-regular').trim()
};
em.remove();
return fonts;
})).toEqual(expect.objectContaining({
italic: expect.stringMatching(/^"?Roboto"?,/),
heading: expect.stringMatching(/^"?Roboto"?,/)
}));
});