import { component, css, html } from '../../src/fudgel.js'; import { scopeStyle } from '../../src/component.js'; import { sandboxStyleRules } from '../../src/elements.js'; component('parent-element', { style: css` :host { background-color: blue; padding: 10px; display: block; } div { background-color: green; } `, template: html`
This should be green
`, }); component('child-element', { style: css` :host, a, b { background-color: white; padding: 10px; display: block; } div.red { background-color: red; } `, template: html`
This should be white
This should be red
`, }); describe('css', () => { beforeEach(() => { cy.mount(''); }); it('verifies the background colors', () => { cy.get('parent-element').should( 'have.css', 'background-color', 'rgb(0, 0, 255)' ); cy.get('parent-element div').should( 'have.css', 'background-color', 'rgb(0, 128, 0)' ); cy.get('child-element').should( 'have.css', 'background-color', 'rgb(255, 255, 255)' ); cy.get('child-element div.white').should( 'have.css', 'background-color', 'rgba(0, 0, 0, 0)' ); cy.get('child-element div.red').should( 'have.css', 'background-color', 'rgb(255, 0, 0)' ); }); }); component( 'test-style', { attr: ['scopeSupported', 'text', 'useShadow'], style: css` .box { border: 1px solid black; } `, template: html`
{{style}}
`, }, class { scopeSupported: string; style = ''; text: string; useShadow: string; onChange() { console.log({ text: this.text, useShadow: this.useShadow }); this.style = scopeStyle( this.text, 'custom-element', 'fudgel-123', this.useShadow === 'true' ); } } ); component( 'test-style-wrapper', { style: css` textarea { width: 100%; height: 5em; } `, template: html`

Light DOM. (#light)

Shadow DOM. (#shadow)

`, }, class { input?: HTMLTextAreaElement; text = ''; update() { this.text = this.input?.value; } } ); const tests = [ // These are strings that are changed into patterns, where single spaces // are replaced and can optionally match any number of spaces (including // 0), and double spaces must match at least one whitespace character. // // confirm: run the test in the browser when the styles are parsed and the // browser's cssText matches these patterns. One pattern per generated // rule. If the browser's CSS parser does not support some of the // CSS here, then the confirmation rule will fail and the test will // be skipped. Information about why the skipping happened is also // logged to the console. // light: light DOM version (scoped and :host is changed) // shadow: shadow DOM version (scoped) { id: '1', input: 'div { background-color: red; }', confirm: ['div { background-color: red; }'], light: 'custom-element div.fudgel-123 { background-color: red; }', shadow: 'div.fudgel-123 { background-color: red; }', }, { id: '2', input: ':host { background-color: blue; }', confirm: [':host { background-color: blue; }'], light: 'custom-element { background-color: blue; }', shadow: ':host { background-color: blue; }', }, { id: '3', input: '@media (max-width:720px){div{span{display:block;}}}', confirm: ['@media (max-width: 720px) { div { span { display: block; } } }'], light: '@media (max-width: 720px) { custom-element div.fudgel-123 { span.fudgel-123 { display: block; } } }', shadow: '@media (max-width: 720px) { div.fudgel-123 { span.fudgel-123 { display: block; } } }', }, { id: '4', input: 'a-b{width:100vw;}@media (max-width:940px){a-b{width: 50vw;}}', confirm: ['a-b { width: 100vw; }', '@media (max-width: 940px) { a-b { width: 50vw; } }'], light: 'custom-element a-b.fudgel-123 { width: 100vw; } @media (max-width: 940px) { custom-element a-b.fudgel-123 { width: 50vw; } }', shadow: 'a-b.fudgel-123 { width: 100vw; } @media (max-width: 940px) { a-b.fudgel-123 { width: 50vw; } }', }, ]; function makePattern(str: string) { return new RegExp( str .replace(/[.*+?^${}()|[\]\\]/g, '\\$&') .replace(/ /g, '[\\n\\r\\s]+') .replace(/ /g, '[\\n\\r\\s]*') ); } describe( 'scopeStyle', { defaultCommandTimeout: 200, }, () => { beforeEach(() => { cy.mount(''); }); for (const test of tests) { const confirm = test.confirm.map((input) => makePattern(input)); const rules = sandboxStyleRules(test.input); let allMatch = true; if ( rules.length !== confirm.length ) { console.log('skip css test', test.id); console.log('# of rules:', rules.length); continue; } // Verify the input was parsed correctly for (let i = 0; i < rules.length; i += 1) { if (!rules[i].cssText.match(confirm[i])) { allMatch = false; console.log('skip css test', test.id); console.log(`cssText[${i}]:`, JSON.stringify(rules[0].cssText)); console.log(`pattern[${i}]:`, makePattern(test.confirm[i])); break; } } if (!allMatch) { describe(`scopeStyle, test ${test.id} - failed to confirm`, () => {}); continue; } describe( `scopeStyle, test ${test.id}`, { defaultCommandTimeout: 200, }, () => { beforeEach(() => { cy.get('textarea').type(test.input, { delay: 0, parseSpecialCharSequences: false, }); }); it('writes correct styles', () => { cy.get('#light .result') .invoke('text') .should('match', makePattern(test.light)); cy.get('#shadow .result') .invoke('text') .should('match', makePattern(test.shadow)); }); } ); } } );