|
|
@@ -66,6 +66,7 @@ class ActivityCatalogTest extends TestCase
|
|
|
(require dirname(__DIR__, 2) . '/database/migrations/2026_10_13_120000_add_activity_eligibility_fields.php')->up();
|
|
|
(require dirname(__DIR__, 2) . '/database/migrations/2026_10_14_120000_add_activity_reward_quotas.php')->up();
|
|
|
$this->migration()->up();
|
|
|
+ (require dirname(__DIR__, 2) . '/database/migrations/2026_10_28_120000_add_activity_click_behavior.php')->up();
|
|
|
$this->request('');
|
|
|
}
|
|
|
|
|
|
@@ -161,6 +162,46 @@ class ActivityCatalogTest extends TestCase
|
|
|
$this->assertSame(0, DB::table('activity_reward_recipients')->count());
|
|
|
}
|
|
|
|
|
|
+ public function test_activity_click_behavior_saves_preserves_and_clears_for_normal_and_type_two_activities(): void
|
|
|
+ {
|
|
|
+ $this->request('options');
|
|
|
+ $this->assertSame(\App\Support\AnnouncementCatalog::options(\App\Support\AnnouncementCatalog::CLICKS),
|
|
|
+ (new AdminActivityReward())->options()->getData(true)['data']['click_types']);
|
|
|
+ foreach ([2, 3] as $type) {
|
|
|
+ $body = $this->save(['type' => $type]);
|
|
|
+ $this->assertSame(HttpStatus::OK, $body['code']);
|
|
|
+ $id = (int) DB::table('activity_rewards')->latest('id')->value('id');
|
|
|
+ $this->assertSame('none', DB::table('activity_rewards')->where('id', $id)->value('click_type'));
|
|
|
+ foreach (['external' => 'https://example.com/promotion?from=activity', 'internal' => '/promotion/detail?id=3'] as $mode => $link) {
|
|
|
+ $body = $this->save(['id' => $id, 'type' => $type, 'click_type' => $mode, 'link' => $link]);
|
|
|
+ $this->assertSame(HttpStatus::OK, $body['code'], $body['msg']);
|
|
|
+ $this->assertSame(HttpStatus::OK, $this->save(['id' => $id, 'type' => $type, 'title' => '只改标题'])['code']);
|
|
|
+ $row = collect($this->listing()['data'])->keyBy('id')->get($id);
|
|
|
+ $this->assertSame($mode, $row['click_type']); $this->assertSame($link, $row['link']); $this->assertTrue($row['can_jump']);
|
|
|
+ }
|
|
|
+ $this->assertSame(HttpStatus::OK, $this->save(['id' => $id, 'type' => $type, 'click_type' => 'none', 'link' => ['unused']])['code']);
|
|
|
+ $row = ActivityReward::findOrFail($id)->toArray();
|
|
|
+ $this->assertSame('none', $row['click_type']); $this->assertNull($row['link']); $this->assertFalse($row['can_jump']);
|
|
|
+ $this->assertNull(DB::table('activity_rewards')->where('id', $id)->value('link'));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_invalid_activity_links_do_not_modify_the_activity(): void
|
|
|
+ {
|
|
|
+ $this->save(['click_type' => 'internal', 'link' => '/original']);
|
|
|
+ $id = (int) DB::table('activity_rewards')->value('id');
|
|
|
+ $before = DB::table('activity_rewards')->where('id', $id)->first();
|
|
|
+ foreach ([['click_type' => 'activity'], ['click_type' => null], ['click_type' => ['none']],
|
|
|
+ ['click_type' => 'external', 'link' => null], ['click_type' => 'external', 'link' => 'javascript:alert(1)'],
|
|
|
+ ['click_type' => 'external', 'link' => 'https://user:pass@example.com'], ['click_type' => 'external', 'link' => '/relative'],
|
|
|
+ ['click_type' => 'internal', 'link' => '//example.com'], ['click_type' => 'internal', 'link' => '/\\evil'],
|
|
|
+ ['click_type' => 'internal', 'link' => 'https://example.com'], ['click_type' => 'external', 'link' => ['bad']]] as $values) {
|
|
|
+ $body = $this->save(['id' => $id] + $values);
|
|
|
+ $this->assertSame(HttpStatus::CUSTOM_ERROR, $body['code']);
|
|
|
+ $this->assertEquals($before, DB::table('activity_rewards')->where('id', $id)->first());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public function test_new_omission_is_null_edit_omission_preserves_category_and_explicit_values_clear_it(): void
|
|
|
{
|
|
|
$result = $this->save();
|