Skip to content

Commit

Permalink
1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
jupegarnica committed Oct 28, 2022
0 parents commit e2b9b11
Show file tree
Hide file tree
Showing 49 changed files with 4,000 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
HOST= https://faker.deno.dev
HOST_HTTPBIN= https://httpbin.org
HOST_HTTP2= https://http2.deno.dev
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
HOST= https://aker.deno.dev
HOST_HTTPBIN= https://httpbin.org
HOST_HTTP2= https://http2.deno.dev
19 changes: 19 additions & 0 deletions .github/workflows/readme.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## create readme on changes to src/cli.ts
name: readme
on:
workflow_dispatch:
push:
paths:
- src/help.ts
jobs:

readme:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: denoland/setup-deno@v1
- run: deno task readme
- uses: EndBug/add-and-commit@v9
with:
message: "docs: update readme"
add: "README.md"
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"deno.enable": true,
"deno.unstable": true
}
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM denoland/deno
WORKDIR /app
COPY . .
RUN deno cache --unstable --lock=lock.json --lock-write src/cli.ts

CMD run --allow-net --allow-read --allow-write --allow-env --unstable src/cli.ts
202 changes: 202 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
```
-------------------------
--------- TEPI ----------
-------------------------
-- A .http Test Runner --
-------------------------
```

Test your HTTP APIs with standard http syntax

## Features:

- 📝 Write end to end API REST tests in `.http` files
- 🔎 Validate Response status, headers and/or body.
- 🔥 Interpolate javascript with eta template `<%= %>`
- 🖊 Write metadata as frontmatter yaml
- 📦 Reference by name another test to run them in advance
- ⏱ Set a timeout for each test or globally in milliseconds. After the timeout,
the test will fail.
- 🚨 Stop running tests after the first failure.
- 🔋 Use env files to load environment variables
- 😎 Fully featured and colorful display modes. (none, minimal, default and full)
- 👁 Watch files for changes and rerun tests.
- 🍯 Standard Response and Request with a automatic getBody()

## Install:

```bash
deno install --unstable --allow-read --allow-env --allow-net -f -n tepi https://deno.land/x/tepi/src/cli.ts
```

Or run remotely width:

```bash
deno run --unstable --allow-read --allow-env --allow-net https://deno.land/x/tepi/src/cli.ts
```

## Usage:

tepi [OPTIONS] [FILES|GLOBS...]

## Options:

- -w `--watch` Watch files for changes and rerun tests.
- -t `--timeout` Set the timeout for each test in milliseconds. After the
timeout, the test will fail.
- -f `--fail-fast` Stop running tests after the first failure.
- -d `--display` Set the display mode. (none, minimal, default and full) * none:
display nothing * minimal: display only a minimal summary * default: list
results and full error summary * full: display also all HTTP requests and
responses * verbose: display also all metadata and not truncate data
- -h `--help` output usage information
- -e `--env-file` load environment variables from a .env file
- `--no-color` output without color
- `--upgrade` upgrade to the latest version

## Examples:

`tepi`

> Run all .http in the current directory and folders. (same as tepi ./**/*.http)
`tepi test.http ./test2.http`

> Run test.http and test2.http
`tepi **/*.http`

> Run all .http in the current directory and folders.
`tepi rest.http --watch`

> Run rest.http and rerun when it changes
`tepi rest.http --watch "src/**/*.ts"`

> Run rest.http and rerun when any .ts file in the src folder changes.
`tepi rest.http --watch "src/**/*.json" --watch "src/**/*.ts"`

> You can use multiple --watch flags. Note: You can use globs here too, but use
> quotes to avoid the shell expanding them.
`tepi --timeout 10000`

> Set the timeout for each test in milliseconds. After the timeout, the test
> will fail.
`tepi --fail-fast`

> Stop running tests after the first failure.
`tepi --display minimal`

> Set the display mode. (none, minimal, default and full)
`tepi --env-file .env --env-file .env.test`

> Load environment variables from a .env and .env.test
## HTTP syntax:

- You can use the standard HTTP syntax in your .http files to run a request and
response validation.
- Use the `###` to separate the requests.
- Use frontmatter yaml to set metadata.

For example, validate the headers, status code, status text and body:

```
GET https://faker.deno.dev/?body=hola&status=400
HTTP/1.1 400 Bad Request
content-type: text/plain; charset=utf-8
hola
#
###
```

## Interpolation:

It's deno 🔥

Uses eta as template engine, see docs: https://deno.land/x/eta

Use `<%= %>` to interpolate values.

All the std assertion module is available:
https://deno.land/std/testing/asserts.ts

Use `<% %>` to run custom assertions or custom JS. For example:

```
GET http://localhost:3000/users
<% assert(response.status === 200) %>
```

Or:

```
<% if (Math.random() > 0.5) { %>
GET http://localhost:3000/users/1
<% } else { %>
GET http://localhost:3000/users/2
<% } %>
```

### Interpolation scope:

In the Interpolation `<%= %>` or `<% %>` you have access to any Deno API and the
following variables:

> request: The Request from the actual block. meta: The metadata from the actual
> block. and the frontmatter global metadata. response: The standard Response
> object from the fetch API from the actual request. (only available in the
> expected response, after the request) body: The extracted body an alias of
> `await response.getBody()` (only available in the expected response, after the
> request)
> [name]: the named block already run for example: `<%= loginTest.body.jwt %>`
> or `<%= loginTest.response.status %>`
The Block signature is:

```ts
type Block = {
meta: {
[key: string]: any;
};
request?: Request;
response?: Response;
expectedResponse?: Response;
error?: Error;
body?: any;
};
```

For example:

```
---
name: login
---
POST https://example.com/login
Content-Type: application/json
{"user": "Garn", "password": "1234"}
HTTP/1.1 200 OK
###
---
needs: login
# not really needed, because the requests run in order of delcaration
---
GET https://example.com/onlyAdmin
Authorization: Bearer <%= loginTest.body.jwt %>
Content-Type: application/json
```
29 changes: 29 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Roadmap

This document describes the roadmap for the project.

## 1.0.0

- [x] Support for the `--watch`
- [x] Support for the `--timeout`
- [x] Support for the `--fail-fast`
- [x] `--display` none, minimal, default , full and verbose
- [x] `--help` output usage information
- [x] `--env-file` load environment variables from a .env file
- [x] `--no-color` output without color
- [x] `--upgrade` upgrade to the latest version
- [x] Support front-matter yaml as metadata, global and per test
- [x] Support meta.host for declaring the base url.
- [x] Support meta.needs for running tests in a specific order.
- [x] Support meta.ignore for skipping tests.
- [x] Support meta.only for running only specific tests.
- [x] Support for eta as template engine.
- [x] Support for meta.display to override the global display mode.
- [x] Support for meta.timeout to override the global timeout.
- [x] Support for meta `import:` to import other files

- [ ] Support for meta.noColor to override the global noColor.
- [ ] Better error display.
- [ ] Support for the `--watch-no-clear`
- [ ] Support for meta `run:` to run shell commands
- [ ] Concurrent test execution
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.0.15
34 changes: 34 additions & 0 deletions compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
services:
faker:
image: jupegarnica/faker.deno.dev
ports:
- 80:8000
networks:
- tepi-net
httpbin:
image: kennethreitz/httpbin
ports:
- "81:80"
networks:
- tepi-net

test:
networks:
- tepi-net

build:
context: .
dockerfile: Dockerfile
volumes:
- .:/app
environment:
- HOST=http://faker:8000
- HOST_HTTPBIN=http://httpbin
command: deno task test
depends_on:
- faker
- httpbin

networks:
tepi-net:
driver: bridge
19 changes: 19 additions & 0 deletions deno.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"tasks": {
"dev": "TEPI_NOT_EXIT=1 deno run -A --unstable --watch ./src/cli.ts",
// test
"test": "NO_LOG=1 deno test -A --unstable",
"test-watch": "FORCE_COLOR=1 deno test -A --unstable --watch test",
"local": "HOST=http://localhost HOST_HTTPBIN=http://localhost:81 deno task test-watch",
// dev
"install": "deno install -fA --unstable --name tepi ./src/cli.ts",
"readme": "NO_COLOR=1 deno run -A --unstable ./src/cli.ts --help > README.md",
"help": " deno run -A --unstable --watch ./src/cli.ts --help",
// chore
"udd": "deno run -A --reload https://deno.land/x/udd/main.ts --test='deno task test' 'src/**/*.ts' 'test/**/*.ts'",
// release
"dnt": "deno run -A https://deno.land/x/dnt_prompt/main.ts",
"version": "deno run -A https://deno.land/x/version/index.ts",
"release": "deno task version patch && git push --tags origin main"
}
}
57 changes: 57 additions & 0 deletions http/assert.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
host: <%= Deno.env.get('HOST') || 'https://faker.deno.dev' %>
---
###

POST /pong?quiet=true
Content-Type: application/json
x-powered-by: Deno

{ "message":"pong", "quiet":true }

HTTP/1.1 200 OK
Content-Type: application/json
x-powered-by: Deno


{
"message":"pong",
"quiet": false
}

###

POST /pong?quiet=true

hello

HTTP/1.1 200 OK

hello
<% assertEquals(await response.getBody(), "hello", 'not body extracted') %>


###
---
name: must fail with custom error
---
POST /pong?quiet=true

hello

HTTP/1.1 200 OK

hello
<% assertEquals(await response.getBody(), "hola", 'failed!') %>



###
---
name: must fail because of headers
---
GET /pong?quiet=true
x-quiet: true

HTTP/1.1 200 OK
x-quiet: false
Loading

0 comments on commit e2b9b11

Please sign in to comment.