profanity-nsfw-violence-checker
Version:
A powerful TypeScript library to detect and censor profanity, sexual content, violence, and hate speech in both plain text and HTML.
350 lines (349 loc) • 17.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const profanityChecker_1 = require("../profanityChecker");
describe('ProfanityChecker', () => {
let checker;
beforeEach(() => {
checker = new profanityChecker_1.ProfanityChecker();
});
describe('Constructor and Initialization', () => {
it('should create an instance with default options', () => {
expect(checker).toBeInstanceOf(profanityChecker_1.ProfanityChecker);
});
it('should accept custom options', () => {
const options = {
censorCharacter: '#',
strictMode: true,
allowWhitelist: false,
customWords: {
profanity: ['customword1'],
sexual: ['customword2'],
violence: ['customword3'],
hateSpeech: ['customword4']
},
severity: {
profanity: 'high',
sexual: 'high',
violence: 'high',
hateSpeech: 'high'
}
};
const customChecker = new profanityChecker_1.ProfanityChecker(options);
expect(customChecker).toBeInstanceOf(profanityChecker_1.ProfanityChecker);
});
});
describe('check() method', () => {
it('should return clean result for clean text', () => {
const result = checker.check('This is a perfectly clean sentence.');
expect(result.isFlagged).toBe(false);
expect(result.isProfane).toBe(false);
expect(result.isSexual).toBe(false);
expect(result.isViolent).toBe(false);
expect(result.isHateSpeech).toBe(false);
expect(result.severity).toBe('low');
expect(result.matches.profanity).toHaveLength(0);
expect(result.matches.sexual).toHaveLength(0);
expect(result.matches.violence).toHaveLength(0);
expect(result.matches.hateSpeech).toHaveLength(0);
});
it('should handle empty or null input', () => {
const result1 = checker.check('');
const result2 = checker.check(null);
const result3 = checker.check(undefined);
[result1, result2, result3].forEach(result => {
expect(result.isFlagged).toBe(false);
expect(result.isProfane).toBe(false);
expect(result.isSexual).toBe(false);
expect(result.isViolent).toBe(false);
expect(result.isHateSpeech).toBe(false);
expect(result.severity).toBe('low');
});
});
it('should handle non-string input', () => {
const result = checker.check(123);
expect(result.isFlagged).toBe(false);
expect(result.originalText).toBe('123');
});
it('should detect profanity and flag as such', () => {
// Note: Using mild examples for testing
const result = checker.check('This is damn annoying.');
expect(result.isFlagged).toBe(true);
expect(result.isProfane).toBe(true);
expect(result.originalText).toBe('This is damn annoying.');
});
it('should detect multiple categories in one text', () => {
// This test assumes you have words in your JSON files
// You may need to adjust based on your actual dictionary content
const result = checker.check('This contains multiple bad words from different categories.');
expect(result.originalText).toBe('This contains multiple bad words from different categories.');
// Add specific assertions based on your dictionary content
});
it('should respect severity levels', () => {
// Test with high severity words
const result = checker.check('Test with high severity content.');
// Add assertions based on your actual dictionary content
expect(result.severity).toMatch(/^(low|medium|high)$/);
});
it('should provide match details with context', () => {
const result = checker.check('This sentence contains a damn word.');
if (result.matches.profanity.length > 0) {
const match = result.matches.profanity[0];
expect(match).toHaveProperty('word');
expect(match).toHaveProperty('position');
expect(match).toHaveProperty('severity');
expect(match).toHaveProperty('context');
expect(typeof match.position).toBe('number');
expect(typeof match.context).toBe('string');
}
});
it('should handle leetspeak and character substitutions', () => {
const result = checker.check('This is d4mn annoying with l33t speak.');
// Should detect "d4mn" as "damn"
expect(result.isFlagged).toBe(true);
});
it('should handle case insensitivity', () => {
const result1 = checker.check('DAMN');
const result2 = checker.check('damn');
const result3 = checker.check('Damn');
expect(result1.isFlagged).toBe(result2.isFlagged);
expect(result2.isFlagged).toBe(result3.isFlagged);
});
});
describe('censor() method', () => {
it('should return original text when no flagged words found', () => {
const text = 'This is a clean sentence.';
const result = checker.censor(text);
expect(result).toBe(text);
});
it('should censor flagged words with default character', () => {
const result = checker.censor('This is damn annoying.');
expect(result).toContain('****'); // Assuming "damn" gets censored
});
it('should use custom censor character', () => {
const customChecker = new profanityChecker_1.ProfanityChecker({ censorCharacter: '#' });
const result = customChecker.censor('This is damn annoying.');
expect(result).toContain('####'); // Assuming "damn" gets censored
});
it('should handle empty or null input', () => {
expect(checker.censor('')).toBe('');
expect(checker.censor(null)).toBe('');
expect(checker.censor(undefined)).toBe('');
});
it('should preserve word boundaries', () => {
const result = checker.censor('This is damn but not condamn.');
// Should only censor the standalone "damn", not "condamn"
expect(result).toContain('condamn');
});
it('should handle multiple flagged words', () => {
const result = checker.censor('This damn text has multiple bad words.');
// Should censor all flagged words
expect(result).toContain('****');
});
it('should handle overlapping matches correctly', () => {
const result = checker.censor('damn damn damn');
// Should censor all instances
expect(result).toMatch(/\*+ \*+ \*+/);
});
});
describe('censorHtml() method', () => {
it('should censor text within HTML while preserving markup', () => {
const html = '<p>This is <strong>damn</strong> annoying.</p>';
const result = checker.censorHtml(html);
expect(result).toContain('<strong>');
expect(result).toContain('</strong>');
expect(result).toContain('****');
});
it('should handle complex HTML structures', () => {
const html = `
<div class="content">
<h1>Title</h1>
<p>This is damn annoying.</p>
<ul>
<li>Item with damn word</li>
<li>Clean item</li>
</ul>
</div>
`;
const result = checker.censorHtml(html);
expect(result).toContain('<div class="content">');
expect(result).toContain('<h1>Title</h1>');
expect(result).toContain('<ul>');
expect(result).toContain('****');
});
it('should handle empty or null HTML input', () => {
expect(checker.censorHtml('')).toBe('');
expect(checker.censorHtml(null)).toBe('');
expect(checker.censorHtml(undefined)).toBe('');
});
it('should not affect HTML attributes', () => {
const html = '<a href="https://example.com/damn" title="damn">Link</a>';
const result = checker.censorHtml(html);
// Should preserve href and title attributes
expect(result).toContain('href="https://example.com/damn"');
expect(result).toContain('title="damn"');
});
});
describe('addWords() method', () => {
it('should add words to profanity category', () => {
const initialStats = checker.getStats();
checker.addWords('profanity', ['testword1', 'testword2']);
const newStats = checker.getStats();
expect(newStats.profanity).toBe(initialStats.profanity + 2);
const result = checker.check('This contains testword1.');
expect(result.isProfane).toBe(true);
});
it('should add words to sexual category', () => {
const initialStats = checker.getStats();
checker.addWords('sexual', ['testsexual1'], 'high');
const newStats = checker.getStats();
expect(newStats.sexual).toBe(initialStats.sexual + 1);
const result = checker.check('This contains testsexual1.');
expect(result.isSexual).toBe(true);
expect(result.severity).toBe('high');
});
it('should add words to violence category', () => {
const initialStats = checker.getStats();
checker.addWords('violence', ['testviolence1']);
const newStats = checker.getStats();
expect(newStats.violence).toBe(initialStats.violence + 1);
const result = checker.check('This contains testviolence1.');
expect(result.isViolent).toBe(true);
});
it('should add words to hateSpeech category', () => {
const initialStats = checker.getStats();
checker.addWords('hateSpeech', ['testhate1']);
const newStats = checker.getStats();
expect(newStats.hateSpeech).toBe(initialStats.hateSpeech + 1);
const result = checker.check('This contains testhate1.');
expect(result.isHateSpeech).toBe(true);
});
it('should handle case insensitivity when adding words', () => {
checker.addWords('profanity', ['TESTWORD']);
const result1 = checker.check('This contains testword.');
const result2 = checker.check('This contains TESTWORD.');
expect(result1.isProfane).toBe(true);
expect(result2.isProfane).toBe(true);
});
});
describe('removeWords() method', () => {
it('should remove words from profanity category', () => {
// First add a word
checker.addWords('profanity', ['removeme']);
expect(checker.check('This contains removeme.').isProfane).toBe(true);
// Then remove it
checker.removeWords('profanity', ['removeme']);
expect(checker.check('This contains removeme.').isProfane).toBe(false);
});
it('should remove words from all categories', () => {
// Add words to all categories
checker.addWords('profanity', ['testremove']);
checker.addWords('sexual', ['testremove']);
checker.addWords('violence', ['testremove']);
checker.addWords('hateSpeech', ['testremove']);
// Remove from all categories
checker.removeWords('profanity', ['testremove']);
checker.removeWords('sexual', ['testremove']);
checker.removeWords('violence', ['testremove']);
checker.removeWords('hateSpeech', ['testremove']);
const result = checker.check('This contains testremove.');
expect(result.isFlagged).toBe(false);
});
it('should handle case insensitivity when removing words', () => {
checker.addWords('profanity', ['testremove']);
checker.removeWords('profanity', ['TESTREMOVE']);
const result = checker.check('This contains testremove.');
expect(result.isProfane).toBe(false);
});
});
describe('addToWhitelist() method', () => {
it('should add words to whitelist', () => {
// First add a word to profanity
checker.addWords('profanity', ['whitelisttest']);
expect(checker.check('This contains whitelisttest.').isProfane).toBe(true);
// Then add to whitelist
checker.addToWhitelist(['whitelisttest']);
expect(checker.check('This contains whitelisttest.').isProfane).toBe(false);
});
it('should handle case insensitivity in whitelist', () => {
checker.addWords('profanity', ['whitelisttest']);
checker.addToWhitelist(['WHITELISTTEST']);
const result = checker.check('This contains whitelisttest.');
expect(result.isProfane).toBe(false);
});
it('should respect allowWhitelist option', () => {
const noWhitelistChecker = new profanityChecker_1.ProfanityChecker({ allowWhitelist: false });
noWhitelistChecker.addWords('profanity', ['whitelisttest']);
noWhitelistChecker.addToWhitelist(['whitelisttest']);
const result = noWhitelistChecker.check('This contains whitelisttest.');
expect(result.isProfane).toBe(true); // Should still be flagged
});
});
describe('getStats() method', () => {
it('should return correct statistics', () => {
const stats = checker.getStats();
expect(stats).toHaveProperty('profanity');
expect(stats).toHaveProperty('sexual');
expect(stats).toHaveProperty('violence');
expect(stats).toHaveProperty('hateSpeech');
expect(stats).toHaveProperty('whitelist');
expect(stats).toHaveProperty('total');
expect(typeof stats.profanity).toBe('number');
expect(typeof stats.sexual).toBe('number');
expect(typeof stats.violence).toBe('number');
expect(typeof stats.hateSpeech).toBe('number');
expect(typeof stats.whitelist).toBe('number');
expect(typeof stats.total).toBe('number');
expect(stats.total).toBe(stats.profanity + stats.sexual + stats.violence + stats.hateSpeech);
});
it('should update statistics when words are added', () => {
const initialStats = checker.getStats();
checker.addWords('profanity', ['newword1', 'newword2']);
checker.addWords('sexual', ['newsexual1']);
checker.addToWhitelist(['whiteword1']);
const newStats = checker.getStats();
expect(newStats.profanity).toBe(initialStats.profanity + 2);
expect(newStats.sexual).toBe(initialStats.sexual + 1);
expect(newStats.whitelist).toBe(initialStats.whitelist + 1);
expect(newStats.total).toBe(initialStats.total + 3);
});
});
describe('strictMode functionality', () => {
it('should detect partial matches in strict mode', () => {
const strictChecker = new profanityChecker_1.ProfanityChecker({ strictMode: true });
// Add a test word
strictChecker.addWords('profanity', ['test']);
const result = strictChecker.check('This is testing.');
expect(result.isProfane).toBe(true); // Should match "test" in "testing"
});
it('should not detect partial matches in non-strict mode', () => {
const normalChecker = new profanityChecker_1.ProfanityChecker({ strictMode: false });
// Add a test word
normalChecker.addWords('profanity', ['test']);
const result = normalChecker.check('This is testing.');
expect(result.isProfane).toBe(false); // Should not match "test" in "testing"
});
});
describe('severity calculation', () => {
it('should return high severity when high severity words are present', () => {
checker.addWords('violence', ['highseverityword'], 'high');
const result = checker.check('This contains highseverityword.');
expect(result.severity).toBe('high');
});
it('should return medium severity when only medium severity words are present', () => {
checker.addWords('profanity', ['mediumseverityword'], 'medium');
const result = checker.check('This contains mediumseverityword.');
expect(result.severity).toBe('medium');
});
it('should return low severity when only low severity words are present', () => {
checker.addWords('profanity', ['lowseverityword'], 'low');
const result = checker.check('This contains lowseverityword.');
expect(result.severity).toBe('low');
});
it('should prioritize highest severity level', () => {
checker.addWords('profanity', ['lowword'], 'low');
checker.addWords('violence', ['highword'], 'high');
const result = checker.check('This contains lowword and highword.');
expect(result.severity).toBe('high');
});
});
});