@afixt/test-utils 1.1.8 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,19 +9,18 @@ const { test, expect } = require('@playwright/test');
9
9
  const path = require('path');
10
10
 
11
11
  test.describe('CSS Pseudo-element Support', () => {
12
- test.beforeEach(async ({ page }) => {
13
- // Load the test fixture HTML
14
- const fixturePath = path.join(__dirname, 'fixtures', 'css-pseudo-elements.html');
15
- await page.goto(`file://${fixturePath}`);
16
-
17
- // Inject the functions into the page
18
- await page.addScriptTag({
19
- content: `
20
- // Fix getComputedStyle usage and make it work in browser
12
+ test.beforeEach(async ({ page }) => {
13
+ // Load the test fixture HTML
14
+ const fixturePath = path.join(__dirname, 'fixtures', 'css-pseudo-elements.html');
15
+ await page.goto(`file://${fixturePath}`);
16
+
17
+ // Inject the functions into the page
18
+ await page.addScriptTag({
19
+ content: `
20
+ // getGeneratedContent: includes textContent alongside pseudo-element content
21
21
  function getGeneratedContent(el) {
22
22
  if (!el) return false;
23
23
 
24
- // Get pseudo-element content properly
25
24
  const beforeStyle = window.getComputedStyle(el, '::before');
26
25
  const afterStyle = window.getComputedStyle(el, '::after');
27
26
 
@@ -29,11 +28,9 @@ test.describe('CSS Pseudo-element Support', () => {
29
28
  let after = afterStyle.getPropertyValue('content') || '';
30
29
  const inner = el.textContent || '';
31
30
 
32
- // Remove quotes from CSS content values
33
31
  before = before.replace(/^["']|["']$/g, '');
34
32
  after = after.replace(/^["']|["']$/g, '');
35
33
 
36
- // Filter out 'none' values
37
34
  if (before === 'none') before = '';
38
35
  if (after === 'none') after = '';
39
36
 
@@ -41,115 +38,251 @@ test.describe('CSS Pseudo-element Support', () => {
41
38
  return result || false;
42
39
  }
43
40
 
41
+ // extractMeaningfulContent: helper for getCSSGeneratedContent
42
+ function extractMeaningfulContent(rawValue) {
43
+ if (!rawValue || rawValue === 'none' || rawValue === 'normal') {
44
+ return false;
45
+ }
46
+ let cleaned = rawValue.replace(/^["'](.*)["']$/, '$1');
47
+ cleaned = cleaned.trim();
48
+ return cleaned.length > 0 ? cleaned : false;
49
+ }
50
+
51
+ // getCSSGeneratedContent: only checks ::before and ::after pseudo-elements
52
+ function getCSSGeneratedContent(el, pseudoElement) {
53
+ if (pseudoElement === undefined) pseudoElement = 'both';
54
+ if (!el) return false;
55
+
56
+ let content = '';
57
+
58
+ try {
59
+ if (pseudoElement === 'before' || pseudoElement === 'both') {
60
+ const style = window.getComputedStyle(el, '::before');
61
+ const before = style.getPropertyValue('content');
62
+ const cleanBefore = extractMeaningfulContent(before);
63
+ if (cleanBefore) {
64
+ content += cleanBefore;
65
+ }
66
+ }
67
+
68
+ if (pseudoElement === 'after' || pseudoElement === 'both') {
69
+ const style = window.getComputedStyle(el, '::after');
70
+ const after = style.getPropertyValue('content');
71
+ const cleanAfter = extractMeaningfulContent(after);
72
+ if (cleanAfter) {
73
+ content += (content ? ' ' : '') + cleanAfter;
74
+ }
75
+ }
76
+ } catch (e) {
77
+ return false;
78
+ }
79
+
80
+ return content ? content.trim() : false;
81
+ }
82
+
44
83
  function hasCSSGeneratedContent(el) {
45
84
  if (!el) return false;
46
- const content = getGeneratedContent(el);
85
+ const content = getCSSGeneratedContent(el);
47
86
  return content !== false;
48
87
  }
49
88
 
50
89
  // Make functions globally available
51
90
  window.getGeneratedContent = getGeneratedContent;
91
+ window.getCSSGeneratedContent = getCSSGeneratedContent;
52
92
  window.hasCSSGeneratedContent = hasCSSGeneratedContent;
53
- `
93
+ `,
94
+ });
54
95
  });
55
- });
56
96
 
57
- test.describe('getGeneratedContent', () => {
58
- test('should return ::before content when present', async ({ page }) => {
59
- const result = await page.evaluate(() => {
60
- const element = document.getElementById('with-before');
61
- return window.getGeneratedContent(element);
62
- });
97
+ test.describe('getGeneratedContent', () => {
98
+ test('should return ::before content when present', async ({ page }) => {
99
+ const result = await page.evaluate(() => {
100
+ const element = document.getElementById('with-before');
101
+ return window.getGeneratedContent(element);
102
+ });
63
103
 
64
- expect(result).toContain('Before Content');
65
- });
104
+ expect(result).toContain('Before Content');
105
+ });
66
106
 
67
- test('should return ::after content when present', async ({ page }) => {
68
- const result = await page.evaluate(() => {
69
- const element = document.getElementById('with-after');
70
- return window.getGeneratedContent(element);
71
- });
107
+ test('should return ::after content when present', async ({ page }) => {
108
+ const result = await page.evaluate(() => {
109
+ const element = document.getElementById('with-after');
110
+ return window.getGeneratedContent(element);
111
+ });
72
112
 
73
- expect(result).toContain('After Content');
74
- });
113
+ expect(result).toContain('After Content');
114
+ });
75
115
 
76
- test('should combine ::before, text content, and ::after', async ({ page }) => {
77
- const result = await page.evaluate(() => {
78
- const element = document.getElementById('with-both');
79
- return window.getGeneratedContent(element);
80
- });
116
+ test('should combine ::before, text content, and ::after', async ({ page }) => {
117
+ const result = await page.evaluate(() => {
118
+ const element = document.getElementById('with-both');
119
+ return window.getGeneratedContent(element);
120
+ });
81
121
 
82
- expect(result).toContain('Before');
83
- expect(result).toContain('Text Content');
84
- expect(result).toContain('After');
85
- });
122
+ expect(result).toContain('Before');
123
+ expect(result).toContain('Text Content');
124
+ expect(result).toContain('After');
125
+ });
86
126
 
87
- test('should handle quoted content values in CSS', async ({ page }) => {
88
- const result = await page.evaluate(() => {
89
- const element = document.getElementById('with-quotes');
90
- return window.getGeneratedContent(element);
91
- });
127
+ test('should handle quoted content values in CSS', async ({ page }) => {
128
+ const result = await page.evaluate(() => {
129
+ const element = document.getElementById('with-quotes');
130
+ return window.getGeneratedContent(element);
131
+ });
92
132
 
93
- expect(result).toBeTruthy();
94
- expect(result).toContain('Quoted');
95
- });
133
+ expect(result).toBeTruthy();
134
+ expect(result).toContain('Quoted');
135
+ });
96
136
 
97
- test('should handle CSS content with special characters', async ({ page }) => {
98
- const result = await page.evaluate(() => {
99
- const element = document.getElementById('with-special-chars');
100
- return window.getGeneratedContent(element);
101
- });
137
+ test('should handle CSS content with special characters', async ({ page }) => {
138
+ const result = await page.evaluate(() => {
139
+ const element = document.getElementById('with-special-chars');
140
+ return window.getGeneratedContent(element);
141
+ });
102
142
 
103
- expect(result).toBeTruthy();
104
- });
143
+ expect(result).toBeTruthy();
144
+ });
105
145
 
106
- test('should trim whitespace from the combined result', async ({ page }) => {
107
- const result = await page.evaluate(() => {
108
- const element = document.getElementById('with-whitespace');
109
- return window.getGeneratedContent(element);
110
- });
146
+ test('should trim whitespace from the combined result', async ({ page }) => {
147
+ const result = await page.evaluate(() => {
148
+ const element = document.getElementById('with-whitespace');
149
+ return window.getGeneratedContent(element);
150
+ });
111
151
 
112
- expect(result).toBeTruthy();
113
- expect(result.startsWith(' ')).toBe(false);
114
- expect(result.endsWith(' ')).toBe(false);
115
- });
152
+ expect(result).toBeTruthy();
153
+ expect(result.startsWith(' ')).toBe(false);
154
+ expect(result.endsWith(' ')).toBe(false);
155
+ });
116
156
 
117
- test('should handle nested elements with generated content', async ({ page }) => {
118
- const result = await page.evaluate(() => {
119
- const element = document.getElementById('nested-content');
120
- return window.getGeneratedContent(element);
121
- });
157
+ test('should handle nested elements with generated content', async ({ page }) => {
158
+ const result = await page.evaluate(() => {
159
+ const element = document.getElementById('nested-content');
160
+ return window.getGeneratedContent(element);
161
+ });
122
162
 
123
- expect(result).toBeTruthy();
124
- });
163
+ expect(result).toBeTruthy();
164
+ });
125
165
 
126
- test('should handle content with HTML entities in CSS', async ({ page }) => {
127
- const result = await page.evaluate(() => {
128
- const element = document.getElementById('with-entities');
129
- return window.getGeneratedContent(element);
130
- });
166
+ test('should handle content with HTML entities in CSS', async ({ page }) => {
167
+ const result = await page.evaluate(() => {
168
+ const element = document.getElementById('with-entities');
169
+ return window.getGeneratedContent(element);
170
+ });
131
171
 
132
- expect(result).toBeTruthy();
172
+ expect(result).toBeTruthy();
173
+ });
133
174
  });
134
- });
135
175
 
136
- test.describe('hasCSSGeneratedContent', () => {
137
- test('should correctly identify elements with ::before content', async ({ page }) => {
138
- const result = await page.evaluate(() => {
139
- const element = document.getElementById('with-before');
140
- return window.hasCSSGeneratedContent(element);
141
- });
176
+ test.describe('getCSSGeneratedContent', () => {
177
+ test('should get ::before content', async ({ page }) => {
178
+ const result = await page.evaluate(() => {
179
+ const element = document.getElementById('with-before');
180
+ return window.getCSSGeneratedContent(element, 'before');
181
+ });
182
+
183
+ expect(result).toBe('Before Content');
184
+ });
185
+
186
+ test('should get ::after content', async ({ page }) => {
187
+ const result = await page.evaluate(() => {
188
+ const element = document.getElementById('with-after');
189
+ return window.getCSSGeneratedContent(element, 'after');
190
+ });
142
191
 
143
- expect(result).toBe(true);
192
+ expect(result).toBe('After Content');
193
+ });
194
+
195
+ test('should get both ::before and ::after content', async ({ page }) => {
196
+ const result = await page.evaluate(() => {
197
+ const element = document.getElementById('with-both');
198
+ return window.getCSSGeneratedContent(element);
199
+ });
200
+
201
+ expect(result).toContain('Before');
202
+ expect(result).toContain('After');
203
+ });
204
+
205
+ test('should handle quoted content', async ({ page }) => {
206
+ const result = await page.evaluate(() => {
207
+ const element = document.getElementById('with-quotes');
208
+ return window.getCSSGeneratedContent(element, 'before');
209
+ });
210
+
211
+ expect(result).toBeTruthy();
212
+ expect(result).toContain('Quoted');
213
+ });
214
+
215
+ test('should handle URL content', async ({ page }) => {
216
+ const result = await page.evaluate(() => {
217
+ const element = document.getElementById('url-content');
218
+ return window.getCSSGeneratedContent(element, 'before');
219
+ });
220
+
221
+ expect(result).toBeTruthy();
222
+ });
223
+
224
+ test('should default pseudoElement to both', async ({ page }) => {
225
+ const result = await page.evaluate(() => {
226
+ const element = document.getElementById('with-before');
227
+ return window.getCSSGeneratedContent(element);
228
+ });
229
+
230
+ expect(result).toBe('Before Content');
231
+ });
232
+
233
+ test('should return false for empty content', async ({ page }) => {
234
+ const result = await page.evaluate(() => {
235
+ const element = document.getElementById('empty-content');
236
+ return window.getCSSGeneratedContent(element);
237
+ });
238
+
239
+ expect(result).toBe(false);
240
+ });
241
+
242
+ test('should return false for content: none', async ({ page }) => {
243
+ const result = await page.evaluate(() => {
244
+ const element = document.getElementById('no-content');
245
+ return window.getCSSGeneratedContent(element);
246
+ });
247
+
248
+ expect(result).toBe(false);
249
+ });
250
+
251
+ test('should return false for null element', async ({ page }) => {
252
+ const result = await page.evaluate(() => {
253
+ return window.getCSSGeneratedContent(null);
254
+ });
255
+
256
+ expect(result).toBe(false);
257
+ });
258
+
259
+ test('should return false for elements with no pseudo-element styles', async ({ page }) => {
260
+ const result = await page.evaluate(() => {
261
+ const element = document.getElementById('plain-div');
262
+ return window.getCSSGeneratedContent(element);
263
+ });
264
+
265
+ expect(result).toBe(false);
266
+ });
144
267
  });
145
268
 
146
- test('should correctly identify elements with ::after content', async ({ page }) => {
147
- const result = await page.evaluate(() => {
148
- const element = document.getElementById('with-after');
149
- return window.hasCSSGeneratedContent(element);
150
- });
269
+ test.describe('hasCSSGeneratedContent', () => {
270
+ test('should correctly identify elements with ::before content', async ({ page }) => {
271
+ const result = await page.evaluate(() => {
272
+ const element = document.getElementById('with-before');
273
+ return window.hasCSSGeneratedContent(element);
274
+ });
275
+
276
+ expect(result).toBe(true);
277
+ });
278
+
279
+ test('should correctly identify elements with ::after content', async ({ page }) => {
280
+ const result = await page.evaluate(() => {
281
+ const element = document.getElementById('with-after');
282
+ return window.hasCSSGeneratedContent(element);
283
+ });
151
284
 
152
- expect(result).toBe(true);
285
+ expect(result).toBe(true);
286
+ });
153
287
  });
154
- });
155
288
  });
@@ -52,6 +52,10 @@
52
52
  #no-content::before {
53
53
  content: none;
54
54
  }
55
+
56
+ #url-content::before {
57
+ content: url('data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7');
58
+ }
55
59
  </style>
56
60
  </head>
57
61
  <body>
@@ -67,6 +71,8 @@
67
71
  <div id="with-entities">Entities</div>
68
72
  <div id="empty-content">Empty</div>
69
73
  <div id="no-content">None</div>
74
+ <div id="url-content">URL Content</div>
75
+ <div id="plain-div">Plain div no pseudo-elements</div>
70
76
 
71
77
  <!-- Load the functions we need directly in the page -->
72
78
  <script type="module">