Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pest Tests & Desafio #1

Open
wants to merge 12 commits into
base: pest
Choose a base branch
from
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
# API TDD

## Sobre

## Desafio
Projeto para fins educacionais e de aprendizado. Desenvolvido em formato Live no canal 🐧 **Pinguim do Laravel**.

📺 Acompanhe: [\#16 - Laravel | TDD](https://www.youtube.com/watch?v=-WUq9QilQVU)

## TO DO

### Desafio

- [ ] Garantir que o código da url curta não se repita

----


- [X] Salvar um endpoint
- [X] Precisar enviar o endpoint que queremos encurtar
- [X] Endpoint tem que ser válido
Expand Down Expand Up @@ -42,9 +48,4 @@
],
"total": 40
}
```





```
13 changes: 0 additions & 13 deletions app/Actions/CodeGenerator.php

This file was deleted.

27 changes: 27 additions & 0 deletions app/Actions/UrlCode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types = 1);

namespace App\Actions;

use App\Models\ShortUrl;

class UrlCode
{
/**
* Generates the code to be used in an ShortURL
*
* @param string|null $code
* @return string
*/
public function generate(string $code = null): string
{
$code = $code ?? str()->random(5);

if (ShortUrl::where('code', $code)->exists()) {
return $this->generate();
}

return $code;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
/**
* @method static string run()
*/
class CodeGenerator extends Facade
class UrlCode extends Facade
{
protected static function getFacadeAccessor(): string
{
return \App\Actions\CodeGenerator::class;
return \App\Actions\UrlCode::class;
}
}
4 changes: 2 additions & 2 deletions app/Http/Controllers/ShortUrlController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace App\Http\Controllers;

use App\Facades\Actions\CodeGenerator;
use App\Facades\Actions\UrlCode;
use App\Models\ShortUrl;
use Symfony\Component\HttpFoundation\Response;

Expand All @@ -14,7 +14,7 @@ public function store()
'url' => 'required|url',
]);

$code = CodeGenerator::run();
$code = UrlCode::generate();

$shortUrl = ShortUrl::query()
->firstOrCreate([
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/StatsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public function lastVisit(ShortUrl $shortUrl)

public function visits(ShortUrl $shortUrl)
{
// Does not work in SQLite

$visits = $shortUrl->visits()
->selectRaw("
Expand All @@ -26,7 +27,6 @@ public function visits(ShortUrl $shortUrl)

ray($visits->toArray());


return [
'total' => $shortUrl->visits()->count(),
'visits' => $visits->toArray(),
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
}
},
"scripts": {
"pestify": "./vendor/bin/pest tests/Feature/Pest/",
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
Expand Down
2 changes: 1 addition & 1 deletion database/factories/ShortUrlFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public function definition(): array
return [
'url' => $this->faker->url(),
'short_url' => $this->faker->url(),
'code' => $this->faker->word(),
'code' => $this->faker->word(5),
];
}
}
6 changes: 4 additions & 2 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
</coverage>
<php>
<env name="APP_ENV" value="testing"/>
<env name="APP_KEY" value="base64:2dQLDuLeEuA14REfNn8XA2c9rqjcA7miikrmlycx6WE="/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_DRIVER" value="array"/>
<!-- <env name="DB_CONNECTION" value="sqlite"/>-->
<env name="DB_DATABASE" value="testing"/>
<env name="DB_CONNECTION" value="sqlite"/>
<!-- <env name="DB_DATABASE" value="testing"/>-->
<env name="DB_DATABASE" value=":memory:"/>
<env name="MAIL_MAILER" value="array"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>
Expand Down
27 changes: 27 additions & 0 deletions tests/Feature/Pest/Actions/UrlCodeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

use App\Facades\Actions\UrlCode;
use App\Models\ShortUrl;

it('generates a 5 characters code')
->expect(fn () => UrlCode::generate())
->toBeString()
->toHaveLength(5);

test('codes cannot be repeated', function () {
$code = '12345';

shortUrl()->create(['code' => $code]);

expect(ShortUrl::all())
->count()->toBe(1)
->first()
->code->toBe($code);

$newCode = UrlCode::generate($code);

expect($newCode)
->toBeString()
->toHaveLength(5)
->not->toBe($code);
});
82 changes: 45 additions & 37 deletions tests/Feature/Pest/ShortUrl/CreateTest.php
Original file line number Diff line number Diff line change
@@ -1,58 +1,66 @@
<?php

use App\Facades\Actions\CodeGenerator;
use App\Facades\Actions\UrlCode;
use App\Models\ShortUrl;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;
use function Pest\Laravel\postJson;

it('should be able to create a short url', function () {
it('successfully creates a short url', function () {
$randomCode = Str::random(5);

CodeGenerator::shouldReceive('run')
UrlCode::shouldReceive('generate')
->once()
->andReturn($randomCode);

postJson(
route('api.short-url.store'),
['url' => 'https://www.google.com']
)
->assertStatus(Response::HTTP_CREATED)
->assertJson([
'short_url' => config('app.url') . '/' . $randomCode,
]);
$testUrl = config('app.url') . '/' . $randomCode;

$this->assertDatabaseHas('short_urls', [
'url' => 'https://www.google.com',
'short_url' => config('app.url') . '/' . $randomCode,
'code' => $randomCode,
]);
$response = storeShortUrl(['url' => 'https://www.google.com']);

expect($response)
->status()->toBeCreated()
->content()
->json()
->toMatchArray(['short_url' => $testUrl]);

expect(ShortUrl::count())->toBe(1);

expect(ShortUrl::first())
->url->ToBe('https://www.google.com')
->code->toBe($randomCode)
->short_url->toBe($testUrl);
});

test('url should be a valid url', function () {
$this->postJson(
route('api.short-url.store'),
['url' => 'not-valid-url']
)->assertStatus(Response::HTTP_UNPROCESSABLE_ENTITY)
->assertJsonValidationErrors([
'url' => __('validation.url', ['attribute' => 'url']),
it('rejects an invalid URL', function () {
$response = storeShortUrl(['url' => 'not-valid-url']);

expect($response)
->status()->toBeUnprocessableEntity()
->content()
->json()
->toMatchArray([
"message" => "The url must be a valid URL.",
"errors" => [
"url" => ["The url must be a valid URL."]
]
]);
});

it('should return the existed code if the url is the same', function () {
ShortUrl::factory()->create([
it('returns the existing code when the URL already exists', function () {
$code = '123456';
$shortUrl = config('app.url') . '/' . $code;

shortUrl()->create([
'url' => 'https://www.google.com',
'short_url' => config('app.url') . '/123456',
'code' => '123456',
'short_url' => $shortUrl,
'code' => $code
]);

postJson(
route('api.short-url.store'),
['url' => 'https://www.google.com']
)->assertJson([
'short_url' => config('app.url') . '/123456',
]);
$response = storeShortUrl(['url' => 'https://www.google.com']);

$this->assertDatabaseCount('short_urls', 1);
});
expect($response)
->status()->toBeCreated()
->content()
->json()
->toMatchArray(['short_url' => $shortUrl]);

expect(ShortUrl::count())->toBe(1);
});
23 changes: 15 additions & 8 deletions tests/Feature/Pest/ShortUrl/DeleteTest.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
<?php

use App\Models\ShortUrl;
use Symfony\Component\HttpFoundation\Response;
use function Pest\Laravel\deleteJson;

it('should be able to delete a short url', function () {
$shortUrl = ShortUrl::factory()->create();
$this->deleteJson(route('api.short-url.destroy', $shortUrl->code))
->assertStatus(Response::HTTP_NO_CONTENT);
it('can delete a short url', function () {
$shortUrl = shortUrl()->create();

$this->assertDatabaseMissing('short_urls', [
'id' => $shortUrl->id,
]);
$response = deleteJson(route('api.short-url.destroy', $shortUrl->code));

expect($response)
->status()
->toBeNoContent();
});

it('can delete a short url [HIGH ORDER]')
->tap(fn () => $this->code = shortUrl()->create()->code)
->tap(fn () => $this->response = deleteJson(route('api.short-url.destroy', $this->code)))
->expect(fn () => $this->response)
->status()->toBeNoContent()
->expect(fn () => $this->count = ShortUrl::count())
->toBe(0);
13 changes: 13 additions & 0 deletions tests/Feature/Pest/ShortUrl/MiscTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

it('has a home page')
->get('/')
->assertOk();

it('is incomplete');

it('will not run')->skip();

test('only this test will run! (//comment me out)')
->expect(true)->toBeTrue()
->only();
Loading