@afixt/test-utils 1.3.0 → 2.0.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.
@@ -1,97 +1,98 @@
1
1
  /**
2
2
  * Tests for getGeneratedContent - designed for Vitest browser mode
3
- *
4
- * These tests are designed to work with the '--browser' flag, which uses a real browser
3
+ *
4
+ * These tests are designed to work with the '--browser' flag, which uses a real browser
5
5
  * environment to ensure proper testing of CSS pseudo-elements.
6
- *
6
+ *
7
7
  * Run with: npm run test -- getGeneratedContent --browser
8
8
  */
9
- import { describe, it, expect, beforeEach } from 'vitest';
9
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
10
10
  import { getGeneratedContent } from '../src/getGeneratedContent.js';
11
11
 
12
12
  // Helper to detect if we're running in a real browser or JSDOM
13
- const isJsdom = typeof window !== 'undefined' &&
14
- window.navigator &&
15
- /jsdom|node/i.test(window.navigator.userAgent);
13
+ const isJsdom =
14
+ typeof window !== 'undefined' &&
15
+ window.navigator &&
16
+ /jsdom|node/i.test(window.navigator.userAgent);
16
17
 
17
18
  describe('getGeneratedContent', () => {
18
- beforeEach(() => {
19
- document.body.innerHTML = '';
20
- // Remove any added stylesheets
21
- const styleElements = document.querySelectorAll('style');
22
- styleElements.forEach(style => style.remove());
23
- });
24
-
25
- // Helper function to create a stylesheet with CSS rules
26
- const addStyleToDocument = (cssRules) => {
27
- const styleElement = document.createElement('style');
28
- styleElement.textContent = cssRules;
29
- document.head.appendChild(styleElement);
30
- };
31
-
32
- // Basic tests that will pass in any environment
33
- describe('Basic functionality tests', () => {
34
- it('should return false for null or undefined elements', () => {
35
- expect(getGeneratedContent(null)).toBe(false);
36
- expect(getGeneratedContent(undefined)).toBe(false);
19
+ beforeEach(() => {
20
+ document.body.innerHTML = '';
21
+ // Remove any added stylesheets
22
+ const styleElements = document.querySelectorAll('style');
23
+ styleElements.forEach(style => style.remove());
37
24
  });
38
25
 
39
- it('should return element text content when no pseudo-elements exist', () => {
40
- // Arrange
41
- const element = document.createElement('div');
42
- element.textContent = 'Test content';
43
- document.body.appendChild(element);
44
-
45
- // Act
46
- const result = getGeneratedContent(element);
47
-
48
- // Assert
49
- expect(result).toBe('Test content');
50
- });
26
+ // Helper function to create a stylesheet with CSS rules
27
+ const addStyleToDocument = cssRules => {
28
+ const styleElement = document.createElement('style');
29
+ styleElement.textContent = cssRules;
30
+ document.head.appendChild(styleElement);
31
+ };
51
32
 
52
- it('should return false for empty elements with no generated content', () => {
53
- // Arrange
54
- const element = document.createElement('div');
55
- document.body.appendChild(element);
56
-
57
- // Act
58
- const result = getGeneratedContent(element);
59
-
60
- // Assert
61
- expect(result).toBe(false);
62
- });
33
+ // Basic tests that will pass in any environment
34
+ describe('Basic functionality tests', () => {
35
+ it('should return false for null or undefined elements', () => {
36
+ expect(getGeneratedContent(null)).toBe(false);
37
+ expect(getGeneratedContent(undefined)).toBe(false);
38
+ });
39
+
40
+ it('should return element text content when no pseudo-elements exist', () => {
41
+ // Arrange
42
+ const element = document.createElement('div');
43
+ element.textContent = 'Test content';
44
+ document.body.appendChild(element);
45
+
46
+ // Act
47
+ const result = getGeneratedContent(element);
48
+
49
+ // Assert
50
+ expect(result).toBe('Test content');
51
+ });
52
+
53
+ it('should return false for empty elements with no generated content', () => {
54
+ // Arrange
55
+ const element = document.createElement('div');
56
+ document.body.appendChild(element);
57
+
58
+ // Act
59
+ const result = getGeneratedContent(element);
60
+
61
+ // Assert
62
+ expect(result).toBe(false);
63
+ });
64
+
65
+ it('should handle elements with CSS but no content property', () => {
66
+ // Arrange
67
+ const element = document.createElement('div');
68
+ element.id = 'with-css-no-content';
69
+ element.textContent = 'Just text';
70
+ document.body.appendChild(element);
63
71
 
64
- it('should handle elements with CSS but no content property', () => {
65
- // Arrange
66
- const element = document.createElement('div');
67
- element.id = 'with-css-no-content';
68
- element.textContent = 'Just text';
69
- document.body.appendChild(element);
70
-
71
- // Add CSS rule without content property
72
- addStyleToDocument(`
72
+ // Add CSS rule without content property
73
+ addStyleToDocument(`
73
74
  #with-css-no-content {
74
75
  color: red;
75
76
  font-weight: bold;
76
77
  }
77
78
  `);
78
-
79
- // Act
80
- const result = getGeneratedContent(element);
81
-
82
- // Assert
83
- expect(result).toBe('Just text');
84
- });
85
-
86
- it('should handle empty string content in CSS', () => {
87
- // Arrange
88
- const element = document.createElement('div');
89
- element.id = 'empty-content';
90
- element.textContent = 'Main content';
91
- document.body.appendChild(element);
92
-
93
- // Add CSS rule with empty content
94
- addStyleToDocument(`
79
+
80
+ // Act
81
+ const result = getGeneratedContent(element);
82
+
83
+ // Assert
84
+ expect(result).toBe('Just text');
85
+ });
86
+
87
+ it('should handle empty string content in CSS', () => {
88
+ // Arrange
89
+ const element = document.createElement('div');
90
+ element.id = 'empty-content';
91
+ element.textContent = 'Main content';
92
+ document.body.appendChild(element);
93
+
94
+ // Add CSS rule with empty content
95
+ addStyleToDocument(`
95
96
  #empty-content::before {
96
97
  content: "";
97
98
  }
@@ -99,68 +100,131 @@ describe('getGeneratedContent', () => {
99
100
  content: "";
100
101
  }
101
102
  `);
102
-
103
- // Act
104
- const result = getGeneratedContent(element);
105
-
106
- // Assert
107
- expect(result).toBe('Main content');
103
+
104
+ // Act
105
+ const result = getGeneratedContent(element);
106
+
107
+ // Assert
108
+ expect(result).toBe('Main content');
109
+ });
108
110
  });
109
- });
110
-
111
- // Tests that need a real browser environment
112
- // These will be conditionally skipped in JSDOM
113
- describe('CSS Pseudo-element tests', () => {
114
- // For each test that requires CSS pseudo-elements, conditionally skip in JSDOM
115
- (isJsdom ? it.skip : it)('should return ::before content when present', () => {
116
- // Arrange
117
- const element = document.createElement('div');
118
- element.id = 'with-before';
119
- document.body.appendChild(element);
120
-
121
- // Add CSS rule for ::before content
122
- addStyleToDocument(`
111
+
112
+ describe('Delegation to getCSSGeneratedContent', () => {
113
+ // Mock window.getComputedStyle to support pseudo-element arguments in JSDOM
114
+ const mockGetComputedStyle = pseudoContentMap => {
115
+ const original = window.getComputedStyle;
116
+ window.getComputedStyle = vi.fn((el, pseudoElt) => {
117
+ if (pseudoElt) {
118
+ const key = pseudoElt.replace('::', '');
119
+ return {
120
+ getPropertyValue: prop => {
121
+ if (prop === 'content' && pseudoContentMap[key]) {
122
+ return `"${pseudoContentMap[key]}"`;
123
+ }
124
+ return '';
125
+ },
126
+ };
127
+ }
128
+ return original(el);
129
+ });
130
+ return () => {
131
+ window.getComputedStyle = original;
132
+ };
133
+ };
134
+
135
+ it('should include pseudo-element content from getCSSGeneratedContent', () => {
136
+ const element = document.createElement('div');
137
+ element.textContent = 'Inner text';
138
+ document.body.appendChild(element);
139
+
140
+ const restore = mockGetComputedStyle({ before: 'Before', after: 'After' });
141
+
142
+ const result = getGeneratedContent(element);
143
+ expect(result).toBe('Before Inner text After');
144
+
145
+ restore();
146
+ });
147
+
148
+ it('should handle only ::before content from getCSSGeneratedContent', () => {
149
+ const element = document.createElement('div');
150
+ element.textContent = 'Content';
151
+ document.body.appendChild(element);
152
+
153
+ const restore = mockGetComputedStyle({ before: 'Prefix' });
154
+
155
+ const result = getGeneratedContent(element);
156
+ expect(result).toBe('Prefix Content');
157
+
158
+ restore();
159
+ });
160
+
161
+ it('should handle only ::after content from getCSSGeneratedContent', () => {
162
+ const element = document.createElement('div');
163
+ element.textContent = 'Content';
164
+ document.body.appendChild(element);
165
+
166
+ const restore = mockGetComputedStyle({ after: 'Suffix' });
167
+
168
+ const result = getGeneratedContent(element);
169
+ expect(result).toBe('Content Suffix');
170
+
171
+ restore();
172
+ });
173
+ });
174
+
175
+ // Tests that need a real browser environment
176
+ // These will be conditionally skipped in JSDOM
177
+ describe('CSS Pseudo-element tests', () => {
178
+ // For each test that requires CSS pseudo-elements, conditionally skip in JSDOM
179
+ (isJsdom ? it.skip : it)('should return ::before content when present', () => {
180
+ // Arrange
181
+ const element = document.createElement('div');
182
+ element.id = 'with-before';
183
+ document.body.appendChild(element);
184
+
185
+ // Add CSS rule for ::before content
186
+ addStyleToDocument(`
123
187
  #with-before::before {
124
188
  content: "Before content";
125
189
  }
126
190
  `);
127
-
128
- // Act
129
- const result = getGeneratedContent(element);
130
-
131
- // Assert
132
- expect(result).toContain('Before content');
133
- });
134
191
 
135
- (isJsdom ? it.skip : it)('should return ::after content when present', () => {
136
- // Arrange
137
- const element = document.createElement('div');
138
- element.id = 'with-after';
139
- document.body.appendChild(element);
140
-
141
- // Add CSS rule for ::after content
142
- addStyleToDocument(`
192
+ // Act
193
+ const result = getGeneratedContent(element);
194
+
195
+ // Assert
196
+ expect(result).toContain('Before content');
197
+ });
198
+
199
+ (isJsdom ? it.skip : it)('should return ::after content when present', () => {
200
+ // Arrange
201
+ const element = document.createElement('div');
202
+ element.id = 'with-after';
203
+ document.body.appendChild(element);
204
+
205
+ // Add CSS rule for ::after content
206
+ addStyleToDocument(`
143
207
  #with-after::after {
144
208
  content: "After content";
145
209
  }
146
210
  `);
147
-
148
- // Act
149
- const result = getGeneratedContent(element);
150
-
151
- // Assert
152
- expect(result).toContain('After content');
153
- });
154
211
 
155
- (isJsdom ? it.skip : it)('should combine ::before, text content, and ::after', () => {
156
- // Arrange
157
- const element = document.createElement('div');
158
- element.id = 'with-all';
159
- element.textContent = 'Inner content';
160
- document.body.appendChild(element);
161
-
162
- // Add CSS rules for ::before and ::after
163
- addStyleToDocument(`
212
+ // Act
213
+ const result = getGeneratedContent(element);
214
+
215
+ // Assert
216
+ expect(result).toContain('After content');
217
+ });
218
+
219
+ (isJsdom ? it.skip : it)('should combine ::before, text content, and ::after', () => {
220
+ // Arrange
221
+ const element = document.createElement('div');
222
+ element.id = 'with-all';
223
+ element.textContent = 'Inner content';
224
+ document.body.appendChild(element);
225
+
226
+ // Add CSS rules for ::before and ::after
227
+ addStyleToDocument(`
164
228
  #with-all::before {
165
229
  content: "Before content";
166
230
  }
@@ -168,72 +232,72 @@ describe('getGeneratedContent', () => {
168
232
  content: "After content";
169
233
  }
170
234
  `);
171
-
172
- // Act
173
- const result = getGeneratedContent(element);
174
-
175
- // Assert - check that all parts are included in the result
176
- expect(result).toContain('Before content');
177
- expect(result).toContain('Inner content');
178
- expect(result).toContain('After content');
179
-
180
- // The combined string should have proper spacing
181
- expect(result).toBe('Before content Inner content After content');
182
- });
183
235
 
184
- (isJsdom ? it.skip : it)('should handle quoted content values in CSS', () => {
185
- // Arrange
186
- const element = document.createElement('div');
187
- element.id = 'with-quotes';
188
- document.body.appendChild(element);
189
-
190
- // Add CSS rule with quoted content
191
- addStyleToDocument(`
236
+ // Act
237
+ const result = getGeneratedContent(element);
238
+
239
+ // Assert - check that all parts are included in the result
240
+ expect(result).toContain('Before content');
241
+ expect(result).toContain('Inner content');
242
+ expect(result).toContain('After content');
243
+
244
+ // The combined string should have proper spacing
245
+ expect(result).toBe('Before content Inner content After content');
246
+ });
247
+
248
+ (isJsdom ? it.skip : it)('should handle quoted content values in CSS', () => {
249
+ // Arrange
250
+ const element = document.createElement('div');
251
+ element.id = 'with-quotes';
252
+ document.body.appendChild(element);
253
+
254
+ // Add CSS rule with quoted content
255
+ addStyleToDocument(`
192
256
  #with-quotes::before {
193
257
  content: '"Quoted content"';
194
258
  }
195
259
  `);
196
-
197
- // Act
198
- const result = getGeneratedContent(element);
199
-
200
- // Assert
201
- expect(result).toContain('"Quoted content"');
202
- });
203
260
 
204
- (isJsdom ? it.skip : it)('should handle CSS content with special characters', () => {
205
- // Arrange
206
- const element = document.createElement('div');
207
- element.id = 'with-special-chars';
208
- document.body.appendChild(element);
209
-
210
- // Add CSS rule with special characters
211
- addStyleToDocument(`
261
+ // Act
262
+ const result = getGeneratedContent(element);
263
+
264
+ // Assert
265
+ expect(result).toContain('"Quoted content"');
266
+ });
267
+
268
+ (isJsdom ? it.skip : it)('should handle CSS content with special characters', () => {
269
+ // Arrange
270
+ const element = document.createElement('div');
271
+ element.id = 'with-special-chars';
272
+ document.body.appendChild(element);
273
+
274
+ // Add CSS rule with special characters
275
+ addStyleToDocument(`
212
276
  #with-special-chars::before {
213
277
  content: "\\2022"; /* Unicode for bullet point */
214
278
  }
215
279
  `);
216
-
217
- // Act
218
- const result = getGeneratedContent(element);
219
-
220
- // Assert
221
- // In a real browser (with --browser flag), this will be a bullet point
222
- expect(result).not.toBe(false);
223
-
224
- // The exact value may depend on the browser, but it should be a bullet character
225
- expect(result).toMatch(/•|\\2022/);
226
- });
227
280
 
228
- (isJsdom ? it.skip : it)('should trim whitespace from the combined result', () => {
229
- // Arrange
230
- const element = document.createElement('div');
231
- element.id = 'trim-test';
232
- element.textContent = ' Inner content ';
233
- document.body.appendChild(element);
234
-
235
- // Add CSS rules with extra spaces
236
- addStyleToDocument(`
281
+ // Act
282
+ const result = getGeneratedContent(element);
283
+
284
+ // Assert
285
+ // In a real browser (with --browser flag), this will be a bullet point
286
+ expect(result).not.toBe(false);
287
+
288
+ // The exact value may depend on the browser, but it should be a bullet character
289
+ expect(result).toMatch(/•|\\2022/);
290
+ });
291
+
292
+ (isJsdom ? it.skip : it)('should trim whitespace from the combined result', () => {
293
+ // Arrange
294
+ const element = document.createElement('div');
295
+ element.id = 'trim-test';
296
+ element.textContent = ' Inner content ';
297
+ document.body.appendChild(element);
298
+
299
+ // Add CSS rules with extra spaces
300
+ addStyleToDocument(`
237
301
  #trim-test::before {
238
302
  content: " Before ";
239
303
  }
@@ -241,33 +305,33 @@ describe('getGeneratedContent', () => {
241
305
  content: " After ";
242
306
  }
243
307
  `);
244
-
245
- // Act
246
- const result = getGeneratedContent(element);
247
-
248
- // Assert - the result should be trimmed at the edges but preserve inner spaces
249
- expect(result).not.toMatch(/^\s+|\s+$/); // No leading/trailing whitespace
250
-
251
- // Check specific content is included
252
- expect(result).toContain('Before');
253
- expect(result).toContain('Inner content');
254
- expect(result).toContain('After');
255
- });
256
-
257
- (isJsdom ? it.skip : it)('should handle nested elements with generated content', () => {
258
- // Arrange
259
- const parent = document.createElement('div');
260
- parent.id = 'parent';
261
-
262
- const child = document.createElement('span');
263
- child.id = 'child';
264
- child.textContent = 'Child content';
265
-
266
- parent.appendChild(child);
267
- document.body.appendChild(parent);
268
-
269
- // Add CSS rules
270
- addStyleToDocument(`
308
+
309
+ // Act
310
+ const result = getGeneratedContent(element);
311
+
312
+ // Assert - the result should be trimmed at the edges but preserve inner spaces
313
+ expect(result).not.toMatch(/^\s+|\s+$/); // No leading/trailing whitespace
314
+
315
+ // Check specific content is included
316
+ expect(result).toContain('Before');
317
+ expect(result).toContain('Inner content');
318
+ expect(result).toContain('After');
319
+ });
320
+
321
+ (isJsdom ? it.skip : it)('should handle nested elements with generated content', () => {
322
+ // Arrange
323
+ const parent = document.createElement('div');
324
+ parent.id = 'parent';
325
+
326
+ const child = document.createElement('span');
327
+ child.id = 'child';
328
+ child.textContent = 'Child content';
329
+
330
+ parent.appendChild(child);
331
+ document.body.appendChild(parent);
332
+
333
+ // Add CSS rules
334
+ addStyleToDocument(`
271
335
  #parent::before {
272
336
  content: "Parent before";
273
337
  }
@@ -281,41 +345,41 @@ describe('getGeneratedContent', () => {
281
345
  content: "Parent after";
282
346
  }
283
347
  `);
284
-
285
- // Act
286
- const parentResult = getGeneratedContent(parent);
287
- const childResult = getGeneratedContent(child);
288
-
289
- // Assert
290
- expect(parentResult).toContain('Parent before');
291
- expect(parentResult).toContain('Child content');
292
- expect(parentResult).toContain('Parent after');
293
-
294
- expect(childResult).toContain('Child before');
295
- expect(childResult).toContain('Child content');
296
- expect(childResult).toContain('Child after');
297
- });
298
-
299
- (isJsdom ? it.skip : it)('should handle content with HTML entities in CSS', () => {
300
- // Arrange
301
- const element = document.createElement('div');
302
- element.id = 'with-entities';
303
- document.body.appendChild(element);
304
-
305
- // Add CSS rule with HTML entity
306
- addStyleToDocument(`
348
+
349
+ // Act
350
+ const parentResult = getGeneratedContent(parent);
351
+ const childResult = getGeneratedContent(child);
352
+
353
+ // Assert
354
+ expect(parentResult).toContain('Parent before');
355
+ expect(parentResult).toContain('Child content');
356
+ expect(parentResult).toContain('Parent after');
357
+
358
+ expect(childResult).toContain('Child before');
359
+ expect(childResult).toContain('Child content');
360
+ expect(childResult).toContain('Child after');
361
+ });
362
+
363
+ (isJsdom ? it.skip : it)('should handle content with HTML entities in CSS', () => {
364
+ // Arrange
365
+ const element = document.createElement('div');
366
+ element.id = 'with-entities';
367
+ document.body.appendChild(element);
368
+
369
+ // Add CSS rule with HTML entity
370
+ addStyleToDocument(`
307
371
  #with-entities::before {
308
372
  content: "\\00A9"; /* Copyright symbol */
309
373
  }
310
374
  `);
311
-
312
- // Act
313
- const result = getGeneratedContent(element);
314
-
315
- // Assert
316
- // In a real browser, this would be a copyright symbol
317
- expect(result).not.toBe(false);
318
- expect(result).toMatch(/©|\\00A9/);
375
+
376
+ // Act
377
+ const result = getGeneratedContent(element);
378
+
379
+ // Assert
380
+ // In a real browser, this would be a copyright symbol
381
+ expect(result).not.toBe(false);
382
+ expect(result).toMatch(/©|\\00A9/);
383
+ });
319
384
  });
320
- });
321
- });
385
+ });