Skip to content

Merge branch 'main' into clickhouse-gracefully-handle-errors

9d2de6e
Select commit
Loading
Failed to load commit list.
Sign in for the full log view
Merged

Fix ClickHouse outage crashing all dashboard pages #151

Merge branch 'main' into clickhouse-gracefully-handle-errors
9d2de6e
Select commit
Loading
Failed to load commit list.
GitHub Actions / JEST Tests succeeded Mar 25, 2026 in 0s

258 passed, 0 failed and 8 skipped

Tests passed successfully

✅ server/reports/jest-junit.xml

266 tests were completed in 49s with 258 passed, 0 failed and 8 skipped.

Test suite Passed Failed Skipped Time
condition_evaluator/conditionSet.test.ts 11✅ 93ms
condition_evaluator/leafCondition.test.ts 1✅ 8ms
graphql/modules/hashBanks/resolvers.test.ts 7✅ 3ms
graphql/modules/signal.test.ts 2✅ 1ms
routes/content/ContentRoutes.test.ts 4✅ 1⚪ 2s
routes/gdpr/gdprRoutes.test.ts 1✅ 2s
routes/index.test.ts 2✅ 3s
routes/items/ItemRoutes.test.ts 2✅ 2s
routes/policies/PoliciesRoutes.test.ts 1⚪ 2s
routes/reporting/ReportingRoutes.test.ts 6✅ 8s
routes/user_scores/UserScoresRoutes.test.ts 2✅ 2s
rule_engine/ActionPublisher.test.ts 1✅ 91ms
scylla/cqlUtils.test.ts 2✅ 0ms
services/analyticsQueries/ItemHistoryQueries.test.ts 1✅ 2ms
services/apiKeyService/apiKeyService.test.ts 5✅ 1ms
services/derivedFieldsService/helpers.test.ts 5✅ 25ms
services/hmaService/index.test.ts 18✅ 7ms
services/itemInvestigationService/itemInvestigationService.test.ts 2✅ 99ms
services/itemProcessingService/extractItemDataValues.test.ts 5✅ 89ms
services/itemProcessingService/fieldTypeHandlers.test.ts 1✅ 18ms
services/itemProcessingService/toNormalizedItemDataOrErrors.test.ts 4✅ 2ms
services/manualReviewToolService/manualReviewToolService.test.ts 2✅ 2⚪ 73ms
services/manualReviewToolService/modules/CommentOperations.test.ts 14✅ 2s
services/manualReviewToolService/modules/JobRouting.test.ts 8✅ 3s
services/manualReviewToolService/modules/QueueOperations.test.ts 5✅ 765ms
services/moderationConfigService/moderationConfigService.test.ts 24✅ 3⚪ 894ms
services/ncmecService/ncmecReporting.test.ts 8✅ 1ms
services/networkingService/index.test.ts 6✅ 436ms
services/orgAwareSignalExecutionService/signalExecutionService.test.ts 2✅ 29ms
services/ruleAnomalyDetectionService/detectRulePassRateAnomaliesJob.test.ts 1✅ 403ms
services/ruleAnomalyDetectionService/getRuleAlarmStatus.test.ts 4✅ 19ms
services/ruleAnomalyDetectionService/getRuleAnomalyDetectionStatistics.test.ts 5✅ 2ms
services/ruleHistoryService/ruleHistoryService.test.ts 2✅ 3ms
services/sendEmailService/sendEmailService.test.ts 9✅ 3ms
services/signalsService/signals/aggregation/AggregationSignal.test.ts 1✅ 2s
services/signalsService/signals/ImageSimilarityDoesNotMatch.test.ts 4✅ 2ms
services/signalsService/signals/ImageSimilarityMatch.test.ts 5✅ 2ms
services/signalsService/signals/text_matching/fuzzy_matching/TextMatchingContainsVariantSignal.test.ts 1⚪ 0ms
services/signalsService/signals/third_party_signals/zentropi/ZentropiLabelerSignal.test.ts 4✅ 1ms
services/signalsService/signals/third_party_signals/zentropi/zentropiUtils.test.ts 14✅ 3ms
services/userManagementService/userManagementService.test.ts 4✅ 42ms
services/userStatisticsService/computeUserScore.test.ts 3✅ 2ms
services/userStatisticsService/fetchUserActionStatistics.test.ts 2✅ 294ms
services/userStatisticsService/fetchUserSubmissionStatistics.test.ts 3✅ 434ms
services/userStatisticsService/userStatisticsService.test.ts 2✅ 1ms
services/userStrikeService/userStrikeService.test.ts 4✅ 31ms
utils/caching.test.ts 5✅ 3ms
utils/collections.test.ts 12✅ 1ms
utils/encoding.test.ts 4✅ 27ms
utils/iterables.test.ts 4✅ 1ms
utils/misc.test.ts 5✅ 2ms
utils/SafeTracer.test.ts 1✅ 0ms
utils/sql.test.ts 2✅ 7ms
utils/string.test.ts 3✅ 1ms
utils/url.test.ts 4✅ 1ms

✅ condition_evaluator/conditionSet.test.ts

Condition Evaluation › getConditionSetResults
  ✅ should run conditions in cost order, skipping unnecessary ones
Condition Evaluation › getConditionSetOutcome › AND
  ✅ should return false if there are any falsey outcomes
  ✅ should preserve the particular falsey outcome when there's only one
  ✅ should return a truthy outcome if there are only truthy outcomes
  ✅ should return null for any mix of null-like and truthy outcomes
Condition Evaluation › getConditionSetOutcome › OR
  ✅ should return true if there are any truthy outcomes
  ✅ should preserve the particular truthy outcome when there's only one
  ✅ should return a falsey outcome if there are only falsey outcomes
  ✅ should return null for any mix of null-like and falsey outcomes
Condition Evaluation › getConditionSetOutcome › XOR
  ✅ should return true if there's exactly one truthy outcome
Condition Evaluation › tryGetOutcomeFromPartialOutcomes
  ✅ should never return a different logical result than we'd get from all outcomes

✅ condition_evaluator/leafCondition.test.ts

LeafCondition handling
  ✅ should return inapplicable if the condition references contentSubmission values, but there's no content, except if testing for IS_NOT_PROVIDED

✅ graphql/modules/hashBanks/resolvers.test.ts

hashBanks resolvers › Mutation.createHashBank
  ✅ creates a bank without exchange
  ✅ creates a bank with exchange and credentials
  ✅ returns success with warning when credentials fail
  ✅ does not set credentials when credentials_json is absent
hashBanks resolvers › Mutation.updateExchangeCredentials
  ✅ calls setExchangeCredentials and returns true
hashBanks resolvers › HashBank.exchange
  ✅ resolves exchange info for a bank
  ✅ returns null when no exchange is configured

✅ graphql/modules/signal.test.ts

flattenSubcategories
  ✅ Should flatten Hive categories correctly
  ✅ Should flatten Rekognition subcategories correctly

✅ routes/content/ContentRoutes.test.ts

POST Content
  ✅ should return the expected response
  ✅ should pass skipBatch param with sync requests
  ✅ should return a 202 with async camelCase requests
  ⚪ should return the requested derived fields
  ✅ should return null for empty/missing derived fields

✅ routes/gdpr/gdprRoutes.test.ts

POST /gdrp/delete
  ✅ should return the expected response

✅ routes/index.test.ts

404 Handling
  ✅ returns the expected response
Error handling
  ✅ errors thrown after sending a response shouldn't lead to sending status twice

✅ routes/items/ItemRoutes.test.ts

POST Items
  ✅ should return the expected response
  ✅ should return errors for only items that failed to be validated

✅ routes/policies/PoliciesRoutes.test.ts

GET policies
  ⚪ Should return expected response

✅ routes/reporting/ReportingRoutes.test.ts

POST Report
  ✅ Should return the expected response for user report and thread
  ✅ Should return the expected response for user report and additional items
  ✅ Should return the expected response for content report and additional items
  ✅ Should fail thread report and additional items
  ✅ Should pass thread report and item thread content items
  ✅ Should fail invalid reportedAt date

✅ routes/user_scores/UserScoresRoutes.test.ts

GET policies
  ✅ Should return expected response
✅ Test that a random user gets a 5 returned back

✅ rule_engine/ActionPublisher.test.ts

ActionPublisher › publishActions
  ✅ should log each action execution exactly once (not N² times)

✅ scylla/cqlUtils.test.ts

buildCQLSelectQuery
  ✅ should only build valid CQL query strings
  ✅ should only build valid CQL query strings with aggregate functions

✅ services/analyticsQueries/ItemHistoryQueries.test.ts

ItemHistoryQueries
  ✅ should issue a proper query

✅ services/apiKeyService/apiKeyService.test.ts

ApiKeyService › #createApiKey
  ✅ should generate a key, store it, return it + the generated key id
ApiKeyService › #getActiveApiKeyForOrg
  ✅ should retrieve the active key for an org
  ✅ should return null if no active key exists
ApiKeyService › #validateApiKey
  ✅ should validate a key and return org ID
  ✅ should return null for invalid key

✅ services/derivedFieldsService/helpers.test.ts

Item type schemas › Derived Field handling › getDerivedContentFieldValue
  ✅ should return the value according to the spec + content submission
  ✅ should properly handle non-scalar inputs
  ✅ should return undefined if there's no proper field to source from
Item type schemas › Derived Field handling › parseDerivedFieldSpec/serializeDerivedFieldSpec
  ✅ should losslessly round-trip derived field specs
  ✅ should reject invalid specs

✅ services/hmaService/index.test.ts

HmaService › createBank
  ✅ creates a standalone bank via POST /c/banks when no exchange is provided
  ✅ creates a bank via POST /c/exchanges when exchange config is provided
  ✅ updates enabled_ratio after exchange creation when not 1.0
  ✅ throws when HMA returns an error for exchange creation
  ✅ throws when HMA returns an error for standalone bank creation
HmaService › setExchangeCredentials
  ✅ sends credentials to the correct endpoint
  ✅ throws when HMA returns an error
HmaService › getExchangeForBank
  ✅ returns null when HMA returns 404 (no exchange configured)
  ✅ returns error info when HMA returns a non-404 error
  ✅ returns error info when HMA is unreachable
  ✅ returns full exchange info with fetch status on success
  ✅ returns fetch failed status
  ✅ detects active fetch in progress
  ✅ gracefully handles status endpoint failure
HmaService › getExchangeApiSchema
  ✅ returns schema from HMA when endpoint is available
  ✅ falls back to built-in schema when HMA endpoint fails
  ✅ falls back to built-in schema on network error
  ✅ returns empty schema for unknown exchange type with no fallback

✅ services/itemInvestigationService/itemInvestigationService.test.ts

Item Investigation Service
  ✅ should be able to call scylla client methods
  ✅ ParentStream query should return the correct items

✅ services/itemProcessingService/extractItemDataValues.test.ts

getFieldValueOrValues
  ✅ should return single values for scalar type fields
  ✅ should return arrays for array type fields
  ✅ should return value arrays for map type fields
  ✅ should return undefined or empty array if a field is missing in the submission, based on field's scalar-ness
getValuesFromFields
  ✅ should always return an array that's the concatenation of the individual results

✅ services/itemProcessingService/fieldTypeHandlers.test.ts

Content type schemas › fieldTypeHandlers
  ✅ should never accept null as a valid field value

✅ services/itemProcessingService/toNormalizedItemDataOrErrors.test.ts

Content type schemas › toNormalizedItemDataOrErrors
  ✅ should give proper errors
  ✅ should return the normalized version of valid submissions
  ✅ should fail for invalid field roles when only parentId is provided
  ✅ should pass for valid field roles

✅ services/manualReviewToolService/manualReviewToolService.test.ts

Manual Review Tool Service
  ✅ should be able to start stalled jobs checker
  ⚪ MRT throws for submitting a job that has already been moved to completed
Manual Review Tool Service › duplicate decision handling
  ✅ should reject duplicate decisions with the same lock token
  ⚪ should reject duplicate decisions on jobs dequeued again after the lock expires

✅ services/manualReviewToolService/modules/CommentOperations.test.ts

CommentOperations › getRelatedJobIds
  ✅ should return single job ID when job not found in job_creations
  ✅ should return all related job IDs when job found in job_creations
CommentOperations › getComments
  ✅ should return comments for single job when job not in job_creations
  ✅ should return comments for all related jobs when job found in job_creations
  ✅ should return empty array when no comments found
  ✅ should order comments by created_at ascending
CommentOperations › getCommentCount
  ✅ should return 0 when no comments found
  ✅ should return correct count for cross-queue comments
CommentOperations › addComment
  ✅ should add comment successfully
CommentOperations › deleteComment
  ✅ should delete comment successfully
  ✅ should return false when comment not found
  ✅ should return false when comment not owned by user
CommentOperations › Cross-queue functionality integration
  ✅ should show comments from previous queue after job moves
  ✅ should count comments from all queues

✅ services/manualReviewToolService/modules/JobRouting.test.ts

JobRouting tests
  ✅ Should enqueue based off of routing rule
  ✅ Should match on policy rule
  ✅ Should not match on policy rule
  ✅ When queueId is passed to enqueue, job is added to that queue (skips routing)
  ✅ Should match on source type
  ✅ Should fall back to default queue when run rules no longer match db's queue list
  ✅ Should not allow to save a routing rule for a queue that does not exist
  ✅ Route to correct queue if policy Id is not provided

✅ services/manualReviewToolService/modules/QueueOperations.test.ts

QueueOperations
  ✅ External ID functions should be inverses of one another
  ✅ Queues should default to having no actions hidden
  ✅ Test hiding an action
  ✅ Test unhiding an action
  ✅ Test hiding some actions and unhiding some others

✅ services/moderationConfigService/moderationConfigService.test.ts

ModerationConfigService › ItemType-Returning methods › Creation methods › #createContentType
  ✅ should return and durably save the new item type
ModerationConfigService › ItemType-Returning methods › Creation methods › #createThreadType
  ✅ should return and durably save the new item type
ModerationConfigService › ItemType-Returning methods › Creation methods › #createUserType
  ✅ should return and durably save the new item type
ModerationConfigService › ItemType-Returning methods › Read methods › #getItemTypes
  ✅ should return all item types, properly formatted
ModerationConfigService › ItemType-Returning methods › Read methods › #getItemTypesByKind
  ✅ should filter by kind
ModerationConfigService › ItemType-Returning methods › Read methods › #getDefaultUserType
  ✅ should return the defualt user type, properly formatted
ModerationConfigService › ItemType-Returning methods › Read methods › #getItemTypesForAction
  ✅ should query from the proper db
  ⚪ should return the right results
ModerationConfigService › ItemType-Returning methods › Read methods › #getItemTypesForRule
  ✅ should query from the proper db
  ⚪ should return the right results
ModerationConfigService › Action-returning methods › Creation methods › #createAction
  ✅ should return and durably save the new action
ModerationConfigService › Action-returning methods › Read methods › #getActions
  ✅ should query from the proper db
  ✅ should return all actions, properly formatted
ModerationConfigService › Policy returning methods › Read methods
  ✅ should query from the proper db
  ⚪ should return all policies, properly formatted
ModerationConfigService › Policy returning methods › Mutations
  ✅ should create a root policy
  ✅ should create parent and child policies
  ✅ should update an existing policy
  ✅ Prevent creation of policy with the same name as an existing policy
ModerationConfigService › TextBank-returning methods › Mutations › #createTextBank
  ✅ should create a text bank
ModerationConfigService › TextBank-returning methods › Read methods › #getTextBanks
  ✅ should return all text banks, properly formatted
ModerationConfigService › TextBank-returning methods › Read methods › #getTextBank
  ✅ should return a specific text bank, properly formatted
ModerationConfigService › #getItemType
  ✅ Should return undefined if an item type with the given ID doesn't exist
  ✅ Should return a partial item type if requested for a selector without a version
  ✅ Should return a partial item type if requested for a selector with a version
  ✅ Should return latest item type if only an ID is provided
  ✅ Should return requested item type version

✅ services/ncmecService/ncmecReporting.test.ts

NCMEC reporting › buildInternetDetailsFromOrgSetting
  ✅ returns undefined when type is null or undefined
  ✅ returns undefined when type is blank string
  ✅ returns undefined for unknown type
  ✅ returns WEB_PAGE incident with moreInfoUrl when provided
  ✅ returns WEB_PAGE incident with "Not specified" when moreInfoUrl is empty
  ✅ returns WEB_PAGE incident with "Not specified" when moreInfoUrl is blank
  ✅ returns correct structure for each valid type (no extra fields)
  ✅ trims type before matching

✅ services/networkingService/index.test.ts

fetchHTTP
  ✅ should parse fetched json data from a server
fetchHTTP › timeout handling › if nothing is sent before the timeout
  ✅ should reject returned promise, regardless of body parsing setup
fetchHTTP › timeout handling › if only headers are sent before the timeout
  ✅ should reject returned promise, regardless of body parsing settings
fetchHTTP › timeout handling › if an incomplete body was sent before the timeout
  ✅ should reject returned promise if the caller requested body parsing
  ✅ should resolve the returned promise, but cancel the stream, if a stream for the body was requested
  ✅ should resolve the returned promise and never error if no body was requested

✅ services/orgAwareSignalExecutionService/signalExecutionService.test.ts

Signal Execution Service › getTransientRunSignalWithCache
  ✅ should batch textBank loads w/i a single tick
  ✅ should not re-run the same signal with the same input

✅ services/ruleAnomalyDetectionService/detectRulePassRateAnomaliesJob.test.ts

Detect Rule Anomalies › worker
  ✅ should generate the proper notifications + update rules

✅ services/ruleAnomalyDetectionService/getRuleAlarmStatus.test.ts

getRuleAlarmStatus
  ✅ should return false when no executions passed
  ✅ should return false if the pass rate in the most recent period is lower than the historical average
  ✅ should produce plausible results given sample data
  ✅ should report some anomalies if the pass rate is 1%

✅ services/ruleAnomalyDetectionService/getRuleAnomalyDetectionStatistics.test.ts

getRuleAnomalyDetectionStatistics
  ✅ should return the result from the warehouse, properly formatted
  ✅ should generate the proper query when given no filters
  ✅ should generate the proper query when given a start time filter
  ✅ should generate the proper query when given a ruleIds filter
  ✅ should generate the proper query when given both filters

✅ services/ruleHistoryService/ruleHistoryService.test.ts

RuleHistory Service › getSimplifiedRuleHistory
  ✅ should run the expected query
  ✅ should support filtering by ids, startTime

✅ services/sendEmailService/sendEmailService.test.ts

sendEmailService › SES backend (default)
  ✅ should create a function
  ✅ should send email with correct SES parameters
  ✅ should format Source as "Name <email>" for object from address
  ✅ should use Body.Text instead of Body.Html for text content
  ✅ should pass array directly to ToAddresses
  ✅ should not throw when SES returns an error
  ✅ should log the error when SES fails
sendEmailService › SendGrid backend
  ✅ should create a function when given an API key
sendEmailService › CoopEmailAddress defaults
  ✅ should have default email addresses

✅ services/signalsService/signals/aggregation/AggregationSignal.test.ts

AggregationSignal
  ✅ rule should evaluate and update aggregation signal

✅ services/signalsService/signals/ImageSimilarityDoesNotMatch.test.ts

ImageSimilarityDoesNotMatchSignal
  ✅ throws when no banks are provided
  ✅ throws when image has no hashes
  ✅ returns score true (does not match) when no bank matches
  ✅ returns score false (does match) when at least one bank matches

✅ services/signalsService/signals/ImageSimilarityMatch.test.ts

ImageSimilarityMatchSignal
  ✅ throws when no banks are provided
  ✅ throws when image has no hashes
  ✅ returns score true and matchedValue when at least one bank matches
  ✅ returns score false and no matchedValue when no bank matches
  ✅ aggregates matched banks across hash types

✅ services/signalsService/signals/text_matching/fuzzy_matching/TextMatchingContainsVariantSignal.test.ts

TextMatchingContainsVariantSignal
  ⚪ Should not get less accurate from normalization

✅ services/signalsService/signals/third_party_signals/zentropi/ZentropiLabelerSignal.test.ts

ZentropiLabelerSignal
  ✅ has correct signal metadata
  ✅ returns disabled info when credentials are missing
  ✅ returns enabled info when credentials are present
  ✅ calls run and returns correct result

✅ services/signalsService/signals/third_party_signals/zentropi/zentropiUtils.test.ts

zentropiUtils › score mapping
  ✅ maps label=1, high confidence to high score (violating)
  ✅ maps label=0, high confidence to low score (safe)
  ✅ maps label=0, low confidence to ~0.4 (uncertain, leaning safe)
  ✅ maps label=1, low confidence to 0.6 (uncertain, leaning violating)
  ✅ handles label as string "1" (API returns strings)
  ✅ handles label as string "0" (API returns strings)
  ✅ returns correct outputType
zentropiUtils › error handling
  ✅ throws when missing credentials
  ✅ throws when missing subcategory
  ✅ passes labelerVersionId from subcategory to fetcher
zentropiUtils › getZentropiScores
  ✅ returns SignalPermanentError for 404
  ✅ returns SignalPermanentError for 401
  ✅ throws transient error for 5xx
  ✅ returns parsed response on success

✅ services/userManagementService/userManagementService.test.ts

UserManagementService › #generatePasswordResetTokenForUser
  ✅ should generate token and send email for valid user in same org
  ✅ should throw UnauthorizedError when user is in different org
  ✅ should throw NotFoundError when user does not exist
  ✅ should continue if email sending fails (email errors are caught internally)

✅ services/userStatisticsService/computeUserScore.test.ts

computeUserScore
  ✅ should count actions triggered by user rules
  ✅ should apply only the most-severe penalty per item submission
  ✅ should return expected results

✅ services/userStatisticsService/fetchUserActionStatistics.test.ts

fetchUserActionStatistics
  ✅ should generate proper query given user item identifiers
  ✅ should batch queries of more than 16,000 unique user ids

✅ services/userStatisticsService/fetchUserSubmissionStatistics.test.ts

fetchUserSubmissionStatistics
  ✅ should generate proper query given org + user ids only
  ✅ should batch queries of more than 16,000 unique user ids
  ✅ should generate proper query given user/org ids + date filters

✅ services/userStatisticsService/userStatisticsService.test.ts

UserStatisticsService › refreshUserScoresCache
  ✅ should fetch stats w/ batching and update accordingly
  ✅ is a no-op without warehouse change streams

✅ services/userStrikeService/userStrikeService.test.ts

Item Investigation Service
  ✅ Should properly calculate strike counts for a given user
  ✅ Should only apply strike for most severe policy violation
  ✅ findMostSeverePolicyViolationFromActions should return undefined if no actions apply user strikes
  ✅ Should properly calculate strike values using getAllUserStrikeCountsForOrg

✅ utils/caching.test.ts

cached
  ✅ should transparently stringify + parse cache key
  ✅ should not cache promise rejections, and should propagate them
  ✅ should only call the producer once during the cache's freshUntilAge
  ✅ should support custom key generation/parsing logic
  ✅ should require custom key generation logic for non-json-compatible key args

✅ utils/collections.test.ts

Collections utils functions › Filter null and undefined
  ✅ should leave array without nulls and undefineds unchanged
  ✅ should filter null
  ✅ should filter undefined
  ✅ should filter null and undefined
Collections utils functions › Move array element
  ✅ Do nothing if fromIndex equals toIndex
  ✅ Do nothing if fromIndex < 0
  ✅ Do nothing if toIndex < 0>
  ✅ Do nothing if fromIndex is out of bounds
  ✅ Do nothing if toIndex is out of bounds
  ✅ Move element from index 0 to index 1
  ✅ Move element from index 2 to index 1
  ✅ Move element from index 2 to beginning of the array

✅ utils/encoding.test.ts

Encoding Utilities › runEncode
  ✅ empty string
  ✅ single character
  ✅ duplicate multiple characters
Encoding Utilities › regexEscape
  ✅ should always produce a valid regex that matches the literal characters of the input

✅ utils/iterables.test.ts

Iterable utils › chunkAsyncIterableBySize
  ✅ should yield chunks of proper size, except for the last chunk, which should hold the remaining items
chunkAsyncIterableByKey
  ✅ should chunk numbers based on even and odd
  ✅ should handle an empty stream
  ✅ should handle undefined as a valid key

✅ utils/misc.test.ts

Misc utils › String inflection › camelToSnakeCase
  ✅ should work for simple fields
Misc utils › String inflection › snakeToCamelCase
  ✅ should work for simple fields
Misc utils › String inflection › camelCaseObjectKeysToSnakeCaseDeep
  ✅ should work for simple objects
  ✅ should work for arrays
Misc utils › safeGet
  ✅ should short-circuit only on null/undefined/other primitives

✅ utils/SafeTracer.test.ts

SafeTracer › traced
  ✅ shuold run the underlying function with provided args, propagate return value

✅ utils/sql.test.ts

Sql Helpers › takeLast
  ✅ should work for simple queries
  ✅ should work for arbitrarily complex queries

✅ utils/string.test.ts

String Helpers › stripEmojis
  ✅ should strip all emojis
  ✅ should not strip normal characters
  ✅ should not strip normal characters

✅ utils/url.test.ts

URL Tests › Deny Prod URLs
  ✅ Deny Coop domains
  ✅ Deny localhost domains
URL Tests › Allow development URLs
  ✅ Deny Coop domains
  ✅ Allow localhost domains