diff --git a/bin/check.js b/bin/check.js
index 7cf553d1..615e55cb 100755
--- a/bin/check.js
+++ b/bin/check.js
@@ -238,10 +238,11 @@ program
}
});
-// Push command (alias for check-tests manual **/**.md)
+// Push command (alias for check-tests manual **/*.test.md)
program
.command('push')
.option('-d, --dir
', 'test directory')
+ .option('-f, --files ', 'file paths or glob patterns to push (defaults to **/*.test.md)')
.option('--no-skipped', 'throw error if skipped tests found')
.option('--typescript', 'enable typescript support')
.option('--sync', 'import tests to testomatio and wait for completion')
@@ -260,12 +261,15 @@ program
.option('--test-alias ', 'Specify custom alias for test/it etc (separated by commas if multiple)')
.option('--exclude ', 'Glob pattern to exclude files from analysis')
.option('--force', 'skip git checks and force push files')
- .description('Push manual tests from markdown files (alias for check-tests manual **/**.md)')
+ .description(
+ 'Push manual tests from markdown files. Use --files to pass paths or glob patterns (defaults to **/*.test.md).',
+ )
.action(async opts => {
- // Alias: call main action with 'manual' framework and '**/**.md' files
const globalOpts = program.opts();
const mergedOpts = { ...globalOpts, ...opts, updateIds: true };
- await mainAction('manual', '**/**.md', mergedOpts);
+ const files =
+ opts.files && opts.files.length ? (opts.files.length === 1 ? opts.files[0] : opts.files) : '**/*.test.md';
+ await mainAction('manual', files, mergedOpts);
});
if (process.argv.length <= 2) {
diff --git a/cli.md b/cli.md
index e37a1c95..6dbcd2f6 100644
--- a/cli.md
+++ b/cli.md
@@ -13,6 +13,57 @@ npx check-tests [options]
- `` - Test framework to analyze (codeceptjs, jasmine, jest, mocha, newman, playwright, qunit, testcafe, nightwatch)
- `` - Glob pattern to match test files (e.g., `"tests/**/*_test.js"`)
+## Push Command
+
+The `push` command is a shortcut for importing markdown-based manual tests into Testomat.io. It is equivalent to `check-tests manual ` with `--update-ids` enabled by default.
+
+```bash
+npx check-tests push [options]
+```
+
+### Push Options
+
+| Option | Description | Default |
+| ------------------------ | ----------------------------------------------- | -------------- |
+| `-d, --dir ` | Test directory to scan | Current dir |
+| `-f, --files ` | One or more file paths or glob patterns to push | `**/*.test.md` |
+| `--force` | Skip git checks and force push files | false |
+
+The `push` command also accepts the same Testomat.io and analysis options as the main command (`--sync`, `--create`, `--no-empty`, `--keep-structure`, `--clean-ids`, `--purge`, `--no-detached`, `--no-skipped`, `--exclude`, etc.).
+
+### `--files` Option
+
+Use `--files` (or `-f`) to override the default glob (`**/*.test.md`). It accepts:
+
+- a **single file path** — push exactly that file
+- **multiple file paths** — push every listed file
+- a **glob pattern** (in quotes) — push every file matched by the pattern
+- **multiple glob patterns** — push the union of files matched by each pattern
+
+Paths and patterns are resolved relative to `--dir` (or the current directory if `--dir` is not set).
+
+### Push Examples
+
+```bash
+# Push every **/*.test.md file under the current directory (default behaviour)
+TESTOMATIO=your-api-key npx check-tests push
+
+# Push a single markdown file
+TESTOMATIO=your-api-key npx check-tests push --files docs/login.test.md
+
+# Push several specific files
+TESTOMATIO=your-api-key npx check-tests push -f docs/login.test.md docs/checkout.test.md
+
+# Push everything matching a custom glob (quote the pattern!)
+TESTOMATIO=your-api-key npx check-tests push --files "manual-tests/**/*.md"
+
+# Combine multiple globs (e.g. smoke + regression suites)
+TESTOMATIO=your-api-key npx check-tests push -f "smoke/**/*.test.md" "regression/**/*.test.md"
+
+# Use a non-default directory together with --files
+TESTOMATIO=your-api-key npx check-tests push -d ./tests --files "**/*.md"
+```
+
## CLI Options
### Basic Options
diff --git a/src/updateIds/updateIds-markdown.js b/src/updateIds/updateIds-markdown.js
index e07b4836..4182dfc3 100644
--- a/src/updateIds/updateIds-markdown.js
+++ b/src/updateIds/updateIds-markdown.js
@@ -4,6 +4,12 @@ const glob = require('glob');
const path = require('path');
const { TAG_REGEX } = require('./constants');
+function resolvePatterns(workDir, pattern) {
+ const base = path.resolve(workDir);
+ const patterns = Array.isArray(pattern) ? pattern : [pattern];
+ return patterns.map(p => path.join(base, p));
+}
+
/**
* Insert test ids (@T12345678) and suite ids (@S12345678) into markdown test files
* @param {*} testomatioMap mapping of test ids received from testomatio server
@@ -12,7 +18,7 @@ const { TAG_REGEX } = require('./constants');
* @returns
*/
function updateIdsMarkdown(testomatioMap, workDir, opts = {}) {
- const patternWithFullPath = path.join(path.resolve(workDir), opts.pattern);
+ const patternWithFullPath = resolvePatterns(workDir, opts.pattern);
const files = glob.sync(patternWithFullPath);
debug('Files:', files);
@@ -131,7 +137,7 @@ function updateId(lines, lineNumber, mappedId) {
* Remove test ids from markdown test files
*/
function cleanIdsMarkdown(testomatioMap, workDir, opts = { dangerous: false }) {
- const patternWithFullPath = path.join(path.resolve(workDir), opts.pattern);
+ const patternWithFullPath = resolvePatterns(workDir, opts.pattern);
const files = glob.sync(patternWithFullPath);
debug('Files:', files);
diff --git a/tests/push_command_test.js b/tests/push_command_test.js
index f71c6834..3b4c27ba 100644
--- a/tests/push_command_test.js
+++ b/tests/push_command_test.js
@@ -5,7 +5,7 @@ const path = require('path');
describe('push command', () => {
let testDir;
- const testMarkdownFile = 'test-manual.md';
+ const testMarkdownFile = 'manual.test.md';
const testMarkdownContent = `
# Manual Test Suite
@@ -67,7 +67,7 @@ priority: medium
});
expect(output).to.include('SHOWING MANUAL TESTS');
- expect(output).to.include('**/**.md');
+ expect(output).to.include('**/*.test.md');
expect(output).to.include('Login functionality');
expect(output).to.include('Invalid login');
} catch (error) {
@@ -157,6 +157,93 @@ priority: medium
}
});
+ it('should accept a single file path via --files', () => {
+ const extraContent = `
+# Extra Suite
+
+
+## Extra Test
+- step
+`;
+ fs.writeFileSync(path.join(testDir, 'extra.md'), extraContent);
+
+ const output = execSync(`node bin/check.js push -d ${testDir} --files extra.md`, {
+ cwd: path.join(__dirname, '..'),
+ encoding: 'utf8',
+ timeout: 10000,
+ });
+
+ expect(output).to.include('SHOWING MANUAL TESTS FROM extra.md');
+ expect(output).to.include('Extra Test');
+ expect(output).to.not.include('Login functionality');
+ });
+
+ it('should accept multiple file paths via --files', () => {
+ const extraContent = `
+# Extra Suite
+
+
+## Extra Test
+- step
+`;
+ fs.writeFileSync(path.join(testDir, 'extra.md'), extraContent);
+
+ const output = execSync(`node bin/check.js push -d ${testDir} -f ${testMarkdownFile} extra.md`, {
+ cwd: path.join(__dirname, '..'),
+ encoding: 'utf8',
+ timeout: 10000,
+ });
+
+ expect(output).to.include('SHOWING MANUAL TESTS');
+ expect(output).to.include('Login functionality');
+ expect(output).to.include('Extra Test');
+ });
+
+ it('should accept a glob pattern via --files', () => {
+ const output = execSync(`node bin/check.js push -d ${testDir} --files "*.md"`, {
+ cwd: path.join(__dirname, '..'),
+ encoding: 'utf8',
+ timeout: 10000,
+ });
+
+ expect(output).to.include('SHOWING MANUAL TESTS FROM *.md');
+ expect(output).to.include('Login functionality');
+ });
+
+ it('should accept a file path inside a subdirectory via --files', () => {
+ const subDir = path.join(testDir, 'nested');
+ fs.mkdirSync(subDir, { recursive: true });
+ const nestedContent = `
+# Nested Suite
+
+
+## Nested Test
+- step
+`;
+ fs.writeFileSync(path.join(subDir, 'nested.md'), nestedContent);
+
+ const output = execSync(`node bin/check.js push -d ${testDir} --files nested/nested.md`, {
+ cwd: path.join(__dirname, '..'),
+ encoding: 'utf8',
+ timeout: 10000,
+ });
+
+ expect(output).to.include('SHOWING MANUAL TESTS FROM nested/nested.md');
+ expect(output).to.include('Nested Test');
+ expect(output).to.not.include('Login functionality');
+ });
+
+ it('should expose --files option in --help output', () => {
+ const output = execSync('node bin/check.js push --help', {
+ cwd: path.join(__dirname, '..'),
+ encoding: 'utf8',
+ });
+
+ expect(output).to.include('--files');
+ expect(output).to.include('-f');
+ expect(output).to.include('**/*.test.md');
+ });
+
it('should work with empty directory (finds tests in current project)', () => {
const emptyDir = path.join(testDir, 'empty');
fs.mkdirSync(emptyDir, { recursive: true });