{"id":18982338,"url":"https://github.com/defactosoftware/test_dispatch","last_synced_at":"2025-12-11T23:52:05.545Z","repository":{"id":38848678,"uuid":"242984704","full_name":"DefactoSoftware/test_dispatch","owner":"DefactoSoftware","description":"Phoenix Integration tests without webdrivers.","archived":false,"fork":false,"pushed_at":"2023-12-15T15:41:25.000Z","size":266,"stargazers_count":5,"open_issues_count":11,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-23T18:15:54.859Z","etag":null,"topics":["elixir","phoenix","test"],"latest_commit_sha":null,"homepage":"","language":"Elixir","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/DefactoSoftware.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null}},"created_at":"2020-02-25T11:35:45.000Z","updated_at":"2022-10-26T21:51:09.000Z","dependencies_parsed_at":"2025-04-16T13:33:13.448Z","dependency_job_id":"b993d7c1-11d3-46f4-8e7f-07f945a7b34b","html_url":"https://github.com/DefactoSoftware/test_dispatch","commit_stats":{"total_commits":193,"total_committers":5,"mean_commits":38.6,"dds":0.4870466321243523,"last_synced_commit":"c1117e65b56b798d286bc9693517a64d75cb8cf8"},"previous_names":["defactosoftware/test_dispatch_form"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/DefactoSoftware/test_dispatch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DefactoSoftware%2Ftest_dispatch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DefactoSoftware%2Ftest_dispatch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DefactoSoftware%2Ftest_dispatch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DefactoSoftware%2Ftest_dispatch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DefactoSoftware","download_url":"https://codeload.github.com/DefactoSoftware/test_dispatch/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DefactoSoftware%2Ftest_dispatch/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268322394,"owners_count":24231818,"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","status":"online","status_checked_at":"2025-08-01T02:00:08.611Z","response_time":67,"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":["elixir","phoenix","test"],"created_at":"2024-11-08T16:13:10.504Z","updated_at":"2025-12-11T23:52:05.471Z","avatar_url":"https://github.com/DefactoSoftware.png","language":"Elixir","readme":"[![Hex pm](http://img.shields.io/hexpm/v/test_dispatch.svg?style=flat)](https://hex.pm/packages/test_dispatch)\n[![codecov](https://codecov.io/gh/DefactoSoftware/test_dispatch/branch/master/graph/badge.svg)](https://codecov.io/gh/DefactoSoftware/test_dispatch)\n[![CircleCI](https://circleci.com/gh/DefactoSoftware/test_dispatch.svg?style=svg)](https://circleci.com/gh/DefactoSoftware/test_dispatch)\n\n# TestDispatch\n\nTestDispatch adds the ability to use controller tests as integration tests\nwithout using headless browsers. It allows tests to submit forms, click on\nlinks, follow redirects and receive mails.\n\n## Documentation\n\nDocumentation can be found on [HexDocs](https://hexdocs.pm/test_dispatch)\n\n## Dependencies\n\n- [Floki](https://github.com/philss/floki) v0.25.x and up\n- [TestSelector](https://github.com/DefactoSoftware/test_selector)\n\n## Installation\n\nThe package can be installed\nby adding `test_dispatch` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:test_dispatch, \"~\u003e 0.3.3\"}\n  ]\nend\n```\n\n## Usage\n\n\n### submit_form\nImport TestDispatch in your test module or your test case and you can call\n`submit_form/3` from there.\n\nTo use `submit_form/3` a request has to be made to a page where a form is\npresent. The conn that is received will be parsed by the `submit_form/3`\nand the form will be dispatched with the attributes that are given or the\ndefault values when they are not given.\n\n```elixir\ndefmodule MyAppWeb.MyTest do\n  use MyAppWeb.ConnCase\n  import TestDispatch\n\n  test \"dispatches form with attributes and entity\" do\n    conn = build_conn()\n\n    assert conn\n           |\u003e get(Routes.user_path(conn, :new))\n           |\u003e submit_form(%{name: \"John Doe\", email: \"john@doe.com\"}, :user)\n           |\u003e redirected_to(Routes.user_path(conn, :index))\n  end\n\n  test \"dispatches form with default values and test_selector\" do\n    conn = build_conn()\n\n    assert conn\n           |\u003e get(Routes.user_path(conn, :index))\n           |\u003e submit_form(User.IndexView.test_selector(\"batch-action\"))\n           |\u003e html_response(200)\n  end\nend\n```\n\n`submit_form/3` will find a form in the HTML response of the given conn by\nentity or by [test_selector](https://github.com/DefactoSoftware/test_selector),\nor, if no entity or test_selector is provided, it will target the last form found\nin the response.\n\nNext it will look for form controls (inputs, selects), convert these to params\nand use the attributes passed to `submit_form/3` to update the values of\nthe params. The params will now only contain field keys found in the controls of\nthe form.\n\nIf an entity is given, the params will be prepended by this entity. So for:\n\n```elixir\nsubmit_form(conn, %{name: \"John Doe\", email: \"john@doe.com\"}, :user)\n```\n\nthis will result in the following params:\n\n```elixir\n%{\"user\" =\u003e %{name: \"John Doe\", email: \"john@doe.com\"}}\n```\n\nUltimately, the conn is dispatched to the conn's `private.phoenix_endpoint`\nusing `Phoenix.ConnTest.dispatch/5`, with the params and with the method and\naction found in the form.\n\n### Clicking on links in mails\n\nDuring the tests emails might be sent that we want to integrate in our flow. For\nthat there is `receive_mail/2`. It expects the conn as the first argument and\nthe found email will be added to the conn as the `resp_body`. Using the conn\ncombined with the `click_link/4` function you can simulate \"clicking\" on the\nlink in an email.\n\n```elixir\nbuild_conn()\n|\u003e get(\"/posts/1\")\n|\u003e click_link(\"post-123-send-as-mail\")\n|\u003e receive_mail()\n|\u003e click_link(\"post-123-show\")\n|\u003e html_response(200)\n```\n\nTestDispatch expects the email to be sent with the message\n`{:delivered_email, %{} = email}` where the mail should contain at least\nthe `to:`, `from:` and `subject:`, `html_body:` fields.\n\nWhen the mail is not received it will raise an error. Specific emails can be\ntargeted by adding the `:subject`, `:to` or `:from` to the second argument of\nreceive mail in a map.\n\n```elixir\nreceive_mail(conn, %{submit: \"This exact message\", to: \"this_address@exmaple.com\"})\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdefactosoftware%2Ftest_dispatch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdefactosoftware%2Ftest_dispatch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdefactosoftware%2Ftest_dispatch/lists"}