doc-detective 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Doc Detective: A Documentation Unit Testing Framework
1
+ # Doc Detective: The Documentation Testing Framework
2
2
 
3
3
  Unit test documentation to validate UX flows, in-GUI text, and images. Primarily useful for process docs, Doc Detective supports test definitions single-sourced in documentation or defined in separate test files to suit your infrastructure needs.
4
4
 
@@ -6,7 +6,7 @@ Doc Detective ingests text files, parses them for test actions, then executes th
6
6
 
7
7
  This project handles test parsing and web-based UI testing--it doesn't support results reporting or notifications. This framework is a part of testing infrastructures and needs to be complimented by other components.
8
8
 
9
- Doc Detective uses `puppeteer` to install, launch, and drive Chromium to perform tests. `puppeteer` removes the requirement to manually configure a local web browser and enables easy screenshotting and video recording.
9
+ Doc Detective uses `puppeteer` to install, launch, and drive Chromium to perform tests. `puppeteer` removes the requirement to manually configure a local web browser and enables easy screenshotting and video recording. In the event `puppeteer` fails to launch Chromium, Doc Detective tries to fall back to local installs of Chromium, Chrome, and Firefox.
10
10
 
11
11
  **Note:** By default, `puppeteer`'s Chromium doesn't run in Docker containers, which means that `puppeteer` doesn't work either. Don't run Doc Detective in a Docker container unless you first confirm that you have a custom implementation of headless Chrome/Chromium functional in the container. The approved answer to [this question](https://askubuntu.com/questions/79280/how-to-install-chrome-browser-properly-via-command-line) works for me, but it may not work in all environments.
12
12
 
@@ -99,6 +99,7 @@ Simple format:
99
99
  "css": "[title=Search]"
100
100
  }
101
101
  ```
102
+
102
103
  Advanced format:
103
104
 
104
105
  ```json
@@ -106,7 +107,7 @@ Advanced format:
106
107
  "action": "find",
107
108
  "css": "[title=Search]",
108
109
  "wait": {
109
- "duration": 10000,
110
+ "duration": 10000
110
111
  },
111
112
  "matchText": {
112
113
  "text": "Search"
@@ -121,7 +122,7 @@ Advanced format:
121
122
  "type": {
122
123
  "keys": "$SHORTHAIR_CAT_SEARCH",
123
124
  "trailingSpecialKey": "Enter",
124
- "envs": "./sample/variables.env"
125
+ "env": "./sample/variables.env"
125
126
  }
126
127
  }
127
128
  ```
@@ -155,7 +156,6 @@ Format:
155
156
  "alignV": "center",
156
157
  "offsetX": 10,
157
158
  "offsetY": 10
158
-
159
159
  }
160
160
  ```
161
161
 
@@ -186,7 +186,7 @@ Advanced format with an environment variable:
186
186
  "css": "input#password",
187
187
  "keys": "$PASSWORD",
188
188
  "trailingSpecialKey": "Enter",
189
- "envs": "./sample/variables.env"
189
+ "env": "./sample/variables.env"
190
190
  }
191
191
  ```
192
192
 
@@ -255,9 +255,52 @@ Format:
255
255
  }
256
256
  ```
257
257
 
258
+ ### HTTP request
259
+
260
+ Perform a generic HTTP request, for example to a REST API. Checks if the server returns an acceptable status code. If `uri` doesn't include a protocol, the protocol defaults to HTTPS. If `statusCodes` isn't specified, defaults to `[200]`.
261
+
262
+ Format:
263
+
264
+ ```json
265
+ {
266
+ "action": "httpRequest",
267
+ "env": "path/to/variables.env",
268
+ "uri": "https://www.api-server.com",
269
+ "method": "post",
270
+ "requestHeaders": {
271
+ "header": "value"
272
+ },
273
+ "requestParams": {
274
+ "param": "value"
275
+ },
276
+ "requestData": {
277
+ "field": "value"
278
+ },
279
+ "responseHeaders": {
280
+ "header": "value"
281
+ },
282
+ "responseData": {
283
+ "field": "value"
284
+ },
285
+ "statusCodes": [200]
286
+ }
287
+ ```
288
+
289
+ | Field | Description | Example |
290
+ | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
291
+ | `action` | Required. The action to perform. | `"httpRequest"` |
292
+ | `env` | Optional. File path for a .env file of variables to load. | `"./path/to/variables.env"` |
293
+ | `uri` | Required. The URI to send the request to.<br>Supports setting values from environment variables. | <ul><li>`"https://www.api-server.com"`</li><li>`"$URI"`</li></ul> |
294
+ | `method` | Optional. The HTTP method for the request. Similar to curl's `-X` option.<br>Defaults to "get". Accepted values: ["get", "post", "put", "patch", "delete"] | `"get"` |
295
+ | `requestHeaders` | Optional. Headers to include in the request formatted as a JSON object. Similar to curl's `-H` option. <br> Supports setting the whole headers object and individual header values from environment variables. | <ul><li>`{ "Content-Type": "application/json" }`</li><li>`"$REQUEST_HEADERS"`</li><li>`{ "Content-Type": "$CONTENT_TYPE" }`</li></ul> |
296
+ | `requestData` | Optional. Data to send with the request. Similar to curl's `-d` option. <br> Supports setting the whole data object and individual data values from environment variables. | <ul><li>`{ "id": 1, "first_name": "George", "last_name": "Washington" }`</li><li>`"$REQUEST_DATA"`</li><li>`{ "id": 1, "first_name": "$FIRST_NAME", "last_name": "$LAST_NAME" }`</li></ul> |
297
+ | `responseHeaders` | Optional. A non-exhaustive object of headers that should be included in the response. If a specified header is missing, or if a specified header value is incorrect, the action fails. If the response headers include headers that aren't specified by this option, the test can still pass. <br> Supports setting the whole headers object and individual header values from environment variables. | <ul><li>`{ "Content-Type": "application/json" }`</li><li>`$RESPONSE_HEADERS`</li><li>`{ "Content-Type": "$CONTENT_TYPE" }`</li></ul> |
298
+ | `responseData` | Optional. A non-exhaustive data object that should be included in the response. If a specified data field is missing, or if a specified value is incorrect, the action fails. If the response data payload includes additional fields that aren't specified by this option, the test can still pass. <br> Supports setting the whole data object and individual data values from environment variables. | <ul><li>`{ "id": 1, "last_name": "Washington" }`</li><li>`"$REQUEST_DATA"`</li><li>`{ "id": 1, "last_name": "$LAST_NAME" }`</li></ul> |
299
+ | `statusCodes` | Optional. An array of accepted HTTP status response codes. Defaults to `[200]`. If the response's status code isn't included in this array, the action fails. | [ 200, 204 ] |
300
+
258
301
  ### Check a link
259
302
 
260
- Check if a link returns an acceptable status code from a GET request. If `uri` doesn't include a protocol, the protocol defaults to HTTPS. If `statuscodes` isn't specified, defaults to `[200]`.
303
+ Check if a link returns an acceptable status code from a GET request. If `uri` doesn't include a protocol, the protocol defaults to HTTPS. If `statusCodes` isn't specified, defaults to `[200]`.
261
304
 
262
305
  Format:
263
306
 
@@ -265,25 +308,27 @@ Format:
265
308
  {
266
309
  "action": "checkLink",
267
310
  "uri": "https://www.google.com",
268
- "statusCodes": [ 200 ]
311
+ "statusCodes": [200]
269
312
  }
270
313
  ```
271
314
 
272
315
  ### Start recording
273
316
 
274
- Start recording the current browser viewport. Must be followed by a `stopRecording` action. Supported extensions: .mp4, .gif
317
+ Start recording the current browser viewport. Must be followed by a `stopRecording` action. Supported extensions: .mp4, .webm, .gif
275
318
 
276
- **Note:** `.gif` format is **not** recommended. Because of file format and encoding differences, `.gif` files tend to be ~6.5 times larger than `.mp4` files, and with lower visual fidelity. But if `.gif` is a hard requirement for you, it's here. Creating `.gif` files also creates `.mp4` files of the recordings.
319
+ **Note:** `.gif` format is **not** recommended. Because of file format and encoding differences, `.gif` files tend to be ~6.5 times larger than `.mp4` files, and with lower visual fidelity. But if `.gif` is a hard requirement for you, it's here.
277
320
 
278
321
  Format:
279
322
 
280
323
  ```json
281
324
  {
282
325
  "action": "startRecording",
283
- "mediaDirectory": "samples",
326
+ "overwrite": false,
327
+ "mediaDirectory": "./samples",
284
328
  "filename": "results.mp4",
285
- "gifFps": 15,
286
- "gifWidth": 400
329
+ "fps": 30,
330
+ "width": 1200,
331
+ "height": 800
287
332
  }
288
333
  ```
289
334
 
@@ -518,20 +563,21 @@ Analytics reporting is off by default. If you want to make extra sure that Doc D
518
563
 
519
564
  **Note:** Updating Doc Detective may revert any modified code, so be ready to make code edits repeatedly.
520
565
 
521
- ## Potential future features
566
+ ## Potential future updates
522
567
 
523
- - Browser auto-detection and fallback.
524
568
  - Docker image with bundled Chromium/Chrome/Firefox.
525
569
  - New/upgraded test actions:
526
- - New: Curl commands. (Support substitution/setting env vars. Only check for `200 OK`.)
527
570
  - New: Test if a referenced image (such as an icon) is present in the captured screenshot.
571
+ - Upgrade: Additional `httpRequest` input sanitization.
528
572
  - Upgrade: `screenshot` and `startRecording` boolean for whether to perform the action or not if the expected output file already exists.
529
- - Upgrade: `startRecording` to remove MP4 when the output is a GIF.
530
573
  - Upgrade: `startRecording` and `stopRecording` to support start, stop, and intermediate test action state image matching to track differences between video captures from different runs.
531
574
  - Upgrade: `startRecording` to store the output file in a different location if a recorded action fails. This could help with debugging.
532
575
  - In-content test framing to identify when content is covered by a test defined in another file. This could enable content coverage analysis.
533
576
  - Suggest tests by parsing document text.
534
577
  - Automatically insert suggested tests based on document text.
578
+ - Detailed field descriptions per action.
579
+ - Refactor tests into individual files.
580
+ - Rewrite cross-action recording status tracking.
535
581
 
536
582
  ## License
537
583
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doc-detective",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Unit test documentation (and record videos of those tests).",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -36,8 +36,8 @@
36
36
  "browserOptions": {
37
37
  "headless": "true",
38
38
  "path": "",
39
- "height": 600,
40
- "width": 800
39
+ "height": 800,
40
+ "width": 1200
41
41
  },
42
42
  "analytics": {
43
43
  "send": false,
@@ -4,7 +4,7 @@ To use Google Search to find information on kittens,
4
4
 
5
5
  1. Open [Google Search](https://www.google.com).
6
6
 
7
- [comment]: # (test {"testId":"process-search-kittens", "action":"startRecording", "filename":"results.gif", "gifFps":15, "gifWidth":300})
7
+ [comment]: # (test {"testId":"process-search-kittens", "action":"startRecording", "overwrite":false, "filename":"results.gif", "fps":15})
8
8
  [comment]: # (test {"testId":"process-search-kittens", "action":"goTo", "uri":"www.google.com"})
9
9
 
10
10
  2. In the search bar, enter "kittens", then press Enter.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "tests": [
3
3
  {
4
- "id": "process-lucky-shorthair",
4
+ "id": "process-search-kittens",
5
5
  "actions": [
6
6
  {
7
7
  "action": "goTo",
@@ -14,7 +14,84 @@
14
14
  {
15
15
  "action": "type",
16
16
  "css": "[title=Search]",
17
- "keys": "american shorthair cats",
17
+ "keys": "kittens",
18
+ "trailingSpecialKey": "Enter",
19
+ "result": {
20
+ "status": "PASS",
21
+ "description": "Typed keys."
22
+ }
23
+ },
24
+ {
25
+ "action": "wait",
26
+ "duration": "5000",
27
+ "result": {
28
+ "status": "PASS",
29
+ "description": "Wait complete."
30
+ }
31
+ },
32
+ {
33
+ "action": "screenshot",
34
+ "filename": "results.png",
35
+ "matchPrevious": false,
36
+ "matchThreshold": 0.1,
37
+ "result": {
38
+ "status": "PASS",
39
+ "description": "Captured screenshot.",
40
+ "image": "/config/workspace/doc-detective/sample/results.png"
41
+ }
42
+ }
43
+ ],
44
+ "status": "PASS"
45
+ },
46
+ {
47
+ "id": "text-match-lucky",
48
+ "actions": [
49
+ {
50
+ "action": "goTo",
51
+ "uri": "www.google.com",
52
+ "result": {
53
+ "status": "PASS",
54
+ "description": "Opened URI."
55
+ }
56
+ },
57
+ {
58
+ "action": "matchText",
59
+ "css": "#gbqfbb",
60
+ "text": "I'm Feeling Lucky",
61
+ "result": {
62
+ "status": "PASS",
63
+ "description": "Element text matched expected text."
64
+ }
65
+ },
66
+ {
67
+ "action": "matchText",
68
+ "css": "#gbqfbb",
69
+ "text": "$TEXT",
70
+ "env": "./sample/variables.env",
71
+ "result": {
72
+ "status": "PASS",
73
+ "description": "Element text matched expected text."
74
+ }
75
+ }
76
+ ],
77
+ "status": "PASS"
78
+ },
79
+ {
80
+ "id": "process-lucky-shorthair",
81
+ "actions": [
82
+ {
83
+ "action": "goTo",
84
+ "uri": "$URL",
85
+ "env": "./sample/variables.env",
86
+ "result": {
87
+ "status": "PASS",
88
+ "description": "Opened URI."
89
+ }
90
+ },
91
+ {
92
+ "action": "type",
93
+ "css": "[title=Search]",
94
+ "keys": "$SHORTHAIR_CAT_SEARCH",
18
95
  "result": {
19
96
  "status": "PASS",
20
97
  "description": "Typed keys."
@@ -22,7 +99,6 @@
22
99
  },
23
100
  {
24
101
  "action": "click",
25
- "moveMouse": true,
26
102
  "css": "#gbqfbb",
27
103
  "result": {
28
104
  "status": "PASS",
@@ -31,6 +107,57 @@
31
107
  }
32
108
  ],
33
109
  "status": "PASS"
110
+ },
111
+ {
112
+ "id": "non-ui-tests",
113
+ "actions": [
114
+ {
115
+ "action": "runShell",
116
+ "command": "echo $USERNAME",
117
+ "env": "./sample/variables.env",
118
+ "result": {
119
+ "status": "PASS",
120
+ "description": "Executed command.",
121
+ "stdout": "foo",
122
+ "stderr": "",
123
+ "exitCode": 0
124
+ }
125
+ },
126
+ {
127
+ "action": "checkLink",
128
+ "uri": "https://www.google.com",
129
+ "statusCodes": [
130
+ 200
131
+ ],
132
+ "result": {
133
+ "status": "PASS",
134
+ "description": "Returned 200"
135
+ }
136
+ },
137
+ {
138
+ "action": "checkLink",
139
+ "uri": "$URL",
140
+ "statusCodes": [
141
+ 200
142
+ ],
143
+ "result": {
144
+ "status": "PASS",
145
+ "description": "Returned 200"
146
+ }
147
+ },
148
+ {
149
+ "action": "httpRequest",
150
+ "uri": "$URL",
151
+ "statusCodes": [
152
+ 200
153
+ ],
154
+ "result": {
155
+ "status": "PASS",
156
+ "description": "Returned 200."
157
+ }
158
+ }
159
+ ],
160
+ "status": "PASS"
34
161
  }
35
162
  ]
36
163
  }
package/sample/tests.json CHANGED
@@ -85,6 +85,13 @@
85
85
  "statusCodes": [
86
86
  200
87
87
  ]
88
+ },
89
+ {
90
+ "action": "httpRequest",
91
+ "uri": "$URL",
92
+ "statusCodes": [
93
+ 200
94
+ ]
88
95
  }
89
96
  ]
90
97
  }
package/src/index.js CHANGED
@@ -40,8 +40,6 @@ async function main(config, argv) {
40
40
 
41
41
  // Run tests
42
42
  const results = await runTests(config, tests);
43
- log(config, "debug", `RESULTS:`);
44
- log(config, "debug", results);
45
43
 
46
44
  // Output
47
45
  outputResults(config, results);