increments('project_id'); $table->unsignedTinyInteger('active')->default(1); $table->json('categories')->nullable(); $table->text('category_notes')->nullable(); $table->text('structure')->nullable(); $table->timestamps(); }); Schema::create('projects_description', function (Blueprint $table) { $table->id(); $table->unsignedInteger('project_id'); $table->char('iso', 3); $table->string('headline')->nullable(); }); }); it('keeps existing categories when the settings panel is not submitted', function () { DB::table('projects')->insert([ 'project_id' => 18, 'active' => 1, 'categories' => json_encode(['1', '2']), 'category_notes' => json_encode(['1' => 'Existing note']), 'structure' => null, 'created_at' => now(), 'updated_at' => now(), ]); DB::table('projects_description')->insert([ 'project_id' => 18, 'iso' => 'sl', 'headline' => 'Before', ]); try { app(ProductsController::class)->update(18, Request::create('/cp/projects/edit/18', 'POST', [ 'active' => '1', 'categories_touched' => '0', ])); } catch (\Throwable) { // The admin redirect route is not loaded in this isolated feature test. } expect(DB::table('projects')->where('project_id', 18)->value('categories'))->toBe(json_encode(['1', '2'])); expect(DB::table('projects')->where('project_id', 18)->value('category_notes'))->toBe(json_encode(['1' => 'Existing note'])); }); it('clears categories when the settings panel is submitted without any selected categories', function () { DB::table('projects')->insert([ 'project_id' => 18, 'active' => 1, 'categories' => json_encode(['1', '2']), 'category_notes' => json_encode(['1' => 'Existing note']), 'structure' => null, 'created_at' => now(), 'updated_at' => now(), ]); DB::table('projects_description')->insert([ 'project_id' => 18, 'iso' => 'sl', 'headline' => 'Before', ]); try { app(ProductsController::class)->update(18, Request::create('/cp/projects/edit/18', 'POST', [ 'active' => '1', 'categories_touched' => '1', ])); } catch (\Throwable) { // The admin redirect route is not loaded in this isolated feature test. } expect(DB::table('projects')->where('project_id', 18)->value('categories'))->toBe(json_encode([])); expect(DB::table('projects')->where('project_id', 18)->value('category_notes'))->toBe(json_encode(['1' => 'Existing note'])); }); it('deduplicates categories when the settings panel submits repeated values', function () { DB::table('projects')->insert([ 'project_id' => 18, 'active' => 1, 'categories' => json_encode(['1']), 'category_notes' => null, 'structure' => null, 'created_at' => now(), 'updated_at' => now(), ]); DB::table('projects_description')->insert([ 'project_id' => 18, 'iso' => 'sl', 'headline' => 'Before', ]); try { app(ProductsController::class)->update(18, Request::create('/cp/projects/edit/18', 'POST', [ 'active' => '1', 'categories_touched' => '1', 'categories' => ['4', '4', '2', '2'], ])); } catch (\Throwable) { // The admin redirect route is not loaded in this isolated feature test. } expect(DB::table('projects')->where('project_id', 18)->value('categories'))->toBe(json_encode(['4', '2'])); });