refactor(dashboard,history): replace ViewModels with Pinia stores and improve backend
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api;
|
||||
|
||||
use App\Contracts\PriceClient;
|
||||
use App\Data\ElectricityData;
|
||||
use App\Data\GasData;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use Mockery;
|
||||
use Tests\TestCase;
|
||||
|
||||
class DashboardApiTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
config(['cache_prices.ttl' => 60]);
|
||||
config(['cache_prices.prefix' => 'test:']);
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Mockery::close();
|
||||
\Illuminate\Support\Facades\Cache::flush();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function test_dashboard_endpoint_returns_electricity_and_gas_data(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
|
||||
$electricityResponse = collect([
|
||||
$this->createElectricityArray($now->copy()->subMinutes(30), 15.0, 80),
|
||||
$this->createElectricityArray($now->copy()->addHour(), 12.0, 90),
|
||||
$this->createElectricityArray($now->copy()->addHours(2), 20.0, 60),
|
||||
$this->createElectricityArray($now->copy()->addHours(3), 10.0, 95),
|
||||
]);
|
||||
|
||||
$gasResponse = collect([
|
||||
$this->createGasArray($now->copy()->startOfDay(), 5.0),
|
||||
$this->createGasArray($now->copy()->addDay(), 4.0),
|
||||
$this->createGasArray($now->copy()->addDays(2), 6.0),
|
||||
]);
|
||||
|
||||
$client = Mockery::mock(PriceClient::class);
|
||||
$client->shouldReceive('getElectricityPrices')->once()->andReturn($electricityResponse);
|
||||
$client->shouldReceive('getGasPrices')->once()->andReturn($gasResponse);
|
||||
|
||||
$this->app->bind(PriceClient::class, fn () => $client);
|
||||
|
||||
$response = $this->getJson('/api/energy-prices');
|
||||
|
||||
$response->assertOk()
|
||||
->assertJsonStructure([
|
||||
'electricity' => [
|
||||
'startDate',
|
||||
'endDate',
|
||||
'period',
|
||||
'totalPriceTaxIncluded',
|
||||
],
|
||||
'electricityCheapest',
|
||||
'electricityDurable',
|
||||
'electricityPriciest',
|
||||
'gas' => [
|
||||
'startDate',
|
||||
'endDate',
|
||||
'period',
|
||||
'totalPriceTaxIncluded',
|
||||
],
|
||||
'gasCheapest',
|
||||
'gasPriciest',
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_dashboard_endpoint_returns_correct_prices(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
|
||||
$electricityResponse = collect([
|
||||
$this->createElectricityArray($now->copy()->subMinutes(30), 15.0, 80),
|
||||
$this->createElectricityArray($now->copy()->addHour(), 12.0, 90),
|
||||
$this->createElectricityArray($now->copy()->addHours(2), 20.0, 60),
|
||||
]);
|
||||
|
||||
$gasResponse = collect([
|
||||
$this->createGasArray($now->copy()->startOfDay(), 5.0),
|
||||
$this->createGasArray($now->copy()->addDay(), 4.0),
|
||||
]);
|
||||
|
||||
$client = Mockery::mock(PriceClient::class);
|
||||
$client->shouldReceive('getElectricityPrices')->once()->andReturn($electricityResponse);
|
||||
$client->shouldReceive('getGasPrices')->once()->andReturn($gasResponse);
|
||||
|
||||
$this->app->bind(PriceClient::class, fn () => $client);
|
||||
|
||||
$response = $this->getJson('/api/energy-prices');
|
||||
|
||||
$response->assertOk();
|
||||
|
||||
$data = $response->json();
|
||||
$this->assertEquals(15.0, $data['electricity']['totalPriceTaxIncluded']);
|
||||
$this->assertEquals(12.0, $data['electricityCheapest']['totalPriceTaxIncluded']);
|
||||
$this->assertEquals(20.0, $data['electricityPriciest']['totalPriceTaxIncluded']);
|
||||
$this->assertEquals(5.0, $data['gas']['totalPriceTaxIncluded']);
|
||||
$this->assertEquals(4.0, $data['gasCheapest']['totalPriceTaxIncluded']);
|
||||
}
|
||||
|
||||
public function test_dashboard_endpoint_handles_empty_data(): void
|
||||
{
|
||||
$client = Mockery::mock(PriceClient::class);
|
||||
$client->shouldReceive('getElectricityPrices')->once()->andReturn(collect());
|
||||
$client->shouldReceive('getGasPrices')->once()->andReturn(collect());
|
||||
|
||||
$this->app->bind(PriceClient::class, fn () => $client);
|
||||
|
||||
$response = $this->getJson('/api/energy-prices');
|
||||
|
||||
$response->assertOk();
|
||||
|
||||
$data = $response->json();
|
||||
$this->assertNull($data['electricity'] ?? null);
|
||||
$this->assertNull($data['gas'] ?? null);
|
||||
}
|
||||
|
||||
private function createElectricityArray(Carbon $startDate, float $price, int $sustainabilityScore): array
|
||||
{
|
||||
return [
|
||||
'start_date' => $startDate->format('Y-m-d H:i:s'),
|
||||
'end_date' => $startDate->copy()->addHour()->format('Y-m-d H:i:s'),
|
||||
'period' => 'elec_hour',
|
||||
'market_price' => (int) ($price * 100),
|
||||
'total_price_tax_included' => $price,
|
||||
'price_incl_handling_vat' => (int) ($price * 100),
|
||||
'price_tax_with_vat' => (int) ($price * 20),
|
||||
'pricing_profile' => 'dynamic',
|
||||
'carbon_footprint_in_gram' => 500,
|
||||
'sustainability_score' => $sustainabilityScore,
|
||||
'start_date_datetime' => $startDate->format('Y-m-d H:i:s'),
|
||||
];
|
||||
}
|
||||
|
||||
private function createGasArray(Carbon $startDate, float $price): array
|
||||
{
|
||||
return [
|
||||
'start_date' => $startDate->format('Y-m-d H:i:s'),
|
||||
'end_date' => $startDate->copy()->addDay()->format('Y-m-d H:i:s'),
|
||||
'period' => 'gas_day',
|
||||
'market_price' => (int) ($price * 100),
|
||||
'total_price_tax_included' => $price,
|
||||
'price_incl_handling_vat' => (int) ($price * 100),
|
||||
'price_tax_with_vat' => (int) ($price * 20),
|
||||
'start_date_datetime' => $startDate->format('Y-m-d H:i:s'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api;
|
||||
|
||||
use App\Contracts\PriceClient;
|
||||
use App\Data\ElectricityData;
|
||||
use App\Data\GasData;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use Mockery;
|
||||
use Tests\TestCase;
|
||||
|
||||
class HistoryApiTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
config(['cache_prices.ttl' => 60]);
|
||||
config(['cache_prices.prefix' => 'test:']);
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Mockery::close();
|
||||
\Illuminate\Support\Facades\Cache::flush();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function test_history_endpoint_returns_electricity_and_gas_data(): void
|
||||
{
|
||||
$date = Carbon::today();
|
||||
|
||||
$electricityResponse = collect([
|
||||
$this->createElectricityArray($date->copy()->setHour(0), 15.0),
|
||||
$this->createElectricityArray($date->copy()->setHour(1), 16.0),
|
||||
]);
|
||||
|
||||
$gasResponse = collect([
|
||||
$this->createGasArray($date, 5.0),
|
||||
]);
|
||||
|
||||
$client = Mockery::mock(PriceClient::class);
|
||||
$client->shouldReceive('getElectricityPricesForDate')
|
||||
->once()
|
||||
->andReturn($electricityResponse);
|
||||
$client->shouldReceive('getGasPricesForDate')
|
||||
->once()
|
||||
->andReturn($gasResponse);
|
||||
|
||||
$this->app->bind(PriceClient::class, fn () => $client);
|
||||
|
||||
$response = $this->getJson('/api/history?date=' . $date->format('Y-m-d'));
|
||||
|
||||
$response->assertOk()
|
||||
->assertJsonStructure([
|
||||
'electricity' => [
|
||||
'*' => [
|
||||
'startDate',
|
||||
'endDate',
|
||||
'period',
|
||||
'totalPriceTaxIncluded',
|
||||
],
|
||||
],
|
||||
'gas' => [
|
||||
'*' => [
|
||||
'startDate',
|
||||
'endDate',
|
||||
'period',
|
||||
'totalPriceTaxIncluded',
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_history_endpoint_returns_correct_data(): void
|
||||
{
|
||||
$date = Carbon::today();
|
||||
|
||||
$electricityResponse = collect([
|
||||
$this->createElectricityArray($date->copy()->setHour(0), 15.0),
|
||||
$this->createElectricityArray($date->copy()->setHour(1), 16.0),
|
||||
]);
|
||||
|
||||
$gasResponse = collect([
|
||||
$this->createGasArray($date, 5.0),
|
||||
]);
|
||||
|
||||
$client = Mockery::mock(PriceClient::class);
|
||||
$client->shouldReceive('getElectricityPricesForDate')
|
||||
->once()
|
||||
->andReturn($electricityResponse);
|
||||
$client->shouldReceive('getGasPricesForDate')
|
||||
->once()
|
||||
->andReturn($gasResponse);
|
||||
|
||||
$this->app->bind(PriceClient::class, fn () => $client);
|
||||
|
||||
$response = $this->getJson('/api/history?date=' . $date->format('Y-m-d'));
|
||||
|
||||
$response->assertOk();
|
||||
|
||||
$data = $response->json();
|
||||
$this->assertCount(2, $data['electricity']);
|
||||
$this->assertCount(1, $data['gas']);
|
||||
$this->assertEquals(15.0, $data['electricity'][0]['totalPriceTaxIncluded']);
|
||||
$this->assertEquals(5.0, $data['gas'][0]['totalPriceTaxIncluded']);
|
||||
}
|
||||
|
||||
public function test_history_endpoint_defaults_to_today(): void
|
||||
{
|
||||
$client = Mockery::mock(PriceClient::class);
|
||||
$client->shouldReceive('getElectricityPricesForDate')
|
||||
->once()
|
||||
->andReturn(collect());
|
||||
$client->shouldReceive('getGasPricesForDate')
|
||||
->once()
|
||||
->andReturn(collect());
|
||||
|
||||
$this->app->bind(PriceClient::class, fn () => $client);
|
||||
|
||||
$response = $this->getJson('/api/history');
|
||||
|
||||
$response->assertOk();
|
||||
}
|
||||
|
||||
public function test_history_endpoint_handles_empty_data(): void
|
||||
{
|
||||
$date = Carbon::today();
|
||||
|
||||
$client = Mockery::mock(PriceClient::class);
|
||||
$client->shouldReceive('getElectricityPricesForDate')
|
||||
->once()
|
||||
->andReturn(collect());
|
||||
$client->shouldReceive('getGasPricesForDate')
|
||||
->once()
|
||||
->andReturn(collect());
|
||||
|
||||
$this->app->bind(PriceClient::class, fn () => $client);
|
||||
|
||||
$response = $this->getJson('/api/history?date=' . $date->format('Y-m-d'));
|
||||
|
||||
$response->assertOk();
|
||||
|
||||
$data = $response->json();
|
||||
$this->assertEmpty($data['electricity']);
|
||||
$this->assertEmpty($data['gas']);
|
||||
}
|
||||
|
||||
private function createElectricityArray(Carbon $startDate, float $price): array
|
||||
{
|
||||
return [
|
||||
'start_date' => $startDate->format('Y-m-d H:i:s'),
|
||||
'end_date' => $startDate->copy()->addHour()->format('Y-m-d H:i:s'),
|
||||
'period' => 'elec_hour',
|
||||
'market_price' => (int) ($price * 100),
|
||||
'total_price_tax_included' => $price,
|
||||
'price_incl_handling_vat' => (int) ($price * 100),
|
||||
'price_tax_with_vat' => (int) ($price * 20),
|
||||
'pricing_profile' => 'dynamic',
|
||||
'carbon_footprint_in_gram' => 500,
|
||||
'sustainability_score' => 80,
|
||||
'start_date_datetime' => $startDate->format('Y-m-d H:i:s'),
|
||||
];
|
||||
}
|
||||
|
||||
private function createGasArray(Carbon $startDate, float $price): array
|
||||
{
|
||||
return [
|
||||
'start_date' => $startDate->format('Y-m-d H:i:s'),
|
||||
'end_date' => $startDate->copy()->addDay()->format('Y-m-d H:i:s'),
|
||||
'period' => 'gas_day',
|
||||
'market_price' => (int) ($price * 100),
|
||||
'total_price_tax_included' => $price,
|
||||
'price_incl_handling_vat' => (int) ($price * 100),
|
||||
'price_tax_with_vat' => (int) ($price * 20),
|
||||
'start_date_datetime' => $startDate->format('Y-m-d H:i:s'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit\Clients;
|
||||
|
||||
use App\Clients\ZonneplanPriceClient;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Client\Factory;
|
||||
use Illuminate\Http\Client\RequestException;
|
||||
use Illuminate\Http\Response;
|
||||
use Mockery;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ZonneplanPriceClientTest extends TestCase
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Mockery::close();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function test_get_electricity_prices_returns_collection(): void
|
||||
{
|
||||
$response = Mockery::mock();
|
||||
$response->shouldReceive('throw')->once();
|
||||
$response->shouldReceive('json')
|
||||
->once()
|
||||
->with('data', [])
|
||||
->andReturn([
|
||||
['start_date' => Carbon::now()->format('Y-m-d H:i:s'), 'total_price_tax_included' => 15.0],
|
||||
]);
|
||||
$response->shouldReceive('status')->once()->andReturn(200);
|
||||
|
||||
$http = Mockery::mock(Factory::class);
|
||||
$http->shouldReceive('baseUrl')->once()->andReturnSelf();
|
||||
$http->shouldReceive('withQueryParameters')->once()->andReturnSelf();
|
||||
$http->shouldReceive('timeout')->once()->andReturnSelf();
|
||||
$http->shouldReceive('retry')->once()->andReturnSelf();
|
||||
$http->shouldReceive('get')->once()->andReturn($response);
|
||||
|
||||
$client = new ZonneplanPriceClient($http);
|
||||
$result = $client->getElectricityPrices();
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
}
|
||||
|
||||
public function test_get_gas_prices_returns_collection(): void
|
||||
{
|
||||
$response = Mockery::mock();
|
||||
$response->shouldReceive('throw')->once();
|
||||
$response->shouldReceive('json')
|
||||
->once()
|
||||
->with('data', [])
|
||||
->andReturn([
|
||||
['start_date' => Carbon::now()->format('Y-m-d H:i:s'), 'total_price_tax_included' => 5.0],
|
||||
]);
|
||||
$response->shouldReceive('status')->once()->andReturn(200);
|
||||
|
||||
$http = Mockery::mock(Factory::class);
|
||||
$http->shouldReceive('baseUrl')->once()->andReturnSelf();
|
||||
$http->shouldReceive('withQueryParameters')->once()->andReturnSelf();
|
||||
$http->shouldReceive('timeout')->once()->andReturnSelf();
|
||||
$http->shouldReceive('retry')->once()->andReturnSelf();
|
||||
$http->shouldReceive('get')->once()->andReturn($response);
|
||||
|
||||
$client = new ZonneplanPriceClient($http);
|
||||
$result = $client->getGasPrices();
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
}
|
||||
|
||||
public function test_get_electricity_prices_for_date_returns_collection(): void
|
||||
{
|
||||
$date = Carbon::today();
|
||||
$response = Mockery::mock();
|
||||
$response->shouldReceive('throw')->once();
|
||||
$response->shouldReceive('json')
|
||||
->once()
|
||||
->with('data', [])
|
||||
->andReturn([
|
||||
['start_date' => $date->format('Y-m-d H:i:s'), 'total_price_tax_included' => 15.0],
|
||||
]);
|
||||
$response->shouldReceive('status')->once()->andReturn(200);
|
||||
|
||||
$http = Mockery::mock(Factory::class);
|
||||
$http->shouldReceive('baseUrl')->once()->andReturnSelf();
|
||||
$http->shouldReceive('withQueryParameters')->once()->andReturnSelf();
|
||||
$http->shouldReceive('timeout')->once()->andReturnSelf();
|
||||
$http->shouldReceive('retry')->once()->andReturnSelf();
|
||||
$http->shouldReceive('get')->once()->andReturn($response);
|
||||
|
||||
$client = new ZonneplanPriceClient($http);
|
||||
$result = $client->getElectricityPricesForDate($date);
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
}
|
||||
|
||||
public function test_get_gas_prices_for_date_returns_collection(): void
|
||||
{
|
||||
$date = Carbon::today();
|
||||
$response = Mockery::mock();
|
||||
$response->shouldReceive('throw')->once();
|
||||
$response->shouldReceive('json')
|
||||
->once()
|
||||
->with('data', [])
|
||||
->andReturn([
|
||||
['start_date' => $date->format('Y-m-d H:i:s'), 'total_price_tax_included' => 5.0],
|
||||
]);
|
||||
$response->shouldReceive('status')->once()->andReturn(200);
|
||||
|
||||
$http = Mockery::mock(Factory::class);
|
||||
$http->shouldReceive('baseUrl')->once()->andReturnSelf();
|
||||
$http->shouldReceive('withQueryParameters')->once()->andReturnSelf();
|
||||
$http->shouldReceive('timeout')->once()->andReturnSelf();
|
||||
$http->shouldReceive('retry')->once()->andReturnSelf();
|
||||
$http->shouldReceive('get')->once()->andReturn($response);
|
||||
|
||||
$client = new ZonneplanPriceClient($http);
|
||||
$result = $client->getGasPricesForDate($date);
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
}
|
||||
|
||||
public function test_client_throws_exception_on_api_failure(): void
|
||||
{
|
||||
$this->expectException(\Exception::class);
|
||||
$this->expectExceptionMessage('Kon energieprijzen niet ophalen');
|
||||
|
||||
$response = Mockery::mock();
|
||||
$response->shouldReceive('throw')->once()->andThrow(
|
||||
new \Illuminate\Http\Client\ConnectionException('API Error')
|
||||
);
|
||||
|
||||
$http = Mockery::mock(Factory::class);
|
||||
$http->shouldReceive('baseUrl')->once()->andReturnSelf();
|
||||
$http->shouldReceive('withQueryParameters')->once()->andReturnSelf();
|
||||
$http->shouldReceive('timeout')->once()->andReturnSelf();
|
||||
$http->shouldReceive('retry')->once()->andReturnSelf();
|
||||
$http->shouldReceive('get')->once()->andReturn($response);
|
||||
|
||||
$client = new ZonneplanPriceClient($http);
|
||||
$client->getElectricityPrices();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit\Repositories;
|
||||
|
||||
use App\Contracts\PriceClient;
|
||||
use App\Data\ElectricityData;
|
||||
use App\Data\GasData;
|
||||
use App\Repositories\ZonneplanPriceRepository;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Mockery;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ZonneplanPriceRepositoryTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
config(['cache_prices.ttl' => 60]);
|
||||
config(['cache_prices.prefix' => 'test:']);
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Mockery::close();
|
||||
Cache::flush();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function test_retrieve_electricity_returns_collection_of_electricity_data(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$electricityResponse = collect([
|
||||
[
|
||||
'start_date' => $now->format('Y-m-d H:i:s'),
|
||||
'end_date' => $now->copy()->addHour()->format('Y-m-d H:i:s'),
|
||||
'period' => 'elec_hour',
|
||||
'market_price' => 1500,
|
||||
'total_price_tax_included' => 15.50,
|
||||
'price_incl_handling_vat' => 1550,
|
||||
'price_tax_with_vat' => 300,
|
||||
'pricing_profile' => 'dynamic',
|
||||
'carbon_footprint_in_gram' => 500,
|
||||
'sustainability_score' => 80,
|
||||
'start_date_datetime' => $now->format('Y-m-d H:i:s'),
|
||||
],
|
||||
]);
|
||||
|
||||
$client = Mockery::mock(PriceClient::class);
|
||||
$client->shouldReceive('getElectricityPrices')
|
||||
->once()
|
||||
->andReturn($electricityResponse);
|
||||
|
||||
$repository = new ZonneplanPriceRepository($client);
|
||||
$result = $repository->retrieveElectricity();
|
||||
|
||||
$this->assertInstanceOf(Collection::class, $result);
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertInstanceOf(ElectricityData::class, $result->first());
|
||||
}
|
||||
|
||||
public function test_retrieve_gas_returns_collection_of_gas_data(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$gasResponse = collect([
|
||||
[
|
||||
'start_date' => $now->format('Y-m-d H:i:s'),
|
||||
'end_date' => $now->copy()->addDay()->format('Y-m-d H:i:s'),
|
||||
'period' => 'gas_day',
|
||||
'market_price' => 500,
|
||||
'total_price_tax_included' => 5.50,
|
||||
'price_incl_handling_vat' => 550,
|
||||
'price_tax_with_vat' => 100,
|
||||
'start_date_datetime' => $now->format('Y-m-d H:i:s'),
|
||||
],
|
||||
]);
|
||||
|
||||
$client = Mockery::mock(PriceClient::class);
|
||||
$client->shouldReceive('getGasPrices')
|
||||
->once()
|
||||
->andReturn($gasResponse);
|
||||
|
||||
$repository = new ZonneplanPriceRepository($client);
|
||||
$result = $repository->retrieveGas();
|
||||
|
||||
$this->assertInstanceOf(Collection::class, $result);
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertInstanceOf(GasData::class, $result->first());
|
||||
}
|
||||
|
||||
public function test_retrieve_electricity_for_date_returns_collection(): void
|
||||
{
|
||||
$date = Carbon::today();
|
||||
$electricityResponse = collect([
|
||||
[
|
||||
'start_date' => $date->copy()->setHour(0)->format('Y-m-d H:i:s'),
|
||||
'end_date' => $date->copy()->setHour(1)->format('Y-m-d H:i:s'),
|
||||
'period' => 'elec_hour',
|
||||
'market_price' => 1500,
|
||||
'total_price_tax_included' => 15.50,
|
||||
'price_incl_handling_vat' => 1550,
|
||||
'price_tax_with_vat' => 300,
|
||||
'pricing_profile' => 'dynamic',
|
||||
'carbon_footprint_in_gram' => 500,
|
||||
'sustainability_score' => 80,
|
||||
'start_date_datetime' => $date->copy()->setHour(0)->format('Y-m-d H:i:s'),
|
||||
],
|
||||
]);
|
||||
|
||||
$client = Mockery::mock(PriceClient::class);
|
||||
$client->shouldReceive('getElectricityPricesForDate')
|
||||
->once()
|
||||
->with($date)
|
||||
->andReturn($electricityResponse);
|
||||
|
||||
$repository = new ZonneplanPriceRepository($client);
|
||||
$result = $repository->retrieveElectricityForDate($date);
|
||||
|
||||
$this->assertInstanceOf(Collection::class, $result);
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertInstanceOf(ElectricityData::class, $result->first());
|
||||
}
|
||||
|
||||
public function test_retrieve_gas_for_date_returns_collection(): void
|
||||
{
|
||||
$date = Carbon::today();
|
||||
$gasResponse = collect([
|
||||
[
|
||||
'start_date' => $date->format('Y-m-d H:i:s'),
|
||||
'end_date' => $date->copy()->addDay()->format('Y-m-d H:i:s'),
|
||||
'period' => 'gas_day',
|
||||
'market_price' => 500,
|
||||
'total_price_tax_included' => 5.50,
|
||||
'price_incl_handling_vat' => 550,
|
||||
'price_tax_with_vat' => 100,
|
||||
'start_date_datetime' => $date->format('Y-m-d H:i:s'),
|
||||
],
|
||||
]);
|
||||
|
||||
$client = Mockery::mock(PriceClient::class);
|
||||
$client->shouldReceive('getGasPricesForDate')
|
||||
->once()
|
||||
->with($date)
|
||||
->andReturn($gasResponse);
|
||||
|
||||
$repository = new ZonneplanPriceRepository($client);
|
||||
$result = $repository->retrieveGasForDate($date);
|
||||
|
||||
$this->assertInstanceOf(Collection::class, $result);
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertInstanceOf(GasData::class, $result->first());
|
||||
}
|
||||
|
||||
public function test_retrieve_electricity_caches_result(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$electricityResponse = collect([
|
||||
[
|
||||
'start_date' => $now->format('Y-m-d H:i:s'),
|
||||
'end_date' => $now->copy()->addHour()->format('Y-m-d H:i:s'),
|
||||
'period' => 'elec_hour',
|
||||
'market_price' => 1500,
|
||||
'total_price_tax_included' => 15.50,
|
||||
'price_incl_handling_vat' => 1550,
|
||||
'price_tax_with_vat' => 300,
|
||||
'pricing_profile' => 'dynamic',
|
||||
'carbon_footprint_in_gram' => 500,
|
||||
'sustainability_score' => 80,
|
||||
'start_date_datetime' => $now->format('Y-m-d H:i:s'),
|
||||
],
|
||||
]);
|
||||
|
||||
$client = Mockery::mock(PriceClient::class);
|
||||
$client->shouldReceive('getElectricityPrices')
|
||||
->once()
|
||||
->andReturn($electricityResponse);
|
||||
|
||||
$repository = new ZonneplanPriceRepository($client);
|
||||
|
||||
$result1 = $repository->retrieveElectricity();
|
||||
$result2 = $repository->retrieveElectricity();
|
||||
|
||||
$this->assertEquals(
|
||||
$result1->first()->totalPriceTaxIncluded,
|
||||
$result2->first()->totalPriceTaxIncluded
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit\Services;
|
||||
|
||||
use App\Contracts\PriceRepository;
|
||||
use App\Data\ElectricityData;
|
||||
use App\Data\GasData;
|
||||
use App\Features\Dashboard\Services\DashboardService;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use Mockery;
|
||||
use Tests\TestCase;
|
||||
|
||||
class DashboardServiceTest extends TestCase
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Mockery::close();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function test_get_dashboard_data_returns_current_cheapest_sustainable_and_expensive_prices(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
|
||||
$electricityData = collect([
|
||||
$this->createElectricityData($now->copy()->subMinutes(30), 15.0, 80),
|
||||
$this->createElectricityData($now->copy()->addHour(), 12.0, 90),
|
||||
$this->createElectricityData($now->copy()->addHours(2), 20.0, 60),
|
||||
$this->createElectricityData($now->copy()->addHours(3), 10.0, 95),
|
||||
]);
|
||||
|
||||
$gasData = collect([
|
||||
$this->createGasData($now->copy()->startOfDay(), 5.0),
|
||||
$this->createGasData($now->copy()->addDay(), 4.0),
|
||||
$this->createGasData($now->copy()->addDays(2), 6.0),
|
||||
]);
|
||||
|
||||
$repository = Mockery::mock(PriceRepository::class);
|
||||
$repository->shouldReceive('retrieveElectricity')->once()->andReturn($electricityData);
|
||||
$repository->shouldReceive('retrieveGas')->once()->andReturn($gasData);
|
||||
|
||||
$service = new DashboardService($repository);
|
||||
$result = $service->getDashboardData();
|
||||
|
||||
$this->assertEquals(15.0, $result->electricity->totalPriceTaxIncluded);
|
||||
$this->assertEquals(10.0, $result->electricityCheapest->totalPriceTaxIncluded);
|
||||
$this->assertEquals(95, $result->electricityDurable->sustainabilityScore);
|
||||
$this->assertEquals(20.0, $result->electricityPriciest->totalPriceTaxIncluded);
|
||||
|
||||
$this->assertEquals(5.0, $result->gas->totalPriceTaxIncluded);
|
||||
$this->assertEquals(4.0, $result->gasCheapest->totalPriceTaxIncluded);
|
||||
$this->assertEquals(6.0, $result->gasPriciest->totalPriceTaxIncluded);
|
||||
}
|
||||
|
||||
public function test_get_dashboard_data_returns_null_for_missing_current_price(): void
|
||||
{
|
||||
$now = Carbon::now();
|
||||
|
||||
$electricityData = collect([
|
||||
$this->createElectricityData($now->copy()->addHours(5), 15.0, 80),
|
||||
]);
|
||||
|
||||
$gasData = collect([
|
||||
$this->createGasData($now->copy()->addDays(5), 5.0),
|
||||
]);
|
||||
|
||||
$repository = Mockery::mock(PriceRepository::class);
|
||||
$repository->shouldReceive('retrieveElectricity')->once()->andReturn($electricityData);
|
||||
$repository->shouldReceive('retrieveGas')->once()->andReturn($gasData);
|
||||
|
||||
$service = new DashboardService($repository);
|
||||
$result = $service->getDashboardData();
|
||||
|
||||
$this->assertNull($result->electricity);
|
||||
$this->assertNull($result->gas);
|
||||
$this->assertNotNull($result->electricityCheapest);
|
||||
$this->assertNotNull($result->gasCheapest);
|
||||
}
|
||||
|
||||
public function test_get_dashboard_data_with_empty_collections(): void
|
||||
{
|
||||
$repository = Mockery::mock(PriceRepository::class);
|
||||
$repository->shouldReceive('retrieveElectricity')->once()->andReturn(collect());
|
||||
$repository->shouldReceive('retrieveGas')->once()->andReturn(collect());
|
||||
|
||||
$service = new DashboardService($repository);
|
||||
$result = $service->getDashboardData();
|
||||
|
||||
$this->assertNull($result->electricity);
|
||||
$this->assertNull($result->electricityCheapest);
|
||||
$this->assertNull($result->electricityDurable);
|
||||
$this->assertNull($result->electricityPriciest);
|
||||
$this->assertNull($result->gas);
|
||||
$this->assertNull($result->gasCheapest);
|
||||
$this->assertNull($result->gasPriciest);
|
||||
}
|
||||
|
||||
private function createElectricityData(Carbon $startDate, float $price, int $sustainabilityScore): ElectricityData
|
||||
{
|
||||
return new ElectricityData(
|
||||
startDate: $startDate,
|
||||
endDate: $startDate->copy()->addHour(),
|
||||
period: 'elec_hour',
|
||||
marketPrice: (int) ($price * 100),
|
||||
totalPriceTaxIncluded: $price,
|
||||
priceInclHandlingVat: (int) ($price * 100),
|
||||
priceTaxWithVat: (int) ($price * 20),
|
||||
pricingProfile: 'dynamic',
|
||||
carbonFootprintInGram: 500,
|
||||
sustainabilityScore: $sustainabilityScore,
|
||||
startDateDatetime: $startDate,
|
||||
);
|
||||
}
|
||||
|
||||
private function createGasData(Carbon $startDate, float $price): GasData
|
||||
{
|
||||
return new GasData(
|
||||
startDate: $startDate,
|
||||
endDate: $startDate->copy()->addDay(),
|
||||
period: 'gas_day',
|
||||
marketPrice: (int) ($price * 100),
|
||||
totalPriceTaxIncluded: $price,
|
||||
priceInclHandlingVat: (int) ($price * 100),
|
||||
priceTaxWithVat: (int) ($price * 20),
|
||||
startDateDatetime: $startDate,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit\Services;
|
||||
|
||||
use App\Contracts\PriceRepository;
|
||||
use App\Data\ElectricityData;
|
||||
use App\Data\GasData;
|
||||
use App\Features\History\Services\HistoryService;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use Mockery;
|
||||
use Tests\TestCase;
|
||||
|
||||
class HistoryServiceTest extends TestCase
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Mockery::close();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function test_get_history_data_returns_electricity_and_gas_for_date(): void
|
||||
{
|
||||
$date = Carbon::today();
|
||||
|
||||
$electricityData = collect([
|
||||
$this->createElectricityData($date->copy()->setHour(0), 15.0),
|
||||
$this->createElectricityData($date->copy()->setHour(1), 16.0),
|
||||
]);
|
||||
|
||||
$gasData = collect([
|
||||
$this->createGasData($date, 5.0),
|
||||
]);
|
||||
|
||||
$repository = Mockery::mock(PriceRepository::class);
|
||||
$repository->shouldReceive('retrieveElectricityForDate')
|
||||
->once()
|
||||
->with($date)
|
||||
->andReturn($electricityData);
|
||||
$repository->shouldReceive('retrieveGasForDate')
|
||||
->once()
|
||||
->with($date)
|
||||
->andReturn($gasData);
|
||||
|
||||
$service = new HistoryService($repository);
|
||||
$result = $service->getHistoryData($date);
|
||||
|
||||
$this->assertCount(2, $result->electricity);
|
||||
$this->assertCount(1, $result->gas);
|
||||
$this->assertEquals(15.0, $result->electricity->first()->totalPriceTaxIncluded);
|
||||
$this->assertEquals(5.0, $result->gas->first()->totalPriceTaxIncluded);
|
||||
}
|
||||
|
||||
public function test_get_history_data_with_empty_collections(): void
|
||||
{
|
||||
$date = Carbon::today();
|
||||
|
||||
$repository = Mockery::mock(PriceRepository::class);
|
||||
$repository->shouldReceive('retrieveElectricityForDate')
|
||||
->once()
|
||||
->andReturn(collect());
|
||||
$repository->shouldReceive('retrieveGasForDate')
|
||||
->once()
|
||||
->andReturn(collect());
|
||||
|
||||
$service = new HistoryService($repository);
|
||||
$result = $service->getHistoryData($date);
|
||||
|
||||
$this->assertCount(0, $result->electricity);
|
||||
$this->assertCount(0, $result->gas);
|
||||
}
|
||||
|
||||
private function createElectricityData(Carbon $startDate, float $price): ElectricityData
|
||||
{
|
||||
return new ElectricityData(
|
||||
startDate: $startDate,
|
||||
endDate: $startDate->copy()->addHour(),
|
||||
period: 'elec_hour',
|
||||
marketPrice: (int) ($price * 100),
|
||||
totalPriceTaxIncluded: $price,
|
||||
priceInclHandlingVat: (int) ($price * 100),
|
||||
priceTaxWithVat: (int) ($price * 20),
|
||||
pricingProfile: 'dynamic',
|
||||
carbonFootprintInGram: 500,
|
||||
sustainabilityScore: 80,
|
||||
startDateDatetime: $startDate,
|
||||
);
|
||||
}
|
||||
|
||||
private function createGasData(Carbon $startDate, float $price): GasData
|
||||
{
|
||||
return new GasData(
|
||||
startDate: $startDate,
|
||||
endDate: $startDate->copy()->addDay(),
|
||||
period: 'gas_day',
|
||||
marketPrice: (int) ($price * 100),
|
||||
totalPriceTaxIncluded: $price,
|
||||
priceInclHandlingVat: (int) ($price * 100),
|
||||
priceTaxWithVat: (int) ($price * 20),
|
||||
startDateDatetime: $startDate,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user