File size: 3,151 Bytes
1477a90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Code generated by @openmeter/typespec-typescript. DO NOT EDIT.

import fetchMock from '@fetch-mock/vitest'
import { beforeEach, describe, expect, it } from 'vitest'
import { Client, funcs } from '../src/index.js'

const meter = {
  id: '01ARZ3NDEKTSV4RRFFQ69G5FAV',
  name: 'API calls',
  key: 'api_calls',
  aggregation: 'count',
  event_type: 'api-request',
  created_at: '2024-01-01T00:00:00Z',
  updated_at: '2024-01-01T00:00:00Z',
}

beforeEach(() => {
  fetchMock.mockReset()
})

function client() {
  return new Client({
    baseUrl: 'https://eu.api.konghq.com/v3',
    apiKey: 'k',
    fetch: fetchMock.fetchHandler,
  })
}

function mockList() {
  fetchMock.route('*', {
    body: { data: [meter], meta: { page: { number: 1, size: 10, total: 1 } } },
    headers: { 'Content-Type': 'application/json' },
  })
}

function lastQuery(): URLSearchParams {
  return new URL(fetchMock.callHistory.lastCall()!.url).searchParams
}

describe('listMeters query serialization', () => {
  it('encodes page as a deep object', async () => {
    mockList()
    await funcs.listMeters(client(), { page: { size: 10, number: 2 } })
    const q = lastQuery()
    expect(q.get('page[size]')).toBe('10')
    expect(q.get('page[number]')).toBe('2')
  })

  it('encodes a scalar filter', async () => {
    mockList()
    await funcs.listMeters(client(), { filter: { key: 'm' } })
    expect(lastQuery().get('filter[key]')).toBe('m')
  })

  it('encodes a nested filter operand as a deep object', async () => {
    mockList()
    await funcs.listMeters(client(), { filter: { key: { eq: 'foo' } } })
    expect(lastQuery().get('filter[key][eq]')).toBe('foo')
  })

  it('comma-joins array operands into a single parameter', async () => {
    mockList()
    await funcs.listMeters(client(), {
      filter: { key: { oeq: ['a', 'b', 'c'] } },
    })
    const q = lastQuery()
    expect(q.getAll('filter[key][oeq]')).toHaveLength(1)
    expect(q.get('filter[key][oeq]')).toBe('a,b,c')
  })

  it('serializes sort as a plain string, snake-ifying the field name', async () => {
    mockList()
    await funcs.listMeters(client(), {
      sort: { by: 'createdAt', order: 'desc' },
    })
    const q = lastQuery()
    expect(q.get('sort')).toBe('created_at desc')
    expect(q.get('sort[by]')).toBeNull()
  })

  it('omits sort order when ascending is implied', async () => {
    mockList()
    await funcs.listMeters(client(), { sort: { by: 'name' } })
    expect(lastQuery().get('sort')).toBe('name')
  })
})

describe('responses are mapped to the camelCase shape', () => {
  it('camelizes known fields and drops fields not in the schema', async () => {
    fetchMock.route('*', {
      body: { ...meter, brand_new_field: 'dropped' },
      headers: { 'Content-Type': 'application/json' },
    })
    const result = await funcs.getMeter(client(), { meterId: 'm' })
    expect(result.ok).toBe(true)
    expect(result.value).toMatchObject({
      id: meter.id,
      eventType: meter.event_type,
      createdAt: new Date(meter.created_at),
    })
    expect('event_type' in result.value!).toBe(false)
    expect('brand_new_field' in result.value!).toBe(false)
  })
})