browser-commander 0.5.3 → 0.5.4

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.4
4
+
5
+ ### Patch Changes
6
+
7
+ - e9043cc: Fix normalizeSelector to validate input type and reject arrays
8
+
9
+ When `normalizeSelector` receives an invalid type (array, number, or non-text-selector object), it now returns `null` with a warning instead of returning the invalid value unchanged.
10
+
11
+ This prevents downstream `querySelectorAll` errors with invalid selector syntax (like trailing commas when arrays are accidentally passed).
12
+
13
+ Fixes #23
14
+
3
15
  ## 0.5.3
4
16
 
5
17
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser-commander",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "Universal browser automation library that supports both Playwright and Puppeteer with a unified API",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -162,6 +162,25 @@ export async function normalizeSelector(options = {}) {
162
162
  throw new Error('selector is required in options');
163
163
  }
164
164
 
165
+ // DEFENSIVE: Validate selector type - must be string or Puppeteer text selector object
166
+ // Arrays and other invalid types should be rejected to prevent downstream querySelectorAll errors
167
+ if (Array.isArray(selector)) {
168
+ console.warn(
169
+ `normalizeSelector received invalid selector type: array. Expected string or text selector object.`
170
+ );
171
+ return null;
172
+ }
173
+
174
+ if (
175
+ typeof selector !== 'string' &&
176
+ (typeof selector !== 'object' || !selector._isPuppeteerTextSelector)
177
+ ) {
178
+ console.warn(
179
+ `normalizeSelector received invalid selector type: ${typeof selector}. Expected string or text selector object.`
180
+ );
181
+ return null;
182
+ }
183
+
165
184
  // Handle Playwright text selectors (strings containing :has-text or :text-is)
166
185
  // These are valid for Playwright's locator API but NOT for document.querySelectorAll
167
186
  if (
@@ -267,6 +286,8 @@ export async function normalizeSelector(options = {}) {
267
286
  }
268
287
  }
269
288
 
289
+ // This line should be unreachable after validation, but kept as a safeguard
290
+ // istanbul ignore next
270
291
  return selector;
271
292
  }
272
293
 
@@ -207,11 +207,41 @@ describe('selectors', () => {
207
207
  assert.strictEqual(result, 'button');
208
208
  });
209
209
 
210
- it('should return non-text-selector object unchanged', async () => {
210
+ it('should return null for invalid object selector', async () => {
211
211
  const page = createMockPlaywrightPage();
212
212
  const obj = { someKey: 'value' };
213
213
  const result = await normalizeSelector({ page, selector: obj });
214
- assert.strictEqual(result, obj);
214
+ assert.strictEqual(result, null);
215
+ });
216
+
217
+ it('should return null for array selector', async () => {
218
+ const page = createMockPlaywrightPage();
219
+ const arr = ['[data-qa="test"]', []];
220
+ const result = await normalizeSelector({ page, selector: arr });
221
+ assert.strictEqual(result, null);
222
+ });
223
+
224
+ it('should return null for number selector', async () => {
225
+ const page = createMockPlaywrightPage();
226
+ const result = await normalizeSelector({ page, selector: 123 });
227
+ assert.strictEqual(result, null);
228
+ });
229
+
230
+ it('should accept valid Puppeteer text selector object', async () => {
231
+ const page = createMockPuppeteerPage();
232
+ page.evaluate = async () => '[data-qa="test"]';
233
+ const textSelector = {
234
+ _isPuppeteerTextSelector: true,
235
+ baseSelector: 'button',
236
+ text: 'Click me',
237
+ exact: false,
238
+ };
239
+ const result = await normalizeSelector({
240
+ page,
241
+ engine: 'puppeteer',
242
+ selector: textSelector,
243
+ });
244
+ assert.strictEqual(result, '[data-qa="test"]');
215
245
  });
216
246
  });
217
247