Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions apps/docs/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8726,6 +8726,33 @@ export function BigQueryIcon(props: SVGProps<SVGSVGElement>) {
)
}

/**
* Splunk wordmark. The lettering is drawn with `currentColor` so it stays legible
* bare in both light and dark mode; the chevron keeps its brand green.
*/
export function SplunkIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg
viewBox='0 0 48 48'
fillRule='evenodd'
clipRule='evenodd'
xmlns='http://www.w3.org/2000/svg'
{...props}
>
<path
fill='currentColor'
d='M13.432 18L13.5 28 15 28 15 18zM32 18v10.005h1.805c0 0 .015-3.609.035-3.608.019.001 2.69 3.743 2.716 3.733.027-.01 1.599-.576 1.599-.59 0-.014-2.684-3.441-2.684-3.448 0-.006 2.251-2.509 2.231-2.529-.06-.06-1.281-.586-1.314-.566-.018.011-2.582 2.796-2.582 2.796V18H32zM2.099 21.05c-.651.137-1.259.552-1.509 1.031-.23.44-.227 1.043.007 1.491.16.305.625.735 1.348 1.246.782.552 1.078.832 1.153 1.092.111.385-.06.752-.434.931-.187.089-.27.101-.603.086-.433-.02-.729-.132-1.172-.446-.14-.099-.269-.167-.285-.152-.016.016-.155.224-.311.466L.01 27.23l.109.081c.06.045.248.158.422.255 1.187.66 2.944.555 3.835-.229.475-.418.697-1.025.602-1.647-.089-.582-.409-.965-1.417-1.695-.791-.573-1.166-.889-1.253-1.059-.167-.326-.049-.643.307-.827.178-.092.251-.102.608-.087.347.015.453.041.741.179l.335.161.263-.41c.144-.224.252-.426.239-.445-.048-.071-.598-.299-.941-.391C3.402 20.995 2.521 20.961 2.099 21.05zM10.031 21.935c.788.369 1.212 1.528 1.041 2.852-.06.467-.227 1.032-.383 1.296-.159.268-.463.56-.705.675-.444.212-1.107.13-1.523-.187-.577-.442-.893-1.524-.772-2.649.111-1.032.483-1.684 1.133-1.986C9.156 21.781 9.7 21.781 10.031 21.935zM9.313 20.784c-.472.106-.85.319-1.254.705l-.366.35V21H6.814 6v5 5h1.693v-4.08l.324.319c.592.583 1.287.814 2.101.701.532-.074.904-.21 1.3-.475 1.111-.743 1.721-2.221 1.554-3.771-.158-1.467-.912-2.484-2.128-2.871C10.531 20.724 9.679 20.702 9.313 20.784zM16.258 21c0 0 .055 5.284.091 5.438.136.583.525 1.137.964 1.374.403.218.727.287 1.333.284.861-.004 1.386-.211 2.027-.8L21 27v1h1.742l-.023-7H21c0 0 .025 4.347 0 4.5-.1.611-.573 1.109-1.053 1.27-.287.096-.786.174-1.086.127C18.549 26.848 18.033 26.507 18 26v-4.977L16.258 21zM30.742 28c0 0-.055-5.284-.091-5.438-.136-.583-.525-1.137-.964-1.374-.403-.218-.727-.287-1.333-.284-.861.004-1.386.211-2.027.8L26 22v-1h-1.742l.023 7H26c0 0-.025-4.347 0-4.5.1-.611.573-1.109 1.053-1.27.287-.096.661-.17 1.086-.127C28.566 22.147 29.031 22.535 29 23v4.977L30.742 28z'
/>
<path
fill='#77b539'
fillRule='evenodd'
clipRule='evenodd'
d='M40 20.5L40 22 46 24 40 26.601 40 28 47 25 47 23z'
/>
</svg>
)
}

export function SnowflakeIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg viewBox='0 0 146.36 139.16' xmlns='http://www.w3.org/2000/svg' {...props}>
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/components/ui/icon-mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ import {
SmartleadIcon,
SmtpIcon,
SnowflakeIcon,
SplunkIcon,
SportmonksIcon,
SQSIcon,
SquareIcon,
Expand Down Expand Up @@ -507,6 +508,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
smartlead: SmartleadIcon,
smtp: SmtpIcon,
snowflake: SnowflakeIcon,
splunk: SplunkIcon,
sportmonks: SportmonksIcon,
sqs: SQSIcon,
square: SquareIcon,
Expand Down
1 change: 1 addition & 0 deletions apps/docs/content/docs/en/integrations/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@
"smtp",
"snowflake",
"snowflake-service-account",
"splunk",
"sportmonks",
"sqs",
"square",
Expand Down
437 changes: 437 additions & 0 deletions apps/docs/content/docs/en/integrations/splunk.mdx

Large diffs are not rendered by default.

138 changes: 138 additions & 0 deletions apps/sim/blocks/blocks/splunk.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/**
* @vitest-environment node
*/
import { describe, expect, it, vi } from 'vitest'

vi.mock('@/triggers', () => ({
getTrigger: () => ({ subBlocks: [] }),
}))

import { SplunkBlock } from '@/blocks/blocks/splunk'

const toParams = SplunkBlock.tools.config?.params

function mapParams(params: Record<string, unknown>) {
if (!toParams) throw new Error('SplunkBlock is missing tools.config.params')
return toParams(params as Parameters<typeof toParams>[0])
}

/**
* What the tool actually receives. The generic handler merges the mapper's return
* over the raw serialized subBlock values (`{ ...inputs, ...transformedParams }`), so a
* key the mapper only assigns conditionally leaves the raw subBlock string in place.
* Assertions about dropping a value are only meaningful against this merged result.
*/
function mergedInputs(params: Record<string, unknown>) {
return { ...params, ...mapParams(params) }
}

describe('SplunkBlock tools.config.params', () => {
describe('search-job toggles', () => {
it('preserves a typed boolean false from a variable or agent tool call', () => {
const result = mapParams({
operation: 'splunk_create_search_job',
enableLookups: false,
allowPartialResults: false,
})

expect(result.enableLookups).toBe(false)
expect(result.allowPartialResults).toBe(false)
})

it('reads the dropdown string form', () => {
expect(
mapParams({
operation: 'splunk_create_search_job',
enableLookups: 'false',
allowPartialResults: 'true',
})
).toMatchObject({ enableLookups: false, allowPartialResults: true })
})

it('leaves an untouched toggle undefined so Splunk applies its own default', () => {
const result = mapParams({
operation: 'splunk_create_search_job',
enableLookups: null,
allowPartialResults: '',
})

expect(result.enableLookups).toBeUndefined()
expect(result.allowPartialResults).toBeUndefined()
})
})

describe('pagination', () => {
it('omits Max Results when untouched rather than asking for every row', () => {
const result = mapParams({ operation: 'splunk_list_indexes', count: null, offset: null })

expect(result).not.toHaveProperty('count')
expect(result).not.toHaveProperty('offset')
})

it('coerces a typed Max Results, including an explicit 0', () => {
expect(
mapParams({ operation: 'splunk_list_indexes', count: '50', offset: '10' })
).toMatchObject({ count: 50, offset: 10 })
expect(mapParams({ operation: 'splunk_list_indexes', count: '0' })).toMatchObject({
count: 0,
})
})
})

describe('switch-typed toggles', () => {
it('converts the switch string form so the tool sees a real boolean', () => {
expect(
mergedInputs({
operation: 'splunk_dispatch_saved_search',
savedSearchName: 'Errors',
triggerActions: 'true',
forceDispatch: 'false',
})
).toMatchObject({ triggerActions: true, forceDispatch: false })

expect(
mergedInputs({
operation: 'splunk_get_search_results',
sid: '1.1',
addSummaryToMetadata: 'false',
})
).toMatchObject({ addSummaryToMetadata: false })
})

it('drops an untouched switch from the merged inputs, not just from the mapper', () => {
const merged = mergedInputs({
operation: 'splunk_dispatch_saved_search',
savedSearchName: 'Errors',
triggerActions: null,
forceDispatch: null,
})

expect(merged.triggerActions).toBeUndefined()
expect(merged.forceDispatch).toBeUndefined()
})
})

describe('subBlock to tool param remapping', () => {
it('maps the saved-search and alert name subBlocks onto the tool name param', () => {
expect(
mapParams({ operation: 'splunk_dispatch_saved_search', savedSearchName: 'Errors' })
).toMatchObject({ name: 'Errors' })
expect(
mapParams({ operation: 'splunk_get_fired_alerts', alertName: 'Errors' })
).toMatchObject({ name: 'Errors' })
})
})
})

describe('SplunkBlock subBlocks', () => {
it('has no duplicate subBlock ids', () => {
const ids = SplunkBlock.subBlocks.map((subBlock) => subBlock.id)
expect(new Set(ids).size).toBe(ids.length)
})

it('exposes every tool in tools.access as an operation option', () => {
const operation = SplunkBlock.subBlocks.find((subBlock) => subBlock.id === 'operation')
const optionIds = (operation?.options as { id: string }[]).map((option) => option.id)
expect([...optionIds].sort()).toEqual([...SplunkBlock.tools.access].sort())
})
})
Loading
Loading