Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
c5fae6e
Add new e2e tests
vasylk-crowdin Jul 24, 2026
5d2ebd6
test(e2e): mask temp workspace paths, extend init coverage, updated b…
bhdnb Jul 28, 2026
1921537
fix(config): prepend leading slash to translation export patterns
bhdnb Jul 28, 2026
eb0ab39
test: fixes for e2e tests
bhdnb Jul 28, 2026
9b23151
test(e2e): stop the bundle suite depending on a hardcoded bundle id
bhdnb Jul 28, 2026
7e60f6e
test(e2e): rework multilingual CSV suite
bhdnb Jul 30, 2026
d8275de
test(e2e): share switchConfig, fix captured-content types
bhdnb Jul 30, 2026
7e82488
test(e2e): fold csv-multilingual-in-root into multilingual-csv
bhdnb Jul 30, 2026
a7f5b20
test(e2e): rename the CSV suites, finish the switchConfig dedupe
bhdnb Jul 30, 2026
aebce6e
test(e2e): assert auto-update against server state, not stdout
bhdnb Jul 30, 2026
33d70f4
test(e2e): make the base-path download tests fail when nothing downloads
bhdnb Jul 30, 2026
019e051
test(e2e): make download assertions real, deterministic snapshot orde…
bhdnb Jul 30, 2026
2000e5c
test: fixes for e2e tests
vasylk-crowdin Aug 31, 2026
2c7e7be
test(e2e): refresh snapshots stale after the normalizer sort change
vasylk-crowdin Aug 31, 2026
189e52a
test(e2e): assert pre-translate diagnostics on stderr and the project…
vasylk-crowdin Aug 31, 2026
b2bb821
test(e2e): assert the real dest-remap outcome instead of an impossibl…
vasylk-crowdin Aug 31, 2026
ffebf17
test(e2e): expect the docx's non-breaking spaces in the segmented string
vasylk-crowdin Aug 31, 2026
45f9335
test(e2e): snapshot the --engine-id error from stderr
vasylk-crowdin Aug 31, 2026
91b8279
test(e2e): drop workarounds for bugs that have since been fixed
bhdnb Sep 1, 2026
11b27e2
test(e2e): cover the app command, install round trip included
bhdnb Sep 1, 2026
ceee68d
test(e2e): cover the status command
bhdnb Sep 1, 2026
495c152
test(e2e): cover the label command
bhdnb Sep 2, 2026
224ae3f
test(e2e): cover the task command
bhdnb Sep 2, 2026
008f922
test(e2e): cover the screenshot command
bhdnb Sep 2, 2026
a440861
test(e2e): cover the distribution command
bhdnb Sep 2, 2026
e67d303
test(e2e): cover the project command
bhdnb Sep 2, 2026
aab222e
test(e2e): drop the null% note now the fix is merged
bhdnb Sep 3, 2026
62163fc
refactor(e2e): cut comments in the app and project suites
bhdnb Sep 3, 2026
fb9a8aa
refactor(e2e): more comment cuts
bhdnb Sep 3, 2026
2b0f2cf
test(e2e): sync notes with fixes merged into main
bhdnb Sep 4, 2026
2f21206
test(e2e): cover the comment command
bhdnb Sep 4, 2026
89caf3a
test(e2e): cover the context command
bhdnb Sep 4, 2026
3eb3796
test(e2e): cover the branch command
bhdnb Sep 4, 2026
d7f57fe
test(e2e): cover the file command
bhdnb Sep 4, 2026
5dba479
test(e2e): cover bundle list, clone and delete
bhdnb Sep 4, 2026
457fe99
test(e2e): cover the bundle flag matrix
bhdnb Sep 4, 2026
eef3b7b
test(e2e): cover the language command
bhdnb Sep 4, 2026
3de8e03
test(e2e): cover the auto-translate option surface
bhdnb Sep 4, 2026
143aa06
refactor(e2e): cut comments across the suites
bhdnb Sep 4, 2026
4af07d2
test(e2e): assert the dest-remapped project paths
bhdnb Sep 4, 2026
4c1edd1
test(e2e): cover the json and toon output contract
bhdnb Sep 7, 2026
118f069
test(e2e,unit): cover the tm command and parseScheme function
bhdnb Sep 7, 2026
2f8e545
test(e2e): cover the glossary command surface
bhdnb Sep 7, 2026
7fcb380
test(e2e): cover the config command
bhdnb Sep 8, 2026
5f9bba6
test(e2e): assert stderr on failing-command tests
bhdnb Sep 8, 2026
c28e3d5
test(cli): expect --scheme en= to be rejected
bhdnb Sep 8, 2026
66818de
test(e2e): cover the string option surface
bhdnb Sep 8, 2026
b320bf8
test(e2e): cover init's default destination and lint round trip
bhdnb Sep 8, 2026
d1e223e
test(e2e): assert the exit code in structured error records
bhdnb Sep 8, 2026
45823c1
test(e2e): cover the upload sources flags
bhdnb Sep 8, 2026
486e592
test(e2e): cover the upload translations flags
bhdnb Sep 8, 2026
827c9ac
test(e2e): assert auto-approve-imported actually approves
bhdnb Sep 8, 2026
b2fe503
test(e2e): cover download sources dryrun and its guards
bhdnb Sep 8, 2026
dd7b9a6
test(e2e): cover the last download translations flags
bhdnb Sep 8, 2026
35d268a
test(e2e): cover --pseudo combined with the other download flags
bhdnb Sep 8, 2026
d680753
test(e2e,unit): cover auto-translate's string-based guards and option…
bhdnb Sep 8, 2026
6ac959e
test(e2e): cover the empty-argument guards
bhdnb Sep 9, 2026
70feac5
test(e2e): cover the per-file config options
bhdnb Sep 9, 2026
48e6f26
test(e2e): cover update_option
bhdnb Sep 9, 2026
3d68ca7
test(e2e): finish the empty-argument guards
bhdnb Sep 9, 2026
df27ff1
test(e2e): cover --debug and context --overwrite
bhdnb Sep 9, 2026
6b67f42
test(e2e): fix five stale expectations
bhdnb Sep 9, 2026
6fd7fcf
test(e2e): cover @arg-file expansion end to end
bhdnb Sep 9, 2026
53eb486
test(e2e): filter the tm listing comparison to this suite's own rows
bhdnb Sep 9, 2026
69d0c28
test(e2e): isolate the CLI from ambient credentials
bhdnb Sep 10, 2026
111af21
test(e2e): run init without a project
bhdnb Sep 10, 2026
1f569af
test(e2e): show CLI output when a success assertion fails
bhdnb Sep 11, 2026
c33fbcb
test(e2e): drop stale and redundant suite comments
bhdnb Sep 11, 2026
c68919b
test: move e2e and unit tests under tests/
bhdnb Sep 11, 2026
24fb79f
test(e2e): run suites four at a time
bhdnb Sep 11, 2026
65421e8
tests: fix for login command test
bhdnb Sep 17, 2026
cb35156
fix(output): honor --no-colors when FORCE_COLOR is set
bhdnb Sep 17, 2026
418ab81
test: drop legacy references from test comments
bhdnb Sep 17, 2026
f0144a9
test(e2e): share duplicated suite lookup helpers
bhdnb Sep 17, 2026
e0bfc24
test(e2e): move inline suite configs into fixtures
bhdnb Sep 17, 2026
e9048ff
test(e2e): let teardownSuite delete extra projects
bhdnb Sep 17, 2026
6f6d471
test(e2e): add expectFilesMatch for expected-file checks
bhdnb Sep 17, 2026
9a47a83
test(e2e): add runJson for json command output
bhdnb Sep 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
12 changes: 6 additions & 6 deletions .agents/skills/add-e2e-test-suite/SKILL.md

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The skill still claims the translation pattern is not applied on download, which basic-upload-download contradicts, and still describes the old normalize behavior.

Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
name: add-e2e-test-suite
description: Adds a new end-to-end (e2e) test suite for the Crowdin CLI under e2e/suites/, exercising real CLI commands against a freshly-created Crowdin project. Covers fixtures, the setupSuite/teardownSuite lifecycle, running the CLI, output normalization, snapshot generation, and file assertions. Use whenever asked to add, write, scaffold, or extend an e2e/integration test suite for the CLI — including new command coverage like upload, download, branch, glossary, or TM — even if the user just says "add an e2e test for X".
description: Adds a new end-to-end (e2e) test suite for the Crowdin CLI under tests/e2e/suites/, exercising real CLI commands against a freshly-created Crowdin project. Covers fixtures, the setupSuite/teardownSuite lifecycle, running the CLI, output normalization, snapshot generation, and file assertions. Use whenever asked to add, write, scaffold, or extend an e2e/integration test suite for the CLI — including new command coverage like upload, download, branch, glossary, or TM — even if the user just says "add an e2e test for X".
---

# Add an e2e test suite (Crowdin CLI)

The framework runs `bun src-next/cli.ts` against a **real, freshly-created Crowdin project**, asserts on normalized output / exit codes / produced files, then tears everything down. Each suite is one file owning one project: `beforeAll` provisions, `test()`s run **in declaration order**, `afterAll` tears down. See [e2e/README.md](../../../e2e/README.md).
The framework runs `bun src-next/cli.ts` against a **real, freshly-created Crowdin project**, asserts on normalized output / exit codes / produced files, then tears everything down. Each suite is one file owning one project: `beforeAll` provisions, `test()`s run **in declaration order**, `afterAll` tears down. See [tests/e2e/README.md](../../../tests/e2e/README.md).

## Iron rule: generate snapshots from a real run, never hand-write them

Expand All @@ -15,7 +15,7 @@ You can't reliably predict the CLI's exact output or where the server lands file

```bash
# user runs this (token already in their env):
bun test e2e/suites/<suite>.test.ts --update-snapshots
bun test tests/e2e/suites/<suite>.test.ts --update-snapshots
```

Then read the committed `.snap` to sanity-check it's real output, not an error/empty build.
Expand All @@ -24,7 +24,7 @@ Same for any server behavior (locale folder names, file layout): **observe it, d

## Steps

**1. Fixtures** — `e2e/fixtures/<suite>/config/crowdin.yml` (template) + input files (e.g. `sources/*.md`). Use only `{{projectId}}` / `{{token}}` placeholders; `renderConfig` throws on any other `{{...}}`. Everything except the top-level `config/` dir is copied into the workspace.
**1. Fixtures** — `tests/e2e/fixtures/<suite>/config/crowdin.yml` (template) + input files (e.g. `sources/*.md`). Use only `{{projectId}}` / `{{token}}` placeholders; `renderConfig` throws on any other `{{...}}`. Everything except the top-level `config/` dir is copied into the workspace.

```yaml
project_id: "{{projectId}}"
Expand All @@ -37,7 +37,7 @@ files:
translation: "translations/%locale%/%original_file_name%"
```

**2. Suite** — `e2e/suites/<suite>.test.ts`:
**2. Suite** — `tests/e2e/suites/<suite>.test.ts`:

```ts
import { afterAll, beforeAll, describe, expect, test } from 'bun:test';
Expand Down Expand Up @@ -82,7 +82,7 @@ No registry to edit (suites are discovered by file). No file cleanup to write (`
- **Prefer literal assertion strings** (`'it/sources/alpha.md'`) over paths derived from the API/config — clearer and obviously correct.
- **Token required.** `setupSuite` throws without `CROWDIN_E2E_TOKEN`. Suites run via `bun run test:e2e`; the network-free helper unit tests run in the regular `bun test`.

## Helpers (`e2e/helpers/`)
## Helpers (`tests/e2e/helpers/`)

- `setupSuite(suite, { sourceLanguageId?, targetLanguageIds? })` → `SuiteContext { env, client, workspace, project, runner }`. Provisions workspace + fixtures + project + rendered config; rolls back the project if a later setup step fails. `ctx.client` is a `@crowdin/crowdin-api-client` `Client` for direct API setup/assertions.
- `teardownSuite(ctx)` — deletes project + removes workspace; honors `CROWDIN_E2E_KEEP=1`; logs, never throws.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ jobs:
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-snapshots
path: e2e/suites/__snapshots__/
path: tests/e2e/suites/__snapshots__/
if-no-files-found: ignore
2 changes: 1 addition & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@
},
"files": {
"ignoreUnknown": false,
"includes": ["src-next/**/*.ts", "tests/**/*.ts", "e2e/**/*.ts", "packages/npm/cli/bin/*.js"]
"includes": ["src-next/**/*.ts", "tests/**/*.ts", "packages/npm/cli/bin/*.js"]
}
}
62 changes: 0 additions & 62 deletions e2e/helpers/cli.ts

This file was deleted.

18 changes: 0 additions & 18 deletions e2e/helpers/files.ts

This file was deleted.

48 changes: 0 additions & 48 deletions e2e/helpers/normalize.test.ts

This file was deleted.

65 changes: 0 additions & 65 deletions e2e/helpers/normalize.ts

This file was deleted.

94 changes: 0 additions & 94 deletions e2e/helpers/suite.ts

This file was deleted.

2 changes: 1 addition & 1 deletion knip.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"$schema": "https://unpkg.com/knip@6/schema.json",
// Scope to the new CLI and its tests. Entry points are inferred from the package.json scripts,
// so only `project` needs narrowing - knip's default would pull in website/ and packages/.
"project": ["src-next/**/*.ts", "tests/**/*.ts", "e2e/**/*.ts"]
"project": ["src-next/**/*.ts", "tests/**/*.ts"]
}
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
"build:linux-arm64-musl": "bun build src-next/cli.ts --compile --target=bun-linux-arm64-musl --outfile packages/npm/linux-arm64-musl/bin/crowdin",
"build:win32-x64": "bun build src-next/cli.ts --compile --target=bun-windows-x64-baseline --outfile packages/npm/win32-x64/bin/crowdin.exe",
"build:all": "bun run build:darwin-arm64 && bun run build:darwin-x64 && bun run build:linux-x64 && bun run build:linux-arm64 && bun run build:linux-x64-musl && bun run build:linux-arm64-musl && bun run build:win32-x64",
"test": "bun test tests/ e2e/helpers/",
"test:coverage": "bun test --coverage tests/ e2e/helpers/",
"test:e2e": "bun test e2e/suites/ --timeout 120000",
"test": "bun test tests/unit/ tests/e2e/helpers/",
"test:coverage": "bun test --coverage tests/unit/ tests/e2e/helpers/",
"test:e2e": "bun test tests/e2e/suites/ --timeout 120000 --parallel=4",
"docs": "bun run src-next/scripts/generate-docs.ts",
"format": "biome format --write",
"lint": "biome check",
Expand Down
Loading