{"id":20292988,"url":"https://github.com/gemini-testing/hermione-codemod","last_synced_at":"2025-08-24T17:38:56.739Z","repository":{"id":45991977,"uuid":"340288075","full_name":"gemini-testing/hermione-codemod","owner":"gemini-testing","description":"Hermione codemod scripts","archived":false,"fork":false,"pushed_at":"2021-11-22T11:34:52.000Z","size":1026,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-02-17T20:21:35.979Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gemini-testing.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-02-19T07:14:32.000Z","updated_at":"2021-11-22T11:34:55.000Z","dependencies_parsed_at":"2022-08-29T22:31:01.951Z","dependency_job_id":null,"html_url":"https://github.com/gemini-testing/hermione-codemod","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gemini-testing%2Fhermione-codemod","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gemini-testing%2Fhermione-codemod/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gemini-testing%2Fhermione-codemod/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gemini-testing%2Fhermione-codemod/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gemini-testing","download_url":"https://codeload.github.com/gemini-testing/hermione-codemod/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241787485,"owners_count":20020101,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T15:20:32.613Z","updated_at":"2025-03-04T05:14:46.598Z","avatar_url":"https://github.com/gemini-testing.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# hermione-codemod [![Build Status](https://travis-ci.com/gemini-testing/hermione-codemod.svg)](https://travis-ci.com/gemini-testing/hermione-codemod)\n\nThis repository contains a collection of codemod scripts to be used with [JSCodeshift](https://github.com/facebook/jscodeshift) that helps to update Hermione APIs.\n\n## Setup \u0026 Run\n\n```sh\nnpm install hermione-codemod --save-dev\nnpx jscodeshift -t \u003ctransform\u003e \u003cpath\u003e [...options]\n```\n* `transform` - name of transform script, see available transforms below;\n* `path` - files or directories that should be transformed (can use glob);\n* `options` - contains options that passed to the runner of [jscodeshift](https://github.com/facebook/jscodeshift) and to the transform script.\n\nFor example you can use the `-d` option for a dry-run and `-p` to print the output for comparison. The remaining jscodeshift options can be found [here](https://github.com/facebook/jscodeshift#usage-cli).\n\n## Included Transforms\n\n### browser-chaining-to-async-await\n\nTransforms calls of browser commands from chaining to async-await style.\nUsed in order to update hermione with wdio@7+ inside in which chaining of browser commands does not work anymore and tests should be rewritten to async-await.\nMoreover in wdio@7 result of calling browser commands does not return to `value` property anymore, to fix this use [remove-browser-prop](#remove-browser-prop) script.\n\n```sh\nnpx jscodeshift -t hermione-codemod/transforms/browser-chaining-to-async-await.js \u003cpath\u003e [...options]\n```\n\nFor example (input):\n```js\nit('test', function() {\n  return this.browser\n    .foo()\n    .bar()\n    .then((res) =\u003e this.browser.baz(res))\n    .qux();\n});\n```\n\nwill be transformed to (output):\n```js\nit('test', async function() {\n  await this.browser.foo();\n  const res = await this.browser.bar();\n  await this.browser.baz(res);\n  await this.browser.qux();\n});\n```\n\nMore examples can be found in [transforms/\\_\\_testfixtures\\_\\_](https://github.com/gemini-testing/hermione-codemod/blob/main/transforms/__testfixtures__) directory.\n\n#### Options\n\n* `--browser-name` - ability to set used name of browser instance variable in your tests. Transform script will find usage of passed browser names with chaining calls and transform them to await nodes. Default value is `browser`.\n\nExample:\n```sh\nnpx jscodeshift -t \u003ctransform\u003e \u003cpath\u003e --browser-name='bro1,bro2'\n```\n\nInput:\n```js\nconst fn1 = () =\u003e bro1.foo().bar();\nconst fn2 = () =\u003e this.bro2.baz().qux();\n```\n\nOutput:\n```js\nconst fn1 = async () =\u003e {\n  await bro1.foo();\n  return bro1.bar();\n};\nconst fn2 = async () =\u003e {\n  await this.bro2.baz();\n  return this.bro2.qux();\n};\n```\n\n* `--not-await` - ability to set names of called nodes that should not be awaited. For example if you do not await assert calls called inside then callback. Default value is `['assert', 'should', 'expect']`.\n\nExample:\n```sh\nnpx jscodeshift -t \u003ctransform\u003e \u003cpath\u003e --not-await='assert,expect'\n```\n\nInput:\n```js\n(function() {\n  return browser.foo()\n    .then(() =\u003e assert.equal(1, 1))\n    .then(() =\u003e expect(2).to.equal(2));\n})();\n```\n\nOutput:\n```js\n(async function() {\n  await browser.foo();\n  assert.equal(1, 1);\n  return expect(2).to.equal(2);\n})();\n```\n\n* `--break-chaining-on` - ability to break chaining on nodes that matched to the passed identifiers. For example if you are using [chai-as-promised](https://www.npmjs.com/package/chai-as-promised) that can be called on browser commands. Default value is `['assert', 'should', 'expect']`.\n\nExample:\n```sh\nnpx jscodeshift -t \u003ctransform\u003e \u003cpath\u003e --break-chaining-on='should'\n```\n\nInput:\n```js\n(function() {\n  return browser.foo()\n    .should.eventually.equal('foo')\n    .bar();\n})();\n```\n\nOutput:\n```js\n(async function() {\n  await browser.foo();\n  static Error(\"hermione-codemod_1: fix code below manually\");\n  should.eventually.equal('foo');\n  static Error(\"hermione-codemod_1: fix code above manually\");\n  await browser.bar();\n})();\n```\n\nAfter that you need to correct the test manually and in the end it might look like this:\n```js\n(async function() {\n  const res = await browser.foo();\n  res.should.equal('foo');\n  await browser.bar();\n})();\n```\n\n#### Areas of improvement\n\n* Can't resolve problem with duplication of identifier declaration. Reproduced when parameters of resolve callback inside then have the same name. Currently it should be fixed manually. To simplify the search for such cases, you just need to run transform script again on the same path. Example:\n  Input:\n  ```js\n  const fn = () =\u003e browser.foo()\n    .then((a) =\u003e browser.bar(a))\n    .then((a) =\u003e browser.baz(a));\n  ```\n  Output:\n  ```js\n  const fn = async () =\u003e {\n    const a = await browser.foo();\n    const a = await browser.bar(a); // Identifier 'a' has already been declared\n    return browser.baz(a);\n  };\n  ```\n* Can't correctly handle the case with call function instead declarate resolve callback in `then` expression. Currently it should be fixed manually. Example:\n  Input:\n  ```js\n  const fn = () =\u003e browser.foo().then(bar.bind(browser));\n  ```\n  Output:\n  ```js\n  const fn = async () =\u003e {\n    await browser.foo();\n    return bar.bind(browser); // problem: bar function will not be called\n  };\n  ```\n  In that case script will inform you about found problem, like this:\n  ```\n  WARN: found CallExpression inside then, maybe you should fix it manually\n      file: /your-test.js\n      position: {\"start\":2,\"end\":2}\n  ```\n* Can't correctly handle the case with usage reject callback in `then` expression. Currently it should be fixed manually. Example:\n  Input:\n  ```js\n  const fn = () =\u003e browser.foo().then(() =\u003e a(), (err) =\u003e b(err));\n  ```\n  Output:\n  ```js\n  const fn = async () =\u003e {\n    await browser.foo();\n    return a();\n  };\n  ```\n  In that case script will inform you about found problem, like this:\n  ```\n  WARN: can't transform onRejected callback inside \"then\", fix it manually\n      file: /your-test.js\n      position: {\"start\":2,\"end\":2}\n  ```\n* Can't correctly handle the case with usage `catch` expression in chaining of browser command calls. Currently it should be fixed manually. Example:\n  Input:\n  ```js\n  const fn = () =\u003e browser.foo().catch((err) =\u003e handle(err));\n  ```\n  Output:\n  ```js\n  const fn = async () =\u003e {\n    await browser.foo();\n    return handle(err); // problem: \"err\" identifier is not declarated\n  };\n  ```\n  In that case script will inform you about found problem, like this:\n  ```\n  WARN: can't correctly transform \"catch\", fix it manually\n      file: /your-test.js\n      position: {\"start\":2,\"end\":2}\n  ```\n* Can't correctly handle the case with usage `finally` expression in chaining of browser command calls. Currently it should be fixed manually. Example:\n  Input:\n  ```js\n  const fn = () =\u003e browser.foo().finally(() =\u003e doSomething());\n  ```\n  Output:\n  ```js\n  const fn = async () =\u003e {\n    await browser.foo();\n    return doSomething(); // problem: should be rewritten with using try - finallly\n  };\n  ```\n  In that case script will inform you about found problem, like this:\n  ```\n  WARN: can't correctly transform \"finally\", fix it manually\n      file: /your-test.js\n      position: {\"start\":2,\"end\":2}\n  ```\n* Can't correctly handle the case with usage logical expression with chaining of browser command calls. Currently it should be fixed manually. Example:\n  Input:\n  ```js\n  const fn = () =\u003e true \u0026\u0026 browser.foo().bar();\n  ```\n  Output:\n  ```js\n  const fn = async () =\u003e true \u0026\u0026 browser.foo().bar(); // problem: should be rewritten using if statement and await browser commands\n  ```\n  In that case script will inform you about found problem, like this:\n  ```\n  WARN: can't correctly transform LogicalExpression, fix it manually\n      file: /your-test.js\n      position: {\"start\":2,\"end\":2}\n  ```\n* Can't correctly handle the case with usage conditional expression with chaining of browser command calls. Currently it should be fixed manually. Example:\n  Input:\n  ```js\n  const fn = () =\u003e a ? browser.foo().bar() : b;\n  ```\n  Output:\n  ```js\n  const fn = async () =\u003e a ? browser.foo().bar() : b; // problem: should be rewritten using if-else statements and await browser commands\n  ```\n  In that case script will inform you about found problem, like this:\n  ```\n  WARN: can't correctly transform ConditionalExpression, fix it manually\n      file: undefined\n      position: {\"start\":2,\"end\":2}\n  ```\n\n#### Example of usage\n\n1. Run transform script on files that should be modified. For example I want modify all files inside `tests/platform/**` whose name matches on `*.hermione.js` or `*.hermione-helper.js`:\n```sh\nnpx jscodeshift -t node_modules/hermione-codemod/transforms/browser-chaining-to-async-await.js tests/platform/**/*.*(hermione|hermione-helper).js --not-await='assert'\n```\n2. After transformation of all tests script may inform you about found problems which are listed [above](#areas-of-improvement), fix them manually.\n3. Run transform script again even if it does not inform you about any problems in previous step. It is necessary because it can found problems with duplication of identifier declaration after transformation code. Rerun transform script until it succeeds and won't inform you that no test has been modified.\n4. Fix code style in trasformed tests:\n```sh\nnpx eslint --fix tests/platform/**/*.*(hermione|hermione-helper).js\n```\n\n### remove-browser-prop\n\nRemoves usages of the passed property from the result of calling browser commands.\nUsed in order to update hermione with wdio@7+ inside in which property `value` not used anymore for store result of executing browser command.\nMust be used only after `browser-chaining-to-async-await` script.\n\n```sh\nnpx jscodeshift -t node_modules/hermione-codemod/transforms/remove-browser-prop.js \u003cpath\u003e [...options]\n```\n\nFor example (input):\n```js\nit('test', async function() {\n  const res1 = await this.browser.foo();\n  const {value: res2} = await this.browser.bar();\n  const res3 = (await this.browser.baz()).value;\n\n  return [res1.value, res2, res3]\n});\n```\n\nwill be transformed to (output):\n```js\nit('test', async function() {\n  const res1 = await this.browser.foo();\n  const res2 = await this.browser.bar();\n  const res3 = await this.browser.baz();\n\n  return [res1, res2, res3];\n});\n```\n\nMore examples can be found in [transforms/\\_\\_testfixtures\\_\\_](https://github.com/gemini-testing/hermione-codemod/blob/main/transforms/__testfixtures__) directory.\n\n#### Options\n\n* `--browser-name` - as like in `browser-chaining-to-async-await` script;\n* `--property-name` - ability to set name of property which should be removed from the result of calling browser commands. Default value is `value`.\n\n  Example:\n  ```sh\n  npx jscodeshift -t \u003ctransform\u003e \u003cpath\u003e --property-name='value'\n  ```\n\n## Recast Options\n\n[Options to recast's printer](https://github.com/benjamn/recast/blob/master/lib/options.ts) can be provided through the `printOptions` command line argument.\n\n```sh\nnpx jscodeshift -t \u003ctransform\u003e \u003cpath\u003e --printOptions='{\"tabWidth\":2}'\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgemini-testing%2Fhermione-codemod","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgemini-testing%2Fhermione-codemod","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgemini-testing%2Fhermione-codemod/lists"}