@skyramp/skyramp 0.4.31

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Skyramp
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # skyramp
2
+
3
+ `skyramp` is an npm module that provides utility functions for leveraging [skyramp CLI](https://skyramp.dev/docs/commands/skyramp/) commands. The `skyramp` module provides functionalities to create and apply mock configurations for both gRPC and REST APIs. It also offers features for testing and asserting scenarios in various test environments. The module exports the following classes: `RestEndpoint`, `GrpcEndpoint`, `Scenario`, and `SkyrampClient`.
4
+
5
+ ## Installation
6
+ To install Skyramp, simply run the following command in your terminal:
7
+ ```bash
8
+ npm install skyramp
9
+ ```
10
+
11
+ ## Usage
12
+ Once you've installed Skyramp, you can import it into your project like this:
13
+
14
+ ```bash
15
+ const { GrpcEndpoint, RestEndpoint, SkyrampClient, Scenario } = require('skyramp');
16
+ ```
17
+
18
+ ### SkyrampClient
19
+ The `SkyrampClient` class is the main entry point to interact with the skyramp module. It allows you to apply configurations, start test scenarios, and deploy and delete workers. First, you must set up the `SkyrampClient` with a kubernetes cluster.
20
+
21
+ **Example: Provision Local Cluster with Skyramp**
22
+ ```bash
23
+ const skyrampClient = new SkyrampClient();
24
+ skyrampClient.applyLocal().then(function() {
25
+ // Local cluster provisioned
26
+ }).catch(function(error) {
27
+ // Error occurred during provisioning
28
+ });
29
+ ```
30
+ Once you have a `SkyrampClient` instance configured with a kubernetes cluster, you can deploy the Skyramp Worker in-cluster, for applying mocks and running tests.
31
+ **Example: Deploy Skyramp Worker**
32
+ ```bash
33
+ skyrampClient.deployWorker('my-namespace').then(function() {
34
+ // Worker deployed successfully
35
+ }).catch(function(error) {
36
+ // Error occurred during deployment
37
+ });
38
+ ```
39
+
40
+ ### RestEndpoint
41
+ The `RestEndpoint` class represents a REST API endpoint and provides methods to configure mock responses to apply them to the `SkyrampClient`.
42
+
43
+ **Example: Create REST Mock Configuration**
44
+ ```bash
45
+ restEndpoint = new RestEndpoint('artists', 'artists-GET', 50050, 'api/openapi/artists.yaml');
46
+ restEndpoint.mockMethodFromFile('artists-GET', 'files/rest-values.yaml');
47
+ skyrampClient.mockerApply('my-namespace', restEndpoint).then(function() {
48
+ // Mock applied successfully
49
+ }).catch(function(error) {
50
+ // Error occurred during mock application
51
+ });
52
+ ```
53
+
54
+ ### GrpcEndpoint
55
+ The `GrpcEndpoint` class represents a gRPC API endpoint and provides methods to configure mock responses to apply them to the `SkyrampClient`.
56
+
57
+ **Example: Create gRPC Mock Configuration**
58
+ ```bash
59
+ grpcEndpoint = new GrpcEndpoint('routeguide', 'RouteGuide', 50051, 'api/pb/routeguide.proto');
60
+ grpcEndpoint.mockMethodFromFile('GetFeature', 'files/grpc-response.yaml');
61
+ skyrampClient.mockerApply('my-namespace', grpcEndpoint).then(function() {
62
+ // Mock applied successfully
63
+ }).catch(function(error) {
64
+ // Error occurred during mock application
65
+ });
66
+ ```
67
+
68
+ ### Scenario
69
+ The `Scenario` class allows you to define test scenarios by specifying a series of API requests and assertions to be made. Once a `Scenario` is created, you can start it using the `SkyrampClient` instance.
70
+
71
+ **Example: Test Assert Scenario (REST)**
72
+ ```bash
73
+ scenario = new Scenario('rest-test')
74
+ step1 = scenario.addRequest(restEndpoint, 'artists-GET');
75
+ step2 = scenario.addAssertEqual(`${step1}.res.items[0].artist_name`, 'abc');
76
+ skyrampClient.testerStart('test-worker', scenario).then(function() {
77
+ // Test scenario started
78
+ }).catch(function(error) {
79
+ // Error occurred during the test scenario
80
+ });
81
+ ```
82
+
83
+ **Example: Test Assert Scenario (gRPC)**
84
+ ```bash
85
+ scenario = new Scenario('routeguide-assert-test')
86
+ step1 = scenario.addRequestFromFile(grpcEndpoint, 'GetFeature', 'files/grpc-request.yaml');
87
+ step2 = scenario.addAssertEqual(`${step1}.res.name`, 'test-feature');
88
+ skyrampClient.testerStart('test-worker', scenario).then(function() {
89
+ // Test scenario started
90
+ }).catch(function(error) {
91
+ // Error occurred during the test scenario
92
+ });
93
+ ```
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@skyramp/skyramp",
3
+ "version": "0.4.31",
4
+ "description": "module for leveraging skyramp cli functionality",
5
+ "scripts": {
6
+ "pack": "npm pack"
7
+ },
8
+ "files": [
9
+ "lib/**",
10
+ "src/*.js",
11
+ "src/*.ts",
12
+ "src/classes/*.js",
13
+ "src/classes/*.ts"
14
+ ],
15
+ "main": "src/index.js",
16
+ "author": "",
17
+ "license": "MIT",
18
+ "dependencies": {
19
+ "fs": "^0.0.1-security",
20
+ "js-yaml": "^4.1.0",
21
+ "koffi": "^2.5.3"
22
+ }
23
+ }
@@ -0,0 +1,6 @@
1
+ export declare class Endpoint {
2
+ constructor(endpointData: string);
3
+ mockMethod(methodName: string, mockObject: string, dynamic?: boolean): void;
4
+ mockMethodFromFile(methodName: string, fileName: string): void;
5
+ writeMockConfigurationToFile(kubernetesService: string): Promise<void>;
6
+ }
@@ -0,0 +1,68 @@
1
+ const lib = require('../lib');
2
+ const { getYamlBytes, readDataFromFile } = require('../utils');
3
+ const writeMockDescriptionWrapper = lib.func('writeMockDescriptionWrapper', 'string', ['string', 'string']);
4
+
5
+ class Endpoint {
6
+ constructor(endpointData) {
7
+ try {
8
+ const endpoint = JSON.parse(endpointData);
9
+ this.services = endpoint.services;
10
+ this.endpoint = endpoint.endpoints[0];
11
+ for (const method of this.endpoint.methods) {
12
+ method.proxy = true;
13
+ }
14
+ this.responseValues = endpoint.responseValues;
15
+ this.mockDescription = {
16
+ services: this.services,
17
+ endpoints: [this.endpoint],
18
+ responseValues: this.responseValues
19
+ };
20
+ } catch(error) {
21
+ throw new Error(endpointData);
22
+ }
23
+ }
24
+
25
+ mockMethod(methodName, mockObject, dynamic=false) {
26
+ for (const method of this.endpoint.methods) {
27
+ if (method.name === methodName || method.type === methodName) {
28
+ const responseName = method.responseValue;
29
+ delete method.proxy;
30
+ for (const responseValue of this.responseValues) {
31
+ if (responseValue.name === responseName) {
32
+ if (dynamic) {
33
+ responseValue.javascriptPath = mockObject;
34
+ delete responseValue.blob;
35
+ } else {
36
+ responseValue.blob = mockObject.responseValue.blob;
37
+ delete responseValue.javascriptPath;
38
+ }
39
+ return;
40
+ }
41
+ }
42
+ }
43
+ }
44
+ throw new Error(`Method ${methodName} not found`);
45
+ }
46
+
47
+ mockMethodFromFile(methodName, fileName) {
48
+ const [jsonData, dynamic] = readDataFromFile(fileName);
49
+ return this.mockMethod(methodName, jsonData, dynamic);
50
+ }
51
+
52
+ writeMockConfigurationToFile(kubernetesService) {
53
+ const yamlContent = getYamlBytes(this.mockDescription);
54
+ return new Promise((resolve, reject) => {
55
+ writeMockDescriptionWrapper.async(yamlContent, kubernetesService, (err, res) => {
56
+ if (err) {
57
+ reject(err);
58
+ } else if (res) {
59
+ reject(new Error(res));
60
+ } else {
61
+ resolve();
62
+ }
63
+ });
64
+ });
65
+ }
66
+ }
67
+
68
+ module.exports = Endpoint;
@@ -0,0 +1,4 @@
1
+ import { Endpoint } from './Endpoint';
2
+ export declare class GrpcEndpoint extends Endpoint {
3
+ constructor(name: string, service: string, port: number, pbFile: string);
4
+ }
@@ -0,0 +1,12 @@
1
+ const Endpoint = require('./Endpoint');
2
+ const lib = require('../lib');
3
+ const newGrpcEndpointWrapper = lib.func('newGrpcEndpointWrapper', 'string', ['string', 'string', 'int', 'string']);
4
+
5
+ class GrpcEndpoint extends Endpoint {
6
+ constructor(name, service, port, pbFile) {
7
+ const response = newGrpcEndpointWrapper(name, service, port, pbFile);
8
+ super(response);
9
+ }
10
+ }
11
+
12
+ module.exports = GrpcEndpoint;
@@ -0,0 +1,4 @@
1
+ import { Endpoint } from './Endpoint';
2
+ export declare class RestEndpoint extends Endpoint {
3
+ constructor(name: string, openApiTag: string, port: number, openapiFile: string);
4
+ }
@@ -0,0 +1,12 @@
1
+ const Endpoint = require('./Endpoint');
2
+ const lib = require('../lib');
3
+ const newRestEndpointWrapper = lib.func('newRestEndpointWrapper', 'string', ['string', 'string', 'int', 'string']);
4
+
5
+ class RestEndpoint extends Endpoint {
6
+ constructor(name, openApiTag, port, openapiFile) {
7
+ const response = newRestEndpointWrapper(name, openApiTag, port, openapiFile);
8
+ super(response);
9
+ }
10
+ }
11
+
12
+ module.exports = RestEndpoint;
@@ -0,0 +1,8 @@
1
+ export declare class Scenario {
2
+ constructor(name: string);
3
+ addRequest(endpoint: any, methodName: string, requestObject?: string, dynamic?: boolean): string;
4
+ addRequestFromFile(endpoint: any, methodName: string, requestFile: string): string;
5
+ buildRequestsFromEndpoint(endpoint: any): void;
6
+ addAssertEqual(value1: string, value2: string): string;
7
+ writeTestConfigurationToFile(): Promise<void>;
8
+ }
@@ -0,0 +1,80 @@
1
+ const lib = require('../lib');
2
+ const { createTestDescriptionFromScenario, getYamlBytes, readDataFromFile } = require('../utils');
3
+ const buildRequestsWrapper = lib.func('buildRequestsWrapper', 'string', ['string']);
4
+ const writeTestDescriptionWrapper = lib.func('writeTestDescriptionWrapper', 'string', ['string', 'string']);
5
+
6
+ class Scenario {
7
+ constructor(name) {
8
+ this.name = name;
9
+ this.steps = [];
10
+ this.services = [];
11
+ this.endpoints = [];
12
+ this.requests = [];
13
+ }
14
+
15
+ addRequest(endpoint, methodName, requestObject=undefined, dynamic=false) {
16
+ this.buildRequestsFromEndpoint(endpoint);
17
+ for (const request of this.requests) {
18
+ if (request.method === methodName) {
19
+ if (dynamic) {
20
+ request.requestValue.javascriptPath = requestObject;
21
+ delete request.requestValue.blob;
22
+ } else if (requestObject !== undefined) {
23
+ request.requestValue = requestObject.requestValue;
24
+ }
25
+ this.steps.push({ request: request.name });
26
+ return request.name;
27
+ }
28
+ }
29
+ throw new Error(`Method ${methodName} not found`);
30
+ }
31
+
32
+ addRequestFromFile(endpoint, methodName, requestFile) {
33
+ const [jsonData, dynamic] = readDataFromFile(requestFile);
34
+ return this.addRequest(endpoint, methodName, jsonData, dynamic);
35
+ }
36
+
37
+ buildRequestsFromEndpoint(endpoint) {
38
+ if (this.endpoints.indexOf(endpoint.endpoint) !== -1) {
39
+ return;
40
+ }
41
+ const processedMethods = endpoint.endpoint.methods.map(method => {
42
+ const { responseValue, proxy, ...rest } = method;
43
+ return rest;
44
+ });
45
+ this.services.push(...endpoint.services);
46
+ this.endpoints.push({ ...endpoint.endpoint, methods: processedMethods });
47
+ const yamlContent = getYamlBytes(endpoint.mockDescription);
48
+ const response = buildRequestsWrapper(yamlContent);
49
+ try {
50
+ const requests = JSON.parse(response);
51
+ this.requests.push(requests[0]);
52
+ } catch (error) {
53
+ throw new Error(response);
54
+ }
55
+ }
56
+
57
+ addAssertEqual(value1, value2) {
58
+ const assertion = `requests.${value1} == "${value2}"`;
59
+ this.steps.push({ asserts: assertion });
60
+ return assertion;
61
+ }
62
+
63
+ writeTestConfigurationToFile() {
64
+ const testDescription = createTestDescriptionFromScenario(this);
65
+ const yamlContent = getYamlBytes(testDescription);
66
+ return new Promise((resolve, reject) => {
67
+ writeTestDescriptionWrapper.async(yamlContent, this.name, (err, res) => {
68
+ if (err) {
69
+ reject(err);
70
+ } else if (res) {
71
+ reject(new Error(res));
72
+ } else {
73
+ resolve();
74
+ }
75
+ });
76
+ });
77
+ }
78
+ }
79
+
80
+ module.exports = Scenario;
@@ -0,0 +1,17 @@
1
+ import { Endpoint } from './Endpoint';
2
+ import { Scenario } from './Scenario';
3
+ export declare class SkyrampClient {
4
+ constructor(kubeconfigPath?: string, clusterName?: string, context?: string);
5
+ applyLocal(): Promise<void>;
6
+ addKubeconfig(context: string, clusterName: string, kubeconfigPath: string): Promise<void>;
7
+ removeCluster(clusterName?: string): Promise<void>;
8
+ removeLocal(): Promise<void>;
9
+ removeClusterFromConfig(clusterName: string): Promise<void>;
10
+ mockerApply(namespace: string, address: string, endpoint: Endpoint): Promise<void>;
11
+
12
+ mockerApplyFromFile(namespace: string, address: string, filePath: string): Promise<void>;
13
+ applyMockDescription(namespace: string, address: string, mockYamlContent: string): Promise<void>;
14
+ testerStart(namespace: string, address: string, scenario: Scenario): Promise<void>;
15
+ testerStartFromFile(namespace: string, address: string, filePath: string): Promise<void>;
16
+ runTesterStart(namespace: string, address: string, testYamlContent: string, generateReport: boolean): Promise<void>;
17
+ }
@@ -0,0 +1,200 @@
1
+ const lib = require('../lib');
2
+ const { createTestDescriptionFromScenario, getYamlBytes, readDataFromFile } = require('../utils');
3
+ const applyLocalWrapper = lib.func('applyLocalWrapper', 'string', []);
4
+ const addKubeconfigWrapper = lib.func('addKubeconfigWrapper', 'string', ['string', 'bool', 'string', 'string']);
5
+ const deleteSkyrampWorkerWrapper = lib.func('deleteSkyrampWorkerWrapper', 'string', ['string'])
6
+ const deploySkyrampWorkerWrapper = lib.func('deploySkyrampWorkerWrapper', 'string', ['string', 'string', 'bool']);
7
+ const getKubeConfigPath = lib.func('getKubeConfigPath', 'string', []);
8
+ const removeLocalWrapper = lib.func('removeLocalWrapper', 'string', []);
9
+ const removeClusterFromConfigWrapper = lib.func('removeClusterFromConfigWrapper', 'string', ['string']);
10
+ const runTesterStartWrapper = lib.func('runTesterStartWrapper', 'string', ['string', 'string', 'string', 'bool']);
11
+ const applyMockDescriptionWrapper = lib.func('applyMockDescriptionWrapper', 'string', ['string', 'string', 'string']);
12
+
13
+ class SkyrampClient {
14
+ constructor(kubeconfigPath, clusterName, context) {
15
+ this.workerNamespaces = [];
16
+ if (kubeconfigPath || clusterName || context) {
17
+ this.addKubeconfig(clusterName, context, kubeconfigPath);
18
+ }
19
+ }
20
+
21
+ async applyLocal() {
22
+ return new Promise((resolve, reject) => {
23
+ applyLocalWrapper.async((err, res) => {
24
+ if (err) {
25
+ reject(err);
26
+ } else if (res) {
27
+ reject(new Error(res));
28
+ } else {
29
+ this.kubeConfigPath = getKubeConfigPath();
30
+ if (this.kubeConfigPath == "") {
31
+ reject(new Error("no kubeconfig found"));
32
+ } else {
33
+ resolve();
34
+ }
35
+ }
36
+ });
37
+ });
38
+ }
39
+
40
+ async addKubeConfig(context, clusterName, kubeConfigPath) {
41
+ return new Promise((resolve, reject) => {
42
+ addKubeconfigWrapper.async(context, clusterName, kubeConfigPath, (err, res) => {
43
+ if (err) {
44
+ reject(err);
45
+ } else if (res) {
46
+ reject(new Error(res));
47
+ } else {
48
+ resolve();
49
+ this.kubeConfigPath = kubeConfigPath;
50
+ }
51
+ });
52
+ });
53
+ }
54
+
55
+ async removeCluster(clusterName) {
56
+ if (clusterName) {
57
+ return this.removeClusterFromConfig(clusterName);
58
+ } else {
59
+ return this.removeLocal();
60
+ }
61
+ }
62
+
63
+ async removeLocal() {
64
+ return new Promise((resolve, reject) => {
65
+ removeLocalWrapper.async((err, res) => {
66
+ if (err) {
67
+ reject(err);
68
+ } else if (res) {
69
+ reject(new Error(res));
70
+ } else {
71
+ resolve();
72
+ }
73
+ });
74
+ });
75
+ }
76
+
77
+ async removeClusterFromConfig(clusterName) {
78
+ return new Promise((resolve, reject) => {
79
+ removeClusterFromConfigWrapper.async(clusterName, (err, res) => {
80
+ if (err) {
81
+ reject(err);
82
+ } else if (res) {
83
+ reject(new Error(res));
84
+ } else {
85
+ resolve();
86
+ }
87
+ });
88
+ });
89
+ }
90
+
91
+ async deploySkyrampWorker(namespace, workerImage='', localImage=false) {
92
+ if (this.kubeConfigPath === null) {
93
+ throw new Error('No cluster to deploy worker to.');
94
+ }
95
+ return new Promise((resolve, reject) => {
96
+ deploySkyrampWorkerWrapper.async(namespace, workerImage, localImage, (err, res) => {
97
+ if (err) {
98
+ reject(err);
99
+ } else if (res) {
100
+ reject(new Error(res));
101
+ } else {
102
+ this.workerNamespaces.push(namespace);
103
+ resolve();
104
+ }
105
+ });
106
+ });
107
+ }
108
+
109
+ async deleteSkyrampWorker(namespace) {
110
+ if (this.kubeConfigPath === null) {
111
+ throw new Error('No cluster to delete worker from.');
112
+ }
113
+ const index = this.workerNamespaces.indexOf(namespace);
114
+ if (index === -1) {
115
+ throw new Error(`No worker to delete from ${namespace} namespace.`);
116
+ }
117
+ return new Promise((resolve, reject) => {
118
+ deleteSkyrampWorkerWrapper.async(namespace, (err, res) => {
119
+ if (err) {
120
+ reject(err);
121
+ } else if (res) {
122
+ reject(new Error(res));
123
+ } else {
124
+ this.workerNamespaces.splice(index, 1);
125
+ resolve();
126
+ }
127
+ });
128
+ });
129
+ }
130
+
131
+ async mockerApply(namespace, address, endpoint) {
132
+ try {
133
+ const yamlContent = getYamlBytes(endpoint.mockDescription);
134
+ await this.applyMockDescription(namespace, address, yamlContent);
135
+ } catch (err) {
136
+ throw err;
137
+ }
138
+ }
139
+
140
+ // NPM only: for VS code extension use
141
+ async mockerApplyFromFile(namespace, address, filepath) {
142
+ try {
143
+ const yamlContent = getYamlBytes(readDataFromFile(filepath)[0]);
144
+ await this.applyMockDescription(namespace, address, yamlContent);
145
+ } catch (err) {
146
+ throw err;
147
+ }
148
+ }
149
+
150
+ async applyMockDescription(namespace, address, yamlContent) {
151
+ return new Promise((resolve, reject) => {
152
+ applyMockDescriptionWrapper.async(namespace, address, yamlContent, (err, res) => {
153
+ if (err) {
154
+ reject(err);
155
+ } else if (res) {
156
+ reject(new Error(res));
157
+ } else {
158
+ resolve();
159
+ }
160
+ });
161
+ });
162
+ }
163
+
164
+ async testerStart(namespace, address, scenario) {
165
+ try {
166
+ const testDescription = createTestDescriptionFromScenario(scenario);
167
+ const testYamlContent = getYamlBytes(testDescription);
168
+ await this.runTesterStart(namespace, address, testYamlContent, false);
169
+ } catch (err) {
170
+ throw err;
171
+ }
172
+ }
173
+
174
+ // NPM only: for VS code extension use
175
+ async testerStartFromFile(namespace, address, filepath) {
176
+ try {
177
+ const testDescription = readDataFromFile(filepath)[0]
178
+ const testYamlContent = getYamlBytes(testDescription);
179
+ await this.runTesterStart(namespace, address, testYamlContent, true);
180
+ } catch (err) {
181
+ throw err;
182
+ }
183
+ }
184
+
185
+ async runTesterStart(namespace, address, testYamlContent, generateReport) {
186
+ return new Promise((resolve, reject) => {
187
+ runTesterStartWrapper.async(namespace, address, testYamlContent, generateReport, (err, res) => {
188
+ if (err) {
189
+ reject(err);
190
+ } else if (res) {
191
+ reject(new Error(res));
192
+ } else {
193
+ resolve();
194
+ }
195
+ });
196
+ });
197
+ }
198
+ }
199
+
200
+ module.exports = SkyrampClient;
package/src/index.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * from './classes/Endpoint';
2
+ export * from './classes/GrpcEndpoint';
3
+ export * from './classes/RestEndpoint';
4
+ export * from './classes/Scenario';
5
+ export * from './classes/SkyrampClient';
6
+ export * from './utils';
package/src/index.js ADDED
@@ -0,0 +1,11 @@
1
+ const SkyrampClient = require('./classes/SkyrampClient');
2
+ const GrpcEndpoint = require('./classes/GrpcEndpoint');
3
+ const RestEndpoint = require('./classes/RestEndpoint');
4
+ const Scenario = require('./classes/Scenario');
5
+
6
+ module.exports = {
7
+ SkyrampClient,
8
+ GrpcEndpoint,
9
+ RestEndpoint,
10
+ Scenario
11
+ }
package/src/lib.js ADDED
@@ -0,0 +1,30 @@
1
+ const koffi = require('koffi');
2
+ const path = require('path');
3
+
4
+ const platform = process.platform;
5
+ const arch = process.arch;
6
+ let libPath = '';
7
+
8
+ if (platform === 'linux') {
9
+ if (arch === 'x64') {
10
+ libPath = 'dev-linux-amd64.so';
11
+ } else if (arch === 'ia32') {
12
+ libPath = 'dev-linux-386.so';
13
+ }
14
+ } else if (platform === 'darwin') {
15
+ if (arch === 'x64') {
16
+ libPath = 'dev-darwin-amd64.dylib';
17
+ } else if (arch === 'arm64') {
18
+ libPath = 'dev-darwin-arm64.dylib';
19
+ }
20
+ } else if (platform === 'win32') {
21
+ libPath = 'dev-windows-amd64.dll';
22
+ }
23
+
24
+ if (!libPath) {
25
+ throw new Error(`Unsupported platform or architecture: ${platform}-${arch}`);
26
+ }
27
+ const libFullPath = path.join(__dirname, '..', 'lib', libPath);
28
+ const lib = koffi.load(libFullPath);
29
+
30
+ module.exports = lib;
package/src/utils.js ADDED
@@ -0,0 +1,58 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const yaml = require('js-yaml');
4
+
5
+ function getYamlBytes(jsonObject) {
6
+ try {
7
+ const yamlContent = yaml.dump(jsonObject, {lineWidth: 100});
8
+ return yamlContent;
9
+ } catch (error) {
10
+ throw new Error('Error converting to YAML bytes:', error);
11
+ }
12
+ }
13
+
14
+ function createTestDescriptionFromScenario(scenario) {
15
+ return {
16
+ test: {
17
+ name: scenario.name,
18
+ testPattern: [{
19
+ startAt: 1,
20
+ scenario: scenario.name
21
+ }]
22
+ },
23
+ services: scenario.services,
24
+ endpoints: scenario.endpoints,
25
+ scenarios: [{
26
+ name: scenario.name,
27
+ steps: scenario.steps
28
+ }],
29
+ requests: scenario.requests
30
+ };
31
+ }
32
+
33
+ function readDataFromFile(filename) {
34
+ try {
35
+ const fileExtension = path.extname(filename);
36
+ let jsonData;
37
+ if (fileExtension === '.json') {
38
+ const jsonContent = fs.readFileSync(filename, 'utf8');
39
+ jsonData = JSON.parse(jsonContent);
40
+ } else if (fileExtension === '.yaml' || fileExtension === '.yml') {
41
+ const yamlContent = fs.readFileSync(filename, 'utf8');
42
+ jsonData = yaml.load(yamlContent);
43
+ } else if (fileExtension === '.js') {
44
+ return [filename, true];
45
+ } else {
46
+ throw new Error('Unsupported file format. Only .json, .yaml, and .js files are supported.');
47
+ }
48
+ return [jsonData, false];
49
+ } catch(error) {
50
+ throw new Error('Error reading or parsing file: ', error);
51
+ }
52
+ }
53
+
54
+ module.exports = {
55
+ createTestDescriptionFromScenario,
56
+ getYamlBytes,
57
+ readDataFromFile
58
+ }