@testflowkit/cli 2.0.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 +81 -0
- package/lib/index.js +48 -0
- package/lib/install.js +170 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# @testflowkit/cli
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@testflowkit/cli)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
**TestFlowKit CLI** - A powerful end-to-end testing framework using Gherkin syntax.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
# Global installation (recommended)
|
|
12
|
+
npm install -g @testflowkit/cli
|
|
13
|
+
|
|
14
|
+
# Or use npx directly
|
|
15
|
+
npx @testflowkit/cli --version
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
### Initialize a new test project
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
tkit init
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Run tests
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
tkit run
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Validate Gherkin files
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
tkit validate
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Check version
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
tkit --version
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Configuration
|
|
45
|
+
|
|
46
|
+
Create a `config.yml` file in your project root:
|
|
47
|
+
|
|
48
|
+
```yaml
|
|
49
|
+
mode: frontend
|
|
50
|
+
browser:
|
|
51
|
+
type: chromium
|
|
52
|
+
headless: true
|
|
53
|
+
features:
|
|
54
|
+
- path: ./features
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Documentation
|
|
58
|
+
|
|
59
|
+
For full documentation, visit [TestFlowKit Documentation](https://testflowkit.github.io/testflowkit/).
|
|
60
|
+
|
|
61
|
+
## Supported Platforms
|
|
62
|
+
|
|
63
|
+
| OS | Architecture |
|
|
64
|
+
|---------|--------------|
|
|
65
|
+
| Linux | x64, arm64 |
|
|
66
|
+
| macOS | x64, arm64 |
|
|
67
|
+
| Windows | x64, arm64 |
|
|
68
|
+
|
|
69
|
+
## Requirements
|
|
70
|
+
|
|
71
|
+
- Node.js >= 16.0.0
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
MIT © [TestFlowKit](https://github.com/TestFlowKit)
|
|
76
|
+
|
|
77
|
+
## Links
|
|
78
|
+
|
|
79
|
+
- [GitHub Repository](https://github.com/TestFlowKit/testflowkit)
|
|
80
|
+
- [Issue Tracker](https://github.com/TestFlowKit/testflowkit/issues)
|
|
81
|
+
- [Releases](https://github.com/TestFlowKit/testflowkit/releases)
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @testflowkit/cli
|
|
3
|
+
*
|
|
4
|
+
* This package provides the TestFlowKit CLI (tkit) for running
|
|
5
|
+
* end-to-end tests using Gherkin syntax.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* npx @testflowkit/cli run
|
|
9
|
+
* npx @testflowkit/cli init
|
|
10
|
+
* npx @testflowkit/cli validate
|
|
11
|
+
* npx @testflowkit/cli --version
|
|
12
|
+
*
|
|
13
|
+
* For programmatic usage, you can get the path to the binary:
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const path = require("path");
|
|
17
|
+
const fs = require("fs");
|
|
18
|
+
|
|
19
|
+
const BINARY_NAME = process.platform === "win32" ? "tkit.exe" : "tkit";
|
|
20
|
+
const binaryPath = path.join(__dirname, "..", "bin", BINARY_NAME);
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get the path to the tkit binary
|
|
24
|
+
* @returns {string} Absolute path to the tkit binary
|
|
25
|
+
* @throws {Error} If the binary is not found
|
|
26
|
+
*/
|
|
27
|
+
function getBinaryPath() {
|
|
28
|
+
if (!fs.existsSync(binaryPath)) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`tkit binary not found. Please reinstall @testflowkit/cli`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return binaryPath;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Check if the binary is installed
|
|
38
|
+
* @returns {boolean} True if the binary exists
|
|
39
|
+
*/
|
|
40
|
+
function isInstalled() {
|
|
41
|
+
return fs.existsSync(binaryPath);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = {
|
|
45
|
+
getBinaryPath,
|
|
46
|
+
isInstalled,
|
|
47
|
+
binaryPath,
|
|
48
|
+
};
|
package/lib/install.js
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const https = require("https");
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const AdmZip = require("adm-zip");
|
|
7
|
+
|
|
8
|
+
const PACKAGE_JSON = require("../package.json");
|
|
9
|
+
const VERSION = PACKAGE_JSON.version;
|
|
10
|
+
const BINARY_NAME = "tkit";
|
|
11
|
+
const GITHUB_RELEASE_URL = `https://github.com/TestFlowKit/testflowkit/releases/download/${VERSION}`;
|
|
12
|
+
|
|
13
|
+
// Platform and architecture mapping from Node.js to Go naming conventions
|
|
14
|
+
const PLATFORM_MAP = {
|
|
15
|
+
darwin: "darwin",
|
|
16
|
+
linux: "linux",
|
|
17
|
+
win32: "windows",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const ARCH_MAP = {
|
|
21
|
+
x64: "amd64",
|
|
22
|
+
arm64: "arm64",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get the binary name for the current platform
|
|
27
|
+
*/
|
|
28
|
+
function getBinaryName() {
|
|
29
|
+
return process.platform === "win32" ? `${BINARY_NAME}.exe` : BINARY_NAME;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Get the download URL for the current platform and architecture
|
|
34
|
+
*/
|
|
35
|
+
function getDownloadUrl() {
|
|
36
|
+
const platform = PLATFORM_MAP[process.platform];
|
|
37
|
+
const arch = ARCH_MAP[process.arch];
|
|
38
|
+
|
|
39
|
+
if (!platform) {
|
|
40
|
+
throw new Error(`Unsupported platform: ${process.platform}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!arch) {
|
|
44
|
+
throw new Error(`Unsupported architecture: ${process.arch}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const filename = `${BINARY_NAME}-${platform}-${arch}.zip`;
|
|
48
|
+
return `${GITHUB_RELEASE_URL}/${filename}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Follow redirects and download file
|
|
53
|
+
*/
|
|
54
|
+
function downloadFile(url, maxRedirects = 5) {
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
if (maxRedirects === 0) {
|
|
57
|
+
reject(new Error("Too many redirects"));
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const protocol = url.startsWith("https") ? https : require("http");
|
|
62
|
+
|
|
63
|
+
protocol
|
|
64
|
+
.get(url, (response) => {
|
|
65
|
+
// Handle redirects (GitHub releases use redirects)
|
|
66
|
+
if (
|
|
67
|
+
response.statusCode >= 300 &&
|
|
68
|
+
response.statusCode < 400 &&
|
|
69
|
+
response.headers.location
|
|
70
|
+
) {
|
|
71
|
+
downloadFile(response.headers.location, maxRedirects - 1)
|
|
72
|
+
.then(resolve)
|
|
73
|
+
.catch(reject);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (response.statusCode !== 200) {
|
|
78
|
+
reject(
|
|
79
|
+
new Error(`Failed to download: HTTP ${response.statusCode}`)
|
|
80
|
+
);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const chunks = [];
|
|
85
|
+
response.on("data", (chunk) => chunks.push(chunk));
|
|
86
|
+
response.on("end", () => resolve(Buffer.concat(chunks)));
|
|
87
|
+
response.on("error", reject);
|
|
88
|
+
})
|
|
89
|
+
.on("error", reject);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Extract zip file using adm-zip (cross-platform, no OS dependency)
|
|
95
|
+
*/
|
|
96
|
+
async function extractZip(zipBuffer, destDir) {
|
|
97
|
+
try {
|
|
98
|
+
const zip = new AdmZip(zipBuffer);
|
|
99
|
+
zip.extractAllTo(destDir, true);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
throw new Error(`Failed to extract zip: ${error.message}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Make the binary executable (Unix only)
|
|
107
|
+
*/
|
|
108
|
+
function makeExecutable(filePath) {
|
|
109
|
+
if (process.platform !== "win32") {
|
|
110
|
+
fs.chmodSync(filePath, 0o755);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Main installation function
|
|
116
|
+
*/
|
|
117
|
+
async function install() {
|
|
118
|
+
const binDir = path.join(__dirname, "..", "bin");
|
|
119
|
+
const binaryName = getBinaryName();
|
|
120
|
+
const binaryPath = path.join(binDir, binaryName);
|
|
121
|
+
|
|
122
|
+
// Check if binary already exists
|
|
123
|
+
if (fs.existsSync(binaryPath)) {
|
|
124
|
+
console.log(`✓ ${BINARY_NAME} binary already exists`);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Ensure bin directory exists
|
|
129
|
+
if (!fs.existsSync(binDir)) {
|
|
130
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const downloadUrl = getDownloadUrl();
|
|
134
|
+
console.log(`Downloading ${BINARY_NAME} v${VERSION}...`);
|
|
135
|
+
console.log(` Platform: ${process.platform} (${PLATFORM_MAP[process.platform]})`);
|
|
136
|
+
console.log(` Architecture: ${process.arch} (${ARCH_MAP[process.arch]})`);
|
|
137
|
+
console.log(` URL: ${downloadUrl}`);
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
// Download the zip file
|
|
141
|
+
const zipBuffer = await downloadFile(downloadUrl);
|
|
142
|
+
console.log(`Downloaded ${(zipBuffer.length / 1024 / 1024).toFixed(2)} MB`);
|
|
143
|
+
|
|
144
|
+
// Extract to bin directory
|
|
145
|
+
console.log("Extracting...");
|
|
146
|
+
await extractZip(zipBuffer, binDir);
|
|
147
|
+
|
|
148
|
+
// Make executable
|
|
149
|
+
makeExecutable(binaryPath);
|
|
150
|
+
|
|
151
|
+
// Verify installation
|
|
152
|
+
if (fs.existsSync(binaryPath)) {
|
|
153
|
+
console.log(`✓ Successfully installed ${BINARY_NAME} v${VERSION}`);
|
|
154
|
+
} else {
|
|
155
|
+
throw new Error("Binary not found after extraction");
|
|
156
|
+
}
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error(`✗ Failed to install ${BINARY_NAME}: ${error.message}`);
|
|
159
|
+
console.error("");
|
|
160
|
+
console.error("You can manually download the binary from:");
|
|
161
|
+
console.error(GITHUB_RELEASE_URL);
|
|
162
|
+
console.error("");
|
|
163
|
+
console.error("Then place it in:");
|
|
164
|
+
console.error(` ${binDir}`);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Run installation
|
|
170
|
+
install();
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@testflowkit/cli",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "TestFlowKit CLI - A powerful end-to-end testing framework using Gherkin syntax",
|
|
8
|
+
"main": "lib/index.js",
|
|
9
|
+
"bin": {
|
|
10
|
+
"tkit": "./bin/tkit"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"postinstall": "node ./lib/install.js"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/TestFlowKit/testflowkit.git"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"testflowkit",
|
|
21
|
+
"testing",
|
|
22
|
+
"e2e",
|
|
23
|
+
"end-to-end",
|
|
24
|
+
"gherkin",
|
|
25
|
+
"cucumber",
|
|
26
|
+
"bdd",
|
|
27
|
+
"cli",
|
|
28
|
+
"automation"
|
|
29
|
+
],
|
|
30
|
+
"author": "TestFlowKit",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/TestFlowKit/testflowkit/issues"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/TestFlowKit/testflowkit#readme",
|
|
36
|
+
"os": [
|
|
37
|
+
"darwin",
|
|
38
|
+
"linux",
|
|
39
|
+
"win32"
|
|
40
|
+
],
|
|
41
|
+
"cpu": [
|
|
42
|
+
"x64",
|
|
43
|
+
"arm64"
|
|
44
|
+
],
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=16.0.0"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"adm-zip": "^0.5.10"
|
|
50
|
+
},
|
|
51
|
+
"files": [
|
|
52
|
+
"bin",
|
|
53
|
+
"lib/install.js",
|
|
54
|
+
"lib/index.js",
|
|
55
|
+
"README.md"
|
|
56
|
+
]
|
|
57
|
+
}
|