Skip to content
This repository has been archived by the owner on Jan 9, 2020. It is now read-only.

Commit

Permalink
New build
Browse files Browse the repository at this point in the history
  • Loading branch information
MishUshakov committed Jul 30, 2019
1 parent 24efad6 commit 39084f6
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 423 deletions.
4 changes: 1 addition & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
FROM scratch
COPY bin/fulfillment-tester-linux /
COPY ui /ui
VOLUME ["/tmp"]
ENTRYPOINT ["/fulfillment-tester-linux"]
ENTRYPOINT /fulfillment-tester-linux
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2019 Ushakov
Copyright 2019 by Mikhail Ushakov

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

Expand Down
73 changes: 43 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,68 +1,81 @@
# Dialogflow Fulfillment Tester
# Fulfillment Tester

Test your Fulfillments like never before!
Test your Dialogflow/Actions on Google Fulfillments like never before!

Start it:
- Works on Windows, Linux and Mac (64 bit)
- Small, embeddable binary with no external dependencies, written in Go (<10 MB)
- Supports any dialogflow fulfillment in any programming language, platform-specific responses and Actions on Google
- No More waiting. Never. Run your fulfillment (locally or remotely) and start testing
- Run automated tests with tools like Jest, Ava, Mocha (or any other of your choice)
- Test with a built-in User Interface or on CI/CD
- Acts exactly like Dialogflow, 100% accurate testing results guaranteed

![](https://i.imgur.com/Y5Ufr32.png)
Just start it:

And test with style using the User Interface:
![](https://i.imgur.com/yE2aiid.png)

![](https://i.imgur.com/YSulY94.png)
And test with style using [Dialogflow for Web](https://github.com/mishushakov/fulfillment-tester):

Or send the requests manually:
![](https://i.imgur.com/sZR5c63.png)
![](https://i.imgur.com/VmPCd0u.png)
![](https://i.imgur.com/BWbropG.png)

Or send requests manually (programmatically):

![](https://i.imgur.com/ywbIjrE.jpg)

## Features
## How it works

- Works on Windows, Linux and Mac (64 bit)
- Small binary with no external dependencies, written in Go (<10 MB)
- Test fulfillments in any programming language and Actions on Google fulfillments
- No More waiting. Never. Just run your fulfillment (locally or remotely) and start testing
- Run automated tests with tools like Jest, Ava, Mocha (or any other of your choice)
- Test with convinience, with a built-in User Interface or on CI/CD
- Works exactly like Dialogflow, 100% accurate testing results guaranteed
![](https://svgur.com/i/EKw.svg)

Excited? Let's get started!
Fulfillment tester acts like a reverse-proxy between Dialogflow and your fulfillment. It fetches Dialogflow response for a given query, forwards it to the specified fulfillment and then responds with a result.

## Installation

Connect your Dialogflow Agent to [Dialogflow Gateway](https://dialogflow.cloud.ushakov.co), read the guide [here](https://github.com/mishushakov/dialogflow-gateway-docs/blob/master/guide.md)
1. Install Dialogflow Gateway first. Fulfillment tester uses Dialogflow Gateway as its backend.

Dialogflow Gateway enables third-party integrations to securely access the Dialogflow V2 API

- [Documentation](https://github.com/mishushakov/dialogflow-gateway-docs)
- [Implementations](https://github.com/mishushakov/dialogflow-gateway-docs#implementations)

Install the latest executable for your operating system from the [Releases Page](https://github.com/mishushakov/dialogflow-fulfillment-tester/releases)
2. Install the latest executable for your operating system from the [Releases Page](https://github.com/mishushakov/fulfillment-tester/releases)

Run

```sh
dialogflow-fulfillment-tester --project <YOUR GOOGLE CLOUD PROJECT ID> --fulfillment <URL>
fulfillment-tester --gateway <GATEWAY URL> --fulfillment <FULFILLMENT URL>
```

Get help:

```sh
dialogflow-fulfillment-tester --help
fulfillment-tester --help
```

Tip: if you are on node and firebase functions, run your function locally using the firebase functions emulator

## Installing the UI
## Accessing the UI

If you want the UI, clone this repo and put the `ui` folder near the executable.
1. Follow the installation instructions in the [Dialogflow for Web repo](https://github.com/mishushakov/dialogflow-web-v2)
2. Change the Gateway URL in the `config.js` to match your fulfillment tester URL

Notice: when running Dialogflow Fulfillment Tester on a diffrent host/port, make sure to change it in the UI as well (`index.html`):

```js
let url = "http://localhost:8899" // <- Change the url, when running on a different host/port
```
Example:

Notice: the UI doesn't display Actions on Google components at the moment.
```js
export default {
app: {
gateway: "http://localhost:8899"
[...]
}
}

Tip: When inspecting using the UI, open the console to see the request/response body
[...]
```

## Making Requests

The request/response format of the Dialogflow Fulfillment Tester is equal to the Dialogflow Gateway request/response format, which is equal to the Dialogflow request/response format. Read the docs [here](https://github.com/mishushakov/dialogflow-gateway-docs/blob/master/api.md)
The request/response format of Fulfillment Tester is equal to the [Dialogflow Gateway API](https://github.com/mishushakov/dialogflow-gateway-docs#api) request/response format

## Building from source

Expand Down
76 changes: 51 additions & 25 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import (
"net/http"
)

// Declaring Variables
// Variables
var (
Project string // Project ID
Fulfillment string // Fulfillment Host
Gateway string // Gateway URL
Fulfillment string // Fulfillment URL
Port string // Port to run the fulfillment-tester at
)

Expand All @@ -21,61 +21,87 @@ func proxy(res http.ResponseWriter, req *http.Request) {
res.Header().Set("Access-Control-Allow-Headers", "Content-Type, Cache-Control")
res.Header().Set("Access-Control-Allow-Methods", "*")

if req.Method == "POST" {
if req.Method == "GET" {
// Retrieve Agent
resp, gateway_conn_err := http.Get(Gateway)
if gateway_conn_err != nil {
panic(gateway_conn_err)
}
body, gateway_res_err := ioutil.ReadAll(resp.Body)
if gateway_res_err != nil {
panic(gateway_res_err)
}

res.Write(body)
} else if req.Method == "POST" {
// Proxy request to Dialogflow Gateway (Session ID is always fulfillment-tester)
resp, _ := http.Post("https://"+Project+".gateway.dialogflow.cloud.ushakov.co/fulfillment-tester", "application/json", req.Body)
resp, gateway_conn_err := http.Post(Gateway+"/fulfillment-tester", "application/json", req.Body)
if gateway_conn_err != nil {
panic(gateway_conn_err)
}
if resp.StatusCode != 200 {
res.WriteHeader(403)
res.WriteHeader(resp.StatusCode)
}

// Read the response from Dialogflow Gateway
// Add session identifier to response
// Generate new JSON
resp_body, _ := ioutil.ReadAll(resp.Body)
resp_body, gateway_res_err := ioutil.ReadAll(resp.Body)
if gateway_res_err != nil {
panic(gateway_res_err)
}

var result map[string]interface{}
json.Unmarshal(resp_body, &result)
result["session"] = "projects/" + Project + "/agent/sessions/fulfillment-tester"

// Add (fake) session identifier to response, so our Webhook can see the session
// Generate new json
result["session"] = "projects/x/agent/sessions/fulfillment-tester"
data, _ := json.Marshal(result)

// Send the response to Fulfillment
fulfillment_resp, _ := http.Post(Fulfillment, "application/json", bytes.NewReader(data))
// Send it to the Fulfillment
fulfillment_resp, fulfillment_conn_err := http.Post(Fulfillment, "application/json", bytes.NewReader(data))
if fulfillment_conn_err != nil {
panic(fulfillment_conn_err)
}

// Parse the fulfillment_messages from the Fulfillment response
// Overwrite queryResult on response (addr is the address of the queryResult field, that can be pointed to later)
// Parse response from fulfillment
// Set queryResult of Dialogflow Gateway response to the fulfillment's response
// That's how Dialogflow actually responds with fulfillment option enabled (you don't have to be a Googler to tell that)
fulfillment_messages, _ := ioutil.ReadAll(fulfillment_resp.Body)
var addr = result["queryResult"]
json.Unmarshal(fulfillment_messages, &addr)
fulfillment_messages, fulfillment_res_err := ioutil.ReadAll(fulfillment_resp.Body)
if fulfillment_res_err != nil {
panic(fulfillment_res_err)
}

var queryResult = result["queryResult"]
json.Unmarshal(fulfillment_messages, &queryResult)

// Convert output back to JSON and send it to the client
// Convert result back to JSON and send it to the client
output, _ := json.Marshal(result)
res.Write(output)
} else if req.Method == "OPTIONS" {
// Pre-flight checks
res.WriteHeader(200)
} else {
// Invalid request method
res.WriteHeader(404)
}
}

func main() {
// Parse flags, setup default flags and descriptions
flag.StringVar(&Project, "project", "dialogflow-web-v2", "Dialogflow Gateway Project ID")
flag.StringVar(&Gateway, "gateway", "https://dialogflow-web-v2.gateway.dialogflow.cloud.ushakov.co", "Dialogflow Gateway URL")
flag.StringVar(&Fulfillment, "fulfillment", "https://us-central1-dialogflow-web-v2.cloudfunctions.net/dialogflowFirebaseFulfillment", "URL to fullfillment (remote or local)")
flag.StringVar(&Port, "port", "8899", "Port to run the fulfillment-tester at")
flag.Parse()

// Log some useful information to console
println("Dialogflow Fulfillment Tester is running 🚀")
println("Listening on: http://localhost:" + Port)
println("Web UI at: http://localhost:" + Port + "/ui" + "\n")
println("Connection 🔌")
println("Project ID: " + Project)
println("Fulfillment URL: " + Fulfillment)
println("\nConnection 🔌")
println("Gateway: " + Gateway)
println("Fulfillment: " + Fulfillment)
println("\nHappy Testing!")

// Setup HTTP Server and Proxy (Handler)
// Setup the Web Server for the Web Client
http.HandleFunc("/", proxy)
http.Handle("/ui/", http.StripPrefix("/ui", http.FileServer(http.Dir("ui"))))
panic(http.ListenAndServe(":"+Port, nil))
}
5 changes: 5 additions & 0 deletions test.http
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
### Get Agent
GET http://localhost:8899
Content-Type: application/json

### Detect Intent
POST http://localhost:8899
Content-Type: application/json

Expand Down
1 change: 0 additions & 1 deletion ui/assets/card.svg

This file was deleted.

1 change: 0 additions & 1 deletion ui/assets/send.svg

This file was deleted.

Loading

0 comments on commit 39084f6

Please sign in to comment.