import 'package:flutter_test/flutter_test.dart'; import 'package:motorcycle_dash/services/clubs/club_slug_validator.dart'; void main() { group('ClubSlugValidator', () { test('accepts valid slugs', () { final validCases = [ 'bay-area-riders', 'sf-mc', 'apex-hunters-99', 'adv1200', 'track-day-paddock', 'moto-club-california', 'canyon-carvers', ]; for (final slug in validCases) { final result = ClubSlugValidator.validate(slug); expect(result.isValid, isTrue, reason: 'Expected $slug to be valid'); expect(result.normalizedSlug, equals(slug)); expect(result.error, isNull); } }); test('normalizes slugs with uppercase and whitespace', () { final result = ClubSlugValidator.validate(' Bay-Area-Riders '); expect(result.isValid, isTrue); expect(result.normalizedSlug, equals('bay-area-riders')); }); test('rejects empty or whitespace-only slug', () { expect(ClubSlugValidator.validate('').isValid, isFalse); expect(ClubSlugValidator.validate(' ').isValid, isFalse); }); test('rejects slugs shorter than 3 characters', () { final result = ClubSlugValidator.validate('ab'); expect(result.isValid, isFalse); expect(result.error, contains('at least 3 characters')); }); test('rejects slugs longer than 30 characters', () { final longSlug = 'a' * 31; final result = ClubSlugValidator.validate(longSlug); expect(result.isValid, isFalse); expect(result.error, contains('cannot exceed 30 characters')); }); test('rejects consecutive hyphens', () { final result = ClubSlugValidator.validate('bay--area'); expect(result.isValid, isFalse); expect(result.error, contains('consecutive hyphens')); }); test('rejects leading or trailing hyphens', () { expect(ClubSlugValidator.validate('-bay-area').isValid, isFalse); expect(ClubSlugValidator.validate('bay-area-').isValid, isFalse); }); test('rejects underscores and special characters', () { expect(ClubSlugValidator.validate('bay_area_mc').isValid, isFalse); expect(ClubSlugValidator.validate('bay.area').isValid, isFalse); expect(ClubSlugValidator.validate('bay@area').isValid, isFalse); expect(ClubSlugValidator.validate('bay!area').isValid, isFalse); }); test('rejects platform reserved keywords', () { final reservedKeywords = [ 'admin', 'administrator', 'motorsignal', 'support', 'system', 'root', 'api', 'mod', ]; for (final kw in reservedKeywords) { final result = ClubSlugValidator.validate(kw); expect(result.isValid, isFalse, reason: 'Expected $kw to be reserved'); expect(result.error, contains('reserved')); } }); test('rejects club-specific reserved words', () { final clubReserved = [ 'club', 'clubs', 'motorcycle', 'motorcycles', 'chapter', 'national', 'official', 'rally', 'groupride', 'event', ]; for (final kw in clubReserved) { final result = ClubSlugValidator.validate(kw); expect(result.isValid, isFalse, reason: 'Expected $kw to be reserved'); expect(result.error, contains('reserved')); } }); }); }