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 });