{"id":25657352,"url":"https://github.com/frlow/estridi-docs","last_synced_at":"2026-02-28T07:09:19.230Z","repository":{"id":245082154,"uuid":"814522902","full_name":"frlow/estridi-docs","owner":"frlow","description":null,"archived":false,"fork":false,"pushed_at":"2024-06-18T21:25:55.000Z","size":105,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-17T07:09:37.101Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/frlow.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-13T07:15:13.000Z","updated_at":"2024-06-19T07:39:16.000Z","dependencies_parsed_at":"2024-06-19T17:35:08.697Z","dependency_job_id":"c87d346d-7edc-4014-8bd0-e892292dc0ed","html_url":"https://github.com/frlow/estridi-docs","commit_stats":null,"previous_names":["frlow/estridi-docs"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/frlow/estridi-docs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frlow%2Festridi-docs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frlow%2Festridi-docs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frlow%2Festridi-docs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frlow%2Festridi-docs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/frlow","download_url":"https://codeload.github.com/frlow/estridi-docs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frlow%2Festridi-docs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29927270,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T19:37:42.220Z","status":"online","status_checked_at":"2026-02-28T02:00:07.010Z","response_time":90,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":"2025-02-23T23:18:11.281Z","updated_at":"2026-02-28T07:09:19.215Z","avatar_url":"https://github.com/frlow.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Estridi tutorial\n\n## Jam file\n\n## Config file\ncreate config file\n```json5\n// estridi.json\n{\n  \"token\": \"your_access_token_here\",\n  \"fileId\": \"figjam_board_file_id\",\n  \"mode\": \"playwright\"\n}\n```\n\n## Create root node\nIn figma add \u003ccode\u003eroot:tutorial\u003c/code\u003e to out arrow on start node\n\n## Run estridi binary\n```bash\nnpx estridi\n```\nAfter you have run the command successfully you should notice 3 new files\n- **someName.spec.ts**\n  - This is where you run and debug your tests from. This file will update everytime you run the estridi command\n- **someName.handles.ts**\n  - This file contains 5 methods:\n    - handleSetup: method for setting up for example environment\n    - handleStart: method for starting up test\n    - handleServiceCall: method for implementing service calls\n    - handleAction: method for implementing actions\n    - handleTestNode: method for implementing tests\n- **scraped.json**\n\n## Install playwright\n```bash\nnpx playwright install\n```\n\n## Your first test\nnow it is time to implement your first test. So in\n- handleSetup, no need to implement anything here just add, `return {}`\n- handleStart, implement `await args.page.goto(\"/\")`\n- handleTestNode, implement your first test, make a new `case '':` and hopefully you'll get correct key as a suggestion, then inside implement the test \n```\nawait expect(args.page.locator('h1:has-text(\"Hello World!\")')).toBeVisible()\n```\n\n## Change requirement\n- Change the title requirement in FigJam from \"Hello World!\" =\u003e \"Estridi tutorial\"\n- Rerun estridi binary\n- Rerun your tests and hopefully they will not pass\n- Now you'll se that because the requirement has changed, you also need to change the implementation of your test\n- Change implementation\n\n## Link first sub-flow\n- To link you subflows, in figma add the \"Name of subflow\" to out arrow on sub flow start node. Like you did for the root node\n- Rerun estridi binary\n\n## Link table\n- When linking tables we often have a subflow that has a name like this: \u003ccode\u003eDisplay fields: Some Fields\u003c/code\u003e or \u003ccode\u003eValidate fields: Some Fields\u003c/code\u003e\n- Then to link you table to the subflow in figma, add \".Name\" to top left corner of the table. In this case you would add \u003ccode\u003e.Some Fields\u003c/code\u003e\n- Rerun estridi binary\n\n## Test Table rows\nImplement test that checks for input fields with labels attached to them\n\n```javascript\nswitch(args.key){\n    // ...\n    case \"1:205: Display fields Some Fields\": {\n      const table = args.getTable(\"1:663: Some Fields\")\n      for (const row of table.values) {\n        const label = row.Id\n        const inputType = row[\"Input Type\"]\n        await expect(\n            args.page.getByLabel(label).and(\n                args.page.locator(`input[type=\"${inputType}\"]`)\n            )).toBeVisible()\n      }\n      break\n    }\n}\n```\n\n## Protect table from requirement changes\n```javascript\nexpect(table.signature).toEqual(`\n8877|9739\n2420|3556\n1134|3076\n`)\n```\n\n## Actions\n- Link actions subflow\n- Rerun estridi\n- Implement action\n\n```javascript\nswitch(args.key){\n    // ...\n  case \"12:809: Clear clicked\":\n    \n    break\n}\n```\n\nImplement corresponding input fields in the html\n\n## Gateways\n- Link gateways subflow\n- Rerun estridi\n- Validate subflow doesn't do anything an can be skipped. \n\nThe handleAction function has access to the gateways object \nthat has the gateway options for the current path. \nThis can be used to determine the behavior of the action. \n\n```javascript\nswitch (args.key) {\n      // ...\n      case \"12:810: Submit clicked\":\n        if(args.gateways[\"24:1050: Any validation errors\"]===\"no\"){\n          await args.page.getByLabel(\"Name\").fill(\"Namn Namnsson\")\n          await args.page.getByLabel(\"Birthday\").fill('2024-06-13')\n          await args.page.locator(\"#submit\").click()\n        }\n        else{\n          await args.page.locator(\"#submit\").click()\n        }\n        break\n    }\n```\n\n## Mock serviceCall\n- Link serviceCalls subflow\n- Rerun estridi\n- Mock the service call\n\n```javascript\nswitch (args.key) {\n  // ...\n  case \"25:1172: submit\": {\n    const gwValue = args.gateways['3895:5989: Error from validate service']\n    if (gwValue === 'yes')\n      await args.context.route(\n              \"/submit\",\n              async (route: Route) =\u003e {\n                await route.fulfill({\n                  status: 400,\n                })\n              }\n      )\n    else {\n      await args.context.route(\n              \"/submit\",\n              async (route: Route) =\u003e {\n                await route.fulfill({\n                  contentType: 'application/json',\n                  json: {message: \"Well done!\"},\n                })\n              }\n      )\n    }\n    break\n  }\n}\n```\n\n# Advanced features\n\n## Filter paths\n```typescript\nfilterPaths: ({allPaths, getGateways}) =\u003e\n        allPaths.filter(path =\u003e {\n            const gateways = getGateways(path)\n            if (gateways\n                .filter(g =\u003e g.text === \"A selected\")\n                .some((g, _, arr) =\u003e g.value !== arr[0].value))\n                return false\n            // Maybe more filters??\n            return true\n        })\n```\n\n## Variants\n```typescript\nswitch(args) {\n    case \"112:621: Show dropdown Values\": {\n        const table = args.getTable(\"112:620: Dropdown\")\n        for (const row of table.values) {\n            await expect(args.page.locator(\"#numbers\")\n                .locator(`option:has-text('${row.Id}')`)).toBeAttached()\n        }\n        break\n    }\n}\n```\n\n## Breaking out separate files\nYou can define a function with types based on Handles\n```typescript\nconst actionHandles: DemoHandles[\"handleAction\"] = async args =\u003e {}\n```\n\n## Concepts demoed\n- [x] Estridi config file\n- [x] Connecting root nodes\n- [x] Running estridi binary\n- [x] Setup\n- [x] Start\n- [x] Test\n- [x] Changing requirements\n- [x] Linking sub-flows\n- [x] Including tables\n- [x] Table requirements changing\n- [x] Testing non-linked sub-flows\n- [x] Skipping tests\n- [x] Reading tables\n- [x] Action\n- [x] Gateways\n- [x] ServiceCall\n\n## Advanced\n- [x] Variants\n- [x] Filter paths\n- [x] Breaking out separate files\n- [ ] Setup-state\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrlow%2Festridi-docs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrlow%2Festridi-docs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrlow%2Festridi-docs/lists"}