import { test } from '@japa/runner'
import {
  FlowResponseDataEnum,
  FlowSourceEnum,
  EqualAssertion,
  DeleteCookieStep,
  ReadDataStep,
  SetVariableStep,
  FlowRequestDataEnum,
  InMemoryCookieJar,
  AmfNamespace as ns,
  createLogger,
  HttpRequestRunner,
  IHttpRequest,
  RequestLogKind,
  ISentRequest,
  RequestConfigKind,
  Property,
  SetDataStep,
  IncludesAssertion,
  ClearInMemoryCookieJar,
  HttpCookie,
  SetCookieStep,
  RequestAuthorizationKind,
} from '../../../../src/index.js'

const logger = createLogger()

test.group('simple request run', () => {
  test('sends a simple request', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
      headers: 'x-test: true',
    }
    const result = await factory.run(request)
    assert.typeOf(result, 'object', 'returns an object')
    assert.equal(result.kind, RequestLogKind, 'has the kind')
    assert.typeOf(result.request, 'object', 'has the request')
    assert.typeOf(result.response, 'object', 'has the response')
    assert.typeOf(result.size, 'object', 'has the size')
  }).tags(['@node', '@runner', 'http'])

  test('applies variables to the URL', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.variables = {
      var1: 'value1',
      var2: 'value2',
    }
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get?parsed={var1}`,
      method: 'GET',
    }
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.include(sent.url, '?parsed=value1', 'has the parsed URL')
  }).tags(['@node', '@runner', 'http'])

  test('applies variables to the method', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.variables = {
      var1: 'value1',
      var2: 'value2',
      operation: 'GET',
    }
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: '{operation}',
    }
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.equal(sent.method, 'GET')
  }).tags(['@node', '@runner', 'http'])

  test('applies variables to the headers', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.variables = {
      var1: 'value1',
      var2: 'value2',
      operation: 'GET',
    }
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
      headers: 'x-test: {var2}',
    }
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.equal(sent.headers, 'x-test: value2')
  }).tags(['@node', '@runner', 'http'])

  test('applies variables to the payload', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.variables = {
      var1: 'value1',
      var2: 'value2',
    }
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'POST',
      headers: 'content-type: application/x-www-form-urlencoded\ncontent-length: 8',
      payload: 'a={var1}',
    }
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.equal(sent.payload, 'a=value1')
  }).tags(['@node', '@runner', 'http'])

  test('applies request configuration (defaultHeaders)', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.config = {
      kind: RequestConfigKind,
      enabled: true,
      defaultHeaders: true,
    }
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'POST',
      headers: 'content-type: application/x-www-form-urlencoded\ncontent-length: 8',
      payload: 'a=b',
    }
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.include(sent.headers, 'user-agent: api client', 'has the user-agent')
    assert.include(sent.headers, 'accept: */*', 'has the accept')
  }).tags(['@node', '@runner', 'http'])

  test('reads headers from the headers model', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
      headersModel: [Property.String('x-a', 'b', true).toJSON(), Property.String('x-b', 'c', false).toJSON()],
    }
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.include(sent.headers, 'x-a: b', 'has the enabled header')
    assert.notInclude(sent.headers, 'x-b', 'does not have disabled header')
  }).tags(['@node', '@runner', 'http'])
})

test.group('request flow conditions', () => {
  test('does not run an action when not enabled', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.variables = {}
    const step = new SetVariableStep('test')
    step.enabled = false
    factory.flows = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [step.toJSON()],
          },
        ],
      },
    ]
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
      headers: 'x-test: true',
    }
    await factory.run(request)
    assert.deepEqual(factory.variables, {})
  }).tags(['@node', '@runner', 'http'])

  test('does not run the action when the condition failed (method)', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.variables = {}
    factory.flows = [
      {
        trigger: 'request',
        condition: {
          // source: FlowSourceEnum.request,
          // data: FlowRequestDataEnum.method,
          // operator: AssertionEnum.equal,
          // value: 'POST',

          steps: [
            new ReadDataStep(FlowSourceEnum.request, '', FlowRequestDataEnum.method).toJSON(),
            new EqualAssertion('POST').toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('value').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
      headers: 'x-test: true',
    }
    await factory.run(request)
    assert.deepEqual(factory.variables, {})
  }).tags(['@node', '@runner', 'http'])

  test('does not run the action when condition failed (url)', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.variables = {}
    factory.flows = [
      {
        trigger: 'request',
        condition: {
          steps: [
            new ReadDataStep(FlowSourceEnum.request, '', FlowRequestDataEnum.url).toJSON(),
            new IncludesAssertion('something').toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('value').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
      headers: 'x-test: true',
    }
    await factory.run(request)
    assert.deepEqual(factory.variables, {})
  }).tags(['@node', '@runner', 'http'])
})

test.group('request flows: cookie delete action', (group) => {
  group.each.teardown(() => {
    ClearInMemoryCookieJar()
  })

  test('deletes a cookie from the request URL', async ({ assert, httpConfig }) => {
    const url = `http://localhost:${httpConfig.httpPort}/v1/get`
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.cookies = new InMemoryCookieJar()
    const cookie = new HttpCookie({ name: 'c', value: 'v' })
    await factory.cookies.setCookies(url, [cookie])

    factory.flows = [
      {
        trigger: 'response',
        actions: [
          {
            steps: [DeleteCookieStep.byName('c').toJSON()],
          },
        ],
      },
    ]
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
      headers: 'x-test: true',
    }
    await factory.run(request)
    const storedCookies = await factory.cookies.listCookies(url)
    assert.deepEqual(storedCookies, [])
  }).tags(['@node', '@runner', 'http'])

  test('deletes a cookie from the passed URL', async ({ assert, httpConfig }) => {
    const url = `https://api.com`
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.cookies = new InMemoryCookieJar()
    const cookie = new HttpCookie({ name: 'c', value: 'v' })
    await factory.cookies.setCookies(url, [cookie])

    factory.flows = [
      {
        trigger: 'response',
        actions: [
          {
            steps: [DeleteCookieStep.byUrl(url).toJSON()],
          },
        ],
      },
    ]

    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
      headers: 'x-test: true',
    }
    await factory.run(request)
    const storedCookies = await factory.cookies.listCookies(url)
    assert.deepEqual(storedCookies, [])
  }).tags(['@node', '@runner', 'http'])

  test('uses the optional name', async ({ assert, httpConfig }) => {
    const url = `http://localhost:${httpConfig.httpPort}/v1/get`
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.cookies = new InMemoryCookieJar()
    const c1 = new HttpCookie({ name: 'c1', value: 'v1' })
    const c2 = new HttpCookie({ name: 'c2', value: 'v2' })
    await factory.cookies.setCookies(url, [c1, c2])

    factory.flows = [
      {
        trigger: 'response',
        actions: [
          {
            steps: [DeleteCookieStep.byName('c1').toJSON()],
          },
        ],
      },
    ]

    const request: IHttpRequest = {
      url,
      method: 'GET',
      headers: 'x-test: true',
    }
    await factory.run(request)
    const storedCookies = await factory.cookies.listCookies(url)
    assert.deepEqual(storedCookies, [c2])
  }).tags(['@node', '@runner', 'http'])
})

test.group('request flows: cookie set action', (group) => {
  group.each.teardown(() => {
    ClearInMemoryCookieJar()
  })

  test('sets a cookie from the request URL', async ({ assert, httpConfig }) => {
    const url = `http://localhost:${httpConfig.httpPort}/v1/get`
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.cookies = new InMemoryCookieJar()
    const now = new Date().getTime()

    factory.flows = [
      {
        trigger: 'response',
        actions: [
          {
            steps: [
              new SetDataStep('v1').toJSON(),
              new SetCookieStep({
                name: 'c1',
                expires: String(now),
                hostOnly: false,
                httpOnly: true,
                secure: false,
                session: false,
              }).toJSON(),
            ],
          },
        ],
      },
    ]

    const request: IHttpRequest = {
      url,
      method: 'GET',
      headers: 'x-test: true',
    }
    await factory.run(request)
    const storedCookies = await factory.cookies.listCookies(url)
    assert.lengthOf(storedCookies, 1, 'has the cookie')

    const [item] = storedCookies
    assert.equal(item.name, 'c1', 'name')
    assert.equal(item.value, 'v1', 'value')
    assert.equal(item.domain, `localhost:${httpConfig.httpPort}`, 'domain')
    assert.equal(item.path, '/v1', 'path')
    assert.equal(item.sameSite, 'unspecified', 'sameSite')
    assert.equal(item.expirationDate, now, 'expirationDate')
    assert.isTrue(item.hostOnly, 'hostOnly')
    assert.isFalse(item.session, 'session')
    assert.isFalse(item.secure, 'secure')
    assert.isTrue(item.httpOnly, 'httpOnly')
  }).tags(['@node', '@runner', 'http'])

  test('sets a cookie from the set URL', async ({ assert, httpConfig }) => {
    const url = `https://api.com`
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.cookies = new InMemoryCookieJar()

    factory.flows = [
      {
        trigger: 'response',
        actions: [
          {
            steps: [
              new SetDataStep('v1').toJSON(),
              new SetCookieStep({
                name: 'c1',
                url,
              }).toJSON(),
            ],
          },
        ],
      },
    ]

    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
      headers: 'x-test: true',
    }
    await factory.run(request)
    const storedCookies = await factory.cookies.listCookies(url)
    assert.lengthOf(storedCookies, 1, 'has the cookie')
    const [item] = storedCookies
    assert.equal(item.domain, `api.com`, 'domain is set')
    assert.equal(item.path, '/', 'path is set')
  }).tags(['@node', '@runner', 'http'])

  test('sets the cookie value from the request', async ({ assert, httpConfig }) => {
    const url = `https://api.com`
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.cookies = new InMemoryCookieJar()

    factory.flows = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, 'query.a', FlowRequestDataEnum.url).toJSON(),
              new SetCookieStep({
                name: 'c1',
                url,
              }).toJSON(),
            ],
          },
        ],
      },
    ]

    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get?a=b`,
      method: 'GET',
    }
    await factory.run(request)
    const storedCookies = await factory.cookies.listCookies(url)
    assert.lengthOf(storedCookies, 1, 'has the cookie')
    const [item] = storedCookies
    assert.equal(item.value, `b`)
  }).tags(['@node', '@runner', 'http'])

  test('sets the cookie value from the response', async ({ assert, httpConfig }) => {
    const url = `https://api.com`
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.cookies = new InMemoryCookieJar()

    factory.flows = [
      {
        trigger: 'response',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.response, 'headers.test', FlowRequestDataEnum.body).toJSON(),
              new SetCookieStep('c1', url).toJSON(),
            ],
          },
        ],
      },
    ]

    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
      headers: 'test: true',
    }
    await factory.run(request)
    const storedCookies = await factory.cookies.listCookies(url)
    assert.lengthOf(storedCookies, 1, 'has the cookie')
    const [item] = storedCookies
    assert.equal(item.name, `c1`)
    assert.equal(item.value, `true`)
  }).tags(['@node', '@runner', 'http'])

  test('runs the action when condition success (status)', async ({ assert, httpConfig }) => {
    const url = `http://localhost:${httpConfig.httpPort}/v1/get`
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.cookies = new InMemoryCookieJar()

    factory.flows = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataStep(FlowSourceEnum.response, '', FlowResponseDataEnum.status).toJSON(),
            new EqualAssertion('200', true, ns.w3.xmlSchema.number).toJSON(),
          ],
        },
        actions: [
          {
            steps: [
              new SetDataStep('v1').toJSON(),
              new SetCookieStep({
                name: 'c1',
              }).toJSON(),
            ],
          },
        ],
      },
    ]

    const request: IHttpRequest = {
      url,
      method: 'GET',
      headers: 'x-test: true',
    }
    await factory.run(request)
    const storedCookies = await factory.cookies.listCookies(url)
    assert.lengthOf(storedCookies, 1, 'has the cookie')
  }).tags(['@node', '@runner', 'http'])
})

test.group('request flows: variable set action', () => {
  test('sets a variable from the passed value', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.variables = {}

    factory.flows = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [new SetDataStep('val1').toJSON(), new SetVariableStep('var1').toJSON()],
          },
        ],
      },
    ]

    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
    }
    await factory.run(request)
    assert.deepEqual(factory.variables, { var1: 'val1' })
  }).tags(['@node', '@runner', 'http'])

  test('sets a variable from the request data', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.variables = {}

    factory.flows = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, 'x-test', FlowRequestDataEnum.headers).toJSON(),
              new SetVariableStep('var2').toJSON(),
            ],
          },
        ],
      },
    ]

    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
      headers: 'x-test: true',
    }
    await factory.run(request)
    assert.deepEqual(factory.variables, { var2: 'true' })
  }).tags(['@node', '@runner', 'http'])
})

test.group('request cookies', (group) => {
  group.each.teardown(() => {
    ClearInMemoryCookieJar()
  })

  test('adds matching cookies to the request', async ({ assert, httpConfig }) => {
    const url = `http://localhost:${httpConfig.httpPort}/v1/get`

    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.cookies = new InMemoryCookieJar()
    const c1 = new HttpCookie({ name: 'c1', value: 'v1' })
    const c2 = new HttpCookie({ name: 'c2', value: 'v2' })
    await factory.cookies.setCookies(url, [c1, c2])
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
      headers: 'x-test: true',
    }
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.equal(sent.headers, 'x-test: true\ncookie: c1=v1; c2=v2')
  }).tags(['@node', '@runner', 'http'])

  test('creates cookies when headers are not set on the request', async ({ assert, httpConfig }) => {
    const url = `http://localhost:${httpConfig.httpPort}/v1/get`

    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.cookies = new InMemoryCookieJar()
    const c1 = new HttpCookie({ name: 'c1', value: 'v1' })
    await factory.cookies.setCookies(url, [c1])
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
    }
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.equal(sent.headers, 'cookie: c1=v1')
  }).tags(['@node', '@runner', 'http'])

  test('does not add cookies when ignored', async ({ assert, httpConfig }) => {
    const url = `http://localhost:${httpConfig.httpPort}/v1/get`

    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.cookies = new InMemoryCookieJar()
    const c1 = new HttpCookie({ name: 'c1', value: 'v1' })
    const c2 = new HttpCookie({ name: 'c2', value: 'v2' })
    await factory.cookies.setCookies(url, [c1, c2])
    factory.config = {
      kind: RequestConfigKind,
      enabled: true,
      ignoreSessionCookies: true,
    }
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
      headers: 'x-test: true',
    }
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.equal(sent.headers, 'x-test: true')
  }).tags(['@node', '@runner', 'http'])
})

test.group('response cookies', (group) => {
  group.each.teardown(() => {
    ClearInMemoryCookieJar()
  })

  test('sets the cookies in the store', async ({ assert, httpConfig }) => {
    const url = `http://localhost:${httpConfig.httpPort}/v1/cookie`
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.cookies = new InMemoryCookieJar()

    const request: IHttpRequest = {
      url,
      method: 'GET',
    }
    await factory.run(request)
    const cookies = await factory.cookies.listCookies(url)
    assert.lengthOf(cookies, 3, 'has all cookies')
    assert.equal(cookies[0].name, 'c1')
    assert.equal(cookies[1].name, 'c2')
    assert.equal(cookies[2].name, 'c3')
  }).tags(['@node', '@runner', 'http'])

  test('ignores cookies when configured', async ({ assert, httpConfig }) => {
    const url = `http://localhost:${httpConfig.httpPort}/v1/cookie`
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.cookies = new InMemoryCookieJar()
    factory.config = {
      kind: RequestConfigKind,
      enabled: true,
      ignoreSessionCookies: true,
    }
    const request: IHttpRequest = {
      url,
      method: 'GET',
    }
    await factory.run(request)
    const cookies = await factory.cookies.listCookies(url)
    assert.lengthOf(cookies, 0, 'has no cookies')
  }).tags(['@node', '@runner', 'http'])

  test('does not ignores cookies when configuration not enabled', async ({ assert, httpConfig }) => {
    const url = `http://localhost:${httpConfig.httpPort}/v1/cookie`
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.cookies = new InMemoryCookieJar()
    factory.config = {
      kind: RequestConfigKind,
      enabled: false,
      ignoreSessionCookies: true,
    }
    const request: IHttpRequest = {
      url,
      method: 'GET',
    }
    await factory.run(request)
    const cookies = await factory.cookies.listCookies(url)
    assert.lengthOf(cookies, 3, 'has all cookies')
  }).tags(['@node', '@runner', 'http'])

  test('ignores setting cookies when no cookies', async ({ assert, httpConfig }) => {
    const url = `http://localhost:${httpConfig.httpPort}/v1/get`
    const factory = new HttpRequestRunner()
    factory.logger = logger
    factory.cookies = new InMemoryCookieJar()
    const request: IHttpRequest = {
      url,
      method: 'GET',
    }
    await factory.run(request)
    const cookies = await factory.cookies.listCookies(url)
    assert.lengthOf(cookies, 0, 'has no cookies')
  }).tags(['@node', '@runner', 'http'])
})

test.group('request authorization', () => {
  test('applies the Bearer token', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
    }
    factory.authorization = [
      {
        kind: RequestAuthorizationKind,
        config: {
          token: 'test123',
        },
        enabled: true,
        type: 'bearer',
        valid: true,
      },
    ]
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.equal(sent.headers, 'authorization: Bearer test123')
  }).tags(['@node', '@runner', 'http'])

  test('applies the OIDC token', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
    }
    factory.authorization = [
      {
        kind: RequestAuthorizationKind,
        config: {
          accessToken: 'test123',
        },
        enabled: true,
        type: 'open id',
        valid: true,
      },
    ]
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.equal(sent.headers, 'authorization: Bearer test123')
  }).tags(['@node', '@runner', 'http'])

  test('applies the OAuth2 token with defaults', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
    }
    factory.authorization = [
      {
        kind: RequestAuthorizationKind,
        config: {
          accessToken: 'test123',
        },
        enabled: true,
        type: 'oauth 2',
        valid: true,
      },
    ]
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.equal(sent.headers, 'authorization: Bearer test123')
  }).tags(['@node', '@runner', 'http'])

  test('applies the OAuth2 token with tokenType', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
    }
    factory.authorization = [
      {
        kind: RequestAuthorizationKind,
        config: {
          accessToken: 'test123',
          tokenType: 'test-type',
        },
        enabled: true,
        type: 'oauth 2',
        valid: true,
      },
    ]
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.equal(sent.headers, 'authorization: test-type test123')
  }).tags(['@node', '@runner', 'http'])

  test('applies the OAuth2 token with deliveryName', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
    }
    factory.authorization = [
      {
        kind: RequestAuthorizationKind,
        config: {
          accessToken: 'test123',
          deliveryName: 'x-auth',
        },
        enabled: true,
        type: 'oauth 2',
        valid: true,
      },
    ]
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.equal(sent.headers, 'x-auth: Bearer test123')
  }).tags(['@node', '@runner', 'http'])

  test('applies the OAuth2 token with deliveryMethod', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
    }
    factory.authorization = [
      {
        kind: RequestAuthorizationKind,
        config: {
          accessToken: 'test123',
          deliveryMethod: 'query',
        },
        enabled: true,
        type: 'oauth 2',
        valid: true,
      },
    ]
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.include(sent.url, 'authorization=Bearer+test123')
  }).tags(['@node', '@runner', 'http'])

  test('ignores OAuth2 when no token', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
      headers: '',
    }
    factory.authorization = [
      {
        kind: RequestAuthorizationKind,
        config: {},
        enabled: true,
        type: 'oauth 2',
        valid: true,
      },
    ]
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.isUndefined(sent.headers)
  }).tags(['@node', '@runner', 'http'])

  test('applies the Basic method', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
    }
    factory.authorization = [
      {
        kind: RequestAuthorizationKind,
        config: {
          username: 'a',
          password: 'b',
        },
        enabled: true,
        type: 'basic',
        valid: true,
      },
    ]
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.equal(sent.headers, 'authorization: Basic YTpi')
  }).tags(['@node', '@runner', 'http'])

  test('ignores the Basic method when no username', async ({ assert, httpConfig }) => {
    const factory = new HttpRequestRunner()
    factory.logger = logger
    const request: IHttpRequest = {
      url: `http://localhost:${httpConfig.httpPort}/v1/get`,
      method: 'GET',
    }
    factory.authorization = [
      {
        kind: RequestAuthorizationKind,
        config: {
          password: 'b',
        },
        enabled: true,
        type: 'basic',
        valid: true,
      },
    ]
    const result = await factory.run(request)
    const sent = result.request as ISentRequest
    assert.isUndefined(sent.headers)
  }).tags(['@node', '@runner', 'http'])
})
