Skip to content

Commit

Permalink
Merge pull request #6 from markhuot/native-snapshots
Browse files Browse the repository at this point in the history
wip native toSnapshot functionality
  • Loading branch information
markhuot authored Dec 1, 2023
2 parents ae12b3b + f84b8ad commit cdfb232
Show file tree
Hide file tree
Showing 114 changed files with 1,290 additions and 1,008 deletions.
1 change: 1 addition & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ jobs:
php src/bin/generate-docs.php src/test/CookieState.php docs/cookies.md
php src/bin/generate-docs.php src/test/ActingAs.php docs/logging-in.md
php src/bin/generate-docs.php src/test/SnapshotAssertions.php docs/snapshots.md
php src/bin/generate-docs.php src/console/PestController.php docs/cli.md
- name: Add files
run: git add -A docs/
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jobs:
CRAFT_DEV_MODE: true
DEV_MODE: true
CRAFT_EXE_PATH: ./src/bin/craft
PRIMARY_SITE_URL: http://localhost:8080

services:
mysql:
Expand Down Expand Up @@ -58,8 +59,6 @@ jobs:
composer.lock
vendor
key: ${{ runner.os }}-craft-vendor-${{ hashFiles('composer.json') }}
restore-keys: |
${{ runner.os }}-craft-vendor-

- name: Install dependencies
run: |
Expand All @@ -78,5 +77,8 @@ jobs:
- name: Run PHPStan
run: ./vendor/bin/phpstan analyse src

- name: Run pint
run: ./vendor/bin/pint --test src/

- name: Run test suite
run: ./vendor/bin/pest
18 changes: 12 additions & 6 deletions bin/post-clone.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@ if [ ! -f ".env" ]; then
cp vendor/craftcms/craft/.env.example.dev ./.env.example
fi

if ! grep -q "CRAFT_RUN_QUEUE_AUTOMATICALLY=false" .env.example; then
echo "" >> .env
if ! grep -q "CRAFT_RUN_QUEUE_AUTOMATICALLY=" .env.example; then
echo "" >> .env.example
echo "CRAFT_RUN_QUEUE_AUTOMATICALLY=false" >> .env.example
echo "" >> .env
echo "" >> .env.example
fi

if ! grep -q "CRAFT_TEMPLATES_PATH=./tests/templates" .env.example; then
echo "" >> .env
if ! grep -q "CRAFT_TEMPLATES_PATH=" .env.example; then
echo "" >> .env.example
echo "CRAFT_TEMPLATES_PATH=./tests/templates" >> .env.example
echo "" >> .env
echo "" >> .env.example
fi

if ! grep -q "CRAFT_OMIT_SCRIPT_NAME_IN_URLS=" .env.example; then
echo "" >> .env.example
echo "CRAFT_OMIT_SCRIPT_NAME_IN_URLS=true" >> .env.example
echo "" >> .env.example
fi

if [ ! -d "config" ]; then
Expand Down
8 changes: 5 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"symfony/dom-crawler": "^6.0.3",
"symfony/process": "^5.3|^6.0",
"illuminate/collections": "^8.23|^9.1|^10.0",
"pestphp/pest": "^2.8",
"pestphp/pest": "^2.26",
"vlucas/phpdotenv": "^2.4|^3.4|^5.4",
"craftcms/cms": "^4.5"
},
Expand All @@ -36,7 +36,8 @@
"bootstrap": "markhuot\\craftpest\\Pest",
"pest": {
"plugins": [
"markhuot\\craftpest\\pest\\Coverage"
"markhuot\\craftpest\\pest\\Coverage",
"markhuot\\craftpest\\pest\\MonkeyPatches"
]
}
},
Expand All @@ -51,7 +52,8 @@
"prefer-stable": true,
"require-dev": {
"craftcms/phpstan": "dev-main",
"craftcms/craft": "^2.0",
"symfony/var-dumper": "^5.0|^6.0",
"craftcms/craft": "^2.0"
"laravel/pint": "^1.13"
}
}
2 changes: 1 addition & 1 deletion docs/assertions/benchmark.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,4 @@ it('loads the homepage')
->endBenchmark()
->assertAllQueriesFasterThan(0.05);
});
```
```
8 changes: 7 additions & 1 deletion docs/assertions/database.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,40 @@
# Database Assertions

You can assert that particular rows appear in the database using database assertions.

## assertDatabaseCount(string $tableName, int $expectedCount)
Check that the given table contains the given number of rows.

```php
$this->assertDatabaseCount('{{%entries}}', 6);
```

## assertDatabaseHas(string $tableName, array $condition)
Check that the given table contains one or more matching rows
for the given condition.

```php
$this->assertDatabaseHas('{{%content}}', ['title' => 'My Great Title']);
```

## assertDatabaseMissing(string $tableName, array $condition)
Check that the given table contains zero matching rows
for the given condition.

```php
$this->assertDatabaseMissing('{{%content}}', ['title' => 'My Great Title']);
```

## assertTrashed(craft\base\Element $element)
Check that the given element has been trashed (soft deleted).

```php
$this->assertTrashed($entry);
```

## assertNotTrashed(craft\base\Element $element)
Check that the given element has not been trashed (soft deleted).

```php
$this->assertNotTrashed($entry);
```
```
6 changes: 0 additions & 6 deletions docs/assertions/element.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,3 @@ Check that the element does not have its `dateDeleted` flag set
```php
Entry::factory()->create()->assertNotTrashed();
```

## assertMatchesSnapshot($args)
Check that an element matches a snapshot of its attributes.
```php
Entry::factory()->create()->assertMatchesSnapshot();
```
27 changes: 25 additions & 2 deletions docs/assertions/response.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Response Assertions

A testable response is returned whenever you perform a HTTP request
with Pest. It is an extension of Craft's native Response with a
number of convience methods added for testing. For example, most
Expand Down Expand Up @@ -55,6 +56,7 @@ Check that a response contains the given cache tag header. This is commonly used
edge-side CDNs to "tag" pages with a unique identifier so that they can be purged
from the cache by that unique tag later. In Craft this will usually be something like
the element ID of any entries being rendered.

```php
$response->assertCacheTag('my-tag');
$response->assertCacheTag('el1234');
Expand All @@ -64,6 +66,7 @@ $response->assertCacheTag('el1234');
Checks that the response contains the given cookie. When not passed a value
the assertion only checks the presence of the cookie. When passed a value the
value will be checked for strict equality.

```php
$response->assertCookie('cookieName'); // checks presence, with any value
$response->assertCookie('cookieName', 'cookie value'); // checks that the values match
Expand All @@ -73,44 +76,51 @@ $response->assertCookie('cookieName', 'cookie value'); // checks that the values
Checks that the given cookie has an expiration in the past. Cookies are sent in headers and if left
unset a cookie will persist from request to request. Therefore, the only way to "remove" a cookie
is to set its expiration to a date in the past (negative number). This is common when logging people out.

```php
$response->assertCookieExpired('cookieName');
```

## assertCookieNotExpired(string $name)
Checks that the given cookie has an expiration in the future.

```php
$response->assertCookieNotExpired('cookieName');
```

## assertCookieMissing(string $name)
Checks that the given cookie is not present in the response

```php
$response->assertCookieMissing('cookieName');
```

## assertCreated()
Checks that the response has a 201 Created status code

```php
$response->assertCreated();
```

## assertDontSee(string $text)
Checks that the given string does not appear in thr response.

```php
$response->assertDontSee('text that should not be in the response');
```

## assertDontSeeText(string $text)
Checks that the given string does not appear in the response after first stripping all non-text elements (like HTML) from the response.
For example, if the response contains `foo <em>bar</em>` you could check against the text `foo bar` because the `<em>` will be stripped.

```php
$response->assertDontSeeText('foo bar');
```

## assertDownload(?string $filename = NULL)
Checks that the response contains a file download, optionally checking that the filename of the download
matches the given filename.

```php
$response->assertDownload(); // checks that any download is returned
$response->assertDownload('file.jpg'); // checks that a download with the name `file.jpg` is returned
Expand All @@ -119,32 +129,37 @@ $response->assertDownload('file.jpg'); // checks that a download with the name `
## assertExactJson(array $json)
Checks that the given JSON exactly matches the returned JSON using PHPUnit's "canonicalizing" logic to
validate the objects.

```php
$response->assertExactJson(['foo' => 'bar']);
```

## assertForbidden()
Checks that the response has a 403 Forbidden status code

```php
$response->assertForbidden();
```

## assertHeader(string $name, ?string $expected = NULL)
Checks that the given header is present in the response and, if provided, that the value of the
header matches the given value.

```php
$response->assertHeader('x-foo'); // checks for presence of header, with any value
$response->assertHeader('x-foo', 'bar'); // checks for header with matching value
```

## assertHeaderMissing(string $name)
Checks that the response headers do not contain the given header.

```php
$response->assertHeaderMissing('x-foo');
```

## assertLocation(string $location, ?array $checkParts = NULL)
Checks that the location header matches the given location

```php
$response->assertLocation('/foo/bar');
```
Expand Down Expand Up @@ -178,30 +193,35 @@ $response->assertFlash('Field is required', 'title');

## assertNoContent($status = 204)
Check that the response has the given status code and no content.

```php
$response->assertNoContent();
```

## assertNotFound()
Check that the response returns a 404 Not Found status code

```php
$response->assertNotFound();
```

## assertOk()
Check that the response returns a 200 OK status code

```php
$response->assertOk();
```

## assertRedirect()
Check that the response returns a 300 status code

```php
$response->assertRedirect();
```

## assertRedirectTo(string $location)
A sugar method that checks the status code as well as the location of the redirect.

```php
$response->assertRedirectTo('/foo/bar');
```
Expand All @@ -220,33 +240,36 @@ request for the redirected page. If the redirected page also contains
a redirect, follow the resulting redirects until you reach a non-300
response code.


```php
$response->assertRedirect()->followRedirects()->assertOk();
```

## assertSee(string $text)
Checks that the response contains the given text

```php
$response->assertSee('foo bar');
```

## assertSeeInOrder(array $texts)
Checks that the response contains the given text, in successive order

```php
$response->assertSee(['first', 'second', 'third']);
```

## assertSeeText(string $text)
Checks that the response contains the given text stripping tags. This would
pass against source code of `<b>foo</b> bar`

```php
$response->assertSeeText('foo bar');
```

## assertSeeTextInOrder(array $texts)
Checks that the response contains the given text, in successive order
while stripping tags.

```php
$response->assertSeeTextInOrder(['first', 'second', 'third']);
```
Expand Down Expand Up @@ -303,4 +326,4 @@ it('ends on the response', function () {

> **Note**
> Unlike the traditional Craft request/response lifecycle you are
free to make multiple requests in a single benchmark.
free to make multiple requests in a single benchmark.
43 changes: 43 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# CLI Commands

## actionIndex()
Run the Pest tests with `php craft pest`. This is a convienence function that internally calls the
`pest/init` method and then `./vendor/bin/pest` executable.

You may pass any pest options to this command by separating them with a `--`. For example, to filter
down to a specific test you may run `php craft pest -- --filter="renders the homepage"`.

## actionInit()
Running `php craft pest/init` will create the `tests` directory, an associated `tests/Pest.php` file, a
default `phpunit.xml` file, and a `modules/pest/seeders` directory. If any of these files or directories
already exist they will be skipped.

This command id idempotent and can be run multiple times without issue. If you even want to reset your
setup to the default `Pest.php`, for example, you can delete your `Pest.php` and re-run `php craft pest/init`
to have the file recreated.

## actionSeed($seeder = NULL)
Pest comes with a built-in database seeder that can be called in your own tests or via the command
line. You may run the seeder with `php craft pest/seed`. By default, this will look for a class
called \modules\pest\seeders\DatabaseSeeder. You may override this by passing a fully qualified class
name as the first argument. For example, `php craft pest/seed \\modules\\pest\\seeders\\UserSeeder`.

Seeders are __invoke-able classes. Inside the invoke method you are free to seed your database however
you would like, although commonly you'll use factories to create your data. For example:

```php
class DatabaseSeeder
{
public function __invoke()
{
return \markhuot\craftpest\factories\Entry::factory()->count(10)->create();
}
}
```

You can override the defaults with the following environment variables,

```bash
PEST_SEEDER_NAMESPACE="\modules\pest\seeders"
PEST_DEFAULT_SEEDER=DatabaseSeeder
```
2 changes: 1 addition & 1 deletion docs/cookies.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ a test are automatically pruned, mimicing the functionality of
a browser.

## getCookieCollection()
Get the stored cookie collection
Get the stored cookie collection
Loading

0 comments on commit cdfb232

Please sign in to comment.