workato-connector-sdk 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +20 -0
  3. data/README.md +1093 -0
  4. data/exe/workato +5 -0
  5. data/lib/workato/cli/edit_command.rb +71 -0
  6. data/lib/workato/cli/exec_command.rb +191 -0
  7. data/lib/workato/cli/generate_command.rb +105 -0
  8. data/lib/workato/cli/generators/connector_generator.rb +94 -0
  9. data/lib/workato/cli/generators/master_key_generator.rb +56 -0
  10. data/lib/workato/cli/main.rb +142 -0
  11. data/lib/workato/cli/push_command.rb +208 -0
  12. data/lib/workato/connector/sdk/account_properties.rb +60 -0
  13. data/lib/workato/connector/sdk/action.rb +88 -0
  14. data/lib/workato/connector/sdk/block_invocation_refinements.rb +30 -0
  15. data/lib/workato/connector/sdk/connector.rb +230 -0
  16. data/lib/workato/connector/sdk/dsl/account_property.rb +15 -0
  17. data/lib/workato/connector/sdk/dsl/call.rb +17 -0
  18. data/lib/workato/connector/sdk/dsl/error.rb +15 -0
  19. data/lib/workato/connector/sdk/dsl/http.rb +60 -0
  20. data/lib/workato/connector/sdk/dsl/lookup_table.rb +15 -0
  21. data/lib/workato/connector/sdk/dsl/time.rb +21 -0
  22. data/lib/workato/connector/sdk/dsl/workato_code_lib.rb +105 -0
  23. data/lib/workato/connector/sdk/dsl/workato_schema.rb +15 -0
  24. data/lib/workato/connector/sdk/dsl.rb +46 -0
  25. data/lib/workato/connector/sdk/errors.rb +30 -0
  26. data/lib/workato/connector/sdk/lookup_tables.rb +62 -0
  27. data/lib/workato/connector/sdk/object_definitions.rb +74 -0
  28. data/lib/workato/connector/sdk/operation.rb +217 -0
  29. data/lib/workato/connector/sdk/request.rb +399 -0
  30. data/lib/workato/connector/sdk/settings.rb +130 -0
  31. data/lib/workato/connector/sdk/summarize.rb +61 -0
  32. data/lib/workato/connector/sdk/trigger.rb +96 -0
  33. data/lib/workato/connector/sdk/version.rb +9 -0
  34. data/lib/workato/connector/sdk/workato_schemas.rb +37 -0
  35. data/lib/workato/connector/sdk/xml.rb +35 -0
  36. data/lib/workato/connector/sdk.rb +58 -0
  37. data/lib/workato/extension/array.rb +124 -0
  38. data/lib/workato/extension/case_sensitive_headers.rb +51 -0
  39. data/lib/workato/extension/currency.rb +15 -0
  40. data/lib/workato/extension/date.rb +14 -0
  41. data/lib/workato/extension/enumerable.rb +55 -0
  42. data/lib/workato/extension/extra_chain_cert.rb +40 -0
  43. data/lib/workato/extension/hash.rb +13 -0
  44. data/lib/workato/extension/integer.rb +17 -0
  45. data/lib/workato/extension/nil_class.rb +17 -0
  46. data/lib/workato/extension/object.rb +38 -0
  47. data/lib/workato/extension/phone.rb +14 -0
  48. data/lib/workato/extension/string.rb +268 -0
  49. data/lib/workato/extension/symbol.rb +13 -0
  50. data/lib/workato/extension/time.rb +13 -0
  51. data/lib/workato/testing/vcr_encrypted_cassette_serializer.rb +38 -0
  52. data/lib/workato/testing/vcr_multipart_body_matcher.rb +32 -0
  53. data/lib/workato-connector-sdk.rb +3 -0
  54. data/templates/.rspec.erb +3 -0
  55. data/templates/Gemfile.erb +10 -0
  56. data/templates/connector.rb.erb +37 -0
  57. data/templates/spec/action_spec.rb.erb +36 -0
  58. data/templates/spec/connector_spec.rb.erb +18 -0
  59. data/templates/spec/method_spec.rb.erb +13 -0
  60. data/templates/spec/object_definition_spec.rb.erb +18 -0
  61. data/templates/spec/pick_list_spec.rb.erb +13 -0
  62. data/templates/spec/spec_helper.rb.erb +38 -0
  63. data/templates/spec/trigger_spec.rb.erb +61 -0
  64. 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.