workato-connector-sdk 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.md +20 -0
- data/README.md +1093 -0
- data/exe/workato +5 -0
- data/lib/workato/cli/edit_command.rb +71 -0
- data/lib/workato/cli/exec_command.rb +191 -0
- data/lib/workato/cli/generate_command.rb +105 -0
- data/lib/workato/cli/generators/connector_generator.rb +94 -0
- data/lib/workato/cli/generators/master_key_generator.rb +56 -0
- data/lib/workato/cli/main.rb +142 -0
- data/lib/workato/cli/push_command.rb +208 -0
- data/lib/workato/connector/sdk/account_properties.rb +60 -0
- data/lib/workato/connector/sdk/action.rb +88 -0
- data/lib/workato/connector/sdk/block_invocation_refinements.rb +30 -0
- data/lib/workato/connector/sdk/connector.rb +230 -0
- data/lib/workato/connector/sdk/dsl/account_property.rb +15 -0
- data/lib/workato/connector/sdk/dsl/call.rb +17 -0
- data/lib/workato/connector/sdk/dsl/error.rb +15 -0
- data/lib/workato/connector/sdk/dsl/http.rb +60 -0
- data/lib/workato/connector/sdk/dsl/lookup_table.rb +15 -0
- data/lib/workato/connector/sdk/dsl/time.rb +21 -0
- data/lib/workato/connector/sdk/dsl/workato_code_lib.rb +105 -0
- data/lib/workato/connector/sdk/dsl/workato_schema.rb +15 -0
- data/lib/workato/connector/sdk/dsl.rb +46 -0
- data/lib/workato/connector/sdk/errors.rb +30 -0
- data/lib/workato/connector/sdk/lookup_tables.rb +62 -0
- data/lib/workato/connector/sdk/object_definitions.rb +74 -0
- data/lib/workato/connector/sdk/operation.rb +217 -0
- data/lib/workato/connector/sdk/request.rb +399 -0
- data/lib/workato/connector/sdk/settings.rb +130 -0
- data/lib/workato/connector/sdk/summarize.rb +61 -0
- data/lib/workato/connector/sdk/trigger.rb +96 -0
- data/lib/workato/connector/sdk/version.rb +9 -0
- data/lib/workato/connector/sdk/workato_schemas.rb +37 -0
- data/lib/workato/connector/sdk/xml.rb +35 -0
- data/lib/workato/connector/sdk.rb +58 -0
- data/lib/workato/extension/array.rb +124 -0
- data/lib/workato/extension/case_sensitive_headers.rb +51 -0
- data/lib/workato/extension/currency.rb +15 -0
- data/lib/workato/extension/date.rb +14 -0
- data/lib/workato/extension/enumerable.rb +55 -0
- data/lib/workato/extension/extra_chain_cert.rb +40 -0
- data/lib/workato/extension/hash.rb +13 -0
- data/lib/workato/extension/integer.rb +17 -0
- data/lib/workato/extension/nil_class.rb +17 -0
- data/lib/workato/extension/object.rb +38 -0
- data/lib/workato/extension/phone.rb +14 -0
- data/lib/workato/extension/string.rb +268 -0
- data/lib/workato/extension/symbol.rb +13 -0
- data/lib/workato/extension/time.rb +13 -0
- data/lib/workato/testing/vcr_encrypted_cassette_serializer.rb +38 -0
- data/lib/workato/testing/vcr_multipart_body_matcher.rb +32 -0
- data/lib/workato-connector-sdk.rb +3 -0
- data/templates/.rspec.erb +3 -0
- data/templates/Gemfile.erb +10 -0
- data/templates/connector.rb.erb +37 -0
- data/templates/spec/action_spec.rb.erb +36 -0
- data/templates/spec/connector_spec.rb.erb +18 -0
- data/templates/spec/method_spec.rb.erb +13 -0
- data/templates/spec/object_definition_spec.rb.erb +18 -0
- data/templates/spec/pick_list_spec.rb.erb +13 -0
- data/templates/spec/spec_helper.rb.erb +38 -0
- data/templates/spec/trigger_spec.rb.erb +61 -0
- metadata +372 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fcda7a1bda0d422376d4f8345bb63c8e7016d62432cb7d5b8838689347f7f18d
|
4
|
+
data.tar.gz: 8e9a38245c57162d41dbdc6ebd7385f464dc3807848decf02eb295b5a8a6d490
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fdc43f6ba0e21396c896afc879883b145306a6f03a1f45701b734d066f6431d66b34dc105d5a79bbfcb3e7b1409a2caab954e04e62e1ae395bbd06632e8a8a3f
|
7
|
+
data.tar.gz: 22fcdc88c6632b992481dd5f6b910ba8ec85b9ba72ea1a3a4345ee3d476aed7b534556b8ac8bc1cfae0f68b4f3be293328739d62d7cd248d371f1301f4e470e9
|
data/LICENSE.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2021 Workato Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,1093 @@
|
|
1
|
+
# `workato-connector-sdk`
|
2
|
+
|
3
|
+
# Getting started with the SDK Gem
|
4
|
+
In this chapter, we'll go over the pre-requisites to get started on using the Workato Gem in a few sections:
|
5
|
+
|
6
|
+
This guide below showcases how you can do the following things:
|
7
|
+
1. [Build, install and run the Workato Gem](#1-build-install-and-run-the-workato-gem)
|
8
|
+
2. [Setting up your connector project](#2-setting-up-your-connector-project)
|
9
|
+
3. [Running CLI commands](#3-running-cli-commands)
|
10
|
+
4. [Building connectors](#4-building-connectors)
|
11
|
+
5. [Write and run RSpec tests for your connector](#5-write-and-run-rspec-tests-for-your-connector)
|
12
|
+
6. [Enable CI/CD on your Github with your connector structure](#6-enabling-cicd-on-github)
|
13
|
+
|
14
|
+
## Prerequisites
|
15
|
+
1. Install [RVM ("Ruby Version Manager")](http://rvm.io/) or a Ruby manager of your choice. You can find more at [here](https://www.ruby-lang.org/en/documentation/installation/)
|
16
|
+
2. Choose between Ruby versions `2.4.10` `2.5.X` or `2.7.X`. Our preferred version is `2.7.X`.
|
17
|
+
3. Verify you're running a valid ruby version. Do this by running either `ruby -v` or the commands within your version manager. i.e., `rvm current` if you have installed RVM.
|
18
|
+
|
19
|
+
```bash
|
20
|
+
ruby -v
|
21
|
+
Output:
|
22
|
+
ruby 2.7.X
|
23
|
+
```
|
24
|
+
|
25
|
+
## 1. Install and run the Workato Gem
|
26
|
+
Installation is also done through bash which then looks for our latest version of the SDK gem in rubygems.org.
|
27
|
+
|
28
|
+
```bash
|
29
|
+
gem install workato-connector-sdk
|
30
|
+
```
|
31
|
+
|
32
|
+
Verify that your gem is correctly installed by typing in the command `workato` in terminal. You should see the following output:
|
33
|
+
|
34
|
+
```bash
|
35
|
+
Commands:
|
36
|
+
workato edit <PATH> # Edit encrypted file, e.g. settings.yaml.enc
|
37
|
+
workato exec <PATH> # Execute connector defined block
|
38
|
+
workato generate <SUBCOMMAND> # Generates code from template
|
39
|
+
workato help [COMMAND] # Describe available commands or one specific command
|
40
|
+
workato new <CONNECTOR_PATH> # Inits new connector folder
|
41
|
+
workato push <FOLDER> # Upload and release connector's code
|
42
|
+
|
43
|
+
Options:
|
44
|
+
[--verbose], [--no-verbose]
|
45
|
+
```
|
46
|
+
|
47
|
+
> *Quick Tip*: Typing the `workato` command allows you to know what commands are possible during development. Find out more about individual keys using `workato help edit` etc.
|
48
|
+
|
49
|
+
You may also know the exact location of the Workato Gem using `gem which`
|
50
|
+
|
51
|
+
```bash
|
52
|
+
gem which workato-connector-sdk
|
53
|
+
```
|
54
|
+
______
|
55
|
+
|
56
|
+
## 2. Setting up your connector project
|
57
|
+
Now that you're familiar with some CLI tools let's get down to actual connector making! We're going to go over some of the basics you'll need that will make your life easier.
|
58
|
+
|
59
|
+
Here is a basic summary of how a self-sufficient connector project should look like: (It looks similar to a normal ruby project)
|
60
|
+
```bash
|
61
|
+
. # Your connector's root folder
|
62
|
+
├── .github # Folder which stores information about your Github workflows if you're using github
|
63
|
+
├── .gitignore # Stores the information which should not be pushed via git
|
64
|
+
├── Gemfile # Store the dependencies of your project
|
65
|
+
├── Gemfile.lock # This will be automatically created.
|
66
|
+
├── README.md # This will become your Connector's description
|
67
|
+
├── logo.png # The logo of your connector. Used when you push your connector to Workato.
|
68
|
+
├── connector.rb # Your actual connector code
|
69
|
+
├── master.key # Your master key if you're encrypting your files
|
70
|
+
├── settings.yaml.enc # Where you store your credentials for your connector
|
71
|
+
├── fixtures # Folder where your input and output JSONs are stored
|
72
|
+
├── tape_library # Folder where your VCR recordings are stored
|
73
|
+
├── .rspec
|
74
|
+
└── spec # Where you store your RSpec tests
|
75
|
+
├── connector_spec.rb
|
76
|
+
├── spec_helper.rb
|
77
|
+
└── vcr_cassettes
|
78
|
+
```
|
79
|
+
|
80
|
+
This folder structure isn't something you need to abide by, but we're going to use this structure for the rest of the documentation!
|
81
|
+
|
82
|
+
> *Quick Tip*: You can use the CLI command `workato new <PATH>` which will generated some of the folder above. Some have been omitted to give you freedom to design your connector project as you see fit.
|
83
|
+
|
84
|
+
So let's take a look at what each of the files should contain:
|
85
|
+
|
86
|
+
### 2.1 .github
|
87
|
+
This folder stores information about your github action workflows. This is what we will use later on for running unit tests on Github.
|
88
|
+
|
89
|
+
### 2.2 .gitignore
|
90
|
+
This stores files that should not be pushed via git. Since you have a master.key which is used to encrypt your settings.yaml files and potentially your VCR recordings, this should be added to your .gitignore.
|
91
|
+
```
|
92
|
+
/.bundle/
|
93
|
+
/.yardoc
|
94
|
+
/_yardoc/
|
95
|
+
/coverage/
|
96
|
+
/doc/
|
97
|
+
/pkg/
|
98
|
+
/spec/reports/
|
99
|
+
/tmp/
|
100
|
+
master.key
|
101
|
+
|
102
|
+
# rspec failure tracking
|
103
|
+
.rspec_status
|
104
|
+
```
|
105
|
+
|
106
|
+
### 2.3 Gemfile
|
107
|
+
This file declares all the gems (dependencies) that your ruby project will need. All of them are needed for you to run rspec.
|
108
|
+
```ruby
|
109
|
+
# frozen_string_literal: true
|
110
|
+
|
111
|
+
source 'https://rubygems.org'
|
112
|
+
|
113
|
+
gem 'rspec'
|
114
|
+
gem 'vcr'
|
115
|
+
gem 'workato-connector-sdk'
|
116
|
+
gem 'webmock'
|
117
|
+
gem 'timecop'
|
118
|
+
gem 'byebug'
|
119
|
+
gem 'rubocop' # Only if you want to use rubocop. Not added by default.
|
120
|
+
```
|
121
|
+
|
122
|
+
### 2.4 Gemfile.lock
|
123
|
+
You don't need to create this file. It'll be created later on. This file just holds a store of all the dependencies you have, their versions, and also the dependencies your dependencies might have.
|
124
|
+
|
125
|
+
### 2.5 README.MD
|
126
|
+
This file shows up on your Github project (or other Git software you use). Use it to document what your connector does! **Not created via `workato new <PATH>` commands.**
|
127
|
+
When you use the `workato push <FOLDER>` command to sync your connector with your Workato workspace, this is the default file for your connector's description.
|
128
|
+
|
129
|
+
### 2.6 logo.png
|
130
|
+
The logo of your connector. **Not created via `workato new <PATH>` commands.**
|
131
|
+
When you use the `workato push <FOLDER>` command to sync your connector with your Workato workspace, this is the default file for your connector's logo.
|
132
|
+
|
133
|
+
### 2.7 connector.rb
|
134
|
+
Well, this is your actual connector code. This file should be a replica of your connector code in Workato.
|
135
|
+
|
136
|
+
### 2.8 master.key
|
137
|
+
The encryption key is used to encrypt your files. This key is not only for encrypting your connection credentials BUT other things that might be sensitive, like account properties. **Not created via `workato new <PATH>` command if you didn't select `secure` for your project settings.**
|
138
|
+
|
139
|
+
### 2.9 settings.yaml.enc or setting.yaml
|
140
|
+
Depending on whether you're encrypting your files or not (you really should!), it'll show as a `.yaml.enc` file or a simple `.yaml` file, respectively. **Not created via `workato new <PATH>` commands.**
|
141
|
+
|
142
|
+
Your settings file should have the following structure if you have multiple credentials.
|
143
|
+
```yaml
|
144
|
+
[Your connection name]:
|
145
|
+
api_key: valid_key
|
146
|
+
domain: valid_domain
|
147
|
+
[Other connections]:
|
148
|
+
api_key: invalid_key
|
149
|
+
domain: invalid_domain
|
150
|
+
```
|
151
|
+
|
152
|
+
If you only require one set of credentials, you may have the credentials defined at the root level.
|
153
|
+
```yaml
|
154
|
+
api_key: valid_key
|
155
|
+
domain: valid_domain
|
156
|
+
```
|
157
|
+
|
158
|
+
To create a `settings.yaml.enc` file, you'll need to run the following command - `EDITOR="nano" workato edit settings.yaml.enc` where you can replace `nano` with your preferred editor. You can either add your credentials in then or just save. Both your `settings.yaml.enc` and `master.key` file will be created. Your `master.key` file may have been created if you selected `secure` whilst using `workato new <PATH>`. When you choose to create new encrypted files, the same `master.key` will be used.
|
159
|
+
|
160
|
+
IMPORTANT: Be sure to add your `master.key` to your `.gitignore` or similar files if you're committing your project. This key will allow anyone to decrypt your files.
|
161
|
+
|
162
|
+
### 2.10 fixtures
|
163
|
+
The folder where you may store your input and output JSONs for use in RSpec or CLI.
|
164
|
+
Sample structure:
|
165
|
+
|
166
|
+
```bash
|
167
|
+
├── fixtures
|
168
|
+
│ ├── actions
|
169
|
+
│ │ └── search_customers
|
170
|
+
│ │ ├── input.json
|
171
|
+
│ │ └── output.json
|
172
|
+
│ ├── methods
|
173
|
+
│ │ └── sample_method
|
174
|
+
│ │ ├── input.json
|
175
|
+
│ │ └── output.json
|
176
|
+
│ ├── pick_lists
|
177
|
+
│ │ └── dependent
|
178
|
+
│ │ └── input.json
|
179
|
+
│ └── triggers
|
180
|
+
│ └── new_updated_object
|
181
|
+
│ ├── customer_config.json
|
182
|
+
│ ├── customer_input_poll.json
|
183
|
+
│ ├── customer_input_poll_page.json
|
184
|
+
│ ├── customer_output_fields.json
|
185
|
+
│ ├── customer_output_poll.json
|
186
|
+
│ └── customer_output_poll_page.json
|
187
|
+
```
|
188
|
+
|
189
|
+
### 2.11 .rspec
|
190
|
+
Holds standard options which will be passed to RSpec whenever it is run.
|
191
|
+
|
192
|
+
Sample .rspec contents:
|
193
|
+
```
|
194
|
+
--format documentation
|
195
|
+
--color
|
196
|
+
--require spec_helper
|
197
|
+
```
|
198
|
+
|
199
|
+
### 2.12 tape_libarary
|
200
|
+
Where RSpec will store your VCR cassettes of API requests recorded. These requests are essential for stable unit tests. **Not created via `workato new <PATH>` commands BUT created when RSpec is run.**
|
201
|
+
|
202
|
+
### 2.13 Your spec folder
|
203
|
+
This is the folder that will contain all your RSpec tests. RSpec is a ruby testing tool that can be used in conjunction with our Workato Gem to allow you to define, write and run unit tests for your connector!
|
204
|
+
|
205
|
+
#### 2.13.1 connector_spec.rb
|
206
|
+
This is your connector's main rspec file which holds all unit tests for your connector. You could split up your connector spec file into multiple folders if it helps organize your spec tests. All of your spec tests can be run in a single command using `bundle exec rspec`.
|
207
|
+
|
208
|
+
#### 2.13.2 spec_helper.rb
|
209
|
+
This file contains all the commands that should be setup before each rspec run. You may copy the files directly below. [See section 5 for more details of what the `spec_heper.rb` file should look like.](#5-write-and-run-rspec-tests-for-your-connector)
|
210
|
+
|
211
|
+
__________
|
212
|
+
|
213
|
+
## 3. Running CLI commands
|
214
|
+
So you've set up your project, and you're finally ready to get started on improving your connector.
|
215
|
+
|
216
|
+
### 3.1 workato help
|
217
|
+
```bash
|
218
|
+
workato help
|
219
|
+
|
220
|
+
Commands:
|
221
|
+
workato edit <PATH> # Edit encrypted file, e.g. settings.yaml.enc
|
222
|
+
workato exec <PATH> # Execute connector defined block
|
223
|
+
workato generate <SUBCOMMAND> # Generates code from template
|
224
|
+
workato help [COMMAND] # Describe available commands or one specific command
|
225
|
+
workato new <CONNECTOR_PATH> # Inits new connector folder
|
226
|
+
workato push <FOLDER> # Upload and release connector's code
|
227
|
+
|
228
|
+
Options:
|
229
|
+
[--verbose], [--no-verbose]
|
230
|
+
```
|
231
|
+
|
232
|
+
You may also gain more info about a specific command via `workato help [command]`
|
233
|
+
|
234
|
+
```
|
235
|
+
workato help [command]
|
236
|
+
|
237
|
+
[ Help for specific Workato gem command ]
|
238
|
+
```
|
239
|
+
|
240
|
+
### 3.2 workato edit
|
241
|
+
```
|
242
|
+
workato help edit
|
243
|
+
|
244
|
+
Usage:
|
245
|
+
workato edit <PATH>
|
246
|
+
|
247
|
+
Options:
|
248
|
+
-k, [--key=KEY] # Path to file with encrypt/decrypt key. NOTE: key from WORKATO_CONNECTOR_MASTER_KEY has higher priority
|
249
|
+
[--verbose], [--no-verbose]
|
250
|
+
|
251
|
+
Edit encrypted file, e.g. settings.yaml.enc
|
252
|
+
```
|
253
|
+
|
254
|
+
> *NOTE*: You will need to use this method to create any encrypted file. When you run this command for the first time, the `.enc` file will be created and the `master.key` will be created.
|
255
|
+
|
256
|
+
> *NOTE*: If no key is specified in your command, the gem will look for the key `master.key` in the root folder of whichever directory you're calling the command from.
|
257
|
+
|
258
|
+
### 3.3 workato exec
|
259
|
+
```
|
260
|
+
workato help exec
|
261
|
+
|
262
|
+
Usage:
|
263
|
+
workato exec <PATH>
|
264
|
+
|
265
|
+
Options:
|
266
|
+
-c, [--connector=CONNECTOR] # Path to connector source code
|
267
|
+
-s, [--settings=SETTINGS] # Path to plain or encrypted file with connection configs, passwords, tokens, secrets etc
|
268
|
+
-n, [--connection=CONNECTION] # Connection name if settings file contains multiple settings
|
269
|
+
-k, [--key=KEY] # Path to file with encrypt/decrypt key. NOTE: key from WORKATO_CONNECTOR_MASTER_KEY has higher priority
|
270
|
+
-i, [--input=INPUT] # Path to file with input JSON
|
271
|
+
[--closure=CLOSURE] # Path to file with next poll closure JSON
|
272
|
+
-a, [--args=ARGS] # Path to file with method arguments JSON
|
273
|
+
[--extended-input-schema=EXTENDED_INPUT_SCHEMA] # Path to file with extended input schema definition JSON
|
274
|
+
[--extended-output-schema=EXTENDED_OUTPUT_SCHEMA] # Path to file with extended output schema definition JSON
|
275
|
+
[--config-fields=CONFIG_FIELDS] # Path to file with config fields JSON
|
276
|
+
-w, [--webhook-payload=WEBHOOK_PAYLOAD] # Path to file with webhook payload JSON
|
277
|
+
[--webhook-params=WEBHOOK_PARAMS] # Path to file with webhook params JSON
|
278
|
+
[--webhook-headers=WEBHOOK_HEADERS] # Path to file with webhook headers JSON
|
279
|
+
[--webhook-url=WEBHOOK_URL] # Webhook URL for automatic webhook subscription
|
280
|
+
-o, [--output=OUTPUT] # Write output to JSON file
|
281
|
+
[--debug], [--no-debug]
|
282
|
+
[--verbose], [--no-verbose]
|
283
|
+
|
284
|
+
Description:
|
285
|
+
The 'workato exec' executes connector's lambda block at <PATH>. Lambda's parameters can be provided if needed, see options part.
|
286
|
+
|
287
|
+
Example:
|
288
|
+
|
289
|
+
workato exec actions.foo.execute # This executes execute block of foo action
|
290
|
+
|
291
|
+
workato exec triggers.bar.poll # This executes poll block of bar action
|
292
|
+
|
293
|
+
workato exec methods.bazz --args=input.json # This executes methods with params from input.json
|
294
|
+
```
|
295
|
+
|
296
|
+
There are a few assumptions we make when you don't declare arguments:
|
297
|
+
1. `--connector` is assumed to be `connector.rb`
|
298
|
+
2. `--settings` is assumed to be `settings.yaml.enc` or `settings.yaml` as a fallback
|
299
|
+
3. `--connection` is NOT assumed. But if there is only one set of credentials in the file, we will use that.
|
300
|
+
|
301
|
+
Some other things of note:
|
302
|
+
1. `--verbose` allows you to track all incoming and outgoing API requests.
|
303
|
+
2. `--input` allows you to reference a file which is the json input to your execute block
|
304
|
+
3. `--output` allows you to write or overwrite the output of a specific CLI utility.
|
305
|
+
|
306
|
+
### 3.4 workato generate
|
307
|
+
```
|
308
|
+
workato help generate
|
309
|
+
|
310
|
+
Commands:
|
311
|
+
workato generate help [COMMAND] # Describe subcommands or one specific subcommand
|
312
|
+
workato generate schema # Generate schema by JSON example
|
313
|
+
workato generate test # Generate empty test for connector
|
314
|
+
```
|
315
|
+
|
316
|
+
**NOTE: `workato generate schema` is currently not implemented.**
|
317
|
+
|
318
|
+
- Use `workato generate test` to generate tests based on your connector.rb file.
|
319
|
+
|
320
|
+
### 3.5 workato new
|
321
|
+
```
|
322
|
+
workato help new
|
323
|
+
|
324
|
+
Usage:
|
325
|
+
workato new <CONNECTOR_PATH>
|
326
|
+
|
327
|
+
Options:
|
328
|
+
[--verbose], [--no-verbose]
|
329
|
+
|
330
|
+
Description:
|
331
|
+
The 'workato new' command creates a new Workato connector with a default directory structure and configuration at the path you specify.
|
332
|
+
|
333
|
+
Example: workato new ~/dev/workato/random
|
334
|
+
|
335
|
+
This generates a skeletal custom connector in ~/dev/workato/random.
|
336
|
+
```
|
337
|
+
|
338
|
+
This helps you to create a sample connector project. You may also use `workato new ./[Connector_name]` to create it in the current directory you're in. There may be secondary questions which prompt you about HTTP mocking behaviour.
|
339
|
+
|
340
|
+
```
|
341
|
+
create
|
342
|
+
create Gemfile
|
343
|
+
create connector.rb
|
344
|
+
create .rspec
|
345
|
+
Please select default HTTP mocking behavior suitable for your project?
|
346
|
+
|
347
|
+
1 - secure. Cause an error to be raised for any unknown requests, all request recordings are encrypted.
|
348
|
+
To record a new cassette you need set VCR_RECORD_MODE environment variable
|
349
|
+
|
350
|
+
Example: VCR_RECORD_MODE=once bundle exec rspec spec/actions/test_action_spec.rb
|
351
|
+
|
352
|
+
2 - simple. Record new interaction if it is a new request, requests are stored as plain text and expose secret tokens.
|
353
|
+
|
354
|
+
```
|
355
|
+
|
356
|
+
- `secure` means all your unit test's HTTP requests will be encrypted. HTTP requests are recorded via [VCR](https://github.com/vcr/vcr) to ensure your tests are stable. As such, we also provide you an easy way to encrypt these recordings so your authorization credentials are not stored in plain text. **This is recommended.**
|
357
|
+
|
358
|
+
- `simple` means your HTTP requests will be stored in plain text.
|
359
|
+
|
360
|
+
### 3.6 workato push
|
361
|
+
```
|
362
|
+
workato help push
|
363
|
+
|
364
|
+
Usage:
|
365
|
+
workato push <FOLDER>
|
366
|
+
|
367
|
+
Options:
|
368
|
+
-t, [--title=TITLE] # Connector title on the Workato Platform
|
369
|
+
-d, [--description=DESCRIPTION] # Path to connector description: Markdown or plain text
|
370
|
+
-l, [--logo=LOGO] # Path to connector logo: png or jpeg file
|
371
|
+
-n, [--notes=NOTES] # Release notes
|
372
|
+
-c, [--connector=CONNECTOR] # Path to connector source code
|
373
|
+
[--api-email=API_EMAIL] # Email for accessing Workato API or set WORKATO_API_EMAIL env
|
374
|
+
[--api-token=API_TOKEN] # Token for accessing Workato API or set WORKATO_API_TOKEN env
|
375
|
+
[--environment=ENVIRONMENT] # Server to push connector code to
|
376
|
+
# Default: live
|
377
|
+
# Possible values: preview, preview-eu, live, live-eu
|
378
|
+
[--verbose], [--no-verbose]
|
379
|
+
|
380
|
+
Upload and release connector's code
|
381
|
+
```
|
382
|
+
|
383
|
+
This allows you to push your connector code from your connector project locally to your workspace. This allows you to quickly cycle from testing connector functionality and the UX of your connector.
|
384
|
+
|
385
|
+
______
|
386
|
+
|
387
|
+
## 4. Building connectors
|
388
|
+
At this point, we should highlight some of the key differences between building your connector on Workato's Cloud SDK console and using the Workato Gem.
|
389
|
+
|
390
|
+
| Workato Cloud SDK Console | Workato Gem |
|
391
|
+
|-|-|
|
392
|
+
| Able to test connections, actions and triggers in their entirety | Able to test specific keys of a connector separately. i.e. execute: and output_fields: can be tested separately |
|
393
|
+
| Able to debug the exact look and feel of input and output fields. i.e. dynamic input and output fields | No UI but able to quickly evaluate resultant Workato schema of input and output fields using CLI Utils |
|
394
|
+
| No unit tests available | Able to convert CLI commands into unit tests quickly |
|
395
|
+
| No access to account_properties or lookup tables in debugger console | Able to store account_properties and credentials in encrypted/unencrypted formats. Able to store lookup tables in unencrypted format. | |
|
396
|
+
|
397
|
+
As we continue to improve on the Workato Gem and its capabilities, more features will soon be added to the Workato Gem. In the meantime, here is an example how the Cloud console and the gem can be used in conjunction with each other.
|
398
|
+
|
399
|
+
### 4.1 Starting a connector build
|
400
|
+
1. Upon creating a new connector on Workato, you will need to first establish connectivity on the cloud console. This is essential for you to do before you bring your connector development locally using the Workato Gem.
|
401
|
+
2. After you have completed successfully creating a connection, you should have a few things on hand
|
402
|
+
- A set of working credentials
|
403
|
+
- Your connector code with a working set of credentials
|
404
|
+
3. Now, you're able to start creating your project structure (defined in step 2 of this guide) with this connector code.
|
405
|
+
4. Enter in your working credentials in the format detailed in [step 2.8](#_2-8-settings-yaml-enc-or-setting-yaml)
|
406
|
+
5. Now you're ready to begin development using the SDK gem.
|
407
|
+
|
408
|
+
### 4.2 Example: Testing your connection on CLI - All auths except OAuth 2 - auth code grant flows
|
409
|
+
Assuming we have a simple connector that uses API key authentication like this:
|
410
|
+
```ruby
|
411
|
+
{
|
412
|
+
title: "Chargebee",
|
413
|
+
|
414
|
+
connection: {
|
415
|
+
fields: [
|
416
|
+
{
|
417
|
+
name: "api_key",
|
418
|
+
control_type: "password",
|
419
|
+
hint: "You can find your API key " \
|
420
|
+
"under 'Settings'=>'Configure Chargebee'=>'API Keys and Webhooks'" \
|
421
|
+
" in Chargebee's web console.",
|
422
|
+
label: "Your API Key"
|
423
|
+
},
|
424
|
+
{
|
425
|
+
name: "domain",
|
426
|
+
control_type: "subdomain",
|
427
|
+
url: "chargebee.com"
|
428
|
+
}
|
429
|
+
],
|
430
|
+
|
431
|
+
authorization: {
|
432
|
+
type: "basic_auth",
|
433
|
+
|
434
|
+
apply: lambda do |connection|
|
435
|
+
user(connection['api_key'])
|
436
|
+
end
|
437
|
+
},
|
438
|
+
|
439
|
+
base_uri: lambda do |connect|
|
440
|
+
"https://#{connect['domain']}.chargebee.com"
|
441
|
+
end
|
442
|
+
},
|
443
|
+
|
444
|
+
test: lambda do |connection|
|
445
|
+
get("/api/v2/plans")
|
446
|
+
end,
|
447
|
+
|
448
|
+
# More code below
|
449
|
+
}
|
450
|
+
```
|
451
|
+
|
452
|
+
and a `settings.yaml.enc` or `settings.yaml` file with the following details
|
453
|
+
|
454
|
+
```yaml
|
455
|
+
My Valid Connection:
|
456
|
+
api_key: valid_api_key
|
457
|
+
domain: valid_domain
|
458
|
+
My Invalid Connection:
|
459
|
+
api_key: invalid_api_key
|
460
|
+
domain: invalid_domain
|
461
|
+
```
|
462
|
+
|
463
|
+
You can now run the following commands to verify that the `test:` lambda function you have defined is working:
|
464
|
+
```bash
|
465
|
+
workato exec test --connection='My Valid Connection' #Output of the test: lambda function should be shown
|
466
|
+
workato exec test --connection='My Invalid Connection' #You should see a `Workato::Connector::Sdk:RequestError` highlighting 401 unauthorized
|
467
|
+
```
|
468
|
+
|
469
|
+
You needn't have to declare the settings file. The Workato Gem automatically looks for a `settings.yaml.enc` or `settings.yaml` file (by this exact file name) so you don't need to declare it.
|
470
|
+
|
471
|
+
> *Note*: The output of this lambda function often isn't important. As with the behaviour of the `test:` in the cloud console, Workato only requires that this lambda function (and all HTTP requests within) are invoked successfully.
|
472
|
+
|
473
|
+
Alternatively, you may also have your `settings.yaml` or `settings.yaml.enc` file with the structure below
|
474
|
+
|
475
|
+
```yaml
|
476
|
+
api_key: valid_api_key
|
477
|
+
domain: valid_domain
|
478
|
+
```
|
479
|
+
|
480
|
+
You can now run the following commands to verify that the `test:` lambda function you have defined is working:
|
481
|
+
|
482
|
+
```bash
|
483
|
+
workato exec test #Output of the test: lambda function should be shown
|
484
|
+
```
|
485
|
+
|
486
|
+
> *Note*: This, of course, removes one less declaration in your call. You may also choose to store your invalid credentials in another file like `invalid_settings.yaml.enc`
|
487
|
+
|
488
|
+
> *Note*: You may also see a intermediary command from the Gem asking if you'd like to refresh your access tokens. This is done when HTTP requests are made which have a response that triggers the `refresh_on` block. Selecting yes would cause the Gem to update your settings file with the latest auth credentials.
|
489
|
+
|
490
|
+
### 4.3 Example: Testing your connection on CLI - OAuth 2 - auth code grant flows
|
491
|
+
For auth code grant flows, the Workato Gem doesn't simulate the browser popup so you'll need to supply the access token and refresh tokens directly!
|
492
|
+
|
493
|
+
```ruby
|
494
|
+
{
|
495
|
+
title: 'TrackVia',
|
496
|
+
connection: {
|
497
|
+
fields: [
|
498
|
+
{
|
499
|
+
name: 'custom_domain',
|
500
|
+
control_type: 'subdomain',
|
501
|
+
label: 'TrackVia subdomain',
|
502
|
+
hint: 'Enter your TrackVia subdomain. e.g. customdomain.trackvia.com. By default, <b>go.trackvia.com</b> will be used.',
|
503
|
+
optional: 'true'
|
504
|
+
},
|
505
|
+
{
|
506
|
+
name: 'client_id'
|
507
|
+
},
|
508
|
+
{
|
509
|
+
name: 'client_secret',
|
510
|
+
control_type: 'password'
|
511
|
+
}
|
512
|
+
],
|
513
|
+
|
514
|
+
authorization: {
|
515
|
+
type: 'oauth2',
|
516
|
+
|
517
|
+
authorization_url: lambda do |connection|
|
518
|
+
"https://#{connection['custom_domain'].presence || 'go.trackvia.com'}/oauth/authorize?response_type=code"
|
519
|
+
end,
|
520
|
+
|
521
|
+
acquire: lambda do |connection, auth_code, redirect_uri|
|
522
|
+
url = "https://#{connection['custom_domain'].presence || 'go.trackvia.com'}"
|
523
|
+
response = post("#{url}/oauth/token").payload(
|
524
|
+
redirect_uri: redirect_uri,
|
525
|
+
grant_type: 'authorization_code',
|
526
|
+
code: auth_code,
|
527
|
+
client_id: connection['client_id'],
|
528
|
+
client_secret: connection['client_secret']
|
529
|
+
).request_format_www_form_urlencoded
|
530
|
+
user_key = get("#{url}/3scale/openapiapps").params(access_token: response['access_token']).dig(0, 'userKey')
|
531
|
+
[
|
532
|
+
response,
|
533
|
+
nil,
|
534
|
+
{
|
535
|
+
user_key: user_key
|
536
|
+
}
|
537
|
+
]
|
538
|
+
end,
|
539
|
+
|
540
|
+
refresh: lambda do |connection, refresh_token|
|
541
|
+
url = "https://#{connection['custom_domain'].presence || 'go.trackvia.com'}"
|
542
|
+
post("#{url}/oauth/token").payload(
|
543
|
+
client_id: connection['client_id'],
|
544
|
+
client_secret: connection['client_secret'],
|
545
|
+
grant_type: 'refresh_token',
|
546
|
+
refresh_token: refresh_token
|
547
|
+
).request_format_www_form_urlencoded
|
548
|
+
end,
|
549
|
+
|
550
|
+
refresh_on: [401, 403],
|
551
|
+
|
552
|
+
apply: lambda { |connection, access_token|
|
553
|
+
params(user_key: connection['user_key'])
|
554
|
+
headers(Authorization: "Bearer #{access_token}")
|
555
|
+
}
|
556
|
+
},
|
557
|
+
|
558
|
+
base_uri: lambda do |connection|
|
559
|
+
if connection['custom_domain'].presence
|
560
|
+
"https://#{connection['custom_domain']}/openapi/"
|
561
|
+
else
|
562
|
+
"https://go.trackvia.com/openapi/"
|
563
|
+
end
|
564
|
+
end
|
565
|
+
},
|
566
|
+
|
567
|
+
test: ->(_connection) { get('views') },
|
568
|
+
# More code below
|
569
|
+
}
|
570
|
+
```
|
571
|
+
|
572
|
+
and a `settings.yaml.enc` or `settings.yaml` file with the following details
|
573
|
+
|
574
|
+
```yaml
|
575
|
+
My Valid Connection:
|
576
|
+
access_token: "valid_access_token"
|
577
|
+
refresh_token: "valid_refresh_token"
|
578
|
+
user_key: "valid_user_key"
|
579
|
+
client_id: "valid_client_id"
|
580
|
+
client_secret: "valid_client_secret"
|
581
|
+
Invalid Access Token:
|
582
|
+
access_token: "invalid_access_token"
|
583
|
+
refresh_token: "valid_refresh_token"
|
584
|
+
user_key: "valid_user_key"
|
585
|
+
client_id: "valid_client_id"
|
586
|
+
client_secret: "valid_client_secret"
|
587
|
+
```
|
588
|
+
|
589
|
+
You can now run the following commands to verify that the `test:` lambda function you have defined is working:
|
590
|
+
```bash
|
591
|
+
workato exec test --connection='My Valid Connection' #Output of the test: lambda function should be shown
|
592
|
+
workato exec test --connection='Invalid Access Token' --verbose #You should see a see a set of request where the test is tried, access token receives 401 and the sequence to refresh the gem using the refresh key is used! This allows you to test how your connector refreshes a connection.
|
593
|
+
```
|
594
|
+
|
595
|
+
> *Note*: `--verbose` can be used to details everything, including the HTTP requests. You may also see a intermediary command from the Gem asking if you'd like to refresh your access tokens. This is done when HTTP requests are made which have a response that triggers the `refresh_on` block. Selecting yes would cause the Gem to update your settings file with the latest auth credentials.
|
596
|
+
|
597
|
+
### Example: Testing a sample action on CLI
|
598
|
+
Continuing from the previous example, let's take a look at a simple action and invoke the individual lambda functions.
|
599
|
+
```ruby
|
600
|
+
{
|
601
|
+
title: "Chargebee",
|
602
|
+
|
603
|
+
connection: {
|
604
|
+
# Connection code found above
|
605
|
+
},
|
606
|
+
|
607
|
+
test: lambda do |connection|
|
608
|
+
get("/api/v2/plans")
|
609
|
+
end,
|
610
|
+
|
611
|
+
actions: {
|
612
|
+
|
613
|
+
search_customers: {
|
614
|
+
title: "Search customers",
|
615
|
+
subtitle: "Search for customers using name",
|
616
|
+
description: "Search customer in Chargebee",
|
617
|
+
|
618
|
+
input_fields: lambda do |object_definitions|
|
619
|
+
[
|
620
|
+
{
|
621
|
+
name: "name",
|
622
|
+
label: "Name to query by",
|
623
|
+
hint: "Provide the name of the customer to query"
|
624
|
+
},
|
625
|
+
{
|
626
|
+
name: "id",
|
627
|
+
label: "Name to query by",
|
628
|
+
hint: "Provide the name of the customer to query"
|
629
|
+
}
|
630
|
+
]
|
631
|
+
end,
|
632
|
+
|
633
|
+
|
634
|
+
execute: lambda do |connection, input, input_schema, output_schema|
|
635
|
+
get("/api/v2/customers",input)
|
636
|
+
end,
|
637
|
+
|
638
|
+
|
639
|
+
output_fields: lambda do |object_definitions|
|
640
|
+
[
|
641
|
+
{
|
642
|
+
name: "first_name"
|
643
|
+
},
|
644
|
+
{
|
645
|
+
name: "last_name"
|
646
|
+
},
|
647
|
+
{
|
648
|
+
name: "id"
|
649
|
+
}
|
650
|
+
]
|
651
|
+
end
|
652
|
+
}
|
653
|
+
|
654
|
+
},
|
655
|
+
}
|
656
|
+
```
|
657
|
+
|
658
|
+
And a `settings.yaml.enc` or `settings.yaml` that is the same as the example for testing your connection.
|
659
|
+
|
660
|
+
You can now run the following commands to execute the `execute:` lambda function for this action.
|
661
|
+
```bash
|
662
|
+
workato exec actions.search_customers.execute --connection="My Valid Connection" --input="fixtures/actions/search_customer/search_customer_input.json" #The output of the lambda function should be shown.
|
663
|
+
```
|
664
|
+
Let's decompose this command.
|
665
|
+
|
666
|
+
- `workato exec actions.search_customers.execute` defines that you first want to test an action, followed by `search_customers` which is the key for the action you're testing. `execute` tells us that you want to test the `execute:` lambda function.
|
667
|
+
|
668
|
+
- `--connection="My Valid Connection"` tells us to use the connection named "My Valid Connection" in our settings file. If your settings file only has one set of connection settings, you don't need to define this.
|
669
|
+
|
670
|
+
- `--input="fixtures/actions/search_customer/search_customer_input.json"` The path to the input json file which mimics the `input` argument for the `execute:` lambda function.
|
671
|
+
|
672
|
+
Now, this command assumes a few things which you can also specify.
|
673
|
+
|
674
|
+
- The file in which the credentials are stored (assumed to be `settings.yaml` or `settings.yaml.enc`) but you can specify it with `--settings=`. If the `connection` argument is used in the `execute` lambda function, this is used for that. It is also used for any authorization logic required for your action's HTTP requests.
|
675
|
+
|
676
|
+
- The connector to reference for the path (`actions.search_customers.execute`). Assumed to be `connector.rb` but you can specify it with `--connector=`
|
677
|
+
|
678
|
+
> *NOTE*: Use `workato help exec` to find more arguments you can use!
|
679
|
+
|
680
|
+
### Example: Testing a method in the CLI
|
681
|
+
So let's talk about testing a method as well. Methods in connectors are essential to reuse code for data pre or post-processing or to store Workato schema.
|
682
|
+
|
683
|
+
```ruby
|
684
|
+
{
|
685
|
+
title: "Chargebee",
|
686
|
+
|
687
|
+
connection: {
|
688
|
+
# Connection code found above
|
689
|
+
},
|
690
|
+
|
691
|
+
test: lambda do |connection|
|
692
|
+
get("/api/v2/plans")
|
693
|
+
end,
|
694
|
+
|
695
|
+
methods: {
|
696
|
+
|
697
|
+
sample_method: lambda do |string1, string2|
|
698
|
+
string1 + string2
|
699
|
+
end
|
700
|
+
},
|
701
|
+
}
|
702
|
+
```
|
703
|
+
|
704
|
+
You can now run the following commands to execute the lambda function for this method.
|
705
|
+
```bash
|
706
|
+
workato exec methods.sample_method --args='fixtures/methods/sample_method/sample_method_input.json' #The output of the lambda function should be shown.
|
707
|
+
```
|
708
|
+
Let's decompose this command.
|
709
|
+
|
710
|
+
- `workato exec methods.sample_method` defines that you first want to test a method, followed by `sample_method`, which is the key for the method you're testing.
|
711
|
+
- `--args='fixtures/methods/sample_method/sample_method_input.json'` tells us to execute the method with the arguments found in the "sample_method_input.json".
|
712
|
+
|
713
|
+
The `sample_method_input.json` might look like this:
|
714
|
+
|
715
|
+
```json
|
716
|
+
[
|
717
|
+
"hello",
|
718
|
+
"world"
|
719
|
+
]
|
720
|
+
```
|
721
|
+
|
722
|
+
As you can see, the json is an array where each index belongs to each argument in the method (`string1` and `string2`), respectively. If only one argument is needed, you could give a single index array or provide the value itself!
|
723
|
+
|
724
|
+
> *Quick Tip*: Testing methods which need to send HTTP requests
|
725
|
+
> Since some methods also send outgoing HTTP requests, you may supply `--settings` to supply authorization credentials. If not, the method will default to your `settings.yaml.enc` or `settings.yaml` file.
|
726
|
+
|
727
|
+
### Example: Using byebug with your connector
|
728
|
+
You may also use byebug in conjunction with your CLI tools to debug efficiently. Do this by first adding `require 'byebug'` to the top of your connector file. Then you may place the word `byebug` anywhere in your code to set a breakpoint for additional debugging.
|
729
|
+
|
730
|
+
|
731
|
+
```ruby
|
732
|
+
require 'byebug' # added before your connector
|
733
|
+
|
734
|
+
{
|
735
|
+
title: "Chargebee",
|
736
|
+
# More code here
|
737
|
+
methods: {
|
738
|
+
get_customers: lambda do
|
739
|
+
response = get('/api/v2/customers')
|
740
|
+
byebug
|
741
|
+
response
|
742
|
+
end,
|
743
|
+
|
744
|
+
sample_method: lambda do |string1, string2|
|
745
|
+
byebug
|
746
|
+
string1 + ' ' + string2
|
747
|
+
end
|
748
|
+
}
|
749
|
+
}
|
750
|
+
```
|
751
|
+
|
752
|
+
where running the sample_method on CLI would allow you to print out variables and control the execution flow of the connector.
|
753
|
+
```bash
|
754
|
+
workato exec methods.sample_method --args='input/sample_method_input.json'
|
755
|
+
|
756
|
+
[777, 786] in connector.rb
|
757
|
+
777: byebug
|
758
|
+
778: response
|
759
|
+
779: end,
|
760
|
+
780:
|
761
|
+
781: sample_method: lambda do |string1, string2|
|
762
|
+
782: byebug
|
763
|
+
=> 783: string1 + ' ' + string2
|
764
|
+
784: end
|
765
|
+
785: }
|
766
|
+
786: }
|
767
|
+
(byebug) string1
|
768
|
+
"hello"
|
769
|
+
(byebug) string2
|
770
|
+
"world"
|
771
|
+
(byebug) c
|
772
|
+
```
|
773
|
+
|
774
|
+
> `c` in byebug means continue, which allows the execution to continue forward. Read more on how to use byebug [here.](https://www.sitepoint.com/the-ins-and-outs-of-debugging-ruby-with-byebug/)
|
775
|
+
|
776
|
+
______
|
777
|
+
|
778
|
+
## 5. Write and run RSpec tests for your connector
|
779
|
+
So now that you can run CLI commands let's get to the fun stuff! Writing unit tests to prevent regressions with your connector.
|
780
|
+
|
781
|
+
Let's begin by revisiting that folder structure we saw in step 2.
|
782
|
+
|
783
|
+
```bash
|
784
|
+
.
|
785
|
+
├── Gemfile
|
786
|
+
├── Gemfile.lock
|
787
|
+
├── README.md
|
788
|
+
├── connector.rb
|
789
|
+
├── fixtures # Folder to store all your input and output jsons for CLI commands and tests
|
790
|
+
│ ├── actions
|
791
|
+
│ │ └── search_customers
|
792
|
+
│ │ ├── search_customers_input.json
|
793
|
+
│ │ └── search_customers_output.json
|
794
|
+
│ └── methods
|
795
|
+
│ ├── get_all_output_fields
|
796
|
+
│ │ └── args.json
|
797
|
+
│ └── make_schema_builder_fields_sticky
|
798
|
+
│ ├── make_schema_builder_fields_sticky_input.json
|
799
|
+
│ └── make_schema_builder_fields_sticky_output.json
|
800
|
+
├── invalid_settings.yaml.enc
|
801
|
+
├── master.key
|
802
|
+
├── settings.yaml.enc
|
803
|
+
├── .rspec
|
804
|
+
└── spec
|
805
|
+
├── connector_spec.rb
|
806
|
+
└── spec_helper.rb
|
807
|
+
```
|
808
|
+
|
809
|
+
You may see that a few more files have been added.
|
810
|
+
|
811
|
+
1. `fixtures`
|
812
|
+
These folders here are for you to store your input and output jsons for various parts of your connector you want to test. Keep in mind that you'll use input json files to test your connector's actions, triggers, methods etc. Input jsons should be formed manually (You may be able to design them yourself or also use the debugger console on the cloud SDK to build these jsons). Output jsons can be created from CLI commands by declaring the `--output` parameter to save the output of a CLI command to a file.
|
813
|
+
|
814
|
+
2. `.rspec` file
|
815
|
+
Holds the configurations for your RSpec runs. The `.rspec` file specifies default flags that get passed to the rspec command when you run your tests. So if you want one of the options you see listed on `rspec --help` to apply by default, you can add them here. `--format documentation` allows your tests to be grouped. `--color` enables coloring in the rspec output. `--require spec_helper` tells your rspec runs to require your `spec_helper.rb` before every run.
|
816
|
+
|
817
|
+
```
|
818
|
+
--format documentation
|
819
|
+
--color
|
820
|
+
--require spec_helper
|
821
|
+
```
|
822
|
+
|
823
|
+
3. spec folder
|
824
|
+
Your spec folder will contain various files and folders that will allow you to run rspec - a ruby unit testing framework. Most of your tests will be contained inside the `connector_spec.rb` file but we'll go over the other files in the folder first.
|
825
|
+
|
826
|
+
- `spec_helper.rb` - loaded in every rspec run where you can define certain common attributes. You can learn more about what configurations you can give over [here.](https://github.com/rspec/rspec-core)
|
827
|
+
```ruby
|
828
|
+
# frozen_string_literal: true
|
829
|
+
|
830
|
+
require "webmock/rspec"
|
831
|
+
require "timecop"
|
832
|
+
require "vcr"
|
833
|
+
require "workato-connector-sdk"
|
834
|
+
require "workato/testing/vcr_encrypted_cassette_serializer"
|
835
|
+
require "workato/testing/vcr_multipart_body_matcher"
|
836
|
+
|
837
|
+
RSpec.configure do |config|
|
838
|
+
# Enable flags like --only-failures and --next-failure
|
839
|
+
config.example_status_persistence_file_path = ".rspec_status"
|
840
|
+
|
841
|
+
# Disable RSpec exposing methods globally on `Module` and `main`
|
842
|
+
config.disable_monkey_patching!
|
843
|
+
|
844
|
+
config.expect_with :rspec do |c|
|
845
|
+
c.syntax = :expect
|
846
|
+
end
|
847
|
+
end
|
848
|
+
|
849
|
+
VCR.configure do |config|
|
850
|
+
config.cassette_library_dir = "tape_library"
|
851
|
+
config.hook_into :webmock
|
852
|
+
config.cassette_serializers[:encrypted] = Workato::Testing::VCREncryptedCassetteSerializer.new
|
853
|
+
config.register_request_matcher :headers_without_user_agent do |request1, request2|
|
854
|
+
request1.headers.except("User-Agent") == request2.headers.except("User-Agent")
|
855
|
+
end
|
856
|
+
config.register_request_matcher :multipart_body do |request1, request2|
|
857
|
+
Workato::Testing::VCRMultipartBodyMatcher.call(request1, request2)
|
858
|
+
end
|
859
|
+
config.default_cassette_options = {
|
860
|
+
record: ENV.fetch('VCR_RECORD_MODE', :none).to_sym,
|
861
|
+
serialize_with: :encrypted,
|
862
|
+
match_requests_on: %i[uri headers_without_user_agent body]
|
863
|
+
}
|
864
|
+
config.configure_rspec_metadata!
|
865
|
+
end
|
866
|
+
```
|
867
|
+
|
868
|
+
> *Quick Tip*: This spec_helper.rb is generated for you when you use `workato new <PATH>` to generate a new connector. The example above shows a spec_helper.rb which is created when your project is `secure`. This encrypts all VCR recordings using your `master.key`. **By default our record mode for secure is `none` which means no new VCR cassettes are recorded. You can change this by setting a new environment variable `VCR_RECORD_MODE` to `once`.**
|
869
|
+
|
870
|
+
- `vcr_cassettes` - VCR allows us to record API requests and stub the response after it is recorded. Find out more [here.](https://relishapp.com/vcr/vcr/docs)
|
871
|
+
|
872
|
+
4. Your connector_spec file (also contained in your spec folder)
|
873
|
+
|
874
|
+
Here's how your connector_spec file MAY look like. Of course, you're able to configure your spec file to your team's liking.
|
875
|
+
We won't go into too much detail about how to write RSpec because it's ultimately up to you how you want to build your unit tests! Below we have a sample that you might find helpful. I also like this [tutorial here.](https://semaphoreci.com/community/tutorials/getting-started-with-rspec). Below, you can see an example
|
876
|
+
|
877
|
+
```ruby
|
878
|
+
# frozen_string_literal: true
|
879
|
+
|
880
|
+
RSpec.describe 'connector', :vcr do
|
881
|
+
let(:connector) { Workato::Connector::Sdk::Connector.from_file('connector.rb', settings) }
|
882
|
+
let(:settings) { Workato::Connector::Sdk::Settings.from_default_file }
|
883
|
+
|
884
|
+
it { expect(connector).to be_present }
|
885
|
+
|
886
|
+
describe 'test' do
|
887
|
+
subject(:output) { connector.test(settings) }
|
888
|
+
|
889
|
+
context 'given valid credentials' do
|
890
|
+
it 'establishes valid connection' do
|
891
|
+
expect(output).to be_truthy
|
892
|
+
end
|
893
|
+
|
894
|
+
it 'returns response that is not excessively large' do
|
895
|
+
# large Test responses might also cause connections to be evaluated wrongly
|
896
|
+
expect(output.to_s.length).to be < 5000
|
897
|
+
end
|
898
|
+
end
|
899
|
+
|
900
|
+
context 'given invalid credentials' do
|
901
|
+
let(:settings) { Workato::Connector::Sdk::Settings.from_encrypted_file('invalid_settings.yaml.enc'}
|
902
|
+
|
903
|
+
it 'establishes invalid connection' do
|
904
|
+
expect { output }
|
905
|
+
.to raise_error('500 Internal Server Error')
|
906
|
+
end
|
907
|
+
end
|
908
|
+
end
|
909
|
+
end
|
910
|
+
```
|
911
|
+
|
912
|
+
> *Quick Tip*: You may also use the command `workato generate test` to generate RSpec test stubs for you to begin writing unit tests for your connector. This handles most of the heavy lifting such as instantiating your connector or settings.
|
913
|
+
|
914
|
+
### 5.1 Running RSpec
|
915
|
+
To run RSpec, you should have the project structure setup. Running rspec is as easy as running the Workato Gem in CLI. You simply type `bundle exec rspec` in bash in your project home directory, and rspec should begin running.
|
916
|
+
|
917
|
+
> note: you may also run `rspec` but using `bundle exec rspec` ensures that the rspec Gem version you're using to run the tests is the version specified in your Gemfile.
|
918
|
+
|
919
|
+
You may also use run only specific tests at a time. If not, rspec will run all spec files in your spec folder.
|
920
|
+
|
921
|
+
```bash
|
922
|
+
bundle exec rspec ./spec/connector_spec.rb:16 #Runs the test or group of tests at line 16 of your spec file.
|
923
|
+
```
|
924
|
+
|
925
|
+
### 5.2 Using the Workato Gem in your connector_spec.rb
|
926
|
+
First, your spec file should have included at least `require 'bundler/setup'` and `require 'workato-connector-sdk'`. Include `require 'json'` to read JSON files as well!
|
927
|
+
|
928
|
+
#### 5.2.1 Instantiating your connector
|
929
|
+
To instantiate your connector, you can use this:
|
930
|
+
```ruby
|
931
|
+
let(:connector) { Workato::Connector::Sdk::Connector.from_file('connector.rb', settings) }
|
932
|
+
```
|
933
|
+
|
934
|
+
#### 5.2.2 Instantiating your settings
|
935
|
+
To instantiate your settings, you can use `from_default_file` which defers to your `settings.yaml.enc` or `settings.yaml` file.
|
936
|
+
```ruby
|
937
|
+
let(:settings) { Workato::Connector::Sdk::Settings.from_default_file }
|
938
|
+
```
|
939
|
+
|
940
|
+
To instantiate your settings from an alternative setting file, you can use `from_encrypted_file` or `from_file`.
|
941
|
+
```ruby
|
942
|
+
let(:settings) { Workato::Connector::Sdk::Settings.from_encrypted_file('invalid_settings.yaml.enc') }
|
943
|
+
```
|
944
|
+
|
945
|
+
#### 5.2.3 Testing your test: key
|
946
|
+
```ruby
|
947
|
+
subject(:output) { connector.test(settings) } # executes the test: key when the subject `output` is used.
|
948
|
+
```
|
949
|
+
|
950
|
+
This method accepts 1 argument. `settings` in the first position similar to the `test:` lambda.
|
951
|
+
|
952
|
+
Example:
|
953
|
+
```ruby
|
954
|
+
context 'given valid credentials' do
|
955
|
+
it 'establishes valid connection' do
|
956
|
+
expect(output).to be_truthy # Since the test lambda gives a response, it is truthy.
|
957
|
+
end
|
958
|
+
|
959
|
+
it 'returns response that is not excessively large' do
|
960
|
+
# large Test responses might also cause connections to be evaluated wrongly
|
961
|
+
expect(output.to_s.length).to be < 5000
|
962
|
+
end
|
963
|
+
end
|
964
|
+
```
|
965
|
+
|
966
|
+
#### 5.2.4 Testing an action
|
967
|
+
```ruby
|
968
|
+
let(:action) { connector.actions.copy_asset }
|
969
|
+
```
|
970
|
+
|
971
|
+
This method accepts four arguments. `settings` in the first position. `input` in the second position. `extended_input_schema` and `extended_output_schema` in the third and fourth position, respectively. In our example below, we have omitted `extended_input_schema` and `extended_output_schema` as they were not used in the action.
|
972
|
+
|
973
|
+
Example:
|
974
|
+
```ruby
|
975
|
+
describe 'execute' do
|
976
|
+
subject(:output) { action.execute(settings, input) }
|
977
|
+
|
978
|
+
context 'given asset'
|
979
|
+
let(:input) { JSON.parse(File.read('fixtures/actions/copy_asset/copy_asset_input.json')) }
|
980
|
+
let(:expected_output) { JSON.parse(File.read('fixtures/actions/copy_asset/copy_asset_output.json')) }
|
981
|
+
it 'uploads asset'
|
982
|
+
expect(output).to eq(expected_output)
|
983
|
+
end
|
984
|
+
end
|
985
|
+
end
|
986
|
+
```
|
987
|
+
|
988
|
+
#### 5.2.4 Testing a method
|
989
|
+
```ruby
|
990
|
+
connector.methods.[method_name](*input) # Where the arguments depend on your method definition.
|
991
|
+
```
|
992
|
+
|
993
|
+
There are two ways to define your method in your tests. You can pass the arguments directly or from a file. For example, given a method:
|
994
|
+
```ruby
|
995
|
+
sample_method: lambda do |string1, string2|
|
996
|
+
string1 + ' ' + string2
|
997
|
+
end
|
998
|
+
```
|
999
|
+
|
1000
|
+
In RSpec, you may pass the `string1` and `string2` arguments directly.
|
1001
|
+
```ruby
|
1002
|
+
connector.methods.sample_method("hello", "world")
|
1003
|
+
```
|
1004
|
+
|
1005
|
+
Or use the same JSON file `sample_method_input.json` we had in [step 4.3](#example-testing-a-method-in-the-cli)
|
1006
|
+
|
1007
|
+
```ruby
|
1008
|
+
input = JSON.parse(File.read('input/sample_method_input.json'))
|
1009
|
+
output = connector.methods.sample_method(*input)
|
1010
|
+
```
|
1011
|
+
|
1012
|
+
Here's another example, given a method:
|
1013
|
+
```ruby
|
1014
|
+
make_schema_builder_fields_sticky: lambda do |input|
|
1015
|
+
input.map do |field|
|
1016
|
+
if field[:properties].present?
|
1017
|
+
field[:properties] = call("make_schema_builder_fields_sticky",
|
1018
|
+
field[:properties])
|
1019
|
+
elsif field["properties"].present?
|
1020
|
+
field["properties"] = call("make_schema_builder_fields_sticky",
|
1021
|
+
field["properties"])
|
1022
|
+
end
|
1023
|
+
field[:sticky] = true
|
1024
|
+
field
|
1025
|
+
end
|
1026
|
+
end,
|
1027
|
+
```
|
1028
|
+
|
1029
|
+
In RSpec, your tests for it may look something like this:
|
1030
|
+
```ruby
|
1031
|
+
RSpec.describe 'methods/make_schema_builder_fields_sticky', :vcr do
|
1032
|
+
let(:connector) { Workato::Connector::Sdk::Connector.from_file('connector.rb') }
|
1033
|
+
let(:settings) { Workato::Connector::Sdk::Settings.from_default_file }
|
1034
|
+
|
1035
|
+
subject(:result) { connector.methods.make_schema_builder_fields_sticky(arg_1) }
|
1036
|
+
|
1037
|
+
context 'given non-sticky schema' do
|
1038
|
+
let(:arg_1) { JSON.parse(File.read('fixtures/methods/make_schema_builder_fields_sticky/make_schema_builder_fields_sticky_input.json')) }
|
1039
|
+
let(:expected_output) { JSON.parse(File.read('fixtures/methods/make_schema_builder_fields_sticky/make_schema_builder_fields_sticky_output.json')) }
|
1040
|
+
it 'makes all fields sticky' do
|
1041
|
+
expect(result).to eq(expected_output)
|
1042
|
+
end
|
1043
|
+
end
|
1044
|
+
end
|
1045
|
+
```
|
1046
|
+
|
1047
|
+
> For methods that send HTTP requests, the credentials used are the ones you instantiate your connector with. i.e. `Workato::Connector::Sdk::Connector.from_file('connector.rb', settings)`
|
1048
|
+
|
1049
|
+
## 6. Enabling CI/CD on Github
|
1050
|
+
This process should remain similar to other CI/CD tools. First, you want to set up dependencies in your CI/CD environment. Depending on whether you're reading this during the Workato Gem's Beta phase or not, you might need to include the Workato Gem's original gemspec and dependencies to build the Workato Gem. When the gem is publicly available, we will release the Workato Gem to rubygems.org, so bundle install should suffice.
|
1051
|
+
|
1052
|
+
Afterward, you will need to create a GitHub workflows file. Under the `.github/workflows` folder, create a `ruby.yml` file.
|
1053
|
+
|
1054
|
+
> Note: If you are using encrypted settings (`settings.yaml.enc`), be sure to add your master.key to your `.gitignore` and set your environment variables in your Github repository. Find out more [here.](https://docs.github.com/en/actions/reference/encrypted-secrets) Your variable should be your master.key's contents. We named it `WORKATO_CONNECTOR_MASTER_KEY` for the purpose of the example below. This environment variable will be used to run the rspec instead of your `master.key` file which shouldn't be present in your Github repository.
|
1055
|
+
|
1056
|
+
|
1057
|
+
```yaml
|
1058
|
+
name: Connector Unit Test
|
1059
|
+
|
1060
|
+
on:
|
1061
|
+
push:
|
1062
|
+
branches: [ main ]
|
1063
|
+
pull_request:
|
1064
|
+
branches: [ main ]
|
1065
|
+
|
1066
|
+
jobs:
|
1067
|
+
test:
|
1068
|
+
|
1069
|
+
runs-on: ubuntu-latest
|
1070
|
+
strategy:
|
1071
|
+
matrix:
|
1072
|
+
ruby-version: ['2.4.10', '2.5', '2.7']
|
1073
|
+
|
1074
|
+
steps:
|
1075
|
+
- uses: actions/checkout@v2
|
1076
|
+
- name: Set up Ruby
|
1077
|
+
uses: ruby/setup-ruby@v1
|
1078
|
+
with:
|
1079
|
+
ruby-version: ${{ matrix.ruby-version }}
|
1080
|
+
bundler-cache: true
|
1081
|
+
- name: Run tests
|
1082
|
+
env: # Only needed if using encrypted files.
|
1083
|
+
WORKATO_CONNECTOR_MASTER_KEY: ${{ secrets.WORKATO_CONNECTOR_MASTER_KEY }}
|
1084
|
+
run: bundle exec rspec
|
1085
|
+
# - name: Push to DEV workspace # Use this to push to DEV. This can be enabled when a PR is merged.
|
1086
|
+
# env:
|
1087
|
+
# WORKATO_API_EMAIL: ${{ secrets.WORKATO_DEV_ENVIRONMENT_API_EMAIL}}
|
1088
|
+
# WORKATO_API_TOKEN: ${{ secrets.WORKATO_DEV_ENVIRONMENT_API_TOKEN}}
|
1089
|
+
# WORKATO_API_FOLDER: ${{ secrets.WORKATO_DEV_ENVIRONMENT_API_HOME_FOLDER}}
|
1090
|
+
# run: workato push $WORKATO_API_FOLDER
|
1091
|
+
```
|
1092
|
+
|
1093
|
+
You may also add more Github actions for rubocop to automate this.
|