From 568a488ae76c631714547614f52ca6be7a121e2d Mon Sep 17 00:00:00 2001 From: nala Date: Thu, 29 Oct 2026 13:33:10 +0200 Subject: [PATCH] fix(clusters): normalize persisted portable analysis version --- app/Services/ClusterCompetitiveness.php | 1 + tests/Feature/ClusterCompetitivenessTest.php | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/app/Services/ClusterCompetitiveness.php b/app/Services/ClusterCompetitiveness.php index 521e80ba..44ac5916 100644 --- a/app/Services/ClusterCompetitiveness.php +++ b/app/Services/ClusterCompetitiveness.php @@ -57,6 +57,7 @@ final class ClusterCompetitiveness } } $clean = Validator::make($draft, $rules)->validate(); + $clean['version'] = 1; $clean['sector'] = trim($clean['sector'] ?? ''); $clean['region'] = trim($clean['region'] ?? ''); foreach (self::FORCES as $force) { diff --git a/tests/Feature/ClusterCompetitivenessTest.php b/tests/Feature/ClusterCompetitivenessTest.php index 76e548d6..e7b30483 100644 --- a/tests/Feature/ClusterCompetitivenessTest.php +++ b/tests/Feature/ClusterCompetitivenessTest.php @@ -121,6 +121,19 @@ class ClusterCompetitivenessTest extends TestCase $this->getJson($this->url($cluster))->assertJsonPath('version', 1)->assertJsonPath('draft.forces.buyers.source', ''); } + public function test_saved_data_keeps_the_portable_file_contract_and_rejects_missing_forces(): void + { + $this->manager(); + $cluster = $this->cluster(); + $draft = $this->draft($cluster); + $draft['version'] = '1'; + $this->postJson($this->url($cluster).'/saved', ['expected_version' => 0, 'draft' => $draft]) + ->assertOk()->assertJsonPath('draft.version', 1); + unset($draft['forces']['suppliers']); + $this->postJson($this->url($cluster).'/saved', ['expected_version' => 1, 'draft' => $draft])->assertUnprocessable(); + $this->getJson($this->url($cluster))->assertJsonPath('version', 1); + } + public function test_anonymous_and_unauthorised_users_cannot_read_history_or_mutate(): void { $cluster = $this->cluster();