Update tests - #1
Merged
Merged
Conversation
Split tests by type at the top level: unit/ (no network, fetch mocked, no API key) and integration/ (real API). Previously unit tests lived in sync/ and async/ while the single integration file sat loose in the tests/ root, and the npm scripts told the two apart by regex-matching the word "integration" anywhere in the path. Select the suites by directory instead. This also fixes a side effect of the old flag: --testPathIgnorePatterns=integration overrode the Jest default of ["/node_modules/"], so node_modules stopped being ignored during unit runs. Tests now import the SDK by package name rather than by relative path to src/. Node resolves the package self-reference through the "exports" map in package.json and Jest honours it, so the suite exercises the same entry points a consumer gets. With direct file imports an export could be dropped from src/index.js, or the "exports" map broken, and every test would still pass while the package was unusable. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Every other test imports the package by name, so a broken main entry point already fails the suite loudly. What stays uncovered is the rest of the "exports" map: the ./tasks and ./exceptions subpaths, and the fact that undeclared subpaths remain private. Asserts that all three entry points resolve, that __version__ matches the version in package.json, that the subpaths and the main entry hand back the same class objects (otherwise instanceof would break for anyone mixing import styles), and that captcha-sdk/client stays unreachable even though the file exists. The class lists are spelled out explicitly rather than derived from the modules under test: comparing an export against itself always passes. Adding a captcha type means extending the list by hand, which is the point where making a class public becomes a deliberate decision. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
collectCoverageFrom: ['src/**/*.js'] makes coverage count every file in src/, not only the ones imported from tests. Without it a new file that nothing imports drops out of the report silently instead of showing 0%. That was not hypothetical: src/index.js was invisible to the report while tests imported src/ files directly, so coverage read 97.5% with the package entry point entirely unexercised. coverageReporters is narrowed to text (console) and lcov (upload target for Coveralls); the default set also wrote clover.xml and a JSON dump that nothing consumes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Runs unit tests on Node 18/20/22, matching engines.node ">=18", on push to main and on every pull request. Coverage is uploaded to Coveralls from the Node 20 job only -- the number does not vary by Node version, so three uploads would just add noise. Integration tests deliberately do not run on pull_request: they spend real account balance, and secrets are unavailable to forked PRs, so the tests would skip themselves and report a false green. They run on a nightly schedule and on demand instead. The integration job fails fast when CAPTCHA_API_KEY is missing. Without that guard an unset secret looks like a passing run, since the tests skip themselves and the job goes green having verified nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
tests/README.md covers what each suite checks, how the sync/async split avoids duplicating serialization tests, how to run everything manually, and what CI does automatically. todo.md tracks the coverage badge, which is deferred because the remaining steps need the web UI: enabling the repository on Coveralls and a first workflow run on main. The badge markdown is ready there. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The previous contents were "./tests" and ".claude". The "./" prefix is not valid in npm ignore patterns, which are gitignore-style, so the tests entry matched nothing. It had no visible effect because "files": ["src/"] in package.json is a whitelist and takes precedence, but the file was not harmless: while an .npmignore exists npm stops falling back to .gitignore when packing, so coverage/ and .env lost the exclusion they were relying on. List every dev-only path explicitly. Verified with npm pack --dry-run that this file on its own yields the same 7-file tarball as the "files" whitelist, so the two layers agree instead of contradicting each other. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude Code writes a local permission allowlist there. It is full of absolute paths to a machine-specific temp directory and one-off command entries, so it is useless to anyone else working on the repository. It stays listed in .npmignore as well: while an .npmignore exists npm does not consult .gitignore when packing, so the two files have to repeat each other. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The whole suite depends on importing 'captcha-sdk' rather than reaching into src/ by relative path, but nothing in the files said so. A contributor seeing the unusual import could "correct" it to ../../../src/client.js, keep every test green, and quietly remove the only thing that catches a broken entry point or "exports" map. Note it where the temptation is, in each test file header. public-api.test.js is left alone -- its header already covers the same ground. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The first live run went red on a PR where every test passed: the Coveralls step returned "Couldn't find a repository matching this job" because the repository is not connected on coveralls.io yet. Uploading coverage is auxiliary. A Coveralls outage, or a repository that is not wired up yet, should not block merging a pull request whose tests are green. A stale badge is visible enough on its own. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The repository is private and the Coveralls free plan only covers public ones, which is why connecting it returns "No repos found" and the CI upload fails with "Couldn't find a repository matching this job". The plan is to make the repository public later, so the existing setup stays as is. Write the reason down: without it the open item looks abandoned rather than waiting on something specific. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`client` said nothing about what the object was, so `client.solve()` and `client.getBalance()` only read clearly with the constructor line in view. `captchaSolver` carries that context to every call site. Covers the README code blocks and both example suites. Prose mentions of "client" and the `clientKey` option are unchanged, as is the tests/ fixture variable -- that one is internal, not something users read to learn the API. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The examples were undocumented: nothing said how to run them, which ones need editing first, or why there are two copies of every scenario. Three READMEs. The parent one carries the shared setup and an index of all 11 scenarios in both styles; each suite README describes its own files and links them to the matching section of the API docs. Four things a reader could previously only learn by hitting them: - Most files run a proxyless and a with-proxy block on every execution, spending balance twice. In sync/ the two even start concurrently. - geetest_v3.js fetches a placeholder init endpoint and cannot run end-to-end unmodified. - The image examples resolve ./captcha.png against the working directory, not the script location, and the repository ships no sample images. - languagePool is the second argument to solve(), not a task field. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
image_to_text.js and coordinates.js read four PNGs that are not in the repository, so both fail with ENOENT before reaching the API -- the only examples that need more than an API key. Adding the files is half the fix: the paths are relative to the working directory, so the reads have to move to new URL(..., import.meta.url) as well, and examples/README.md currently documents the opposite. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The suite is about to grow a test per captcha type, and a single client.test.js would have made every new one a paid test by default. Split along cost rather than captcha type, since that is what actually separates these tests: balance.test.js spends nothing and needs no target page, so it works as a smoke test that the key and the network path are fine. Everything calling solve() bills the account on every nightly run and now lives in its own file. helpers.js holds the pieces that would otherwise be copied into each new file: the key, a client factory, and the skip guard. The guard changes behaviour. It used to be `if (!apiKey) return` inside each test body, so a keyless run reported green "passed" for tests that never called the API. Skipping at the describe level reports "skipped" instead. The run still exits 0 having verified nothing, so the CI fail-early step stays necessary. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adds real-API tests for reCAPTCHA v3, Turnstile, GeeTest v4, Yandex SmartCaptcha, Tencent and Image to Text, one file per type. No target page or sitekey is committed. Every target comes from the environment and a suite whose variables are unset skips itself, so the repository carries no links to real sites and no keys of theirs. The Google demo page that recaptcha_v2.test.js used to fall back on is gone, and .env.example now ships variable names with empty values instead of working keys for reCAPTCHA, Turnstile and GeeTest. describeTarget() in helpers.js is describeIntegration() plus that check; it hands the collected values to the suite body. helpers.js also loads dotenv now, so a local run reads .env instead of exporting a dozen variables by hand. Values already in the environment still win, and unit tests do not import the file. Two consequences worth stating: - A fresh clone has no working integration check beyond the balance, by design. image_to_text.test.js is the exception: it needs an image rather than a page, and .env.example carries a usable one. - The nightly CI job passes only CAPTCHA_API_KEY, so it now verifies the balance and skips all seven solve suites. Running them there is not planned yet; tests/README.md records what to do when it is. GeeTest v3 stays uncovered on purpose -- its challenge is per-session and has to be scraped immediately before the task is created. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The "one file or one test" section showed unit examples only, so the commands for the paid suites had to be inferred. Adds the integration equivalents and two caveats that apply only there: a bare -t filter also matches the paid suites, and Jest runs files in parallel, so a whole-directory run submits several billed tasks at once. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The two image-based flows -- image to text and coordinates -- needed a picture that the repository did not have. The examples read ./captcha.png and friends and died with ENOENT before reaching the API, and the integration test took its image from IMAGE_TO_TEXT_BASE64 in .env.example, whose sample string was a valid PNG of 26x26 pixels: nothing to recognise, so every run failed with ERROR_CAPTCHA_UNSOLVABLE and spent balance doing it. Both samples now live in examples/assets/, one copy shared by the examples and the tests so the two cannot drift apart. Paths resolve through new URL(..., import.meta.url), against the script rather than the working directory, so everything runs from the repository root. - Add tests/integration/coordinates.test.js. It asserts the points fall inside the picture, with the bounds read from the PNG's IHDR chunk so swapping the sample cannot silently invalidate the check. - image_to_text.test.js reads the file instead of the environment; IMAGE_TO_TEXT_BASE64 is gone. Both image suites now need only a key, which also means the nightly CI job solves two captchas for real. - Fix hints that contradicted the sample: numeric: 1 (digits only) on a letters captcha, and a comment about a green apple on a grid of street signs. - Comment out the three example blocks that need an instruction image the repository still does not ship, naming the file they expect. - Stop calling every target identifier a sitekey: Tencent has an appId and GeeTest v4 a captchaId. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
package.json and the __version__ export are asserted to match by tests/unit/public-api.test.js, so move both together. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Five claims had gone stale against the tree: the integration suite is nine files, not eight; the skip-mode output and the count of paid tasks per run followed from that; and the unit run is well under two seconds, not seven. Also moves the --experimental-vm-modules and Node 18+ paragraphs out of the coverage section, where they had ended up during an earlier restructure, into a Requirements subsection under the manual-run instructions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.