the browser-facing portion of osu!
1<?php
2
3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
4// See the LICENCE file in the repository root for full licence text.
5
6namespace Tests\Singletons;
7
8use App\Exceptions\ContentModerationException;
9use App\Models\ChatFilter;
10use Tests\TestCase;
11
12class ChatFiltersTest extends TestCase
13{
14 public static function plainFilterTests()
15 {
16 return [
17 ['bad phrase', 'good phrase'],
18 ['WHAT HAPPENS IF I SAY BAD THING IN CAPS', 'WHAT HAPPENS IF I SAY good THING IN CAPS'],
19 ['thing is bad', 'thing is good'],
20 ['look at this badness', 'look at this goodness'],
21 ];
22 }
23
24 public static function fullWordFilterTests()
25 {
26 return [
27 ['fullword at the start', 'okay at the start'],
28 ['FULLWORD IN CAPS!!', 'okay IN CAPS!!'],
29 ['at the end is fullword', 'at the end is okay'],
30 ['middle is where the fullword is', 'middle is where the okay is'],
31 ['anotherfullword is not replaced', 'anotherfullword is not replaced'],
32 ['fullword fullword2', 'okay great'],
33 ['fullwordfullword2', 'fullwordfullword2'],
34 ['i do a delimiter/inside', 'i do a nice try'],
35 ['español', 'español'],
36 ];
37 }
38
39 public static function blockingFilterTests()
40 {
41 return [
42 ['absolutely forbidden'],
43 ['sPoNGeBoB SaYS aBSolUtElY FoRbIdDeN'],
44 ['this is absolutely forbidden full stop!!!'],
45 ];
46 }
47
48 /**
49 * @dataProvider plainFilterTests
50 */
51 public function testPlainFilterReplacement($input, $expectedOutput)
52 {
53 ChatFilter::factory()->createMany([
54 ['match' => 'bad', 'replacement' => 'good'],
55 ['match' => 'fullword', 'replacement' => 'okay', 'whitespace_delimited' => true],
56 ['match' => 'absolutely forbidden', 'replacement' => '', 'block' => true],
57 ]);
58
59 $result = app('chat-filters')->filter($input);
60 $this->assertSame($expectedOutput, $result);
61 }
62
63 /**
64 * @dataProvider fullWordFilterTests
65 */
66 public function testWhitespaceDelimitedFilterReplacement($input, $expectedOutput)
67 {
68 ChatFilter::factory()->createMany([
69 ['match' => 'bad', 'replacement' => 'good'],
70 ['match' => 'fullword', 'replacement' => 'okay', 'whitespace_delimited' => true],
71 ['match' => 'fullword2', 'replacement' => 'great', 'whitespace_delimited' => true],
72 ['match' => 'delimiter/inside', 'replacement' => 'nice try', 'whitespace_delimited' => true],
73 ['match' => 'absolutely forbidden', 'replacement' => '', 'block' => true],
74 ['match' => 'ñ', 'replacement' => 'nnnn', 'whitespace_delimited' => true],
75 ]);
76
77 $result = app('chat-filters')->filter($input);
78 $this->assertSame($expectedOutput, $result);
79 }
80
81 /**
82 * @dataProvider blockingFilterTests
83 */
84 public function testBlockingFilter($input)
85 {
86 ChatFilter::factory()->createMany([
87 ['match' => 'bad', 'replacement' => 'good'],
88 ['match' => 'fullword', 'replacement' => 'okay', 'whitespace_delimited' => true],
89 ['match' => 'absolutely forbidden', 'replacement' => '', 'block' => true],
90 ]);
91
92 $this->expectException(ContentModerationException::class);
93 app('chat-filters')->filter($input);
94 }
95
96 public function testLackOfBlockingFilters()
97 {
98 ChatFilter::factory()->createMany([
99 ['match' => 'bad', 'replacement' => 'good'],
100 ['match' => 'fullword', 'replacement' => 'okay', 'whitespace_delimited' => true],
101 ]);
102
103 $this->expectNotToPerformAssertions();
104 app('chat-filters')->filter('this should be completely fine');
105 }
106}