Compare commits

...
Sign in to create a new pull request.

7 commits

Author SHA1 Message Date
300c8cafc9 added a /api/food_orders/latest/ endpoint to recieve the latest food order 2025-06-17 21:26:05 +02:00
ee32852789
api api 2025-06-15 13:57:17 +02:00
9d2f0204e3
locki 2025-06-15 13:03:18 +02:00
a948e992d8
remove trash 2025-06-15 12:58:37 +02:00
f731b46f86
fixi 2025-06-15 12:57:18 +02:00
937973e8e9
upidati 2025-06-15 12:55:41 +02:00
314063f15c
bump ci image 2025-05-24 21:50:48 +02:00
23 changed files with 1031 additions and 1928 deletions

4
.env.dev Normal file
View file

@ -0,0 +1,4 @@
###> symfony/framework-bundle ###
APP_SECRET=11c8937d48993fb3aee1a476413161f5
###< symfony/framework-bundle ###

View file

@ -3,7 +3,7 @@ jobs:
ls: ls:
runs-on: docker runs-on: docker
container: container:
image: git.php.fail/lubiana/container/php:8.4.1-ci image: git.php.fail/lubiana/container/php:8.4.8-ci
steps: steps:
- name: Manually checkout - name: Manually checkout
env: env:

View file

@ -6,7 +6,7 @@ jobs:
ls: ls:
runs-on: docker runs-on: docker
container: container:
image: git.php.fail/lubiana/container/php:8.4.1-ci image: git.php.fail/lubiana/container/php:8.4.8-ci
steps: steps:
- name: Manually checkout - name: Manually checkout
env: env:

View file

@ -4,7 +4,7 @@ jobs:
ls: ls:
runs-on: docker runs-on: docker
container: container:
image: git.php.fail/lubiana/container/php:8.4.1-ci image: git.php.fail/lubiana/container/php:8.4.8-ci
steps: steps:
- name: Manually checkout - name: Manually checkout
env: env:

9
.gitignore vendored
View file

@ -17,3 +17,12 @@
###< phpunit/phpunit ### ###< phpunit/phpunit ###
.DS_Store .DS_Store
###> squizlabs/php_codesniffer ###
/.phpcs-cache
/phpcs.xml
###< squizlabs/php_codesniffer ###
###> phpstan/phpstan ###
phpstan.neon
###< phpstan/phpstan ###

View file

@ -7,46 +7,46 @@
"php": ">=8.4", "php": ">=8.4",
"ext-ctype": "*", "ext-ctype": "*",
"ext-iconv": "*", "ext-iconv": "*",
"api-platform/doctrine-orm": "^4.0.0", "api-platform/doctrine-orm": "*",
"api-platform/symfony": "4.1.4", "api-platform/symfony": "*",
"doctrine/dbal": "^4.1", "doctrine/dbal": "^4.2.3",
"doctrine/doctrine-bundle": "^2.12", "doctrine/doctrine-bundle": "^2.14.1",
"doctrine/doctrine-migrations-bundle": "^3.3.1", "doctrine/doctrine-migrations-bundle": "^3.4.2",
"doctrine/orm": "^3.2.1", "doctrine/orm": "^3.4.0",
"nelmio/cors-bundle": "^2.5", "nelmio/cors-bundle": "^2.5",
"phpdocumentor/reflection-docblock": "^5.6", "phpdocumentor/reflection-docblock": "^5.6.2",
"phpstan/phpdoc-parser": "^1.33", "phpstan/phpdoc-parser": "^1.33",
"psr/clock": "^1.0", "psr/clock": "^1.0",
"symfony/asset": "7.2.*", "symfony/asset": "7.3.*",
"symfony/console": "7.1.*", "symfony/console": "7.3.*",
"symfony/dotenv": "7.1.*", "symfony/dotenv": "7.3.*",
"symfony/expression-language": "7.2.*", "symfony/expression-language": "7.3.*",
"symfony/flex": "^2.4.6", "symfony/flex": "^2.7.1",
"symfony/form": "7.1.*", "symfony/form": "7.3.*",
"symfony/framework-bundle": "7.1.*", "symfony/framework-bundle": "7.3.*",
"symfony/property-access": "7.2.*", "symfony/property-access": "7.3.*",
"symfony/property-info": "7.2.*", "symfony/property-info": "7.3.*",
"symfony/runtime": "7.1.*", "symfony/runtime": "7.3.*",
"symfony/security-bundle": "7.2.*", "symfony/security-bundle": "7.3.*",
"symfony/security-csrf": "7.1.*", "symfony/security-csrf": "7.3.*",
"symfony/serializer": "7.2.*", "symfony/serializer": "7.3.*",
"symfony/twig-bundle": "7.1.*", "symfony/twig-bundle": "7.3.*",
"symfony/uid": "7.1.*", "symfony/uid": "7.3.*",
"symfony/validator": "7.1.*", "symfony/validator": "7.3.*",
"symfony/yaml": "7.1.*" "symfony/yaml": "7.3.*"
}, },
"require-dev": { "require-dev": {
"doctrine/doctrine-fixtures-bundle": "^4.0", "doctrine/doctrine-fixtures-bundle": "^4.1",
"liip/test-fixtures-bundle": "^3.2", "liip/test-fixtures-bundle": "^3.4",
"lubiana/code-quality": "^1.7.2", "lubiana/code-quality": "^1.7.2",
"pestphp/pest": "^3.6", "pestphp/pest": "^3.8.2",
"symfony/browser-kit": "7.2.*", "symfony/browser-kit": "7.3.*",
"symfony/css-selector": "7.2.*", "symfony/css-selector": "7.3.*",
"symfony/http-client": "7.2.*", "symfony/http-client": "7.3.*",
"symfony/maker-bundle": "^1.60", "symfony/maker-bundle": "^1.63",
"symfony/stopwatch": "7.2.*", "symfony/stopwatch": "7.3.*",
"symfony/web-profiler-bundle": "7.2.*", "symfony/web-profiler-bundle": "7.3.*",
"symplify/config-transformer": "^12.3.4" "symplify/config-transformer": "^12.4.0"
}, },
"config": { "config": {
"allow-plugins": { "allow-plugins": {
@ -80,7 +80,8 @@
"symfony/polyfill-php80": "*", "symfony/polyfill-php80": "*",
"symfony/polyfill-php81": "*", "symfony/polyfill-php81": "*",
"symfony/polyfill-php82": "*", "symfony/polyfill-php82": "*",
"symfony/polyfill-php83": "*" "symfony/polyfill-php83": "*",
"symfony/polyfill-php84": "*"
}, },
"scripts": { "scripts": {
"auto-scripts": { "auto-scripts": {
@ -106,7 +107,7 @@
"extra": { "extra": {
"symfony": { "symfony": {
"allow-contrib": false, "allow-contrib": false,
"require": "7.2.*" "require": "7.3.*"
} }
} }
} }

2514
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -42,11 +42,11 @@ return [
NelmioCorsBundle::class => [ NelmioCorsBundle::class => [
'all' => true, 'all' => true,
], ],
ApiPlatformBundle::class => [
'all' => true,
],
LiipTestFixturesBundle::class => [ LiipTestFixturesBundle::class => [
'dev' => true, 'dev' => true,
'test' => true, 'test' => true,
], ],
ApiPlatformBundle::class => [
'all' => true,
],
]; ];

View file

@ -4,10 +4,8 @@ use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigura
return static function (ContainerConfigurator $containerConfigurator): void { return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension('api_platform', [ $containerConfigurator->extension('api_platform', [
'title' => 'Futtern API', 'title' => 'Hello API Platform',
'version' => '1.0.0', 'version' => '1.0.0',
'show_webby' => false,
'enable_swagger' => true,
'defaults' => [ 'defaults' => [
'stateless' => true, 'stateless' => true,
'cache_headers' => [ 'cache_headers' => [

20
config/packages/csrf.php Normal file
View file

@ -0,0 +1,20 @@
<?php declare(strict_types=1);
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension('framework', [
'form' => [
'csrf_protection' => [
'token_id' => 'submit',
],
],
'csrf_protection' => [
'stateless_token_ids' => [
'submit',
'authenticate',
'logout',
],
],
]);
};

View file

@ -0,0 +1,11 @@
<?php declare(strict_types=1);
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension('framework', [
'property_info' => [
'with_constructor_extractor' => true,
],
]);
};

View file

@ -1,20 +0,0 @@
<?php declare(strict_types=1);
use PhpStyler\Config;
use PhpStyler\Files;
use PhpStyler\Styler;
return new Config(
styler: new Styler(lineLen: 79),
files: new Files(
__DIR__ . '/bin',
__DIR__ . '/public',
__DIR__ . '/src',
__DIR__ . '/config',
__DIR__ . '/tests',
__DIR__ . '/php-styler.php',
__DIR__ . '/ecs.php',
__DIR__ . '/rector.php',
),
cache: __DIR__ . '/.php-styler.cache',
);

View file

@ -3,9 +3,14 @@
namespace App\Entity; namespace App\Entity;
use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Delete;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use App\Repository\FoodOrderRepository; use App\Repository\FoodOrderRepository;
use App\State\OpenFoodOrderProvider; use App\State\OpenOrdersProvider;
use App\State\LatestOrderProvider;
use DateInterval; use DateInterval;
use DateTimeImmutable; use DateTimeImmutable;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
@ -16,12 +21,26 @@ use Symfony\Component\Uid\Ulid;
use function iterator_to_array; use function iterator_to_array;
#[ORM\Entity(repositoryClass: FoodOrderRepository::class)] #[ApiResource(
#[GetCollection( operations: [
uriTemplate: '/food_orders/open', new GetCollection(
provider: OpenFoodOrderProvider::class, uriTemplate: 'food_orders/open',
description: 'Get only open orders',
provider: OpenOrdersProvider::class,
),
new GetCollection(
uriTemplate: 'food_orders/latest',
description: 'Get the latest created order',
provider: LatestOrderProvider::class,
),
new GetCollection,
new Get,
new Post,
new Put,
new Delete,
]
)] )]
#[ApiResource] #[ORM\Entity(repositoryClass: FoodOrderRepository::class)]
class FoodOrder class FoodOrder
{ {
#[ORM\Column(nullable: true)] #[ORM\Column(nullable: true)]

View file

@ -12,8 +12,8 @@ use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator;
use Symfony\Bridge\Doctrine\Types\UlidType; use Symfony\Bridge\Doctrine\Types\UlidType;
use Symfony\Component\Uid\Ulid; use Symfony\Component\Uid\Ulid;
#[ORM\Entity(repositoryClass: MenuItemRepository::class)]
#[ApiResource] #[ApiResource]
#[ORM\Entity(repositoryClass: MenuItemRepository::class)]
class MenuItem class MenuItem
{ {
#[ORM\Column(length: 255)] #[ORM\Column(length: 255)]

View file

@ -9,8 +9,8 @@ use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator;
use Symfony\Bridge\Doctrine\Types\UlidType; use Symfony\Bridge\Doctrine\Types\UlidType;
use Symfony\Component\Uid\Ulid; use Symfony\Component\Uid\Ulid;
#[ORM\Entity(repositoryClass: OrderItemRepository::class)]
#[ApiResource] #[ApiResource]
#[ORM\Entity(repositoryClass: OrderItemRepository::class)]
class OrderItem class OrderItem
{ {
#[ORM\Column(length: 255)] #[ORM\Column(length: 255)]

View file

@ -62,4 +62,16 @@ final class FoodOrderRepository extends ServiceEntityRepository
->getQuery() ->getQuery()
->getResult(); ->getResult();
} }
/**
* @return FoodOrder|null
*/
public function findLatestOrder(): ?FoodOrder
{
return $this->createQueryBuilder('alias')
->orderBy('alias.id', 'DESC')
->setMaxResults(1)
->getQuery()
->getOneOrNullResult();
}
} }

View file

@ -0,0 +1,22 @@
<?php declare(strict_types=1);
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Entity\FoodOrder;
use App\Repository\FoodOrderRepository;
use Override;
final readonly class LatestOrderProvider implements ProviderInterface
{
public function __construct(
private FoodOrderRepository $repository
) {}
#[Override]
public function provide(Operation $operation, array $uriVariables = [], array $context = []): ?FoodOrder
{
return $this->repository->findLatestOrder();
}
}

View file

@ -4,17 +4,21 @@ namespace App\State;
use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface; use ApiPlatform\State\ProviderInterface;
use App\Entity\FoodOrder;
use App\Repository\FoodOrderRepository; use App\Repository\FoodOrderRepository;
use Override; use Override;
final readonly class OpenFoodOrderProvider implements ProviderInterface final readonly class OpenOrdersProvider implements ProviderInterface
{ {
public function __construct( public function __construct(
private FoodOrderRepository $repository private FoodOrderRepository $repository
) {} ) {}
/**
* @return FoodOrder[]
*/
#[Override] #[Override]
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null public function provide(Operation $operation, array $uriVariables = [], array $context = []): array
{ {
return $this->repository->findOpenOrders(); return $this->repository->findOpenOrders();
} }

View file

@ -1,11 +1,11 @@
{ {
"api-platform/symfony": { "api-platform/core": {
"version": "4.0", "version": "4.1",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
"version": "4.0", "version": "4.0",
"ref": "e9952e9f393c2d048f10a78f272cd35e807d972b" "ref": "cb9e6b8ceb9b62f32d41fc8ad72a25d5bd674c6d"
}, },
"files": [ "files": [
"config/packages/api_platform.yaml", "config/packages/api_platform.yaml",
@ -13,13 +13,22 @@
"src/ApiResource/.gitignore" "src/ApiResource/.gitignore"
] ]
}, },
"doctrine/doctrine-bundle": { "doctrine/deprecations": {
"version": "2.12", "version": "1.1",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
"version": "2.12", "version": "1.0",
"ref": "7266981c201efbbe02ae53c87f8bb378e3f825ae" "ref": "87424683adc81d7dc305eefec1fced883084aab9"
}
},
"doctrine/doctrine-bundle": {
"version": "2.14",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.13",
"ref": "620b57f496f2e599a6015a9fa222c2ee0a32adcb"
}, },
"files": [ "files": [
"config/packages/doctrine.yaml", "config/packages/doctrine.yaml",
@ -28,7 +37,7 @@
] ]
}, },
"doctrine/doctrine-fixtures-bundle": { "doctrine/doctrine-fixtures-bundle": {
"version": "4.0", "version": "4.1",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
@ -40,7 +49,7 @@
] ]
}, },
"doctrine/doctrine-migrations-bundle": { "doctrine/doctrine-migrations-bundle": {
"version": "3.3", "version": "3.4",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
@ -53,7 +62,7 @@
] ]
}, },
"liip/test-fixtures-bundle": { "liip/test-fixtures-bundle": {
"version": "3.2.1" "version": "3.4.0"
}, },
"nelmio/cors-bundle": { "nelmio/cors-bundle": {
"version": "2.5", "version": "2.5",
@ -68,39 +77,46 @@
] ]
}, },
"phpstan/phpstan": { "phpstan/phpstan": {
"version": "1.11", "version": "1.12",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes-contrib", "repo": "github.com/symfony/recipes-contrib",
"branch": "main", "branch": "main",
"version": "1.0", "version": "1.0",
"ref": "5e490cc197fb6bb1ae22e5abbc531ddc633b6767" "ref": "5e490cc197fb6bb1ae22e5abbc531ddc633b6767"
} },
"files": [
"phpstan.dist.neon"
]
}, },
"phpunit/phpunit": { "phpunit/phpunit": {
"version": "11.4", "version": "11.5",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
"version": "9.6", "version": "11.1",
"ref": "7364a21d87e658eb363c5020c072ecfdc12e2326" "ref": "c6658a60fc9d594805370eacdf542c3d6b5c0869"
}, },
"files": [ "files": [
".env.test", ".env.test",
"phpunit.xml.dist", "phpunit.xml.dist",
"tests/bootstrap.php" "tests/bootstrap.php",
"bin/phpunit"
] ]
}, },
"squizlabs/php_codesniffer": { "squizlabs/php_codesniffer": {
"version": "3.10", "version": "3.13",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes-contrib", "repo": "github.com/symfony/recipes-contrib",
"branch": "main", "branch": "main",
"version": "3.6", "version": "3.6",
"ref": "1019e5c08d4821cb9b77f4891f8e9c31ff20ac6f" "ref": "1019e5c08d4821cb9b77f4891f8e9c31ff20ac6f"
} },
"files": [
"phpcs.xml.dist"
]
}, },
"symfony/console": { "symfony/console": {
"version": "7.1", "version": "7.3",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
@ -112,24 +128,37 @@
] ]
}, },
"symfony/flex": { "symfony/flex": {
"version": "2.4", "version": "2.7",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
"version": "1.0", "version": "2.4",
"ref": "146251ae39e06a95be0fe3d13c807bcf3938b172" "ref": "52e9754527a15e2b79d9a610f98185a1fe46622a"
}, },
"files": [ "files": [
".env" ".env",
".env.dev"
]
},
"symfony/form": {
"version": "7.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.2",
"ref": "7d86a6723f4a623f59e2bf966b6aad2fc461d36b"
},
"files": [
"config/packages/csrf.yaml"
] ]
}, },
"symfony/framework-bundle": { "symfony/framework-bundle": {
"version": "7.1", "version": "7.3",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
"version": "7.0", "version": "7.3",
"ref": "6356c19b9ae08e7763e4ba2d9ae63043efc75db5" "ref": "5a1497d539f691b96afd45ae397ce5fe30beb4b9"
}, },
"files": [ "files": [
"config/packages/cache.yaml", "config/packages/cache.yaml",
@ -139,11 +168,12 @@
"config/services.yaml", "config/services.yaml",
"public/index.php", "public/index.php",
"src/Controller/.gitignore", "src/Controller/.gitignore",
"src/Kernel.php" "src/Kernel.php",
".editorconfig"
] ]
}, },
"symfony/maker-bundle": { "symfony/maker-bundle": {
"version": "1.60", "version": "1.63",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
@ -151,8 +181,20 @@
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f" "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
} }
}, },
"symfony/property-info": {
"version": "7.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.3",
"ref": "dae70df71978ae9226ae915ffd5fad817f5ca1f7"
},
"files": [
"config/packages/property_info.yaml"
]
},
"symfony/routing": { "symfony/routing": {
"version": "7.1", "version": "7.3",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
@ -165,7 +207,7 @@
] ]
}, },
"symfony/security-bundle": { "symfony/security-bundle": {
"version": "7.2", "version": "7.3",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
@ -178,7 +220,7 @@
] ]
}, },
"symfony/twig-bundle": { "symfony/twig-bundle": {
"version": "7.1", "version": "7.3",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
@ -191,7 +233,7 @@
] ]
}, },
"symfony/uid": { "symfony/uid": {
"version": "7.1", "version": "7.3",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
@ -200,7 +242,7 @@
} }
}, },
"symfony/validator": { "symfony/validator": {
"version": "7.1", "version": "7.3",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
@ -212,12 +254,12 @@
] ]
}, },
"symfony/web-profiler-bundle": { "symfony/web-profiler-bundle": {
"version": "7.1", "version": "7.3",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
"version": "6.1", "version": "7.3",
"ref": "e42b3f0177df239add25373083a564e5ead4e13a" "ref": "5b2b543e13942495c0003f67780cb4448af9e606"
}, },
"files": [ "files": [
"config/packages/web_profiler.yaml", "config/packages/web_profiler.yaml",

View file

@ -1,26 +0,0 @@
<?php declare(strict_types=1);
namespace App\Tests;
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
use ApiPlatform\Symfony\Bundle\Test\Client;
use App\DataFixtures\AppFixtures;
use Doctrine\ORM\EntityManagerInterface;
use Liip\TestFixturesBundle\Services\DatabaseToolCollection;
use Override;
abstract class DbApiTestCase extends ApiTestCase
{
protected EntityManagerInterface $manager;
protected Client $client;
#[Override]
protected function setUp(): void
{
parent::setUp();
$this->client = static::createClient();
$this->manager = static::getContainer()->get('doctrine')->getManager();
$toolKit = self::getContainer()->get(DatabaseToolCollection::class)->get();
$toolKit->loadFixtures([AppFixtures::class]);
}
}

View file

@ -1,48 +0,0 @@
<?php declare(strict_types=1);
test('orders', function (): void {
$response = $this->client->request('GET', '/api/food_orders');
$this->assertResponseIsSuccessful();
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
$this->assertJsonContains([
'@context' => '/api/contexts/FoodOrder',
'@id' => '/api/food_orders',
'@type' => 'Collection',
'totalItems' => 1,
]);
$array = $response->toArray();
expect($array['member'][0]['orderItems'])->toHaveCount(10);
});
test('open orders', function (): void {
$response = $this->client->request('GET', '/api/food_orders/open');
$this->assertResponseIsSuccessful();
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
$this->assertJsonContains([
'@context' => '/api/contexts/FoodOrder',
'@id' => '/api/food_orders/open',
'@type' => 'Collection',
]);
// Get the response content and verify that all returned orders are open
$array = $response->toArray();
// If we have no items, we should still have a successful response
if ($array['totalItems'] === 0) {
return;
}
// For each order in the response, check that it is not closed
foreach ($array['member'] as $order) {
// An order is considered open if either:
// 1. closedAt is null or
// 2. closedAt is in the future
$closedAt = isset($order['closedAt']) ? new DateTimeImmutable($order['closedAt']) : null;
$now = new DateTimeImmutable;
// Assert that the order is open (not closed)
$isOpen = (! $closedAt instanceof DateTimeImmutable || $closedAt > $now);
expect($isOpen)
->toBeTrue('Order should be open but is closed');
}
});

View file

@ -231,6 +231,30 @@ describe(FoodOrderController::class, function (): void {
$this->assertTrue($openOrder->isClosed()); $this->assertTrue($openOrder->isClosed());
}); });
test('api_latest_order', function (): void {
// Create an older order
$olderOrder = new FoodOrder($this->generateOldUlid());
$olderOrder->setFoodVendor($this->vendor);
$this->manager->persist($olderOrder);
// Create the latest order
$latestOrder = new FoodOrder;
$latestOrder->setFoodVendor($this->vendor);
$this->manager->persist($latestOrder);
$this->manager->flush();
// Test the API endpoint
$this->client->request('GET', '/api/food_orders/latest');
$this->assertResponseIsSuccessful();
$this->assertResponseHeaderSame('Content-Type', 'application/ld+json; charset=utf-8');
$response = json_decode($this->client->getResponse()->getContent(), true);
$this->assertIsArray($response);
$this->assertArrayHasKey('@id', $response);
$this->assertStringContainsString($latestOrder->getId()->__toString(), $response['@id']);
});
}) })
->covers( ->covers(
FoodOrderController::class, FoodOrderController::class,

View file

@ -1,6 +1,5 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
use App\Tests\DbApiTestCase;
use App\Tests\DbWebTest; use App\Tests\DbWebTest;
/* /*
@ -16,8 +15,6 @@ use App\Tests\DbWebTest;
pest() pest()
->extends(DbWebTest::class)->in('Feature/Controller/*.php'); ->extends(DbWebTest::class)->in('Feature/Controller/*.php');
pest()
->extends(DbApiTestCase::class)->in('Feature/Api/*.php');
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------