# Instructions

- Following Playwright test failed.
- Explain why, be concise, respect Playwright best practices.
- Provide a snippet of code with the fix, if possible.

# Test info

- Name: tests/ui/voters-count.spec.ts >> /api/voters/count >> only GET is allowed
- Location: tests/ui/voters-count.spec.ts:48:7

# Error details

```
Error: apiRequestContext.fetch: connect ECONNREFUSED 10.1.105.22:80
Call log:
  - → POST http://10.1.105.22/api/voters/count?q=state:VT
    - user-agent: Playwright/1.64.1 (x64; ubuntu 22.04) node/20.9 CI/1
    - accept: */*
    - accept-encoding: gzip,deflate,br
    - Content-Type: application/json
    - content-length: 33

```

# Test source

```ts
  1  | import { test, expect, type APIRequestContext } from '@playwright/test';
  2  | 
  3  | /*
  4  |  * /api/voters/count is the one public window onto the premium electinfo-voters index (nginx.conf): the bare total for
  5  |  * the homepage and /voters/. Until sites#495 it forwarded the query string and body to OpenSearch _count, so anyone
  6  |  * could count voters matching any Lucene query (a name + ZIP + birth date says whether that person is on the file).
  7  |  * Every request must get the same total, whatever it carries. Aggregate filters only here, never personal data.
  8  |  */
  9  | 
  10 | const FILTERS = [
  11 |   '?q=state:VT',
  12 |   '?q=state:VT&q=state:WY',
  13 |   '?q=',
  14 |   '?source=%7B%22query%22%3A%7B%22term%22%3A%7B%22state%22%3A%22VT%22%7D%7D%7D&source_content_type=application/json',
  15 |   '?terminate_after=1',
  16 | ];
  17 | 
  18 | async function total(request: APIRequestContext, query = ''): Promise<{ status: number; count?: number }> {
  19 |   const res = await request.get(`/api/voters/count${query}`, { maxRedirects: 0 });
  20 |   if (res.status() !== 200) return { status: res.status() };
  21 |   const body = await res.json() as { count?: number };
  22 |   return { status: 200, count: body.count };
  23 | }
  24 | 
  25 | test.describe('/api/voters/count', () => {
  26 |   test('a query string never changes the total', async ({ request }) => {
  27 |     const bare = await total(request);
  28 |     // The CI test pod may not reach OpenSearch; the method checks below still run there.
  29 |     test.skip(bare.status !== 200, `bare count answered ${bare.status}`);
  30 |     expect(bare.count).toBeGreaterThan(1_000_000);
  31 |     for (const query of FILTERS) {
  32 |       expect(await total(request, query), query).toEqual(bare);
  33 |     }
  34 |   });
  35 | 
  36 |   test('a GET body never changes the total', async ({ request }) => {
  37 |     const bare = await total(request);
  38 |     test.skip(bare.status !== 200, `bare count answered ${bare.status}`);
  39 |     const res = await request.fetch('/api/voters/count', {
  40 |       method: 'GET',
  41 |       headers: { 'Content-Type': 'application/json' },
  42 |       data: { query: { term: { state: 'VT' } } },
  43 |     });
  44 |     expect(res.status()).toBe(200);
  45 |     expect((await res.json() as { count?: number }).count).toBe(bare.count);
  46 |   });
  47 | 
  48 |   test('only GET is allowed', async ({ request }) => {
  49 |     for (const method of ['POST', 'PUT', 'DELETE', 'PATCH']) {
> 50 |       const res = await request.fetch('/api/voters/count?q=state:VT', {
     |                                 ^ Error: apiRequestContext.fetch: connect ECONNREFUSED 10.1.105.22:80
  51 |         method,
  52 |         headers: { 'Content-Type': 'application/json' },
  53 |         data: { query: { term: { state: 'VT' } } },
  54 |       });
  55 |       expect(res.status(), method).toBe(403);
  56 |     }
  57 |   });
  58 | 
  59 |   test('other spellings do not reach OpenSearch', async ({ request }) => {
  60 |     // Traefik answers 400 for some encoded forms on the front door; nginx answers 404.
  61 |     for (const path of ['/api/voters/count/', '/api/voters/count/?q=state:VT', '/api/voters/count;q=state:VT', '/API/voters/count?q=state:VT']) {
  62 |       const res = await request.get(path, { maxRedirects: 0 });
  63 |       expect([400, 404], `${path}: ${res.status()}`).toContain(res.status());
  64 |     }
  65 |   });
  66 | });
  67 | 
```