tux.cogs.admin.mock
¶
Classes:
Name | Description |
---|---|
ErrorTestDefinition | Defines how to construct and test a specific error type. |
ErrorTestRegistry | Dynamic registry of errors that can be tested, based on the actual error handler. |
Mock | |
Classes¶
ErrorTestDefinition(error_class: type[Exception], args: tuple[Any, ...] = (), kwargs: dict[str, Any] | None = None, description: str = '', category: str = 'General')
¶
Defines how to construct and test a specific error type.
Methods:
Name | Description |
---|---|
create_error | Create an instance of this error for testing. |
get_config | Get the error handler configuration for this error type. |
Source code in tux/cogs/admin/mock.py
def __init__(
self,
error_class: type[Exception],
args: tuple[Any, ...] = (),
kwargs: dict[str, Any] | None = None,
description: str = "",
category: str = "General",
):
self.error_class = error_class
self.args = args
self.kwargs = kwargs or {}
self.description = description
self.category = category
self.name = error_class.__name__
Functions¶
create_error() -> Exception
¶
get_config() -> dict[str, Any] | None
¶
Get the error handler configuration for this error type.
Source code in tux/cogs/admin/mock.py
def get_config(self) -> dict[str, Any] | None:
"""Get the error handler configuration for this error type."""
if not (config := ERROR_CONFIG_MAP.get(self.error_class)):
return None
return {
"message_format": config.message_format,
"log_level": config.log_level,
"send_to_sentry": config.send_to_sentry,
"has_detail_extractor": config.detail_extractor is not None,
}
ErrorTestRegistry()
¶
Dynamic registry of errors that can be tested, based on the actual error handler.
Methods:
Name | Description |
---|---|
get_test_names | Get all test names. |
get_test_names_by_category | Get test names grouped by category. |
get_test | Get a specific test by name. |
Source code in tux/cogs/admin/mock.py
Functions¶
_build_test_registry() -> None
¶
Build test cases dynamically from ERROR_CONFIG_MAP.
Source code in tux/cogs/admin/mock.py
def _build_test_registry(self) -> None:
"""Build test cases dynamically from ERROR_CONFIG_MAP."""
# Build all tests from ERROR_CONFIG_MAP - this keeps us perfectly in sync
for error_type in ERROR_CONFIG_MAP:
if error_type.__module__.startswith("discord.app_commands"):
self._add_app_command_test(error_type)
elif error_type.__module__.startswith("discord.ext.commands"):
self._add_traditional_command_test(error_type)
elif error_type.__module__ == "discord" or error_type.__module__.startswith("discord."):
self._add_discord_api_test(error_type)
elif error_type.__module__ == "builtins":
self._add_builtin_test(error_type)
else:
# Custom errors from tux modules
self._add_custom_test(error_type)
_add_test(name: str, error_class: type[Exception], args: tuple[Any, ...] = (), description: str = '', category: str = 'General') -> None
¶
Add a test case to the registry.
Source code in tux/cogs/admin/mock.py
_add_app_command_test(error_type: type[Exception]) -> None
¶
Add app command specific test cases.
Source code in tux/cogs/admin/mock.py
def _add_app_command_test(self, error_type: type[Exception]) -> None:
"""Add app command specific test cases."""
name = error_type.__name__
# Specific mappings for app command errors
specific_mappings = {
app_commands.CommandInvokeError: (
"App command wrapping another error",
(ValueError("Original error inside app command"),),
),
app_commands.TransformerError: (
"App command argument transformation failed",
("Transformer failed", discord.AppCommandOptionType.string, type("MockTransformer", (), {})),
),
app_commands.MissingAnyRole: ("App command missing any of multiple roles", ([987654321, "AnotherRole"],)),
app_commands.MissingPermissions: (
"App command missing permissions",
(["manage_messages", "kick_members"],),
),
app_commands.CommandOnCooldown: ("App command on cooldown", (app_commands.Cooldown(1, 10.0), 7.54)),
app_commands.BotMissingPermissions: (
"Bot missing permissions for app command",
(["send_messages", "embed_links"],),
),
}
if error_type in specific_mappings:
description, args = specific_mappings[error_type]
self.tests[name] = ErrorTestDefinition(error_type, args, {}, description, "App Commands")
elif error_type == app_commands.MissingRole:
self.tests[f"{name}_str"] = ErrorTestDefinition(
error_type,
("RequiredAppRole",),
{},
"App command missing role (by name)",
"App Commands",
)
self.tests[f"{name}_int"] = ErrorTestDefinition(
error_type,
(123456789012345678,),
{},
"App command missing role (by ID)",
"App Commands",
)
elif hasattr(error_type, "__name__"):
realistic_args = self._get_realistic_app_command_args(name)
self.tests[name] = ErrorTestDefinition(
error_type,
realistic_args,
{},
f"App command {name.lower().replace('error', ' error')}",
"App Commands",
)
_get_realistic_app_command_args(error_name: str) -> tuple[Any, ...]
¶
Get realistic arguments for app command errors.
Source code in tux/cogs/admin/mock.py
def _get_realistic_app_command_args(self, error_name: str) -> tuple[Any, ...]:
"""Get realistic arguments for app command errors."""
error_name_lower = error_name.lower()
# Use mapping instead of multiple if statements
arg_mappings = {
("command", "not"): ("/nonexistent_command",),
("command",): ("/mock error",),
("check",): ("Permission check failed",),
("transform", "convert"): ("invalid_input",),
}
return next(
(
args
for keywords, args in arg_mappings.items()
if all(keyword in error_name_lower for keyword in keywords)
),
(f"app_command_{error_name_lower}_example",),
)
_add_traditional_command_test(error_type: type[Exception]) -> None
¶
Add traditional command specific test cases.
Source code in tux/cogs/admin/mock.py
def _add_traditional_command_test(self, error_type: type[Exception]) -> None:
"""Add traditional command specific test cases."""
name = error_type.__name__
# Specific mappings for traditional command errors
specific_mappings = {
commands.CommandInvokeError: (
"Traditional command wrapping another error",
(ValueError("Original error inside traditional command"),),
),
commands.ConversionError: (
"Traditional command argument conversion failed",
(MockParameter("failed_param"), ValueError("Conversion failed")),
),
commands.MissingAnyRole: (
"Traditional command missing any of multiple roles",
([123456789, "AnotherRole"],),
),
commands.MissingPermissions: (
"Traditional command missing permissions",
(["manage_guild", "ban_members"],),
),
commands.FlagError: ("Traditional command flag error", ("Generic flag parsing error",)),
commands.BadFlagArgument: (
"Traditional command bad flag argument",
(MockFlag("test_flag"), ValueError("Invalid flag value")),
),
commands.MissingRequiredFlag: ("Traditional command missing required flag", (MockFlag("required_flag"),)),
commands.CommandOnCooldown: ("Traditional command on cooldown", (commands.Cooldown(1, 15.0), 11.99)),
commands.MissingRequiredArgument: (
"Traditional command missing required argument",
(MockParameter("required_arg"),),
),
commands.TooManyArguments: ("Traditional command too many arguments", ("Too many arguments provided",)),
commands.BotMissingPermissions: (
"Bot missing permissions for traditional command",
(["administrator", "manage_channels"],),
),
commands.MemberNotFound: ("Traditional command member not found", ("NonExistentUser#1234",)),
commands.ExtensionNotLoaded: ("Extension not loaded error", ("fake.extension.name",)),
}
if error_type in specific_mappings:
description, args = specific_mappings[error_type]
self.tests[name] = ErrorTestDefinition(error_type, args, {}, description, "Traditional Commands")
elif error_type == commands.MissingRole:
self.tests[f"{name}_str"] = ErrorTestDefinition(
error_type,
("RequiredRole",),
{},
"Traditional command missing role (by name)",
"Traditional Commands",
)
self.tests[f"{name}_int"] = ErrorTestDefinition(
error_type,
(987654321012345678,),
{},
"Traditional command missing role (by ID)",
"Traditional Commands",
)
elif hasattr(error_type, "__name__") and not error_type.__name__.startswith("Extension"):
realistic_args = self._get_realistic_traditional_command_args(name)
self.tests[name] = ErrorTestDefinition(
error_type,
realistic_args,
{},
f"Traditional command {name.lower().replace('error', ' error')}",
"Traditional Commands",
)
_get_realistic_traditional_command_args(error_name: str) -> tuple[Any, ...]
¶
Get realistic arguments for traditional command errors.
Source code in tux/cogs/admin/mock.py
def _get_realistic_traditional_command_args(self, error_name: str) -> tuple[Any, ...]:
"""Get realistic arguments for traditional command errors."""
error_name_lower = error_name.lower()
# Use mapping for cleaner logic
if "notfound" in error_name_lower.replace("_", ""):
notfound_mappings = {
"channel": ("#invalid-channel",),
"user": ("@InvalidUser#0000",),
"member": ("@InvalidUser#0000",),
"role": ("@InvalidRole",),
}
for keyword, args in notfound_mappings.items():
if keyword in error_name_lower:
return args
# Other mappings
other_mappings = {
("command", "not"): ("$nonexistent_command",),
("command",): ("$mock error",),
("check",): ("Permission check failed",),
("conversion",): ("invalid_argument",),
}
return next(
(
args
for keywords, args in other_mappings.items()
if all(keyword in error_name_lower for keyword in keywords)
),
(f"traditional_{error_name_lower}_example",),
)
_add_discord_api_test(error_type: type[Exception]) -> None
¶
Add Discord API specific test cases.
Source code in tux/cogs/admin/mock.py
def _add_discord_api_test(self, error_type: type[Exception]) -> None:
"""Add Discord API specific test cases."""
name = error_type.__name__
# Specific mappings for Discord API errors
specific_mappings = {
discord.HTTPException: (
"Discord API HTTP error response",
(MockObject(status=500, reason="Mock Internal Server Error"), "Mock HTTP Error"),
),
discord.RateLimited: ("Discord API rate limit hit", (15.5,)),
discord.Forbidden: (
"Discord API forbidden action",
(),
),
discord.NotFound: (
"Discord API resource not found",
(),
),
discord.DiscordServerError: (
"Discord server error",
(),
),
discord.ConnectionClosed: ("Discord connection closed", (None, 4004)),
discord.GatewayNotFound: (
"Discord gateway not found",
(),
),
discord.InvalidData: ("Discord API invalid data", ("Invalid JSON response",)),
discord.LoginFailure: (
"Bot authentication failed",
(),
),
discord.PrivilegedIntentsRequired: ("Missing privileged intents", (None,)),
discord.InteractionResponded: (
"Interaction already responded",
(),
),
discord.MissingApplicationID: (
"Missing application ID",
(),
),
}
if error_type in specific_mappings:
description, args = specific_mappings[error_type]
self.tests[name] = ErrorTestDefinition(error_type, args, {}, description, "Discord API")
elif hasattr(error_type, "__name__"):
realistic_args = self._get_realistic_discord_args(name)
self.tests[name] = ErrorTestDefinition(
error_type,
realistic_args,
{},
f"Discord API {name.lower().replace('error', ' error')}",
"Discord API",
)
_get_realistic_discord_args(error_name: str) -> tuple[Any, ...]
¶
Get realistic arguments for Discord API errors.
Source code in tux/cogs/admin/mock.py
def _get_realistic_discord_args(self, error_name: str) -> tuple[Any, ...]:
"""Get realistic arguments for Discord API errors."""
error_name_lower = error_name.lower()
# Use mapping for cleaner logic
arg_mappings = {
("notfound", "channel"): ("#invalid-channel",),
("notfound", "user"): ("@InvalidUser#0000",),
("notfound", "member"): ("@InvalidUser#0000",),
("notfound", "role"): ("@InvalidRole",),
("notfound", "webhook"): ("https://discord.com/api/webhooks/invalid",),
("forbidden",): ("403 Forbidden",),
("invalid",): ("Invalid parameter",),
("http",): ("HTTP 500 Error",),
("timeout",): ("Request timeout",),
}
return next(
(
args
for keywords, args in arg_mappings.items()
if all(keyword in error_name_lower for keyword in keywords)
),
(f"discord_{error_name_lower}_example",),
)
_add_builtin_test(error_type: type[Exception]) -> None
¶
Add Python built-in error test cases for unhandled error testing.
Source code in tux/cogs/admin/mock.py
def _add_builtin_test(self, error_type: type[Exception]) -> None:
"""Add Python built-in error test cases for unhandled error testing."""
name = error_type.__name__
realistic_args = self._get_realistic_builtin_args(name)
self.tests[name] = ErrorTestDefinition(
error_type,
realistic_args,
{},
f"Python built-in {name.lower().replace('error', ' error')} (should be unhandled)",
"Unhandled",
)
_get_realistic_builtin_args(error_name: str) -> tuple[Any, ...]
¶
Get realistic arguments for Python built-in errors.
Source code in tux/cogs/admin/mock.py
def _get_realistic_builtin_args(self, error_name: str) -> tuple[Any, ...]:
"""Get realistic arguments for Python built-in errors."""
error_name_lower = error_name.lower()
# Use mapping for cleaner logic
arg_mappings = {
"valueerror": ("invalid literal for int() with base 10: 'abc'",),
"typeerror": ("'NoneType' object is not iterable",),
"keyerror": ("'missing_key'",),
"indexerror": ("list index out of range",),
"attributeerror": ("'str' object has no attribute 'missing_attr'",),
"filenotfounderror": ("[Errno 2] No such file or directory: 'missing_file.txt'",),
"permissionerror": ("[Errno 13] Permission denied: '/protected/file.txt'",),
"zerodivisionerror": ("division by zero",),
"assertionerror": ("Test assertion failed",),
}
return arg_mappings.get(error_name_lower, (f"python_{error_name_lower}_example",))
_add_custom_test(error_type: type[Exception]) -> None
¶
Add custom error test cases for tux module errors.
Source code in tux/cogs/admin/mock.py
def _add_custom_test(self, error_type: type[Exception]) -> None:
"""Add custom error test cases for tux module errors."""
name = error_type.__name__
realistic_args = self._get_realistic_custom_args(name)
self.tests[name] = ErrorTestDefinition(
error_type,
realistic_args,
{},
f"Custom tux {name.lower().replace('error', ' error')}",
"Custom",
)
_get_realistic_custom_args(error_name: str) -> tuple[Any, ...]
¶
Get realistic arguments for custom tux errors.
Source code in tux/cogs/admin/mock.py
def _get_realistic_custom_args(self, error_name: str) -> tuple[Any, ...]:
"""Get realistic arguments for custom tux errors."""
error_name_lower = error_name.lower()
# Use mapping for cleaner logic
arg_mappings = {
("config",): ("Configuration error",),
("database",): ("Database connection failed",),
("permission",): ("Insufficient permissions",),
("validation",): ("Input validation failed",),
}
return next(
(
args
for keywords, args in arg_mappings.items()
if all(keyword in error_name_lower for keyword in keywords)
),
(f"custom_{error_name_lower}_example",),
)
get_test_names() -> list[str]
¶
get_test_names_by_category() -> dict[str, list[str]]
¶
Get test names grouped by category.
Source code in tux/cogs/admin/mock.py
get_test(name: str) -> ErrorTestDefinition | None
¶
Mock(bot: Tux)
¶
Bases: Cog
Methods:
Name | Description |
---|---|
mock | Base command group for mocking various bot behaviors. |
error_name_autocomplete | Autocomplete function for error names based on the selected category. |
mock_error | Raises a specified error to test the global error handler. |
error_type_autocomplete | Autocomplete function for error types with category information. |
mock_test | Alternative error testing command with autocomplete support. |
Source code in tux/cogs/admin/mock.py
Functions¶
_create_error_info_embed(test_name: str, test_def: ErrorTestDefinition, ctx: commands.Context[Tux]) -> discord.Embed
async
¶
Create an informative embed showing error details and expected handler behavior.
Source code in tux/cogs/admin/mock.py
async def _create_error_info_embed(
self,
test_name: str,
test_def: ErrorTestDefinition,
ctx: commands.Context[Tux],
) -> discord.Embed:
"""Create an informative embed showing error details and expected handler behavior."""
config = test_def.get_config()
# Create main embed with cleaner title and description
embed = EmbedCreator.create_embed(
embed_type=EmbedCreator.INFO,
bot=self.bot,
title=f"🧪 Testing: `{test_def.error_class.__name__}`",
description=f"**{test_def.description}**",
user_name=ctx.author.display_name,
user_display_avatar=ctx.author.display_avatar.url,
)
# Enhanced status line with category included - user-friendly format
if config:
sentry_status = "✅ Enabled" if config["send_to_sentry"] else "❌ Disabled"
log_level = config["log_level"]
log_icon = {"ERROR": "🔴", "WARNING": "🟡", "INFO": "🔵", "DEBUG": "⚪"}.get(log_level, "🔵")
embed_type = "🎯 Custom" if config["has_detail_extractor"] else "📝 Standard"
category_icon = {
"App Commands": "↗️",
"Traditional Commands": "💲",
"Discord API": "☁️",
"Custom": "🗒️",
"Unhandled": "🔎",
}.get(test_def.category, "📁")
status_line = f"**Sentry:** {sentry_status} • **Log Level:** {log_icon} {log_level} • **Embed Type:** {embed_type} • **Category:** {category_icon} {test_def.category}"
embed.add_field(
name="⚙️ Handler Configuration",
value=status_line,
inline=False,
)
else:
category_icon = "🚫"
status_line = f"**Sentry:** ❌ Disabled • **Log Level:** 🔴 ERROR • **Embed Type:** 📝 Standard • **Category:** {category_icon} {test_def.category}"
embed.add_field(
name="⚠️ Unhandled Error",
value=status_line,
inline=False,
)
# Use single-column layout for better readability
if config:
# Show the user message format (truncated for readability)
message_preview = config["message_format"]
if len(message_preview) > 100:
message_preview = f"{message_preview[:97]}..."
embed.add_field(
name="💬 User Message",
value=f"```\n{message_preview}\n```",
inline=False,
)
else:
embed.add_field(
name="💬 User Message",
value="```\nUnhandled error logged to console\n```",
inline=False,
)
# Technical details - show real source
args_preview = str(test_def.args)
if len(args_preview) > 60:
args_preview = f"{args_preview[:57]}..."
embed.add_field(
name="🔧 Technical Info",
value=f"**Module:** `{test_def.error_class.__module__}`\n**Args:** `{args_preview}`",
inline=False,
)
# Context-aware "What's Next" section
if config:
severity = config["log_level"]
if severity == "ERROR":
next_msg = "🚨 **High Severity** - This error will be raised in **1 second**:\n• Error response sent to channel\n• Console logging\n• Sentry event tracked"
elif config["send_to_sentry"]:
next_msg = "🚀 **Monitored Error** - Raising in **1 second**:\n• User-friendly response\n• Console logging\n• Sentry tracking enabled"
else:
next_msg = "🔍 **Standard Error** - Raising in **1 second**:\n• User response in channel\n• Console logging only"
else:
next_msg = "⚠️ **Unhandled Path** - Raising in **1 second**:\n• No user response (unexpected error)\n• Full stack trace logged\n• May trigger fallback handling"
embed.add_field(
name="🚀 What Happens Next",
value=next_msg,
inline=False,
)
return embed
_send_test_summary(ctx: commands.Context[Tux]) -> None
async
¶
Send a summary of available error tests.
Source code in tux/cogs/admin/mock.py
async def _send_test_summary(self, ctx: commands.Context[Tux]) -> None:
"""Send a summary of available error tests."""
categories = self.error_registry.get_test_names_by_category()
embed = EmbedCreator.create_embed(
embed_type=EmbedCreator.INFO,
bot=self.bot,
title="🧪 Available Error Tests",
description=f"There are **{len(self.error_registry.get_test_names())}** error tests available across **{len(categories)}** categories.",
user_name=ctx.author.display_name,
user_display_avatar=ctx.author.display_avatar.url,
)
for category, tests in categories.items():
test_list = ", ".join(f"`{test}`" for test in sorted(tests)[:5])
if len(tests) > 5:
test_list += f" ... and {len(tests) - 5} more"
embed.add_field(
name=f"📁 {category} ({len(tests)})",
value=test_list or "None",
inline=False,
)
embed.add_field(
name="💡 Usage",
value="Use `/mock error <error_name>` or `$mock error <error_name>` with autocomplete to test specific errors.",
inline=False,
)
await ctx.send(embed=embed)
mock(ctx: commands.Context[Tux]) -> None
async
¶
Base command group for mocking various bot behaviors. Requires System Administrator permissions (Level 8).
Source code in tux/cogs/admin/mock.py
@commands.hybrid_group(name="mock", description="Commands to mock bot behaviors for testing.")
@checks.has_pl(level=8)
async def mock(self, ctx: commands.Context[Tux]) -> None:
"""
Base command group for mocking various bot behaviors.
Requires System Administrator permissions (Level 8).
"""
if ctx.invoked_subcommand is None:
await self._send_test_summary(ctx)
error_name_autocomplete(interaction: discord.Interaction, current: str) -> list[app_commands.Choice[str]]
async
¶
Autocomplete function for error names based on the selected category.
Source code in tux/cogs/admin/mock.py
async def error_name_autocomplete(
self,
interaction: discord.Interaction,
current: str,
) -> list[app_commands.Choice[str]]:
"""Autocomplete function for error names based on the selected category."""
# Get the category from the current interaction
category = None
if interaction.namespace:
category = getattr(interaction.namespace, "category", None)
if not category:
# If no category selected yet, show popular/common errors
common_errors = [
"ValueError",
"RuntimeError",
"App_MissingRole_str",
"Cmd_MissingPermissions",
"HTTPException",
"Forbidden",
"App_CommandOnCooldown",
"Cmd_CommandOnCooldown",
]
choices = [
app_commands.Choice(name=error_name, value=error_name)
for error_name in common_errors
if current.lower() in error_name.lower()
]
else:
# Filter errors by the selected category
categories = self.error_registry.get_test_names_by_category()
if category == "All":
# Show all errors if "All" is selected
available_errors = self.error_registry.get_test_names()
else:
# Show only errors from the selected category
available_errors = categories.get(category, [])
# Filter based on current input and limit to 25
filtered_errors = [error_name for error_name in available_errors if current.lower() in error_name.lower()]
choices = [
app_commands.Choice(
name=(
f"{error_name} [{self.error_registry.tests[error_name].category}]"
if category == "All" and error_name in self.error_registry.tests
else error_name
),
value=error_name,
)
for error_name in filtered_errors
]
# Sort and limit choices
choices.sort(key=lambda x: x.name)
return choices[:25]
mock_error(ctx: commands.Context[Tux], category: str, error_name: str | None = None) -> None
async
¶
Raises a specified error to test the global error handler.
This command shows detailed information about how the error will be handled, then raises the error to demonstrate the actual behavior.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
ctx | Context[Tux] | The command invocation context. | required |
category | str | The category of error to test (required for slash commands). | required |
error_name | str | The specific error name to test. If not provided, shows available errors in the category. | None |
Notes
This command intentionally raises various exceptions based on the input. These exceptions will propagate up to the global ErrorHandler cog. Requires System Administrator permissions (Level 8).
Source code in tux/cogs/admin/mock.py
@mock.command(name="error", description="Raise a specified error for testing error handling.")
@app_commands.describe(
category="Select the category of error to test",
error_name="Choose the specific error from the selected category",
)
@app_commands.choices(
category=[
app_commands.Choice(name="↗️ App Commands", value="App Commands"),
app_commands.Choice(name="💲 Traditional Commands", value="Traditional Commands"),
app_commands.Choice(name="☁️ Discord API", value="Discord API"),
app_commands.Choice(name="🗒️ Custom Errors", value="Custom"),
app_commands.Choice(name="🔎 Unhandled Errors", value="Unhandled"),
app_commands.Choice(name="🏴 All Categories", value="All"),
],
)
@app_commands.autocomplete(error_name=error_name_autocomplete)
@checks.has_pl(level=8)
async def mock_error(self, ctx: commands.Context[Tux], category: str, error_name: str | None = None) -> None:
"""
Raises a specified error to test the global error handler.
This command shows detailed information about how the error will be handled,
then raises the error to demonstrate the actual behavior.
Parameters
----------
ctx : commands.Context[Tux]
The command invocation context.
category : str
The category of error to test (required for slash commands).
error_name : str, optional
The specific error name to test. If not provided, shows available errors in the category.
Notes
-----
This command intentionally raises various exceptions based on the input.
These exceptions will propagate up to the global ErrorHandler cog.
Requires System Administrator permissions (Level 8).
"""
# If no specific error name provided, show available errors in the category
if not error_name:
await self._send_category_summary(ctx, category)
return
# Handle "All" category - need to find the error across all categories
if category != "All":
# Find the error in the specific category
category_tests = self.error_registry.get_test_names_by_category().get(category, [])
if error_name not in category_tests:
await self._send_error_not_in_category(ctx, error_name, category)
return
test_def = self.error_registry.get_test(error_name)
if not test_def:
await self._send_error_not_found(ctx, error_name, category)
return
# Create and send the info embed first
info_embed = await self._create_error_info_embed(error_name, test_def, ctx)
await ctx.send(embed=info_embed)
# Add a small delay for dramatic effect and to ensure the info embed is sent first
await asyncio.sleep(1.0)
# Log the intentional error raising
logger.debug(f"Mock error test: {error_name} by {ctx.author}")
# Now raise the actual error for testing
error = test_def.create_error()
raise error
_send_category_summary(ctx: commands.Context[Tux], category: str) -> None
async
¶
Send a summary of available errors in a specific category.
Source code in tux/cogs/admin/mock.py
async def _send_category_summary(self, ctx: commands.Context[Tux], category: str) -> None:
"""Send a summary of available errors in a specific category."""
categories = self.error_registry.get_test_names_by_category()
if category == "All":
await self._send_test_summary(ctx)
return
if category not in categories:
embed = EmbedCreator.create_embed(
embed_type=EmbedCreator.ERROR,
bot=self.bot,
title="❌ Invalid Category",
description=f"Category `{category}` not found.",
user_name=ctx.author.display_name,
user_display_avatar=ctx.author.display_avatar.url,
)
await ctx.send(embed=embed)
return
tests = categories[category]
embed = EmbedCreator.create_embed(
embed_type=EmbedCreator.INFO,
bot=self.bot,
title=f"🧪 {category} Error Tests",
description=f"Available error tests in the **{category}** category ({len(tests)} total):",
user_name=ctx.author.display_name,
user_display_avatar=ctx.author.display_avatar.url,
)
# Group tests into chunks for better display
test_chunks = [tests[i : i + 10] for i in range(0, len(tests), 10)]
for i, chunk in enumerate(test_chunks):
field_name = (
f"📁 Tests {i * 10 + 1}-{min((i + 1) * 10, len(tests))}"
if len(test_chunks) > 1
else "📁 Available Tests"
)
test_list = "\n".join(f"• `{test}`" for test in sorted(chunk))
embed.add_field(name=field_name, value=test_list, inline=False)
embed.add_field(
name="💡 Usage",
value=f"Use `/mock error category:{category} error_name:<test_name>` to test a specific error.",
inline=False,
)
await ctx.send(embed=embed)
_send_error_not_in_category(ctx: commands.Context[Tux], error_name: str, category: str) -> None
async
¶
Send an error message when the error is not found in the specified category.
Source code in tux/cogs/admin/mock.py
async def _send_error_not_in_category(self, ctx: commands.Context[Tux], error_name: str, category: str) -> None:
"""Send an error message when the error is not found in the specified category."""
categories = self.error_registry.get_test_names_by_category()
category_tests = categories.get(category, [])
embed = EmbedCreator.create_embed(
embed_type=EmbedCreator.ERROR,
bot=self.bot,
title="❌ Error Not Found in Category",
description=f"Error `{error_name}` not found in category `{category}`.",
user_name=ctx.author.display_name,
user_display_avatar=ctx.author.display_avatar.url,
)
if category_tests:
# Show some available tests in this category
test_list = ", ".join(f"`{test}`" for test in sorted(category_tests)[:5])
if len(category_tests) > 5:
test_list = f"{test_list} ... and {len(category_tests) - 5} more"
embed.add_field(
name=f"📁 Available in {category}",
value=test_list,
inline=False,
)
# Check if the error exists in other categories
for cat_name, cat_tests in categories.items():
if error_name in cat_tests and cat_name != category:
embed.add_field(
name="💡 Found in Different Category",
value=f"`{error_name}` is available in the **{cat_name}** category.",
inline=False,
)
break
await ctx.send(embed=embed)
_send_error_not_found(ctx: commands.Context[Tux], error_name: str, category: str) -> None
async
¶
Send an error message when the error is not found at all.
Source code in tux/cogs/admin/mock.py
async def _send_error_not_found(self, ctx: commands.Context[Tux], error_name: str, category: str) -> None:
"""Send an error message when the error is not found at all."""
available_categories = self.error_registry.get_test_names_by_category()
embed = EmbedCreator.create_embed(
embed_type=EmbedCreator.ERROR,
bot=self.bot,
title="❌ Error Test Not Found",
description=f"Error type `{error_name}` not found in category `{category}` or any other category.",
user_name=ctx.author.display_name,
user_display_avatar=ctx.author.display_avatar.url,
)
# Show available categories
for cat_name, tests in list(available_categories.items())[:3]: # Show first 3 categories
test_list = ", ".join(f"`{test}`" for test in sorted(tests)[:3])
if len(tests) > 3:
test_list = f"{test_list} ... ({len(tests)} total)"
embed.add_field(name=f"📁 {cat_name}", value=test_list, inline=False)
embed.add_field(
name="💡 Tip",
value="Use the category dropdown first, then specify the error name, or run `$mock` to see all available tests.",
inline=False,
)
await ctx.send(embed=embed)
error_type_autocomplete(interaction: discord.Interaction, current: str) -> list[app_commands.Choice[str]]
async
¶
Autocomplete function for error types with category information.
Source code in tux/cogs/admin/mock.py
async def error_type_autocomplete(
self,
interaction: discord.Interaction,
current: str,
) -> list[app_commands.Choice[str]]:
"""Autocomplete function for error types with category information."""
choices = [
app_commands.Choice(name=f"[{test_def.category}] {name}", value=name)
for name, test_def in self.error_registry.tests.items()
if current.lower() in name.lower()
]
# Sort by category, then by name, and limit to 25
choices.sort(key=lambda x: x.name)
return choices[:25]
mock_test(ctx: commands.Context[Tux], *, error_type: str) -> None
async
¶
Alternative error testing command with autocomplete support.
This provides the old interface for those who prefer typing error names directly.
Source code in tux/cogs/admin/mock.py
@mock.command(name="test", description="Test a specific error by name (with autocomplete).")
@app_commands.autocomplete(error_type=error_type_autocomplete)
@checks.has_pl(level=8)
async def mock_test(self, ctx: commands.Context[Tux], *, error_type: str) -> None:
"""
Alternative error testing command with autocomplete support.
This provides the old interface for those who prefer typing error names directly.
"""
test_def = self.error_registry.get_test(error_type)
if not test_def:
await self._send_error_not_found(ctx, error_type, "All")
return
# Create and send the info embed first
info_embed = await self._create_error_info_embed(error_type, test_def, ctx)
await ctx.send(embed=info_embed)
# Add a small delay for dramatic effect
await asyncio.sleep(1.0)
# Log the intentional error raising
logger.debug(f"Mock error test: {error_type} by {ctx.author}")
# Now raise the actual error for testing
error = test_def.create_error()
raise error