mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-15 19:52:15 +01:00
Allow NONE filter value to shared reports and add shared-report tests
This commit is contained in:
@@ -16,6 +16,7 @@ use App\Models\Task;
|
||||
use App\Models\TimeEntry;
|
||||
use App\Service\CurrencyService;
|
||||
use App\Service\Dto\ReportPropertiesDto;
|
||||
use App\Service\TimeEntryFilter;
|
||||
use Illuminate\Support\Str;
|
||||
use Tests\Unit\Endpoint\Api\V1\ApiEndpointTestAbstract;
|
||||
|
||||
@@ -423,4 +424,244 @@ class PublicReportEndpointTest extends ApiEndpointTestAbstract
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_show_returns_only_entries_without_project_when_none_project_filter_is_set(): void
|
||||
{
|
||||
// Arrange
|
||||
$organization = Organization::factory()->create();
|
||||
$project = Project::factory()->forOrganization($organization)->create();
|
||||
|
||||
// Entry with project (should be excluded)
|
||||
TimeEntry::factory()->forOrganization($organization)
|
||||
->forProject($project)
|
||||
->startWithDuration(now()->subDay(), 100)
|
||||
->create();
|
||||
// Entry without project (should be included)
|
||||
TimeEntry::factory()->forOrganization($organization)
|
||||
->startWithDuration(now()->subDay(), 200)
|
||||
->create();
|
||||
|
||||
$reportDto = new ReportPropertiesDto;
|
||||
$reportDto->start = now()->subDays(2);
|
||||
$reportDto->end = now();
|
||||
$reportDto->group = TimeEntryAggregationType::Project;
|
||||
$reportDto->subGroup = TimeEntryAggregationType::Task;
|
||||
$reportDto->historyGroup = TimeEntryAggregationTypeInterval::Day;
|
||||
$reportDto->weekStart = Weekday::Monday;
|
||||
$reportDto->timezone = 'Europe/Vienna';
|
||||
$reportDto->setProjectIds([TimeEntryFilter::NONE_VALUE]);
|
||||
$report = Report::factory()->forOrganization($organization)->public()->create([
|
||||
'public_until' => null,
|
||||
'properties' => $reportDto,
|
||||
]);
|
||||
|
||||
// Act
|
||||
$response = $this->getJson(route('api.v1.public.reports.show'), [
|
||||
'X-Api-Key' => $report->share_secret,
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$response->assertOk();
|
||||
$response->assertJson([
|
||||
'data' => [
|
||||
'seconds' => 200,
|
||||
'cost' => 0,
|
||||
'grouped_type' => TimeEntryAggregationType::Project->value,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_show_returns_entries_with_and_without_project_when_none_and_real_id_combined(): void
|
||||
{
|
||||
// Arrange
|
||||
$organization = Organization::factory()->create();
|
||||
$projectA = Project::factory()->forOrganization($organization)->create();
|
||||
$projectB = Project::factory()->forOrganization($organization)->create();
|
||||
|
||||
// Entry with project A (should be included)
|
||||
TimeEntry::factory()->forOrganization($organization)
|
||||
->forProject($projectA)
|
||||
->startWithDuration(now()->subDay(), 100)
|
||||
->create();
|
||||
// Entry with project B (should be excluded)
|
||||
TimeEntry::factory()->forOrganization($organization)
|
||||
->forProject($projectB)
|
||||
->startWithDuration(now()->subDay(), 100)
|
||||
->create();
|
||||
// Entry without project (should be included)
|
||||
TimeEntry::factory()->forOrganization($organization)
|
||||
->startWithDuration(now()->subDay(), 200)
|
||||
->create();
|
||||
|
||||
$reportDto = new ReportPropertiesDto;
|
||||
$reportDto->start = now()->subDays(2);
|
||||
$reportDto->end = now();
|
||||
$reportDto->group = TimeEntryAggregationType::Project;
|
||||
$reportDto->subGroup = TimeEntryAggregationType::Task;
|
||||
$reportDto->historyGroup = TimeEntryAggregationTypeInterval::Day;
|
||||
$reportDto->weekStart = Weekday::Monday;
|
||||
$reportDto->timezone = 'Europe/Vienna';
|
||||
$reportDto->setProjectIds([$projectA->getKey(), TimeEntryFilter::NONE_VALUE]);
|
||||
$report = Report::factory()->forOrganization($organization)->public()->create([
|
||||
'public_until' => null,
|
||||
'properties' => $reportDto,
|
||||
]);
|
||||
|
||||
// Act
|
||||
$response = $this->getJson(route('api.v1.public.reports.show'), [
|
||||
'X-Api-Key' => $report->share_secret,
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$response->assertOk();
|
||||
$response->assertJson([
|
||||
'data' => [
|
||||
'seconds' => 300,
|
||||
'cost' => 0,
|
||||
'grouped_type' => TimeEntryAggregationType::Project->value,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_show_returns_only_entries_without_task_when_none_task_filter_is_set(): void
|
||||
{
|
||||
// Arrange
|
||||
$organization = Organization::factory()->create();
|
||||
$project = Project::factory()->forOrganization($organization)->create();
|
||||
$task = Task::factory()->forOrganization($organization)->forProject($project)->create();
|
||||
|
||||
// Entry with task (should be excluded)
|
||||
TimeEntry::factory()->forOrganization($organization)
|
||||
->forTask($task)
|
||||
->startWithDuration(now()->subDay(), 100)
|
||||
->create();
|
||||
// Entry without task (should be included)
|
||||
TimeEntry::factory()->forOrganization($organization)
|
||||
->forProject($project)
|
||||
->startWithDuration(now()->subDay(), 200)
|
||||
->create();
|
||||
|
||||
$reportDto = new ReportPropertiesDto;
|
||||
$reportDto->start = now()->subDays(2);
|
||||
$reportDto->end = now();
|
||||
$reportDto->group = TimeEntryAggregationType::Project;
|
||||
$reportDto->subGroup = TimeEntryAggregationType::Task;
|
||||
$reportDto->historyGroup = TimeEntryAggregationTypeInterval::Day;
|
||||
$reportDto->weekStart = Weekday::Monday;
|
||||
$reportDto->timezone = 'Europe/Vienna';
|
||||
$reportDto->setTaskIds([TimeEntryFilter::NONE_VALUE]);
|
||||
$report = Report::factory()->forOrganization($organization)->public()->create([
|
||||
'public_until' => null,
|
||||
'properties' => $reportDto,
|
||||
]);
|
||||
|
||||
// Act
|
||||
$response = $this->getJson(route('api.v1.public.reports.show'), [
|
||||
'X-Api-Key' => $report->share_secret,
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$response->assertOk();
|
||||
$response->assertJson([
|
||||
'data' => [
|
||||
'seconds' => 200,
|
||||
'cost' => 0,
|
||||
'grouped_type' => TimeEntryAggregationType::Project->value,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_show_returns_only_entries_without_client_when_none_client_filter_is_set(): void
|
||||
{
|
||||
// Arrange
|
||||
$organization = Organization::factory()->create();
|
||||
$client = Client::factory()->forOrganization($organization)->create();
|
||||
$projectWithClient = Project::factory()->forClient($client)->forOrganization($organization)->create();
|
||||
|
||||
// Entry with client (should be excluded)
|
||||
TimeEntry::factory()->forOrganization($organization)
|
||||
->forProject($projectWithClient)
|
||||
->startWithDuration(now()->subDay(), 100)
|
||||
->create();
|
||||
// Entry without client (should be included)
|
||||
TimeEntry::factory()->forOrganization($organization)
|
||||
->startWithDuration(now()->subDay(), 200)
|
||||
->create();
|
||||
|
||||
$reportDto = new ReportPropertiesDto;
|
||||
$reportDto->start = now()->subDays(2);
|
||||
$reportDto->end = now();
|
||||
$reportDto->group = TimeEntryAggregationType::Project;
|
||||
$reportDto->subGroup = TimeEntryAggregationType::Task;
|
||||
$reportDto->historyGroup = TimeEntryAggregationTypeInterval::Day;
|
||||
$reportDto->weekStart = Weekday::Monday;
|
||||
$reportDto->timezone = 'Europe/Vienna';
|
||||
$reportDto->setClientIds([TimeEntryFilter::NONE_VALUE]);
|
||||
$report = Report::factory()->forOrganization($organization)->public()->create([
|
||||
'public_until' => null,
|
||||
'properties' => $reportDto,
|
||||
]);
|
||||
|
||||
// Act
|
||||
$response = $this->getJson(route('api.v1.public.reports.show'), [
|
||||
'X-Api-Key' => $report->share_secret,
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$response->assertOk();
|
||||
$response->assertJson([
|
||||
'data' => [
|
||||
'seconds' => 200,
|
||||
'cost' => 0,
|
||||
'grouped_type' => TimeEntryAggregationType::Project->value,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_show_returns_only_entries_without_tags_when_none_tag_filter_is_set(): void
|
||||
{
|
||||
// Arrange
|
||||
$organization = Organization::factory()->create();
|
||||
$tag = Tag::factory()->forOrganization($organization)->create();
|
||||
|
||||
// Entry with tag (should be excluded)
|
||||
TimeEntry::factory()->forOrganization($organization)
|
||||
->startWithDuration(now()->subDay(), 100)
|
||||
->create([
|
||||
'tags' => [$tag->getKey()],
|
||||
]);
|
||||
// Entry without tags (should be included)
|
||||
TimeEntry::factory()->forOrganization($organization)
|
||||
->startWithDuration(now()->subDay(), 200)
|
||||
->create();
|
||||
|
||||
$reportDto = new ReportPropertiesDto;
|
||||
$reportDto->start = now()->subDays(2);
|
||||
$reportDto->end = now();
|
||||
$reportDto->group = TimeEntryAggregationType::Project;
|
||||
$reportDto->subGroup = TimeEntryAggregationType::Task;
|
||||
$reportDto->historyGroup = TimeEntryAggregationTypeInterval::Day;
|
||||
$reportDto->weekStart = Weekday::Monday;
|
||||
$reportDto->timezone = 'Europe/Vienna';
|
||||
$reportDto->setTagIds([TimeEntryFilter::NONE_VALUE]);
|
||||
$report = Report::factory()->forOrganization($organization)->public()->create([
|
||||
'public_until' => null,
|
||||
'properties' => $reportDto,
|
||||
]);
|
||||
|
||||
// Act
|
||||
$response = $this->getJson(route('api.v1.public.reports.show'), [
|
||||
'X-Api-Key' => $report->share_secret,
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$response->assertOk();
|
||||
$response->assertJson([
|
||||
'data' => [
|
||||
'seconds' => 200,
|
||||
'cost' => 0,
|
||||
'grouped_type' => TimeEntryAggregationType::Project->value,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user