{"id":37362380,"url":"https://github.com/ohnotnow/scenarios","last_synced_at":"2026-01-16T04:47:37.069Z","repository":{"id":57030527,"uuid":"93760086","full_name":"ohnotnow/scenarios","owner":"ohnotnow","description":"Very simple 'scenarios' for testing in PHP","archived":false,"fork":false,"pushed_at":"2017-06-08T15:11:55.000Z","size":12,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-08T12:41:45.514Z","etag":null,"topics":["php","testing"],"latest_commit_sha":null,"homepage":null,"language":"PHP","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/ohnotnow.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-06-08T14:38:38.000Z","updated_at":"2017-06-08T14:41:12.000Z","dependencies_parsed_at":"2022-08-23T17:40:58.665Z","dependency_job_id":null,"html_url":"https://github.com/ohnotnow/scenarios","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ohnotnow/scenarios","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ohnotnow%2Fscenarios","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ohnotnow%2Fscenarios/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ohnotnow%2Fscenarios/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ohnotnow%2Fscenarios/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ohnotnow","download_url":"https://codeload.github.com/ohnotnow/scenarios/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ohnotnow%2Fscenarios/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28420732,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:47:48.104Z","status":"ssl_error","status_checked_at":"2026-01-14T10:46:19.031Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["php","testing"],"created_at":"2026-01-16T04:47:36.983Z","updated_at":"2026-01-16T04:47:37.063Z","avatar_url":"https://github.com/ohnotnow.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Simple PHP Scenarios\n\nThis is a *very* basic PHP class and trait to make using 'scenarios' easier.  Initially it\nwas written with Laravel phpunit tests in mind, but in theory it could be used for other things.\n\n## What are... 'Scenarios'?\n\nWhen writing tests I often find myself having to do repetative things like this a lot in each test :\n\n```php\n$admin = factory(User::class)-\u003estates('admin')-\u003ecreate();\n$user = factory(User::class)-\u003estates('regular')-\u003ecreate();\n$post = factory(Post::class, 3)-\u003estates('unpublished')-\u003ecreate(['user_id' =\u003e $user-\u003eid]);\n...\n```\n\nThat code gets repeated in maybe a dozen tests.  So sometimes I write a helper function - sometimes\nnot as it's quicker to just copy'n'paste the code from the previous test.  So I decided\nto write a very simple helper which is pretty much a key/value store so that I could do something\na little more expressive in the test like the following :\n\n```php\n$this-\u003escenarios()-\u003eplayout('there is an admin and a user with three posts');\n```\n\n## Usage\n\nAssuming you want to use the trait :\n\n```php\nclass SomeTest {\n\n    use \\Ohffs\\Scenarios\\HasScenarios;\n\n    public function setUp()\n    {\n        parent::setUp();\n        $this-\u003escenarios()-\u003ewrite('there is an unpublished post and an admin', function ($params) {\n            $admin = factory(User::class)-\u003estates('admin')-\u003ecreate();\n            $post = factory(Post::class)-\u003estates('unpublished')-\u003ecreate($params);\n            return [$admin, $post];\n        });\n        $this-\u003escenarios()-\u003ewrite('we have a published post', function () {\n            return factory(Post::class)-\u003estates('published')-\u003ecreate();\n        });\n        $this-\u003escenarios()-\u003ewrite('we have an admin', function () {\n            return factory(User::class)-\u003estates('admin')-\u003ecreate();\n        });\n        $this-\u003escenarios()-\u003ewrite('we have a regular user', function () {\n            return factory(User::class)-\u003estates('regular')-\u003ecreate();\n        });\n    }\n\n    public function test_an_admin_can_mark_a_post_as_published()\n    {\n        [$admin, $post] = $this-\u003escenarios()\n                            -\u003eplayout('there is an unpublished post and an admin', ['title' =\u003e 'A Post Title'])\n                            -\u003eandReturnResults();\n\n        $response = $this-\u003eactingAs($admin)-\u003epost('/posts/' . $post-\u003eid, ['status' =\u003e 'published']);\n\n        $this-\u003eassertEquals(1, Post::published()-\u003ecount());\n    }\n\n    public function test_an_admin_can_delete_a_post()\n    {\n        [$admin, $post] = $this-\u003escenarios()-\u003eplayout('there is an unpublished post and an admin')-\u003eandReturnResults();\n\n        $response = $this-\u003eactingAs($admin)-\u003edelete('/posts/' . $post-\u003eid);\n\n        $this-\u003eassertEquals(0, Post::count());\n    }\n\n\n    public function test_a_user_cant_delete_posts_that_are_not_theirs()\n    {\n        [$post, $badUser] = $this-\u003escenarios()\n                                -\u003eplayout('we have a published post')\n                                -\u003eandAlso('we have a regular user')\n                                -\u003eandReturnResults();\n\n        $response = $this-\u003eactingAs($badUser)-\u003edelete('/posts/' . $post-\u003eid);\n\n        $response-\u003eassertStatus(302);\n        $this-\u003eassertEquals(1, Post::count());\n    }\n}\n```\n\n## Notes\n\nIf you try and 'playout' a scenario which doesn't exist, the code will throw an \\InvalidArgumentException.\n\nIf your scenario list only calls one 'thing' then it will be returned 'as is', otherwise it'll return an array of\nthe things. Eg.\n\n```php\n$this-\u003escenarios()-\u003ewrite('we have a regular user', function () {\n    return ['username' =\u003e 'jenny', 'status' =\u003e 'normal'];\n});\n$this-\u003escenarios()-\u003ewrite('we have a super user', function () {\n    return ['username' =\u003e 'marlene', 'status' =\u003e 'admin'];\n});\n\n$admin = $this-\u003escenarios()-\u003eplayout('we have a super user')-\u003eandReturnResults();\n$user = $this-\u003escenarios()-\u003eplayout('we have a regular user')-\u003eandReturnResults();\n[$user, $admin] = $this-\u003escenarios()-\u003eplayout('we have a regular user')-\u003eandAlso('we have a super user')-\u003eandReturnResults();\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fohnotnow%2Fscenarios","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fohnotnow%2Fscenarios","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fohnotnow%2Fscenarios/lists"}