@@ -73,6 +73,76 @@ def self.disable_animations
7373 session . execute_script ( DISABLE_ANIMATIONS_SCRIPT )
7474 end
7575
76+ DEFAULT_NORMALIZE_CSS = <<~CSS
77+ /* Kill animations and transitions */
78+ *, *::before, *::after {
79+ animation-duration: 0s !important;
80+ animation-delay: 0s !important;
81+ animation-iteration-count: 1 !important;
82+ transition-duration: 0s !important;
83+ transition-delay: 0s !important;
84+ scroll-behavior: auto !important;
85+ }
86+
87+ /* Standardize font rendering */
88+ * {
89+ -webkit-font-smoothing: antialiased !important;
90+ -moz-osx-font-smoothing: grayscale !important;
91+ text-rendering: geometricPrecision !important;
92+ }
93+
94+ /* Neutralize inputs and dynamic artifacts */
95+ * { caret-color: transparent !important; }
96+ input[type="number"]::-webkit-inner-spin-button,
97+ input[type="number"]::-webkit-outer-spin-button {
98+ -webkit-appearance: none !important;
99+ }
100+
101+ /* Hide OS-specific scrollbars */
102+ ::-webkit-scrollbar { display: none !important; }
103+ * { scrollbar-width: none !important; -ms-overflow-style: none !important; }
104+ CSS
105+
106+ def self . normalize_css ( css = nil )
107+ css ||= DEFAULT_NORMALIZE_CSS
108+
109+ session . execute_script ( <<~JS , css )
110+ (function(cssText) {
111+ if (!document.getElementById('csdNormalizeStyle')) {
112+ let style = document.createElement('style');
113+ style.setAttribute('id', 'csdNormalizeStyle');
114+ style.textContent = cssText;
115+ document.head.appendChild(style);
116+ }
117+ })(arguments[0]);
118+ JS
119+ end
120+
121+ def self . inject_custom_stylesheets ( stylesheets )
122+ Array ( stylesheets ) . each_with_index do |css , index |
123+ inject_stylesheet ( css , "csdCustomStyle#{ index } " )
124+ end
125+ end
126+
127+ def self . inject_custom_scripts ( scripts )
128+ Array ( scripts ) . each do |script |
129+ session . execute_script ( script )
130+ end
131+ end
132+
133+ def self . inject_stylesheet ( css , element_id )
134+ session . execute_script ( <<~JS , css , element_id )
135+ (function(cssText, styleId) {
136+ if (!document.getElementById(styleId)) {
137+ let style = document.createElement('style');
138+ style.setAttribute('id', styleId);
139+ style.textContent = cssText;
140+ document.head.appendChild(style);
141+ }
142+ })(arguments[0], arguments[1]);
143+ JS
144+ end
145+
76146 FIND_ACTIVE_ELEMENT_SCRIPT = <<~JS
77147 function activeElement(){
78148 const ae = document.activeElement;
@@ -113,6 +183,17 @@ def self.pending_image_to_load
113183 BrowserHelpers . session . evaluate_script ( IMAGE_WAIT_SCRIPT )
114184 end
115185
186+ FONTS_READY_SCRIPT = <<~JS
187+ (function() {
188+ if (!document.fonts) return true;
189+ return document.fonts.status === "loaded";
190+ })();
191+ JS
192+
193+ def self . fonts_ready?
194+ BrowserHelpers . session . evaluate_script ( FONTS_READY_SCRIPT )
195+ end
196+
116197 def self . current_capybara_driver_class
117198 session . driver . class
118199 end
0 commit comments