import { test } from '@japa/runner'
import {
  FlowResponseDataEnum,
  FlowSourceEnum,
  EqualAssertion,
  DeleteCookieStep,
  ReadDataStep,
  SetVariableStep,
  FlowRequestDataEnum,
  InMemoryCookieJar,
  AmfNamespace as ns,
  IHttpRequest,
  ISentRequest,
  Property,
  SetDataStep,
  HttpCookie,
  SetCookieStep,
  IHttpFlow,
  IResponse,
  NotOkAssertion,
  OkAssertion,
  ReadDataSourceStep,
  ReadValueStep,
} from '../../../../src/index.js'
import { clearStore } from '../../../../src/cookies/InMemoryCookieJar.js'
import { HttpFlowRunner } from '../../../../src/runtime/http-runner/HttpFlowRunner.js'

test.group('Request flows', (group) => {
  let variables: Record<string, string>
  let cookieJar: InMemoryCookieJar
  let factory: HttpFlowRunner

  group.each.setup(() => {
    variables = {}
    cookieJar = new InMemoryCookieJar()
    clearStore()
    factory = new HttpFlowRunner()
    factory.cookies = cookieJar
    factory.variables = variables
  })

  test('deletes a cookie before a request matched with a request URL', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'GET',
    }
    const c1 = HttpCookie.fromValue('c1', 'v1')
    cookieJar.setCookies(request.url, [c1])
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [DeleteCookieStep.byName('c1').toJSON()],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    const remainingCookies = await cookieJar.listCookies(request.url)
    assert.deepEqual(remainingCookies, [])
  })

  test('ignores other cookies', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'GET',
    }
    const c1 = HttpCookie.fromValue('c1', 'v1')
    cookieJar.setCookies('https://v8.com', [c1])
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [DeleteCookieStep.byName('c1').toJSON()],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    const remainingCookies = await cookieJar.listCookies('https://v8.com')
    assert.lengthOf(remainingCookies, 1)
  })

  test('deletes a cookie matched with a set URL', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'GET',
    }
    const c1 = HttpCookie.fromValue('c1', 'v1')
    cookieJar.setCookies(request.url, [c1])
    const c2 = HttpCookie.fromValue('c1', 'v2')
    cookieJar.setCookies('https://v8.com', [c2])
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [DeleteCookieStep.byName('c1', 'https://v8.com').toJSON()],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    const requestCookies = await cookieJar.listCookies(request.url)
    assert.lengthOf(requestCookies, 1, 'did not remove request cookies')
    const otherCookies = await cookieJar.listCookies('https://v8.com')
    assert.lengthOf(otherCookies, 0, 'removes other cookies')
  })

  test('sets a cookie for the request URL', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'GET',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [new SetDataStep('data').toJSON(), new SetCookieStep('c1').toJSON()],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    const requestCookies = await cookieJar.listCookies(request.url)
    assert.lengthOf(requestCookies, 1, 'has the cookies')
    const [c1] = requestCookies
    assert.equal(c1.name, 'c1')
  })

  test('sets a cookie for another URL', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'GET',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [new SetDataStep('data').toJSON(), new SetCookieStep('c1', 'https://v8.com').toJSON()],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    const requestCookies = await cookieJar.listCookies(request.url)
    assert.lengthOf(requestCookies, 0, 'has no cookies related to the request URL')
    const otherCookies = await cookieJar.listCookies('https://v8.com')
    assert.lengthOf(otherCookies, 1, 'has the other cookies')
  })

  test('sets a variable from the set value', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'GET',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [new SetDataStep('data').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.equal(variables.v1, 'data')
  })

  test('sets a variable from the URL.host', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'GET',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, 'host', FlowRequestDataEnum.url).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.equal(variables.v1, 'api.com')
  })

  test('sets a variable from the URL.protocol', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'GET',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, 'protocol', FlowRequestDataEnum.url).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.equal(variables.v1, 'http:')
  })

  test('sets a variable from the URL.path', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'GET',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, 'path', FlowRequestDataEnum.url).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.equal(variables.v1, '/v1')
  })

  test('sets a variable from the URL.query', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1?a=b',
      method: 'GET',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, 'query', FlowRequestDataEnum.url).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.equal(variables.v1, 'a=b')
  })

  test('sets a variable from the URL.query.param-name', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1?a=b',
      method: 'GET',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, 'query.a', FlowRequestDataEnum.url).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.equal(variables.v1, 'b')
  })

  test('sets a variable from the URL.hash', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1#a=b',
      method: 'GET',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, 'hash', FlowRequestDataEnum.url).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.equal(variables.v1, 'a=b')
  })

  test('sets a variable from the URL.hash.param-name', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1#a=b',
      method: 'GET',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, 'hash.a', FlowRequestDataEnum.url).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.equal(variables.v1, 'b')
  })

  test('sets a variable from the headers.header-name', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'GET',
      headers: 'x-token: abc',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, 'x-token', FlowRequestDataEnum.headers).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.equal(variables.v1, 'abc')
  })

  test('sets a variable from the headers model', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'GET',
      headersModel: [Property.String('x-token', 'abc', true).toJSON()],
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, 'x-token', FlowRequestDataEnum.headers).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.equal(variables.v1, 'abc')
  })

  test('ignores setting up variable when no headers', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'GET',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, 'x-token', FlowRequestDataEnum.headers).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.deepEqual(variables, {})
  })

  test('ignores setting up variable when no header', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'GET',
      headers: 'x-other: abc',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, 'x-token', FlowRequestDataEnum.headers).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.deepEqual(variables, {})
  })

  test('ignores setting up variable when no body', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'GET',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, 'test', FlowRequestDataEnum.body).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.deepEqual(variables, {})
  })

  test('sets the variable from the entire body', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'POST',
      payload: 'test-value',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, '', FlowRequestDataEnum.body).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.deepEqual(variables, { v1: 'test-value' })
  })

  test('sets the variable from the body path', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'POST',
      headersModel: [Property.String('content-type', 'application/json', true).toJSON()],
      payload: '{"a":{"b":"c"}}',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.request, 'a.b', FlowRequestDataEnum.body).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.deepEqual(variables, { v1: 'c' })
  })
})

test.group('Request conditions', (group) => {
  let variables: Record<string, string>
  let cookieJar: InMemoryCookieJar
  let factory: HttpFlowRunner

  group.each.setup(() => {
    variables = {}
    cookieJar = new InMemoryCookieJar()
    clearStore()
    factory = new HttpFlowRunner()
    factory.cookies = cookieJar
    factory.variables = variables
  })

  test('passes when checking for url param', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1?a=b',
      method: 'GET',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        condition: {
          steps: [
            new ReadDataStep(FlowSourceEnum.request, 'query.a', FlowRequestDataEnum.url).toJSON(),
            new OkAssertion().toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test123').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.equal(variables.v1, 'test123')
  })

  test('does no pass when no url param', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1',
      method: 'GET',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        condition: {
          steps: [
            new ReadDataStep(FlowSourceEnum.request, 'query.a', FlowRequestDataEnum.url).toJSON(),
            new OkAssertion().toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test123').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.deepEqual(variables, {})
  })

  test('only runs steps for a condition that passes', async ({ assert }) => {
    const request: IHttpRequest = {
      url: 'http://api.com/v1?a=b',
      method: 'GET',
    }
    const flows: IHttpFlow[] = [
      {
        trigger: 'request',
        condition: {
          steps: [
            new ReadDataStep(FlowSourceEnum.request, '', FlowRequestDataEnum.method).toJSON(),
            new EqualAssertion('GET').toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('set1').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
      {
        trigger: 'request',
        condition: {
          steps: [
            new ReadDataStep(FlowSourceEnum.request, '', FlowRequestDataEnum.method).toJSON(),
            new EqualAssertion('POST').toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('set2').toJSON(), new SetVariableStep('v2').toJSON()],
          },
        ],
      },
    ]
    await factory.request(request, flows)
    assert.deepEqual(variables, { v1: 'set1' })
  })
})

test.group('Response flows', (group) => {
  let variables: Record<string, string>
  let cookieJar: InMemoryCookieJar
  let factory: HttpFlowRunner

  group.each.setup(() => {
    variables = {}
    cookieJar = new InMemoryCookieJar()
    clearStore()
    factory = new HttpFlowRunner()
    factory.cookies = cookieJar
    factory.variables = variables
  })

  test('sets a local cookie from a response cookie', async ({ assert }) => {
    const request: ISentRequest = {
      startTime: 0,
      endTime: 0,
      url: 'https://api.com?a=b',
      method: 'GET',
    }
    const response: IResponse = {
      loadingTime: 0,
      status: 200,
      headers: 'content-type: text/plain\nset-cookie: sis=1',
      payload: 'test',
    }

    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.response, 'sis', FlowResponseDataEnum.cookie).toJSON(),
              new SetCookieStep('my-sis').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    const requestCookies = await cookieJar.listCookies(request.url)
    assert.lengthOf(requestCookies, 1, 'has the cookies')
    const [c1] = requestCookies
    assert.equal(c1.name, 'my-sis', 'has the cookie name')
    assert.equal(c1.value, '1', 'has the cookie value')
  })

  test('sets a variable from a response cookie', async ({ assert }) => {
    const request: ISentRequest = {
      startTime: 0,
      endTime: 0,
      url: 'https://api.com?a=b',
      method: 'GET',
    }
    const response: IResponse = {
      loadingTime: 0,
      status: 200,
      headers: 'content-type: text/plain\nset-cookie: sis=1',
      payload: 'test',
    }

    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.response, 'sis', FlowResponseDataEnum.cookie).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.equal(variables.v1, '1')
  })

  test('sets a local cookie from a response body', async ({ assert }) => {
    const request: ISentRequest = {
      startTime: 0,
      endTime: 0,
      url: 'https://api.com?a=b',
      method: 'GET',
    }
    const response: IResponse = {
      loadingTime: 0,
      status: 200,
      headers: 'content-type: text/plain',
      payload: 'test-token',
    }

    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.response, '', FlowResponseDataEnum.body).toJSON(),
              new SetCookieStep('my-sis').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    const requestCookies = await cookieJar.listCookies(request.url)
    assert.lengthOf(requestCookies, 1, 'has the cookies')
    const [c1] = requestCookies
    assert.equal(c1.name, 'my-sis', 'has the cookie name')
    assert.equal(c1.value, 'test-token', 'has the cookie value')
  })

  test('sets a variable from a response body', async ({ assert }) => {
    const request: ISentRequest = {
      startTime: 0,
      endTime: 0,
      url: 'https://api.com?a=b',
      method: 'GET',
    }
    const response: IResponse = {
      loadingTime: 0,
      status: 200,
      headers: 'content-type: text/plain',
      payload: 'test-token',
    }

    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.response, '', FlowResponseDataEnum.body).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.equal(variables.v1, 'test-token')
  })

  test('sets a variable from a response body (x-www-form-urlencoded)', async ({ assert }) => {
    const request: ISentRequest = {
      startTime: 0,
      endTime: 0,
      url: 'https://api.com?a=b',
      method: 'GET',
    }
    const response: IResponse = {
      loadingTime: 0,
      status: 200,
      headers: 'content-type: application/x-www-form-urlencoded',
      payload: 'access_token=test%20token&token_type=Bearer',
    }

    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.response, 'access_token', FlowResponseDataEnum.body).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.equal(variables.v1, 'test token')
  })

  test('sets a variable from a response body (JSON)', async ({ assert }) => {
    const request: ISentRequest = {
      startTime: 0,
      endTime: 0,
      url: 'https://api.com?a=b',
      method: 'GET',
    }
    const response: IResponse = {
      loadingTime: 0,
      status: 200,
      headers: 'content-type: application/json',
      payload: '{"access_token":"test token"}',
    }

    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        actions: [
          {
            steps: [
              new ReadDataStep(FlowSourceEnum.response, 'access_token', FlowResponseDataEnum.body).toJSON(),
              new SetVariableStep('v1').toJSON(),
            ],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.equal(variables.v1, 'test token')
  })
})

test.group('Response conditions', (group) => {
  let variables: Record<string, string>
  let cookieJar: InMemoryCookieJar
  let factory: HttpFlowRunner
  let request: ISentRequest
  let response: IResponse

  group.each.setup(() => {
    variables = {}
    cookieJar = new InMemoryCookieJar()
    clearStore()
    factory = new HttpFlowRunner()
    factory.cookies = cookieJar
    factory.variables = variables

    request = {
      startTime: 0,
      endTime: 0,
      url: 'https://api.com?a=b',
      method: 'GET',
    }
    response = {
      loadingTime: 0,
      status: 200,
      statusText: 'OK',
      headers: 'content-type: text/plain',
      payload: 'test',
    }
  })

  test('executes the flow when checking for status code (ReadDataStep)', async ({ assert }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataStep(FlowSourceEnum.response, '', FlowResponseDataEnum.status).toJSON(),
            new EqualAssertion('200', true, ns.aml.vocabularies.shapes.number).toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.equal(variables.v1, 'test')
  })

  test('executes the flow when checking for status code (ReadDataSourceStep)', async ({ assert }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataSourceStep(FlowSourceEnum.response, FlowResponseDataEnum.status).toJSON(),
            new EqualAssertion('200', true, ns.aml.vocabularies.shapes.number).toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.equal(variables.v1, 'test')
  })

  test('does not execute the flow when status code invalid (ReadDataStep)', async ({ assert }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataStep(FlowSourceEnum.response, '', FlowResponseDataEnum.status).toJSON(),
            new EqualAssertion('201', true, ns.aml.vocabularies.shapes.number).toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.deepEqual(variables, {})
  })

  test('does not execute the flow when status code invalid (ReadDataSourceStep)', async ({ assert }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataSourceStep(FlowSourceEnum.response, FlowResponseDataEnum.status).toJSON(),
            new EqualAssertion('201', true, ns.aml.vocabularies.shapes.number).toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.deepEqual(variables, {})
  })

  test('executes the flow when checking for status text (ReadDataStep)', async ({ assert }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataStep(FlowSourceEnum.response, '', FlowResponseDataEnum.statusText).toJSON(),
            new EqualAssertion('OK').toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.equal(variables.v1, 'test')
  })

  test('executes the flow when checking for status text (ReadDataSourceStep)', async ({ assert }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataSourceStep(FlowSourceEnum.response, FlowResponseDataEnum.statusText).toJSON(),
            new EqualAssertion('OK').toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.equal(variables.v1, 'test')
  })

  test('does not execute the flow when status text invalid (ReadDataStep)', async ({ assert }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataStep(FlowSourceEnum.response, '', FlowResponseDataEnum.statusText).toJSON(),
            new EqualAssertion('NOT FOUND', true, ns.aml.vocabularies.shapes.number).toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.deepEqual(variables, {})
  })

  test('does not execute the flow when status text invalid (ReadDataSourceStep)', async ({ assert }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataSourceStep(FlowSourceEnum.response, FlowResponseDataEnum.statusText).toJSON(),
            new EqualAssertion('NOT FOUND', true, ns.aml.vocabularies.shapes.number).toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.deepEqual(variables, {})
  })

  test('executes the flow when checking whether headers are set (ReadDataStep)', async ({ assert }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataStep(FlowSourceEnum.response, '', FlowResponseDataEnum.headers).toJSON(),
            new OkAssertion().toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.equal(variables.v1, 'test')
  })

  test('executes the flow when checking whether headers are set (ReadDataSourceStep)', async ({ assert }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataSourceStep(FlowSourceEnum.response, FlowResponseDataEnum.headers).toJSON(),
            new OkAssertion().toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.equal(variables.v1, 'test')
  })

  test('does not execute the flow when checking whether headers are set (ReadDataStep)', async ({ assert }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataStep(FlowSourceEnum.response, '', FlowResponseDataEnum.headers).toJSON(),
            new NotOkAssertion().toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.deepEqual(variables, {})
  })

  test('does not execute the flow when checking whether headers are set (ReadDataSourceStep)', async ({ assert }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataSourceStep(FlowSourceEnum.response, FlowResponseDataEnum.headers).toJSON(),
            new NotOkAssertion().toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.deepEqual(variables, {})
  })

  test('executes the flow when checking whether a header is set (ReadDataStep)', async ({ assert }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataStep(FlowSourceEnum.response, 'content-type', FlowResponseDataEnum.headers).toJSON(),
            new EqualAssertion('text/plain').toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.equal(variables.v1, 'test')
  })

  test('executes the flow when checking whether a header is set (ReadDataSourceStep + ReadValueStep)', async ({
    assert,
  }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataSourceStep(FlowSourceEnum.response, FlowResponseDataEnum.headers).toJSON(),
            new ReadValueStep('content-type'),
            new EqualAssertion('text/plain').toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.equal(variables.v1, 'test')
  })

  test('does not execute the flow when checking whether a header is set (ReadDataStep)', async ({ assert }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataStep(FlowSourceEnum.response, 'x-token', FlowResponseDataEnum.headers).toJSON(),
            new EqualAssertion('text/plain').toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.deepEqual(variables, {})
  })

  test('does not execute the flow when checking whether a header is set (ReadDataSourceStep + ReadValueStep)', async ({
    assert,
  }) => {
    const flows: IHttpFlow[] = [
      {
        trigger: 'response',
        condition: {
          steps: [
            new ReadDataSourceStep(FlowSourceEnum.response, FlowResponseDataEnum.headers).toJSON(),
            new ReadValueStep('x-token'),
            new EqualAssertion('text/plain').toJSON(),
          ],
        },
        actions: [
          {
            steps: [new SetDataStep('test').toJSON(), new SetVariableStep('v1').toJSON()],
          },
        ],
      },
    ]
    await factory.response(request, response, flows)
    assert.deepEqual(variables, {})
  })
})
