{"id":13770035,"url":"https://github.com/abiyasa/marko-jest","last_synced_at":"2025-06-21T23:08:55.923Z","repository":{"id":57291361,"uuid":"110251780","full_name":"abiyasa/marko-jest","owner":"abiyasa","description":"[DEPRECATED] Jest Marko transformer, import .marko files in jest tests","archived":false,"fork":false,"pushed_at":"2020-05-15T16:03:36.000Z","size":514,"stargazers_count":3,"open_issues_count":8,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-05T11:31:47.961Z","etag":null,"topics":["behaviour-testing","jest","marko","marko-jest","snapshot-testing","unit-testing"],"latest_commit_sha":null,"homepage":"","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/abiyasa.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-11-10T13:47:39.000Z","updated_at":"2025-04-23T18:26:41.000Z","dependencies_parsed_at":"2022-08-27T16:50:53.849Z","dependency_job_id":null,"html_url":"https://github.com/abiyasa/marko-jest","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/abiyasa/marko-jest","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abiyasa%2Fmarko-jest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abiyasa%2Fmarko-jest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abiyasa%2Fmarko-jest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abiyasa%2Fmarko-jest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/abiyasa","download_url":"https://codeload.github.com/abiyasa/marko-jest/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abiyasa%2Fmarko-jest/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261206107,"owners_count":23124840,"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":["behaviour-testing","jest","marko","marko-jest","snapshot-testing","unit-testing"],"created_at":"2024-08-03T17:00:33.696Z","updated_at":"2025-06-21T23:08:50.892Z","avatar_url":"https://github.com/abiyasa.png","language":"JavaScript","funding_links":[],"categories":["Packages"],"sub_categories":["Processor"],"readme":"## Marko Jest \u0026middot; [![Coverage Status](https://coveralls.io/repos/github/abiyasa/marko-jest/badge.svg?branch=master)](https://coveralls.io/github/abiyasa/marko-jest?branch=master) [![CircleCI Status](https://circleci.com/gh/abiyasa/marko-jest/tree/master.svg?style=shield\u0026circle-token=:circle-token)](https://circleci.com/gh/abiyasa/marko-jest/tree/master)\n\n[DEPRECATED] Jest Marko transformer and rendering test utility.\n\n## DEPRECATED ⚠\n\nThis module is deprecated and no longer maintained, in favour of the official [@marko/jest](https://github.com/marko-js/jest) 🖖\n\n## What is this?\n\nTransformer and rendering test library for [Marko 4](https://markojs.com/) component with Jest \u0026 JSDOM.\n\n- Renders Marko component on JSDOM\n- Supports rendering and client-side behaviour testing\n- Snapshot testing\n- TypeScript support\n\n## Requirements\n\n- Jest: 23.x\n- Marko: ^4.9.0\n\n## Setup\n\n1. Add `marko-jest` to your dev dependencies. You could do it by `yarn add marko-jest --dev` or `npm install marko-jest --save-dev`.\n\n1. Register marko preprocessor/transformer on your Jest config. This allows Jest to process and compile Marko file. Add the following lines to the Jest transform section:\n\n```json\n// package.json or jest config\n{\n  ...\n\n  \"jest\": {\n    \"transform\": {\n      \"^.+\\\\.marko$\": \"\u003crootDir\u003e/node_modules/marko-jest/preprocessor.js\"\n    },\n    ...\n  },\n\n  ...\n}\n```\n\n## Quick Start\n\nThese are a quick steps to test a Marko component with marko-jest:\n\n1. Require marko-jest module and use the `init` function to initiate the Marko component you want to test. This is the way to 'require' Marko component on test files.\n\n1. The `init` function will return `render` function which you can use to render the initiated Marko component.\n\n    ```javascript\n    // __tests__/component.spec.js\n    import { init } from 'marko-jest';\n    // or const { init } = require('marko-jest');\n\n    // init() requires full path to Marko component\n    const componentPath = path.resolve(__dirname, '../index.marko');\n    const { render } = init(componentPath);\n\n    describe('test-button', () =\u003e {\n      ...\n    });\n    ```\n\n1. The `render` function returns `RenderResult` object which allows you to get the component instance. Use the component instance to access its [properties](https://markojs.com/docs/components/#properties) (e.g `el`, `els`, or `state`) or [methods](https://markojs.com/docs/components/#methods) (e.g `getEl()`, `update()`, `rerender()`) for testing.\n\n    ```javascript\n    // __tests__/component.spec.js\n    import { init, cleanup } from 'marko-jest';\n\n    const componentPath = path.resolve(__dirname, '../index.marko');\n    const { render } = init(componentPath);\n\n    describe('test-button', () =\u003e {\n      let renderResult;\n\n      afterEach(cleanup);\n\n      describe('on rendering', () =\u003e {\n        const input = { label: 'Click here' };\n\n        beforeEach(async () =\u003e {\n          renderResult = await render(input);\n        });\n\n        it('should render a link given default input', () =\u003e {\n          const button = renderResult.component.el.querySelector('a');\n          expect(button).toBeDefined();\n        });\n      });\n    });\n    ```\n\n## Component Rendering Test\n\nOne way to test a component is to test its generated HTML. You can access it from the `RenderResult` object returned by the `render` function.\n\nYou can use the following methods/property from the `RenderResult` object:\n  - Property `component`: component instance. You can access the output HTML element using Marko component instance's [properties](https://markojs.com/docs/components/#properties) (such as `el` or `els`), or [methods](https://markojs.com/docs/components/#methods) (`getEl(key)` or `getEls(key)`).\n  - Property `container`: the test container element, which is a div element. Behind the scene, marko-jest `render` function automatically creates a test container and renders the component inside it.\n  - Method `getNodes`: return the list of rendered HTML elements. Usually useful for snapshot testing (see next section).\n\nOnce you get the HTML element, you can use any native HTML methods to assert if a certain element or class is existed.\n\nExamples:\n\n```javascript\n// container\nit('should render icon DOWN', () =\u003e {\n  const iconEl = return renderResult.container.querySelector('.btn__icon');\n  expect(iconEl.innerHTML).toContain('#svg-icon-chevron-down');\n});\n\n// component instance with property el\nit('should render a link given default input', () =\u003e {\n  const ctaLink = rendereResult.component.el.querySelector('main-cta');\n  expect(ctaLink.textContent).toBe('Shop Now');\n});\n\n// component instance with getEl() if you have key attribute inside Marko template\nit('should render a link given default input', () =\u003e {\n  const button = component.getEl('main-cta');\n  expect(button).toBeDefined();\n});\n\n// component instance with getEls()\nit('should render benefit links', () =\u003e {\n  const benefitLinks = component.getEls('benefits');\n  expect(benefitLinks.lenth).toBeGreaterThan(2);\n});\n\n```\n\n## Accessing Non-Element Nodes\n\nMarko's `getEl()` and `getEls()` returns HTML elements only, which means it does not return any non-element nodes such as **text and comment nodes**. If you want to access element \u0026 non-elements (e.g for snapshot testing), you can use RenderResult `getNodes()` which will return array of all Nodes, including HTML elements, text, and comment nodes.\n\n```javascript\nit('should render text node', () =\u003e {\n  const nodes = renderResult.getNodes();\n\n  expect(nodes[0].nodeType).toEqual(Node.TEXT_NODE);\n});\n```\n\nA use case for this is you have a component which can render a text node without any HTML element as container\n\n```marko\n// span-or-text-component.marko\n\u003cspan body-only-if(!input.showSpan)\u003e\n  ${input.text}\n\u003c/span\u003e\n```\n\n```javascript\n// test-span-or-text-component.spec.js\nimport { init, cleanup } from 'marko-jest';\nconst { render } = init(path.resolve(__dirname, './resources/body-only-item/index.marko'));\n\ndescribe('span-or-text component', () =\u003e {\n  let renderResult;\n\n  afterEach(cleanup);\n\n  it('should render component as a span element', async () =\u003e {\n    renderResult = await render({ showSpan: true, text: 'test' });\n    const nodes = renderResult.getNodes();\n\n    expect(nodes[0].nodeName).toEqual('SPAN');\n    expect(nodes[0].nodeType).toEqual(Node.ELEMENT_NODE);\n  });\n\n  it('should render component as a text node', async () =\u003e {\n    renderResult = await render({ showSpan: false, text: 'test' });\n    const nodes = renderResult.getNodes();\n\n    expect(nodes[0].nodeName).toEqual('#text');\n    expect(nodes[0].nodeType).toEqual(Node.TEXT_NODE);\n  });\n});\n```\n\n## Snapshot testing\n\nYou can utilize Jest snapshot testing to test component rendering.\nThe RenderResult `getNodes()` will return array of HTML elements which we can use for Jest snapshot feature.\n\nExample:\n\n```javascript\n// __tests__/component.spec.js\nimport * as path from 'path';\nimport { init, cleanup } from 'marko-jest';\n\nconst componentPath = path.resolve(__dirname, '../index.marko');\nconst { render } = init(componentPath);\n\ndescribe('test-button', () =\u003e {\n  afterEach(cleanup);\n\n  it('should render correctly given default input', async () =\u003e {\n    const input = { label: 'Click here' };\n    const renderResult = await render(input);\n\n    expect(renderResult.getNodes()).toMatchSnapshot();\n  });\n});\n```\n\n## Behaviour Testing\n\nYou can test component behaviour (e.g click handler) by triggering event though the HTML element.\n\nExample on testing a toggle button:\n\n```marko\n// index.marko\nclass {\n  onCreate() {\n    this.state = {\n      clicked: false\n    };\n  }\n\n  toggleButton() {\n    this.state.clicked = !this.state.clicked;\n  }\n}\n\n\u003cbutton class=\"btn\" on-click('toggleButton')\u003e\n  \u003cspan if(state.clicked)\u003eDONE\u003c/span\u003e\n  \u003cspan else\u003eClick me\u003c/span\u003e\n\u003c/button\u003e\n```\n\nYou can access the button element and trigger the click:\n\n```javascript\n// __tests__/index.spec.js\nimport * as path from 'path';\nimport { init, cleanup } from 'marko-jest';\n\nconst componentPath = path.resolve(__dirname, '../index.marko');\nconst { render } = init(componentPath);\n\ndescribe('test-simple-button', () =\u003e {\n  let component;\n\n  afterEach(cleanup);\n\n  describe('on rendering', () =\u003e {\n    let mainButton;\n\n    beforeEach(async () =\u003e {\n      const renderResult = await render({ });\n\n      component = renderResult.component;\n      mainButton = component.getEl('rootButton');\n    });\n\n    it('should render a button', () =\u003e {\n      expect(mainButton).toBeTruthy();\n    });\n\n    it('should render default label', () =\u003e {\n      const buttonLabel = mainButton.textContent;\n      expect(buttonLabel).toEqual('Click me');\n    });\n\n    describe('when clicked', () =\u003e {\n      beforeEach(() =\u003e {\n        mainButton.click();\n        component.update();\n      });\n\n      it('should change the button label', () =\u003e {\n        const buttonLabel = mainButton.textContent;\n        expect(buttonLabel).toEqual('DONE');\n      });\n    });\n  });\n});\n```\n\nYou can also combine it with snapshot testing:\n\n```javascript\nimport * as path from 'path';\nimport { init, cleanup } from 'marko-jest';\n\nconst componentPath = path.resolve(__dirname, '../index.marko');\nconst { render } = init(componentPath);\n\ndescribe('test-simple-button', () =\u003e {\n  let renderResult;\n  let component;\n\n  afterEach(cleanup);\n\n  describe('on rendering', () =\u003e {\n    beforeEach(async () =\u003e {\n      renderResult = await render({ });\n      component = renderResult.component;\n    });\n\n    it('should render correctly', () =\u003e {\n      expect(renderResult.getNodes()).toMatchSnapshot();\n    });\n\n    describe('when clicked', () =\u003e {\n      beforeEach(() =\u003e {\n        component.getEl('rootButton').click();\n        component.update();\n      });\n\n      it('should update the element', () =\u003e {\n        expect(renderResult.getNodes()).toMatchSnapshot();\n      });\n    });\n  });\n});\n```\n\n## TypeScript Support\n\n`marko-jest` module provides TypeScript type definition. Make sure you also install type definition for Marko by adding module `@types/marko` to your project.\n\n## Shallow Rendering\n\nmarko-jest can do [shallow rendering](https://reactjs.org/docs/shallow-renderer.html) on external component. If you use external Marko component module/library (such as [ebayui-core](https://github.com/eBay/ebayui-core)), you can exclude those components from being rendered deeply by adding the module name to Jest globals config `taglibExcludePackages`. marko-jest will use Marko's [`taglibFinder.excludePackage()`](https://markojs.com/docs/custom-tags/#hiding-taglibs) to prevent any components from those modules to be rendered.\n\nFor example, if you want to do shallow rendering on all components from `@ebay/ebayui-core` module, add the module name to Jest globals config:\n\n```json\n// package.json\n{\n  ...\n\n  \"jest\": {\n    \"transform\": {\n      ...\n    },\n    ...\n    \"globals\": {\n      \"marko-jest\": {\n        \"taglibExcludePackages\": [\n          \"@ebay/ebayui-core\",\n          \"marko-material\"\n        ]\n      }\n    }\n  },\n\n  ...\n}\n```\n\nNow Marko Jest will render your Marko component:\n\n```marko\n// cta-component.marko\n\u003csection\u003e\n  \u003cebay-button priority=\"primary\" on-click('toggleButton')\u003e\n    PAY\n  \u003c/ebay-button\u003e\n\u003c/section\u003e\n```\n\nAs:\n\n```html\n\u003csection\u003e\n  \u003cebay-button priority=\"primary\"\u003ePAY\u003c/ebay-button\u003e\n\u003csection\u003e\n```\n\nInstead of\n\n```html\n\u003csection\u003e\n  \u003cbutton type=\"button\" class=\"btn btn--primary\"\u003ePAY\u003c/button\u003e\n\u003csection\u003e\n```\n\nOne of the advantages of shallow rendering is to isolate your unit test so you can focus on testing your component instead of the external ones. On the example above, if the `ebay-button` implementation has changed (e.g css class name or new attribute added), your snapshot test will not failed.\n\n### Current Limitation of marko-jest shallow rendering\n\n- The shallow rendering will affect ALL test suites, you cannot turn it on or off\n during runtime.\n- You can only do shallow rendering on external modules. Unfortunately, you cannot do shallow rendering on component from the same project. The only workaround so far is to separate your UI component as external module (npm package) and consume it on your project.\n\n\n## marko-jest APIs\n\nmarko-jest API provides 2 high level functions: `init` and `cleanup`.\n\n### `init(fullPathToMarkoComponent: string): InitResult`\n\nThis is a way to 'require' Marko component on test file. It requires full path to Marko component.\n\nAt the moment, you can't easily require Marko component on Node.js with JSDOM. By default, when a Marko component is required on Node.js, you can only do server-side-only component. This means you can render the component as HTML but without any browser-side features such as render to virtual DOM, DOM event handling, or browser-side lifecycle.\n\n`init` function will 'trick' Marko to require a component on Node.js as if it's done on browser. Therefore, the required component will have all browser-side features, including component rendering.\n\nThe `init` function will return an object **`InitResult`** which has:\n\n  * property **`componentClass: Component`**, the Class of require/init-ed Marko Component. Quite useful if you want to spy on Marko component lifecycle method.\n  * function **`render(input: any): Promise\u003cRenderResult\u003e`**: Asynchronously render the component using the given input. This will return a promise which will be resolved with an instance of `RenderResult`.\n\nThe **`RenderResult`** is the result of component rendering which has:\n\n  * property **`component: Component`**: the rendered component instance. Use this instance to access any Marko component [properties](https://markojs.com/docs/components/#properties) or [methods](https://markojs.com/docs/components/#methods).\n  * property **`container: HTMLElement`**: the test container element, which is a div element. Behind the scene, marko-jest `render` function automatically creates a test container and renders the component inside it.\n  * method **`getNodes(): HTMLElement[]`**: return the list of any rendered HTML elements. This method is better than Marko's `getEl()` and `getEls()` which does not return any non-element nodes such as **text and comment nodes**. If you want to access element \u0026 non-elements (e.g for snapshot testing), you can use `getNodes()` which will return array of all Nodes, including HTML elements, text, and comment nodes.\n\n\n### `cleanup(): void`\n\nRemove all test containers created by the `render` function. Totally recommended to call cleanup on Jest `afterEach`.\n\nFor more info about marko-jest API, you can check the TypeScript type definition [here](index.d.ts)\n\n## Known Issues\n\n* Failed rendering Marko component with custom transformer\n* Limited support of shallow rendering, see Shallow Rendering above or https://github.com/abiyasa/marko-jest/issues/1\n\n## Roadmap\n\nPlanned new features and improvements:\n\n* Better support of shallow and deep rendering.\n\n## Contributing\n\nContributing guidelines is still WIP but you're welcome to contribute by creating issues or Pull Request.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabiyasa%2Fmarko-jest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabiyasa%2Fmarko-jest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabiyasa%2Fmarko-jest/lists"}