From 253fcf18da1716307deac6e621022b703ed52673 Mon Sep 17 00:00:00 2001 From: zzzz Date: Thu, 17 Dec 2020 05:40:37 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20keep=20the=20order=20of=20cssRul?= =?UTF-8?q?es=20for=20styled-component=20rebuilding=20(#1161)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Zack Zeng --- .../dynamicAppend/__tests__/common.test.ts | 58 +++++++++++++++++++ src/sandbox/patchers/dynamicAppend/common.ts | 3 +- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/sandbox/patchers/dynamicAppend/__tests__/common.test.ts diff --git a/src/sandbox/patchers/dynamicAppend/__tests__/common.test.ts b/src/sandbox/patchers/dynamicAppend/__tests__/common.test.ts new file mode 100644 index 0000000..d058145 --- /dev/null +++ b/src/sandbox/patchers/dynamicAppend/__tests__/common.test.ts @@ -0,0 +1,58 @@ +import { rebuildCSSRules, recordStyledComponentsCSSRules, getStyledElementCSSRules } from '../common'; + +jest.mock('import-html-entry', () => ({ + execScripts: jest.fn(), +})); + +const cssRuleText1 = '#foo { color: red; }'; +const cssRuleText2 = 'span { font-weight: bold; }'; + +const createStyleElement = () => { + document.body.innerHTML = ''; + return document.getElementById('style-under-test') as HTMLStyleElement; +}; + +beforeEach(() => { + document.body.innerHTML = ''; +}); + +test('should record Styled-Component CSS Rules correctly', () => { + const styleElement = createStyleElement(); + const cssStyleSheet = styleElement.sheet; + cssStyleSheet?.insertRule(cssRuleText1); + cssStyleSheet?.insertRule(cssRuleText2); + + recordStyledComponentsCSSRules([styleElement]); + + const cssRules: CSSRuleList | undefined = getStyledElementCSSRules(styleElement); + expect(cssRules).toBeDefined(); + expect(cssRules?.length).toEqual(2); + expect((cssStyleSheet?.cssRules[0] as CSSStyleRule).selectorText).toEqual('span'); + expect((cssStyleSheet?.cssRules[1] as CSSStyleRule).selectorText).toEqual('#foo'); +}); + +test('should rebuild Styled-Component CSS Rules in the correct order', () => { + const styleElement = createStyleElement(); + const cssStyleSheet = styleElement.sheet; + cssStyleSheet?.insertRule(cssRuleText1); + cssStyleSheet?.insertRule(cssRuleText2); + + recordStyledComponentsCSSRules([styleElement]); + + expect((cssStyleSheet?.cssRules[0] as CSSStyleRule).selectorText).toEqual('span'); + expect((cssStyleSheet?.cssRules[1] as CSSStyleRule).selectorText).toEqual('#foo'); + + // Set sheet to be writiable so we can overwrite the value for sheet + Object.defineProperty(window.HTMLStyleElement.prototype, 'sheet', { + writable: true, + value: {}, + }); + // @ts-ignore + styleElement.sheet = new CSSStyleSheet(); + rebuildCSSRules([styleElement], () => true); + + expect(styleElement.sheet.cssRules.length).toEqual(2); + // Verify that the order of the styles is the same as the recorded ones + expect((cssStyleSheet?.cssRules[0] as CSSStyleRule).selectorText).toEqual('span'); + expect((cssStyleSheet?.cssRules[1] as CSSStyleRule).selectorText).toEqual('#foo'); +}); diff --git a/src/sandbox/patchers/dynamicAppend/common.ts b/src/sandbox/patchers/dynamicAppend/common.ts index 85542a1..42c117d 100644 --- a/src/sandbox/patchers/dynamicAppend/common.ts +++ b/src/sandbox/patchers/dynamicAppend/common.ts @@ -369,7 +369,8 @@ export function rebuildCSSRules( // eslint-disable-next-line no-plusplus for (let i = 0; i < cssRules.length; i++) { const cssRule = cssRules[i]; - (stylesheetElement.sheet as CSSStyleSheet).insertRule(cssRule.cssText); + const cssStyleSheetElement = stylesheetElement.sheet as CSSStyleSheet; + cssStyleSheetElement.insertRule(cssRule.cssText, cssStyleSheetElement.cssRules.length); } } }