@pipedream/testmo 0.1.0 → 0.3.0

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 ADDED
@@ -0,0 +1,11 @@
1
+ # Overview
2
+
3
+ The Testmo API enables automation and integration of your testing workflows into the broader CI/CD pipeline. With Pipedream, you can use this API to trigger tests, update test cases, log results, and sync status with other project management tools. By creating custom serverless workflows on Pipedream, you can connect Testmo to various apps, manage test lifecycles, and respond to events from other services in real-time.
4
+
5
+ # Example Use Cases
6
+
7
+ - **Trigger Test Runs After Code Commits**: When a new commit is pushed to a repository in GitHub, use a Pipedream workflow to automatically trigger a series of test cases in Testmo. This ensures that new code is tested immediately, keeping your deployment pipeline efficient.
8
+
9
+ - **Sync Test Results with Project Management Tools**: After tests are completed in Testmo, send the results to a project management tool like Jira or Asana. Use a Pipedream workflow to create or update issues based on the test outcomes, keeping your team in sync with the latest testing status.
10
+
11
+ - **Aggregate Test Reports for Analytics**: Collect test results from Testmo and send them to a data visualization tool like Google Sheets or Data Studio. With a Pipedream workflow, you can create custom dashboards or reports that provide insights into your testing process and help identify areas for improvement.
@@ -0,0 +1,104 @@
1
+ import testmo from "../../testmo.app.mjs";
2
+ import constants from "../../common/constants.mjs";
3
+
4
+ export default {
5
+ key: "testmo-append-to-automation-run",
6
+ name: "Append to Automation Run",
7
+ version: "0.0.2",
8
+ annotations: {
9
+ destructiveHint: false,
10
+ openWorldHint: true,
11
+ readOnlyHint: false,
12
+ },
13
+ description: "Appends test artifacts, fields or links to an existing automation run. [See the documentation](https://docs.testmo.com/api/reference/automation-runs#post-automation-runs-automation_run_id-append)",
14
+ type: "action",
15
+ props: {
16
+ testmo,
17
+ projectId: {
18
+ propDefinition: [
19
+ testmo,
20
+ "projectId",
21
+ ],
22
+ },
23
+ automationRunId: {
24
+ propDefinition: [
25
+ testmo,
26
+ "automationRunId",
27
+ (c) => ({
28
+ projectId: c.projectId,
29
+ }),
30
+ ],
31
+ },
32
+ artifacts: {
33
+ propDefinition: [
34
+ testmo,
35
+ "artifacts",
36
+ ],
37
+ },
38
+ links: {
39
+ type: "string[]",
40
+ label: "Links",
41
+ description: "List of links to attach to the automation run (such as a link back to the build in the CI tool that triggered the tests).",
42
+ optional: true,
43
+ },
44
+ numFields: {
45
+ type: "integer",
46
+ label: "Number of Fields",
47
+ description: "Number of fields to enter name, type, and value for",
48
+ optional: true,
49
+ reloadProps: true,
50
+ },
51
+ },
52
+ async additionalProps() {
53
+ const props = {};
54
+ for (let i = 1; i <= this.numFields; i++) {
55
+ props[`name_${i}`] = {
56
+ type: "string",
57
+ label: `Field ${i} - Name`,
58
+ };
59
+ props[`type_${i}`] = {
60
+ type: "integer",
61
+ label: `Field ${i} - Type`,
62
+ options: constants.FIELD_TYPES,
63
+ };
64
+ props[`value_${i}`] = {
65
+ type: "string",
66
+ label: `Field ${i} - Value`,
67
+ optional: true,
68
+ };
69
+ }
70
+ return props;
71
+ },
72
+ async run({ $ }) {
73
+ const artifacts = this.artifacts?.map((artifact) => ({
74
+ name: artifact,
75
+ url: artifact,
76
+ }));
77
+ const links = this.links?.map((link) => ({
78
+ name: link,
79
+ url: link,
80
+ }));
81
+ const fields = [];
82
+ for (let i = 1; i <= this.numFields; i++) {
83
+ fields.push({
84
+ name: this[`name_${i}`],
85
+ type: this[`type_${i}`],
86
+ value: this[`value_${i}`],
87
+ });
88
+ }
89
+
90
+ const response = await this.testmo.appendToAutomationRun({
91
+ automationRunId: this.automationRunId,
92
+ data: {
93
+ artifacts,
94
+ links,
95
+ fields,
96
+ },
97
+ $,
98
+ });
99
+
100
+ $.export("$summary", `Successfully appended data to automation run with ID ${this.automationRunId}.`);
101
+
102
+ return response;
103
+ },
104
+ };
@@ -0,0 +1,152 @@
1
+ import testmo from "../../testmo.app.mjs";
2
+ import constants from "../../common/constants.mjs";
3
+
4
+ export default {
5
+ key: "testmo-append-to-thread",
6
+ name: "Append to Thread in Automation Run",
7
+ version: "0.0.2",
8
+ annotations: {
9
+ destructiveHint: false,
10
+ openWorldHint: true,
11
+ readOnlyHint: false,
12
+ },
13
+ description: "Appends test artifacts, fields or test results to an existing thread in an automation run. [See the documentation](https://docs.testmo.com/api/reference/automation-runs#post-automation-runs-threads-automation_run_thread_id-append)",
14
+ type: "action",
15
+ props: {
16
+ testmo,
17
+ projectId: {
18
+ propDefinition: [
19
+ testmo,
20
+ "projectId",
21
+ ],
22
+ },
23
+ automationRunId: {
24
+ propDefinition: [
25
+ testmo,
26
+ "automationRunId",
27
+ (c) => ({
28
+ projectId: c.projectId,
29
+ }),
30
+ ],
31
+ },
32
+ threadId: {
33
+ propDefinition: [
34
+ testmo,
35
+ "threadId",
36
+ (c) => ({
37
+ automationRunId: c.automationRunId,
38
+ }),
39
+ ],
40
+ },
41
+ elapsedObserved: {
42
+ type: "integer",
43
+ label: "Elapsed Observed",
44
+ description: "Partial observed elapsed (execution time) in microseconds to add to the overall observed time of the thread.",
45
+ optional: true,
46
+ },
47
+ artifacts: {
48
+ propDefinition: [
49
+ testmo,
50
+ "artifacts",
51
+ ],
52
+ },
53
+ numFields: {
54
+ type: "integer",
55
+ label: "Number of Fields",
56
+ description: "Number of fields to append",
57
+ optional: true,
58
+ reloadProps: true,
59
+ },
60
+ numTests: {
61
+ type: "integer",
62
+ label: "Number of Tests",
63
+ description: "Number of tests to append",
64
+ optional: true,
65
+ reloadProps: true,
66
+ },
67
+ },
68
+ async additionalProps() {
69
+ const props = {};
70
+ if (this.numFields) {
71
+ for (let i = 1; i <= this.numFields; i++) {
72
+ props[`fieldName_${i}`] = {
73
+ type: "string",
74
+ label: `Field ${i} - Name`,
75
+ };
76
+ props[`type_${i}`] = {
77
+ type: "integer",
78
+ label: `Field ${i} - Type`,
79
+ options: constants.FIELD_TYPES,
80
+ };
81
+ props[`value_${i}`] = {
82
+ type: "string",
83
+ label: `Field ${i} - Value`,
84
+ optional: true,
85
+ };
86
+ }
87
+ }
88
+ if (this.numTests) {
89
+ for (let i = 1; i <= this.numTests; i++) {
90
+ props[`key_${i}`] = {
91
+ type: "string",
92
+ label: `Test ${i} - Key`,
93
+ description: "Key used to identify tests across multiple automation runs (in the context of the same source)",
94
+ };
95
+ props[`testName_${i}`] = {
96
+ type: "string",
97
+ label: `Test ${i} - Name`,
98
+ description: "Name of the test",
99
+ };
100
+ props[`status_${i}`] = {
101
+ type: "string",
102
+ label: `Test ${i} - Status`,
103
+ description: "Alias of the status for the result of the test (for example, `failed` or `passed`). The status aliases can be configured in Testmo's admin area.",
104
+ };
105
+ props[`folder_${i}`] = {
106
+ type: "string",
107
+ label: `Test ${i} - Folder`,
108
+ description: "Fully qualified name of the target folder of the test. Folders can be used to group related tests and usually map to class or type names as defined in the test automation suite",
109
+ };
110
+ }
111
+ }
112
+ return props;
113
+ },
114
+ async run({ $ }) {
115
+ const artifacts = this.artifacts?.map((artifact) => ({
116
+ name: artifact,
117
+ url: artifact,
118
+ }));
119
+ const fields = [];
120
+ for (let i = 1; i <= this.numFields; i++) {
121
+ fields.push({
122
+ name: this[`fieldName_${i}`],
123
+ type: this[`type_${i}`],
124
+ value: this[`value_${i}`],
125
+ });
126
+ }
127
+ const tests = [];
128
+ for (let i = 1; i <= this.numTests; i++) {
129
+ tests.push({
130
+ key: this[`key_${i}`],
131
+ name: this[`testName_${i}`],
132
+ status: this[`status_${i}`],
133
+ folder: this[`folder_${i}`],
134
+ });
135
+ }
136
+
137
+ const response = await this.testmo.appendToThread({
138
+ threadId: this.threadId,
139
+ data: {
140
+ elapsed_observed: this.elapsedObserved,
141
+ artifacts,
142
+ fields,
143
+ tests,
144
+ },
145
+ $,
146
+ });
147
+
148
+ $.export("$summary", `Successfully appended data to automation run thread with ID ${this.threadId}.`);
149
+
150
+ return response;
151
+ },
152
+ };
@@ -4,7 +4,12 @@ import testmo from "../../testmo.app.mjs";
4
4
  export default {
5
5
  key: "testmo-create-automation-run",
6
6
  name: "Create Automation Run",
7
- version: "0.0.1",
7
+ version: "0.0.3",
8
+ annotations: {
9
+ destructiveHint: false,
10
+ openWorldHint: true,
11
+ readOnlyHint: false,
12
+ },
8
13
  description: "Creates a new automation run in a target project in preparation for adding threads and test results. [See the documentation](https://docs.testmo.com/api/reference/automation-runs#post-projects-project_id-automation-runs)",
9
14
  type: "action",
10
15
  props: {
@@ -3,7 +3,12 @@ import testmo from "../../testmo.app.mjs";
3
3
  export default {
4
4
  key: "testmo-list-automation-runs",
5
5
  name: "List Automation Runs",
6
- version: "0.0.1",
6
+ version: "0.0.3",
7
+ annotations: {
8
+ destructiveHint: false,
9
+ openWorldHint: true,
10
+ readOnlyHint: true,
11
+ },
7
12
  description: "List all automation runs for a project. [See the documentation](https://docs.testmo.com/api/reference/automation-runs#get-projects-project_id-automation-runs)",
8
13
  type: "action",
9
14
  props: {
@@ -0,0 +1,33 @@
1
+ import testmo from "../../testmo.app.mjs";
2
+
3
+ export default {
4
+ key: "testmo-list-project-id-options",
5
+ name: "List Project ID Options",
6
+ description: "Retrieves available options for the Project ID field.",
7
+ version: "0.0.1",
8
+ type: "action",
9
+ annotations: {
10
+ destructiveHint: false,
11
+ openWorldHint: true,
12
+ readOnlyHint: true,
13
+ },
14
+ props: {
15
+ testmo,
16
+ page: {
17
+ type: "integer",
18
+ label: "Page",
19
+ description: "The page of results to retrieve.",
20
+ min: 0,
21
+ default: 0,
22
+ },
23
+ },
24
+ async run({ $ }) {
25
+ const options = await testmo.propDefinitions.projectId.options.call(this.testmo, {
26
+ page: this.page,
27
+ });
28
+ $.export("$summary", `Successfully retrieved ${options.length} option${options.length === 1
29
+ ? ""
30
+ : "s"}`);
31
+ return options;
32
+ },
33
+ };
@@ -0,0 +1,46 @@
1
+ import testmo from "../../testmo.app.mjs";
2
+
3
+ export default {
4
+ key: "testmo-list-project-sessions",
5
+ name: "List Project Sessions",
6
+ version: "0.0.2",
7
+ annotations: {
8
+ destructiveHint: false,
9
+ openWorldHint: true,
10
+ readOnlyHint: true,
11
+ },
12
+ description: "List all sessions for a project. [See the documentation](https://docs.testmo.com/api/reference/sessions#get-projects-project_id-sessions)",
13
+ type: "action",
14
+ props: {
15
+ testmo,
16
+ projectId: {
17
+ propDefinition: [
18
+ testmo,
19
+ "projectId",
20
+ ],
21
+ },
22
+ },
23
+ async run({ $ }) {
24
+ const {
25
+ testmo,
26
+ projectId,
27
+ } = this;
28
+
29
+ const items = testmo.paginate({
30
+ fn: testmo.listSessions,
31
+ projectId,
32
+ });
33
+
34
+ const responseArray = [];
35
+
36
+ for await (const item of items) {
37
+ responseArray.push(item);
38
+ }
39
+
40
+ $.export("$summary", `${responseArray.length} session${responseArray.length === 1
41
+ ? " was"
42
+ : "s were"} successfully retrieved!`);
43
+
44
+ return responseArray;
45
+ },
46
+ };
@@ -0,0 +1,26 @@
1
+ const FIELD_TYPES = [
2
+ {
3
+ value: 1,
4
+ label: "Regular string",
5
+ },
6
+ {
7
+ value: 2,
8
+ label: "Plain text",
9
+ },
10
+ {
11
+ value: 3,
12
+ label: "HTML text",
13
+ },
14
+ {
15
+ value: 4,
16
+ label: "Text to display in a terminal/console frame (with a monospaced font)",
17
+ },
18
+ {
19
+ value: 5,
20
+ label: "URL",
21
+ },
22
+ ];
23
+
24
+ export default {
25
+ FIELD_TYPES,
26
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipedream/testmo",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Pipedream Testmo Components",
5
5
  "main": "testmo.app.mjs",
6
6
  "keywords": [
@@ -13,6 +13,6 @@
13
13
  "access": "public"
14
14
  },
15
15
  "dependencies": {
16
- "@pipedream/platform": "^1.5.1"
16
+ "@pipedream/platform": "^1.6.8"
17
17
  }
18
18
  }
package/testmo.app.mjs CHANGED
@@ -62,6 +62,53 @@ export default {
62
62
  return result.map(({ name }) => name);
63
63
  },
64
64
  },
65
+ automationRunId: {
66
+ type: "string",
67
+ label: "Automation Run Id",
68
+ description: "The Id of the automation run.",
69
+ async options({
70
+ projectId, page,
71
+ }) {
72
+ const { result } = await this.listAutomationRuns({
73
+ projectId,
74
+ params: {
75
+ page: page + 1,
76
+ },
77
+ });
78
+
79
+ return result.map(({
80
+ id: value, name: label,
81
+ }) => ({
82
+ label,
83
+ value,
84
+ }));
85
+ },
86
+ },
87
+ threadId: {
88
+ type: "string",
89
+ label: "Thread Id",
90
+ description: "The Id of the thread of the automation run.",
91
+ async options({ automationRunId }) {
92
+ const { result } = await this.getAutomationRun({
93
+ automationRunId,
94
+ });
95
+ if (!result || !result?.threads) {
96
+ return;
97
+ }
98
+ return result.threads.map(({
99
+ id: value, name: label,
100
+ }) => ({
101
+ label,
102
+ value,
103
+ }));
104
+ },
105
+ },
106
+ artifacts: {
107
+ type: "string[]",
108
+ label: "Artifacts",
109
+ description: "List of URLs of externally stored test artifacts to link to the thread (such as log files, screenshots or test data)",
110
+ optional: true,
111
+ },
65
112
  },
66
113
  methods: {
67
114
  _apiUrl() {
@@ -122,6 +169,40 @@ export default {
122
169
  ...args,
123
170
  });
124
171
  },
172
+ getAutomationRun({
173
+ automationRunId, ...args
174
+ }) {
175
+ return this._makeRequest({
176
+ path: `automation/runs/${automationRunId}`,
177
+ ...args,
178
+ });
179
+ },
180
+ listSessions({
181
+ projectId, ...args
182
+ }) {
183
+ return this._makeRequest({
184
+ path: `projects/${projectId}/sessions`,
185
+ ...args,
186
+ });
187
+ },
188
+ appendToAutomationRun({
189
+ automationRunId, ...args
190
+ }) {
191
+ return this._makeRequest({
192
+ method: "POST",
193
+ path: `automation/runs/${automationRunId}/append`,
194
+ ...args,
195
+ });
196
+ },
197
+ appendToThread({
198
+ threadId, ...args
199
+ }) {
200
+ return this._makeRequest({
201
+ method: "POST",
202
+ path: `automation/runs/threads/${threadId}/append`,
203
+ ...args,
204
+ });
205
+ },
125
206
  async *paginate({
126
207
  fn, params = {}, maxResults = null, ...args
127
208
  }) {