Netflix / pollyjs

Record, Replay, and Stub HTTP Interactions.
https://netflix.github.io/pollyjs
Apache License 2.0
10.2k stars 350 forks source link

[Vitest] AWS SDK mocking request fail when ignoring headers: TypeError: Cannot delete property 'authorization' of #<Object> #495

Open andresgutgon opened 2 months ago

andresgutgon commented 2 months ago

Description

Hi, thanks for this tool looks super helpful. So far is going well I manage to setup Polly.js and Vitest when testing a AWS Endpoint that is accessed using AWS JS SDK.

The problem is when I try to obfuscate headers for security reasons.

Shareable Source

This is the relevant part

// ./src/tests/polly.js
import { Polly } from '@pollyjs/core'
import NodeHttpAdapter from '@pollyjs/adapter-node-http'
import FSPersister from '@pollyjs/persister-fs'
import { beforeAll, afterAll } from 'vitest'

Polly.register(NodeHttpAdapter)
Polly.register(FSPersister)
let polly: Polly

export default function useCassettes({
  cassetteName,
  excludedHeaders = [],
}: {
  cassetteName: string
  excludedHeaders?: string[]
}) {
  beforeAll(() => {
    polly = new Polly(cassetteName, {
      adapters: ['node-http'],
      persister: 'fs',
      persisterOptions: {
        fs: {
          recordingsDir: './tests/recordings',
        },
      },
      matchRequestsBy: {
        headers: false,
        order: false,
      },
    })

    polly.server.any().on('beforePersist', (req) => {
      if (excludedHeaders.length > 0) {
        // IT FAILS HERE 💥💥💥
        req.removeHeaders(excludedHeaders)
      }
    })
  })

  afterAll(async () => {
    await polly.stop()
  })
}

Then I use this useCassettes in my tests like this:

import { describe, it, expect } from 'vitest'
import createSecret from './createSecret'
import useCassettes from 'tests/polly'

describe('createSecret', () => {
  useCassettes({
    cassetteName: 'aws_secrets',
    excludedHeaders: ['authorization']
  })

  it.only('creates the secret in aws', async (ctx) => {
    const { workspace }  = await ctx.factories.createWorkspace({
      name: 'patata1'
    })

    const result = await createSecret({
      app: 'myApp',
      workspace,
    })

    expect(result?.successful).toBeTruthy()
  })
})

Error Message & Stack Trace

I'm getting the error when trying to modify the headers beforePersits

TypeError: Cannot delete property 'authorization' of #<Object>
 ❯ Object.set ../../node_modules/.pnpm/@pollyjs+core@6.0.6/node_modules/@pollyjs/core/src/utils/http-headers.js:17:23
 ❯ Proxy.setHeader ../../node_modules/.pnpm/@pollyjs+core@6.0.6/node_modules/@pollyjs/core/src/-private/http-base.js:18:5
 ❯ Proxy.removeHeader ../../node_modules/.pnpm/@pollyjs+core@6.0.6/node_modules/@pollyjs/core/src/-private/http-base.js:32:10
 ❯ Proxy.removeHeaders ../../node_modules/.pnpm/@pollyjs+core@6.0.6/node_modules/@pollyjs/core/src/-private/http-base.js:39:12
 ❯ listener tests/polly.ts:34:13
     32|     polly.server.any().on('beforePersist', (req) => {
     33|       if (excludedHeaders.length > 0) {
     34|         req.removeHeaders(excludedHeaders)
       |             ^
     35|       }
     36|     })
 ❯ EventEmitter.emit ../../node_modules/.pnpm/@pollyjs+core@6.0.6/node_modules/@pollyjs/core/src/-private/event-emitter.js:213:13
 ❯ Route.emit ../../node_modules/.pnpm/@pollyjs+core@6.0.6/node_modules/@pollyjs/core/src/server/route.js:104:58
 ❯ FSPersister.persist ../../node_modules/.pnpm/@pollyjs+persister@6.0.6/node_modules/@pollyjs/persister/dist/cjs/pollyjs-persister.js:3540:9
 ❯ Polly.stop ../../node_modules/.pnpm/@pollyjs+core@6.0.6/node_modules/@pollyjs/core/dist/cjs/pollyjs-core.js:6454:7

Dependencies

{
  "@pollyjs/adapter-node-http": "^6.0.6",
  "@pollyjs/core": "^6.0.6",
  "@pollyjs/persister-fs": "^6.0.6",
  "vite-tsconfig-paths": "^4.3.2",
  "vitest": "^1.5.0"
}

Environment

Node.js v18.7.0
darwin 22.4.0
PNPM 8.6.3
andresgutgon commented 2 months ago

I think the issue could be here no? https://github.com/Netflix/pollyjs/blob/master/packages/%40pollyjs/core/src/-private/http-base.js#L104

req.headers are freeze so I can't modify them.

Is there any other way of obfuscate headers values?

monarchwadia commented 1 month ago

I ended up using beforeResponse instead of beforePersist and it worked well. No freezing of objects here.

Out of curiosity, did ChatGPT tell you to use beforePersist ?