codeceptjs 4.0.2-beta.9 → 4.0.2
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 +39 -28
- package/bin/codecept.js +15 -2
- package/bin/codeceptq.js +49 -0
- package/bin/mcp-server.js +1189 -0
- package/docs/advanced.md +201 -0
- package/docs/agents.md +181 -0
- package/docs/ai.md +489 -0
- package/docs/aitrace.md +266 -0
- package/docs/api.md +332 -0
- package/docs/architecture.md +235 -0
- package/docs/assertions.md +415 -0
- package/docs/auth.md +318 -0
- package/docs/basics.md +424 -0
- package/docs/bdd.md +539 -0
- package/docs/best.md +240 -0
- package/docs/bootstrap.md +132 -0
- package/docs/commands.md +352 -0
- package/docs/community-helpers.md +63 -0
- package/docs/configuration.md +185 -0
- package/docs/continuous-integration.md +431 -0
- package/docs/custom-helpers.md +297 -0
- package/docs/data.md +448 -0
- package/docs/debugging.md +332 -0
- package/docs/detox.md +235 -0
- package/docs/docker.md +107 -0
- package/docs/effects.md +179 -0
- package/docs/element-based-testing.md +295 -0
- package/docs/element-selection.md +125 -0
- package/docs/els.md +328 -0
- package/docs/environment-variables.md +131 -0
- package/docs/examples.md +160 -0
- package/docs/heal.md +213 -0
- package/docs/helpers/ApiDataFactory.md +267 -0
- package/docs/helpers/Appium.md +1419 -0
- package/docs/helpers/Detox.md +665 -0
- package/docs/helpers/ExpectHelper.md +275 -0
- package/docs/helpers/FileSystem.md +152 -0
- package/docs/helpers/GraphQL.md +152 -0
- package/docs/helpers/GraphQLDataFactory.md +226 -0
- package/docs/helpers/JSONResponse.md +255 -0
- package/docs/helpers/MockRequest.md +377 -0
- package/docs/helpers/Playwright.md +2970 -0
- package/docs/helpers/Puppeteer-firefox.md +86 -0
- package/docs/helpers/Puppeteer.md +2583 -0
- package/docs/helpers/REST.md +289 -0
- package/docs/helpers/WebDriver.md +2639 -0
- package/docs/hooks.md +148 -0
- package/docs/index.md +111 -0
- package/docs/installation.md +121 -0
- package/docs/internal-test-server.md +89 -0
- package/docs/locators.md +355 -0
- package/docs/mcp.md +485 -0
- package/docs/migrate-from-cypress.md +98 -0
- package/docs/migrate-from-java.md +108 -0
- package/docs/migrate-from-protractor.md +101 -0
- package/docs/migrate-from-testcafe.md +99 -0
- package/docs/migration-4.md +745 -0
- package/docs/mobile.md +338 -0
- package/docs/pageobjects.md +399 -0
- package/docs/parallel.md +187 -0
- package/docs/playwright.md +714 -0
- package/docs/plugins/aiTrace.md +49 -0
- package/docs/plugins/analyze.md +66 -0
- package/docs/plugins/auth.md +241 -0
- package/docs/plugins/autoDelay.md +48 -0
- package/docs/plugins/browser.md +41 -0
- package/docs/plugins/coverage.md +39 -0
- package/docs/plugins/customLocator.md +119 -0
- package/docs/plugins/customReporter.md +16 -0
- package/docs/plugins/expose.md +75 -0
- package/docs/plugins/heal.md +44 -0
- package/docs/plugins/junitReporter.md +51 -0
- package/docs/plugins/pageInfo.md +34 -0
- package/docs/plugins/pause.md +43 -0
- package/docs/plugins/pauseOnFail.md +18 -0
- package/docs/plugins/retryFailedStep.md +75 -0
- package/docs/plugins/screencast.md +55 -0
- package/docs/plugins/screenshot.md +58 -0
- package/docs/plugins/screenshotOnFail.md +18 -0
- package/docs/plugins/stepTimeout.md +65 -0
- package/docs/plugins.md +87 -0
- package/docs/puppeteer.md +314 -0
- package/docs/quickstart.md +120 -0
- package/docs/reports.md +195 -0
- package/docs/retry.md +311 -0
- package/docs/secrets.md +150 -0
- package/docs/sessions.md +80 -0
- package/docs/shadow.md +68 -0
- package/docs/store.md +94 -0
- package/docs/test-structure.md +275 -0
- package/docs/timeouts.md +183 -0
- package/docs/translation.md +247 -0
- package/docs/tutorial.md +323 -0
- package/docs/typescript.md +159 -0
- package/docs/web-element.md +251 -0
- package/docs/webdriver.md +641 -0
- package/docs/within.md +55 -0
- package/lib/actor.js +1 -36
- package/lib/ai.js +3 -2
- package/lib/aria.js +260 -0
- package/lib/assertions.js +18 -0
- package/lib/codecept.js +34 -25
- package/lib/command/check.js +2 -1
- package/lib/command/definitions.js +6 -7
- package/lib/command/dryRun.js +24 -5
- package/lib/command/generate.js +3 -1
- package/lib/command/gherkin/snippets.js +5 -4
- package/lib/command/init.js +249 -270
- package/lib/command/list.js +150 -10
- package/lib/command/query.js +218 -0
- package/lib/command/run-multiple.js +3 -1
- package/lib/command/run-workers.js +2 -14
- package/lib/command/run.js +3 -17
- package/lib/command/utils.js +14 -0
- package/lib/command/workers/runTests.js +84 -41
- package/lib/config.js +96 -18
- package/lib/container.js +115 -17
- package/lib/effects.js +17 -0
- package/lib/element/WebElement.js +246 -2
- package/lib/els.js +12 -6
- package/lib/globals.js +32 -19
- package/lib/heal.js +7 -4
- package/lib/helper/ApiDataFactory.js +2 -1
- package/lib/helper/Appium.js +8 -8
- package/lib/helper/FileSystem.js +3 -2
- package/lib/helper/GraphQLDataFactory.js +2 -1
- package/lib/helper/Playwright.js +358 -467
- package/lib/helper/Puppeteer.js +335 -192
- package/lib/helper/WebDriver.js +324 -111
- package/lib/helper/errors/ElementNotFound.js +5 -2
- package/lib/helper/errors/MultipleElementsFound.js +52 -0
- package/lib/helper/errors/NonFocusedType.js +8 -0
- package/lib/helper/extras/Download.js +45 -0
- package/lib/helper/extras/PlaywrightLocator.js +7 -107
- package/lib/helper/extras/elementSelection.js +58 -0
- package/lib/helper/extras/focusCheck.js +43 -0
- package/lib/helper/extras/richTextEditor.js +178 -0
- package/lib/helper/scripts/dropFile.js +11 -0
- package/lib/history.js +3 -2
- package/lib/html.js +103 -16
- package/lib/index.js +9 -1
- package/lib/listener/config.js +6 -4
- package/lib/listener/emptyRun.js +2 -1
- package/lib/listener/globalRetry.js +32 -6
- package/lib/listener/helpers.js +4 -1
- package/lib/listener/mocha.js +2 -1
- package/lib/listener/pageobjects.js +43 -0
- package/lib/listener/result.js +3 -2
- package/lib/locator.js +158 -16
- package/lib/mocha/cli.js +19 -1
- package/lib/mocha/factory.js +11 -1
- package/lib/mocha/inject.js +1 -1
- package/lib/mocha/scenarioConfig.js +2 -1
- package/lib/mocha/ui.js +5 -6
- package/lib/parser.js +2 -2
- package/lib/pause.js +38 -4
- package/lib/plugin/aiTrace.js +457 -0
- package/lib/plugin/analyze.js +9 -9
- package/lib/plugin/auth.js +5 -4
- package/lib/plugin/browser.js +77 -0
- package/lib/plugin/expose.js +159 -0
- package/lib/plugin/heal.js +47 -3
- package/lib/plugin/junitReporter.js +303 -0
- package/lib/plugin/pageInfo.js +54 -52
- package/lib/plugin/pause.js +131 -0
- package/lib/plugin/pauseOnFail.js +11 -33
- package/lib/plugin/retryFailedStep.js +43 -32
- package/lib/plugin/screencast.js +289 -0
- package/lib/plugin/screenshot.js +558 -0
- package/lib/plugin/screenshotOnFail.js +9 -170
- package/lib/plugin/stepTimeout.js +3 -2
- package/lib/recorder.js +1 -1
- package/lib/rerun.js +2 -1
- package/lib/result.js +2 -1
- package/lib/step/base.js +10 -9
- package/lib/step/comment.js +2 -2
- package/lib/step/config.js +15 -2
- package/lib/step/helper.js +4 -4
- package/lib/step/meta.js +3 -3
- package/lib/step/record.js +5 -5
- package/lib/store.js +72 -3
- package/lib/translation.js +2 -1
- package/lib/utils/loaderCheck.js +28 -0
- package/lib/utils/mask_data.js +2 -1
- package/lib/utils/pluginParser.js +151 -0
- package/lib/utils/trace.js +297 -0
- package/lib/utils/typescript.js +188 -23
- package/lib/utils.js +77 -3
- package/lib/workers.js +65 -40
- package/package.json +35 -30
- package/typings/index.d.ts +119 -8
- package/typings/promiseBasedTypes.d.ts +3158 -6065
- package/typings/types.d.ts +3453 -6494
- package/docs/webapi/amOnPage.mustache +0 -11
- package/docs/webapi/appendField.mustache +0 -11
- package/docs/webapi/attachFile.mustache +0 -12
- package/docs/webapi/blur.mustache +0 -18
- package/docs/webapi/checkOption.mustache +0 -13
- package/docs/webapi/clearCookie.mustache +0 -9
- package/docs/webapi/clearField.mustache +0 -9
- package/docs/webapi/click.mustache +0 -29
- package/docs/webapi/clickLink.mustache +0 -8
- package/docs/webapi/closeCurrentTab.mustache +0 -7
- package/docs/webapi/closeOtherTabs.mustache +0 -8
- package/docs/webapi/dontSee.mustache +0 -11
- package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
- package/docs/webapi/dontSeeCookie.mustache +0 -8
- package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
- package/docs/webapi/dontSeeElement.mustache +0 -8
- package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
- package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
- package/docs/webapi/dontSeeInField.mustache +0 -11
- package/docs/webapi/dontSeeInSource.mustache +0 -8
- package/docs/webapi/dontSeeInTitle.mustache +0 -8
- package/docs/webapi/dontSeeTraffic.mustache +0 -13
- package/docs/webapi/doubleClick.mustache +0 -13
- package/docs/webapi/downloadFile.mustache +0 -12
- package/docs/webapi/dragAndDrop.mustache +0 -9
- package/docs/webapi/dragSlider.mustache +0 -11
- package/docs/webapi/executeAsyncScript.mustache +0 -24
- package/docs/webapi/executeScript.mustache +0 -26
- package/docs/webapi/fillField.mustache +0 -16
- package/docs/webapi/flushNetworkTraffics.mustache +0 -5
- package/docs/webapi/focus.mustache +0 -13
- package/docs/webapi/forceClick.mustache +0 -28
- package/docs/webapi/forceRightClick.mustache +0 -18
- package/docs/webapi/grabAllWindowHandles.mustache +0 -7
- package/docs/webapi/grabAttributeFrom.mustache +0 -10
- package/docs/webapi/grabAttributeFromAll.mustache +0 -9
- package/docs/webapi/grabBrowserLogs.mustache +0 -9
- package/docs/webapi/grabCookie.mustache +0 -11
- package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
- package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
- package/docs/webapi/grabCurrentUrl.mustache +0 -9
- package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
- package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
- package/docs/webapi/grabElementBoundingRect.mustache +0 -20
- package/docs/webapi/grabGeoLocation.mustache +0 -8
- package/docs/webapi/grabHTMLFrom.mustache +0 -10
- package/docs/webapi/grabHTMLFromAll.mustache +0 -9
- package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
- package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
- package/docs/webapi/grabPageScrollPosition.mustache +0 -8
- package/docs/webapi/grabPopupText.mustache +0 -5
- package/docs/webapi/grabRecordedNetworkTraffics.mustache +0 -10
- package/docs/webapi/grabSource.mustache +0 -8
- package/docs/webapi/grabTextFrom.mustache +0 -10
- package/docs/webapi/grabTextFromAll.mustache +0 -9
- package/docs/webapi/grabTitle.mustache +0 -8
- package/docs/webapi/grabValueFrom.mustache +0 -9
- package/docs/webapi/grabValueFromAll.mustache +0 -8
- package/docs/webapi/grabWebElement.mustache +0 -9
- package/docs/webapi/grabWebElements.mustache +0 -9
- package/docs/webapi/moveCursorTo.mustache +0 -12
- package/docs/webapi/openNewTab.mustache +0 -7
- package/docs/webapi/pressKey.mustache +0 -12
- package/docs/webapi/pressKeyDown.mustache +0 -12
- package/docs/webapi/pressKeyUp.mustache +0 -12
- package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
- package/docs/webapi/refreshPage.mustache +0 -6
- package/docs/webapi/resizeWindow.mustache +0 -6
- package/docs/webapi/rightClick.mustache +0 -14
- package/docs/webapi/saveElementScreenshot.mustache +0 -10
- package/docs/webapi/saveScreenshot.mustache +0 -12
- package/docs/webapi/say.mustache +0 -10
- package/docs/webapi/scrollIntoView.mustache +0 -11
- package/docs/webapi/scrollPageToBottom.mustache +0 -6
- package/docs/webapi/scrollPageToTop.mustache +0 -6
- package/docs/webapi/scrollTo.mustache +0 -12
- package/docs/webapi/see.mustache +0 -11
- package/docs/webapi/seeAttributesOnElements.mustache +0 -9
- package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
- package/docs/webapi/seeCookie.mustache +0 -8
- package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
- package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
- package/docs/webapi/seeElement.mustache +0 -8
- package/docs/webapi/seeElementInDOM.mustache +0 -8
- package/docs/webapi/seeInCurrentUrl.mustache +0 -8
- package/docs/webapi/seeInField.mustache +0 -12
- package/docs/webapi/seeInPopup.mustache +0 -8
- package/docs/webapi/seeInSource.mustache +0 -7
- package/docs/webapi/seeInTitle.mustache +0 -8
- package/docs/webapi/seeNumberOfElements.mustache +0 -11
- package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
- package/docs/webapi/seeTextEquals.mustache +0 -9
- package/docs/webapi/seeTitleEquals.mustache +0 -8
- package/docs/webapi/seeTraffic.mustache +0 -36
- package/docs/webapi/selectOption.mustache +0 -21
- package/docs/webapi/setCookie.mustache +0 -16
- package/docs/webapi/setGeoLocation.mustache +0 -12
- package/docs/webapi/startRecordingTraffic.mustache +0 -8
- package/docs/webapi/startRecordingWebSocketMessages.mustache +0 -8
- package/docs/webapi/stopRecordingTraffic.mustache +0 -5
- package/docs/webapi/stopRecordingWebSocketMessages.mustache +0 -7
- package/docs/webapi/switchTo.mustache +0 -9
- package/docs/webapi/switchToNextTab.mustache +0 -10
- package/docs/webapi/switchToPreviousTab.mustache +0 -10
- package/docs/webapi/type.mustache +0 -21
- package/docs/webapi/uncheckOption.mustache +0 -13
- package/docs/webapi/wait.mustache +0 -8
- package/docs/webapi/waitForClickable.mustache +0 -11
- package/docs/webapi/waitForCookie.mustache +0 -9
- package/docs/webapi/waitForDetached.mustache +0 -10
- package/docs/webapi/waitForDisabled.mustache +0 -6
- package/docs/webapi/waitForElement.mustache +0 -11
- package/docs/webapi/waitForEnabled.mustache +0 -6
- package/docs/webapi/waitForFunction.mustache +0 -17
- package/docs/webapi/waitForInvisible.mustache +0 -10
- package/docs/webapi/waitForNumberOfTabs.mustache +0 -9
- package/docs/webapi/waitForText.mustache +0 -13
- package/docs/webapi/waitForValue.mustache +0 -10
- package/docs/webapi/waitForVisible.mustache +0 -10
- package/docs/webapi/waitInUrl.mustache +0 -9
- package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
- package/docs/webapi/waitToHide.mustache +0 -10
- package/docs/webapi/waitUrlEquals.mustache +0 -10
- package/lib/helper/AI.js +0 -214
- package/lib/helper/Mochawesome.js +0 -96
- package/lib/helper/extras/PlaywrightReactVueLocator.js +0 -52
- package/lib/helper/extras/React.js +0 -65
- package/lib/listener/enhancedGlobalRetry.js +0 -110
- package/lib/plugin/enhancedRetryFailedStep.js +0 -99
- package/lib/plugin/htmlReporter.js +0 -3648
- package/lib/plugin/stepByStepReport.js +0 -427
- package/lib/plugin/subtitles.js +0 -89
- package/lib/retryCoordinator.js +0 -207
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
permalink: /migrate-from-java
|
|
3
|
+
title: Migrate from Java Selenium to CodeceptJS
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Migrate from Java Selenium to CodeceptJS
|
|
7
|
+
|
|
8
|
+
## Start here: what changes when you leave the JVM
|
|
9
|
+
|
|
10
|
+
On the JVM, an end-to-end suite is basically its own product. It has its own Maven or Gradle build, its own dependencies, and a JVM that has to warm up before anything runs. In practice it ends up with its own team too — application engineers stay on the app, QA stays on the tests, and the suite drifts whenever nobody is watching it.
|
|
11
|
+
|
|
12
|
+
In Node there is no compile or build step. Running tests in NodeJS saves time. NodeJS ecosystem is fastest growing opensource ecosystem, with awesome depenency management tools like npm, bun, pnpm. While Java tests still work JS ecosystem is richer and easier to use. Tools like Playwright and Puppeteer originally started on NodeJS.
|
|
13
|
+
|
|
14
|
+
Even migrating from Java to JavaScript seems like a huge task, it is actually not.
|
|
15
|
+
We prepared a set of skills for, so you can relax and
|
|
16
|
+
[let an agent do the migration](#let-an-agent-do-the-migration).
|
|
17
|
+
|
|
18
|
+
## Comparison
|
|
19
|
+
|
|
20
|
+
The original test in Java Selenium:
|
|
21
|
+
|
|
22
|
+
```java
|
|
23
|
+
// Java + Selenium + JUnit
|
|
24
|
+
@Test
|
|
25
|
+
public void userCanLogin() {
|
|
26
|
+
WebDriver driver = new ChromeDriver();
|
|
27
|
+
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
|
|
28
|
+
|
|
29
|
+
driver.get("https://example.com/login");
|
|
30
|
+
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("username")));
|
|
31
|
+
|
|
32
|
+
driver.findElement(By.id("username")).sendKeys("alice");
|
|
33
|
+
driver.findElement(By.id("password")).sendKeys("secret");
|
|
34
|
+
driver.findElement(By.cssSelector("button[type=submit]")).click();
|
|
35
|
+
|
|
36
|
+
wait.until(ExpectedConditions.urlContains("/dashboard"));
|
|
37
|
+
WebElement welcome = wait.until(
|
|
38
|
+
ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".welcome"))
|
|
39
|
+
);
|
|
40
|
+
assertEquals("Welcome, Alice", welcome.getText());
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Will look in CodeceptJS:
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
// CodeceptJS
|
|
48
|
+
Scenario('user can log in', ({ I }) => {
|
|
49
|
+
I.amOnPage('/login');
|
|
50
|
+
I.fillField('Username', 'alice');
|
|
51
|
+
I.fillField('Password', 'secret');
|
|
52
|
+
I.click('Sign in');
|
|
53
|
+
I.seeInCurrentUrl('/dashboard');
|
|
54
|
+
I.see('Welcome, Alice', '.welcome');
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
And here is how this test looks while running — every step is printed live, in the same order it was written:
|
|
59
|
+
|
|
60
|
+
```text
|
|
61
|
+
user can log in
|
|
62
|
+
I am on page "/login"
|
|
63
|
+
I fill field "Username", "alice"
|
|
64
|
+
I fill field "Password", "secret"
|
|
65
|
+
I click "Sign in"
|
|
66
|
+
I see in current url "/dashboard"
|
|
67
|
+
I see "Welcome, Alice", ".welcome"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Let an agent do the migration
|
|
71
|
+
|
|
72
|
+
The conversions above are mechanical, so you do not have to do them by hand, and the work does not cost you working time. Install the skills bundle, point an agent at the repo, and check back when it reports.
|
|
73
|
+
|
|
74
|
+
The **`migrate-selenium-java-to-codeceptjs`** skill in the [CodeceptJS skills bundle](https://github.com/codeceptjs/skills) does the whole port:
|
|
75
|
+
|
|
76
|
+
1. Inventories the page objects, helper classes, hooks, and data providers.
|
|
77
|
+
2. Sets up CodeceptJS beside the Java suite with the WebDriver helper.
|
|
78
|
+
3. Ports the page objects and helpers.
|
|
79
|
+
4. Converts each spec.
|
|
80
|
+
5. Runs the full suite.
|
|
81
|
+
|
|
82
|
+
First runs fail, because locators drift and timing changes. The agent then uses the `debugging-codeceptjs-tests` skill to fix each failure against the live browser before moving on. Your Java suite keeps running in CI until the port is green, so nothing is at risk while the agent works.
|
|
83
|
+
|
|
84
|
+
Install the bundle in Claude Code:
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
/plugin marketplace add codeceptjs/skills
|
|
88
|
+
/plugin install codeceptjs@codeceptjs-skills
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Or any other agent:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
npx skills add codeceptjs/skills
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Then ask: *"Migrate this Java Selenium suite to CodeceptJS."* The skill triggers on the Maven or Gradle and `org.openqa.selenium` signatures in your repo. Start it, do other work, and read the step output when it reports back.
|
|
98
|
+
|
|
99
|
+
## Pointers
|
|
100
|
+
|
|
101
|
+
- [/agents](/agents) for how the agent and MCP loop works
|
|
102
|
+
- [/webdriver](/webdriver) for the default helper in this migration, with driver auto-start
|
|
103
|
+
- [/playwright](/playwright) for the optional follow-up swap
|
|
104
|
+
- [/locators](/locators) for semantic, ARIA, and `locate()` locators
|
|
105
|
+
- [/pageobjects](/pageobjects) for ported `@FindBy` page objects
|
|
106
|
+
- [/auth](/auth) for login and session reuse
|
|
107
|
+
- [/api](/api) for the REST helper used in RestAssured ports
|
|
108
|
+
- [/bdd](/bdd) for CodeceptJS BDD in Cucumber-JVM ports
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
permalink: /migrate-from-protractor
|
|
3
|
+
title: Migrate from Protractor to CodeceptJS
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Migrate from Protractor to CodeceptJS
|
|
7
|
+
|
|
8
|
+
## Start here: a dead dependency with an Angular wrapper
|
|
9
|
+
|
|
10
|
+
Protractor was end-of-lifed in April 2023 and has shipped nothing since. Its design wrapped Selenium with two things: `waitForAngular`, which blocked each action until Angular's digest cycle settled, and the ControlFlow promise manager, which ordered commands so test code could be written as if it were synchronous. That is why a Protractor suite pins an old Selenium version and threads results through `.then()`. The dependency only ages from here.
|
|
11
|
+
|
|
12
|
+
CodeceptJS drops the Angular coupling. The helper waits on the element you are acting on, not on Angular's digest, so the same test works on an Angular app, a React app, or a static page. It still speaks the WebDriver protocol, so an existing Selenium Grid keeps serving the new suite, or you switch the config to Playwright and run the same test code faster.
|
|
13
|
+
|
|
14
|
+
Migrating a Protractor suite looks like a lot of work. It is not. We prepared a set of skills, so you can relax and [let an agent do the migration](#let-an-agent-do-the-migration).
|
|
15
|
+
|
|
16
|
+
## Comparison
|
|
17
|
+
|
|
18
|
+
The original test in Protractor:
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
// Protractor + Jasmine
|
|
22
|
+
describe('login', function () {
|
|
23
|
+
it('user can log in', function () {
|
|
24
|
+
browser.get('https://example.com/login');
|
|
25
|
+
element(by.model('user.email')).sendKeys('alice@example.com');
|
|
26
|
+
element(by.model('user.password')).sendKeys('secret');
|
|
27
|
+
element(by.css('button[type=submit]')).click();
|
|
28
|
+
expect(browser.getCurrentUrl()).toContain('/dashboard');
|
|
29
|
+
expect(element(by.css('.welcome')).getText()).toContain('Welcome, Alice');
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Will look in CodeceptJS:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
// CodeceptJS
|
|
38
|
+
Scenario('user can log in', ({ I }) => {
|
|
39
|
+
I.amOnPage('/login');
|
|
40
|
+
I.fillField('Email', 'alice@example.com');
|
|
41
|
+
I.fillField('Password', 'secret');
|
|
42
|
+
I.click('Sign in');
|
|
43
|
+
I.seeInCurrentUrl('/dashboard');
|
|
44
|
+
I.see('Welcome, Alice', '.welcome');
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The `describe`/`it` nesting, the `by.model` strategy, and the Jasmine assertions are gone. The steps read as a sequence instead of a chain of `.then()` calls.
|
|
49
|
+
|
|
50
|
+
And here is how the test looks while it runs. Every step is printed live, in the same order it was written:
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
user can log in
|
|
54
|
+
I am on page "/login"
|
|
55
|
+
I fill field "Email", "alice@example.com"
|
|
56
|
+
I fill field "Password", "secret"
|
|
57
|
+
I click "Sign in"
|
|
58
|
+
I see in current url "/dashboard"
|
|
59
|
+
I see "Welcome, Alice", ".welcome"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
When a step fails, the output stays on that line, with the locator that missed and a screenshot attached. There is no separate report step before you know what happened.
|
|
63
|
+
|
|
64
|
+
## Let an agent do the migration
|
|
65
|
+
|
|
66
|
+
The conversions are mechanical, so you do not have to do them by hand, and the work does not cost you working time. Install the skills bundle, point an agent at the repo, and check back when it reports.
|
|
67
|
+
|
|
68
|
+
The **`migrate-protractor-to-codeceptjs`** skill in the [CodeceptJS skills bundle](https://github.com/codeceptjs/skills) does the whole port:
|
|
69
|
+
|
|
70
|
+
1. Inventories the page objects, shared helpers, and config hooks.
|
|
71
|
+
2. Sets up CodeceptJS beside the Protractor suite.
|
|
72
|
+
3. Ports the page objects and helpers.
|
|
73
|
+
4. Converts each spec.
|
|
74
|
+
5. Runs the full suite.
|
|
75
|
+
|
|
76
|
+
First runs fail, because locators drift and timing changes. The agent then uses the `debugging-codeceptjs-tests` skill to fix each failure against the live browser before moving on. Your Protractor suite keeps running in CI until the port is green, so nothing is at risk while the agent works.
|
|
77
|
+
|
|
78
|
+
Install the bundle in Claude Code:
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
/plugin marketplace add codeceptjs/skills
|
|
82
|
+
/plugin install codeceptjs@codeceptjs-skills
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Or any other agent:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npx skills add codeceptjs/skills
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Then ask: *"Migrate this Protractor suite to CodeceptJS."* The skill triggers on the Protractor signatures in your repo. Start it, do other work, and read the step output when it reports back.
|
|
92
|
+
|
|
93
|
+
## Pointers
|
|
94
|
+
|
|
95
|
+
- [/agents](/agents) for how the agent and MCP loop works
|
|
96
|
+
- [/playwright](/playwright) for the recommended target helper
|
|
97
|
+
- [/webdriver](/webdriver) for the target if you keep a Selenium Grid
|
|
98
|
+
- [/locators](/locators) for semantic, ARIA, `locate()`, and the `customLocator` plugin
|
|
99
|
+
- [/pageobjects](/pageobjects) for ported Protractor page objects
|
|
100
|
+
- [/auth](/auth) for programmatic login and session reuse
|
|
101
|
+
- [/api](/api) for the REST helper used in HTTP-call ports
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
permalink: /migrate-from-testcafe
|
|
3
|
+
title: Migrate from TestCafe to CodeceptJS
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Migrate from TestCafe to CodeceptJS
|
|
7
|
+
|
|
8
|
+
## Start here: what the proxy costs you
|
|
9
|
+
|
|
10
|
+
TestCafe does not drive a browser through a driver. It runs a proxy in front of the browser, rewrites every page and script as they load, and injects its automation into the rewritten page. That worked when it was built, but the web platform now fights it. Content Security Policy blocks the injected script. HSTS, SameSite cookies, and COOP/COEP assume the origin the browser actually requested, not a proxied one. Service workers cache the rewritten responses. The proxy has more to paper over every release, and every action in a test needs its own `await` because each one is a round trip through the injected runtime.
|
|
11
|
+
|
|
12
|
+
CodeceptJS drives a real browser through a driver: Playwright over CDP, across the same Chromium, Firefox, and WebKit engines TestCafe targeted, with nothing in the request path. The page the test sees is the page the server sent, so there is nothing to rewrite and nothing for the platform to break. Actions queue internally, so they read top to bottom without `await` on every line.
|
|
13
|
+
|
|
14
|
+
Migrating a TestCafe suite looks like a lot of work. It is not. We prepared a set of skills, so you can relax and [let an agent do the migration](#let-an-agent-do-the-migration).
|
|
15
|
+
|
|
16
|
+
## Comparison
|
|
17
|
+
|
|
18
|
+
The original test in TestCafe:
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
// TestCafe
|
|
22
|
+
fixture`Login`.page`https://example.com/login`;
|
|
23
|
+
|
|
24
|
+
test('user can log in', async t => {
|
|
25
|
+
await t.typeText(Selector('#username'), 'alice');
|
|
26
|
+
await t.typeText(Selector('#password'), 'secret');
|
|
27
|
+
await t.click(Selector('button').withText('Sign in'));
|
|
28
|
+
await t.expect(getLocation()).contains('/dashboard');
|
|
29
|
+
await t.expect(Selector('.welcome').innerText).contains('Welcome, Alice');
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Will look in CodeceptJS:
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
// CodeceptJS
|
|
37
|
+
Scenario('user can log in', ({ I }) => {
|
|
38
|
+
I.amOnPage('/login');
|
|
39
|
+
I.fillField('Username', 'alice');
|
|
40
|
+
I.fillField('Password', 'secret');
|
|
41
|
+
I.click('Sign in');
|
|
42
|
+
I.seeInCurrentUrl('/dashboard');
|
|
43
|
+
I.see('Welcome, Alice', '.welcome');
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Every `await`, every `t`, and every `Selector` is gone. The steps read as a sequence instead of a chain of awaited calls.
|
|
48
|
+
|
|
49
|
+
And here is how the test looks while it runs. Every step is printed live, in the same order it was written:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
user can log in
|
|
53
|
+
I am on page "/login"
|
|
54
|
+
I fill field "Username", "alice"
|
|
55
|
+
I fill field "Password", "secret"
|
|
56
|
+
I click "Sign in"
|
|
57
|
+
I see in current url "/dashboard"
|
|
58
|
+
I see "Welcome, Alice", ".welcome"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
When a step fails, the output stays on that line, with the locator that missed and a screenshot attached. There is no separate report step before you know what happened.
|
|
62
|
+
|
|
63
|
+
## Let an agent do the migration
|
|
64
|
+
|
|
65
|
+
The conversions are mechanical, so you do not have to do them by hand, and the work does not cost you working time. Install the skills bundle, point an agent at the repo, and check back when it reports.
|
|
66
|
+
|
|
67
|
+
The **`migrate-testcafe-to-codeceptjs`** skill in the [CodeceptJS skills bundle](https://github.com/codeceptjs/skills) does the whole port:
|
|
68
|
+
|
|
69
|
+
1. Inventories the shared logic: `Role` setup, `ClientFunction` wrappers, page models, and request mocks.
|
|
70
|
+
2. Sets up CodeceptJS beside the TestCafe suite with the Playwright helper.
|
|
71
|
+
3. Ports the abstractions into custom helpers and page objects.
|
|
72
|
+
4. Converts each spec.
|
|
73
|
+
5. Runs the full suite.
|
|
74
|
+
|
|
75
|
+
First runs fail, because locators drift and timing changes. The agent then uses the `debugging-codeceptjs-tests` skill to fix each failure against the live browser before moving on. Your TestCafe suite keeps running in CI until the port is green, so nothing is at risk while the agent works.
|
|
76
|
+
|
|
77
|
+
Install the bundle in Claude Code:
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
/plugin marketplace add codeceptjs/skills
|
|
81
|
+
/plugin install codeceptjs@codeceptjs-skills
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Or any other agent:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npx skills add codeceptjs/skills
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Then ask: *"Migrate this TestCafe suite to CodeceptJS."* The skill triggers on the TestCafe signatures in your repo. Start it, do other work, and read the step output when it reports back.
|
|
91
|
+
|
|
92
|
+
## Pointers
|
|
93
|
+
|
|
94
|
+
- [/agents](/agents) for how the agent and MCP loop works
|
|
95
|
+
- [/playwright](/playwright) for the default helper in this migration
|
|
96
|
+
- [/locators](/locators) for semantic, ARIA, and `locate()` locators in place of `Selector` chains
|
|
97
|
+
- [/auth](/auth) for the plugin that replaces `Role` and `t.useRole`
|
|
98
|
+
- [/api](/api) for the REST helper used in API testing
|
|
99
|
+
- [/pageobjects](/pageobjects) for ported page objects
|