Skip to content

Commit 729e80a

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
fix(ci): align control regression tests with repository audits
1 parent a83149f commit 729e80a

8 files changed

Lines changed: 51 additions & 47 deletions

File tree

‎apps/sim/app/(auth)/verify/otp-error-source.test.tsx‎

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
/** @vitest-environment jsdom */
22
import { act, type ButtonHTMLAttributes, type InputHTMLAttributes, type ReactNode } from 'react'
3+
import { emcnMock } from '@sim/testing/mocks/emcn.mock'
4+
import { nextNavigationMock } from '@sim/testing/mocks/next-navigation.mock'
35
import { createRoot, type Root } from 'react-dom/client'
46
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
57

@@ -8,11 +10,10 @@ const mocks = vi.hoisted(() => ({
810
chatVerify: vi.fn(),
911
fileRequest: vi.fn(),
1012
fileVerify: vi.fn(),
11-
refresh: vi.fn(),
1213
}))
1314

1415
vi.mock('@sim/emcn', () => ({
15-
cn: (...values: Array<string | false | null | undefined>) => values.filter(Boolean).join(' '),
16+
...emcnMock,
1617
ChipInput: ({
1718
error: _error,
1819
size: _size,
@@ -75,7 +76,7 @@ vi.mock('@/components/auth/public-auth-header', () => ({
7576
vi.mock('@/app/f/[token]/public-file-auth-shell', () => ({
7677
PublicFileAuthShell: ({ children }: { children: ReactNode }) => <div>{children}</div>,
7778
}))
78-
vi.mock('next/navigation', () => ({ useRouter: () => ({ refresh: mocks.refresh }) }))
79+
vi.mock('next/navigation', () => nextNavigationMock)
7980
vi.mock('@/hooks/queries/chats', () => ({
8081
useChatEmailOtpRequest: () => ({ mutateAsync: mocks.chatRequest, isPending: false }),
8182
useChatEmailOtpVerify: () => ({ mutateAsync: mocks.chatVerify, isPending: false }),
@@ -96,6 +97,12 @@ function changeInput(input: HTMLInputElement, value: string) {
9697
input.dispatchEvent(new Event('input', { bubbles: true }))
9798
}
9899

100+
function input(selector: string) {
101+
const found = container.querySelector<HTMLInputElement>(selector)
102+
if (!found) throw new Error(`Missing input: ${selector}`)
103+
return found
104+
}
105+
99106
function button(label: string) {
100107
const found = Array.from(container.querySelectorAll('button')).find(
101108
(candidate) => candidate.textContent?.trim() === label
@@ -114,7 +121,6 @@ function expectOtpInvalid(invalid: boolean) {
114121
}
115122

116123
beforeEach(() => {
117-
vi.clearAllMocks()
118124
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true)
119125
mocks.chatRequest.mockResolvedValue({})
120126
mocks.chatVerify.mockResolvedValue({})
@@ -128,15 +134,12 @@ beforeEach(() => {
128134
afterEach(() => {
129135
act(() => root.unmount())
130136
container.remove()
131-
vi.unstubAllGlobals()
132137
})
133138

134139
describe('OTP error provenance', () => {
135140
it('keeps the chat code valid on resend failure and marks only a failed verification invalid', async () => {
136141
act(() => root.render(<EmailAuth identifier='chat-1' />))
137-
act(() =>
138-
changeInput(container.querySelector<HTMLInputElement>('#email')!, 'member@example.com')
139-
)
142+
act(() => changeInput(input('#email'), 'member@example.com'))
140143
await act(async () => button('Continue').click())
141144

142145
mocks.chatRequest.mockRejectedValueOnce(new Error('Delivery failed'))
@@ -145,18 +148,14 @@ describe('OTP error provenance', () => {
145148
expectOtpInvalid(false)
146149

147150
mocks.chatVerify.mockRejectedValueOnce(new Error('Incorrect code'))
148-
await act(async () =>
149-
changeInput(container.querySelector<HTMLInputElement>('[data-testid="otp-code"]')!, '123456')
150-
)
151+
await act(async () => changeInput(input('[data-testid="otp-code"]'), '123456'))
151152
expect(container.textContent).toContain('Incorrect code')
152153
expectOtpInvalid(true)
153154
})
154155

155156
it('keeps the public-file code valid on resend failure and marks only a failed verification invalid', async () => {
156157
act(() => root.render(<PublicFileEmailAuth token='share-1' />))
157-
act(() =>
158-
changeInput(container.querySelector<HTMLInputElement>('#email')!, 'member@example.com')
159-
)
158+
act(() => changeInput(input('#email'), 'member@example.com'))
160159
await act(async () => button('Continue').click())
161160

162161
mocks.fileRequest.mockRejectedValueOnce(new Error('Delivery failed'))
@@ -165,9 +164,7 @@ describe('OTP error provenance', () => {
165164
expectOtpInvalid(false)
166165

167166
mocks.fileVerify.mockRejectedValueOnce(new Error('Incorrect code'))
168-
await act(async () =>
169-
changeInput(container.querySelector<HTMLInputElement>('[data-testid="otp-code"]')!, '123456')
170-
)
167+
await act(async () => changeInput(input('[data-testid="otp-code"]'), '123456'))
171168
expect(container.textContent).toContain('Incorrect code')
172169
expectOtpInvalid(true)
173170
})

‎apps/sim/app/workspace/[workspaceId]/components/index.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ export type {
4242
PaginationConfig,
4343
ResourceCell,
4444
ResourceCellEditing,
45-
ResourceColumn,
4645
ResourceRow,
4746
ResourceTableHandle,
4847
RowDragDropConfig,

‎apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-sidebar-layout.test.tsx‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@ describe('table sidebar layout', () => {
3939
}
4040

4141
render(true)
42-
const dialog = container.querySelector<HTMLElement>('[role="dialog"]')!
43-
const input = container.querySelector<HTMLInputElement>('input')!
44-
const scrollBody = input.parentElement!
42+
const dialog = container.querySelector<HTMLElement>('[role="dialog"]')
43+
const input = container.querySelector<HTMLInputElement>('input')
44+
if (!dialog || !input) throw new Error('Missing sidebar dialog or workflow input')
45+
const scrollBody = input.parentElement
46+
if (!scrollBody) throw new Error('Missing sidebar scroll body')
4547
expect(dialog.getAttribute('aria-label')).toBe('Configure workflow')
4648
expect(dialog.classList.contains('translate-x-0')).toBe(true)
4749
expect(dialog.classList.contains('shadow-overlay')).toBe(true)

‎apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/chat/chat-field-error.test.tsx‎

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import type { ComponentProps, PropsWithChildren } from 'react'
2+
import { deploymentShapeMock } from '@sim/testing/mocks/deployment-shape.mock'
3+
import { emcnIconsMock } from '@sim/testing/mocks/emcn-icons.mock'
4+
import { emcnMock } from '@sim/testing/mocks/emcn.mock'
25
import { JSDOM } from 'jsdom'
36
import { renderToStaticMarkup } from 'react-dom/server'
47
import { describe, expect, it, vi } from 'vitest'
@@ -12,27 +15,22 @@ const validation = vi.hoisted(() => ({
1215
}))
1316

1417
vi.mock('@sim/emcn', () => ({
18+
...emcnMock,
1519
Input: (props: ComponentProps<'input'>) => <input {...props} />,
1620
Label: (props: ComponentProps<'label'>) => (
1721
<label htmlFor={props.htmlFor} className={props.className}>
1822
{props.children}
1923
</label>
2024
),
21-
cn: (...values: unknown[]) => values.filter(Boolean).join(' '),
2225
Tooltip: {
2326
Root: ({ children }: PropsWithChildren) => <>{children}</>,
2427
Trigger: ({ children }: PropsWithChildren) => <>{children}</>,
2528
Content: ({ children }: PropsWithChildren) => <>{children}</>,
2629
},
2730
}))
28-
vi.mock('@sim/emcn/icons', () => ({ Check: () => null, TriangleAlert: () => null }))
29-
vi.mock('@sim/logger', () => ({ createLogger: () => ({}) }))
31+
vi.mock('@sim/emcn/icons', () => emcnIconsMock)
3032
vi.mock('@/components/ui', () => ({ GeneratedPasswordInput: () => null }))
31-
vi.mock('@/lib/core/config/deployment-shape', () => ({ useDeploymentShape: () => ({}) }))
32-
vi.mock('@/lib/core/utils/urls', () => ({
33-
getBaseUrl: () => 'https://sim.ai',
34-
getEmailDomain: () => 'sim.ai',
35-
}))
33+
vi.mock('@/lib/core/config/deployment-shape', () => deploymentShapeMock)
3634
vi.mock('@/lib/messaging/email/validation', () => ({ validateAllowlistEntry: () => true }))
3735
vi.mock('@/lib/workflows/streaming/output-selector', () => ({
3836
formatInternalOutputSelector: () => '',

‎apps/sim/app/workspace/[workspaceId]/w/components/preview/components/preview-editor/preview-readonly-styles.test.tsx‎

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22
* @vitest-environment jsdom
33
*/
44
import { act } from 'react'
5+
import { nextNavigationMock, nextNavigationMockFns } from '@sim/testing/mocks/next-navigation.mock'
56
import { createRoot, type Root } from 'react-dom/client'
67
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
78

8-
vi.mock('next/navigation', () => ({
9-
useParams: () => ({ workspaceId: 'workspace-1' }),
10-
usePathname: () => '/workspace/workspace-1/w/workflow-1',
11-
}))
9+
vi.mock('next/navigation', () => nextNavigationMock)
1210
vi.mock('@/hooks/use-webhook-management', () => ({
1311
useWebhookManagement: () => ({ webhookUrl: null }),
1412
}))
@@ -33,6 +31,8 @@ let container: HTMLDivElement
3331
let root: Root
3432

3533
beforeEach(() => {
34+
nextNavigationMockFns.mockUseParams.mockReturnValue({ workspaceId: 'workspace-1' })
35+
nextNavigationMockFns.mockUsePathname.mockReturnValue('/workspace/workspace-1/w/workflow-1')
3636
;(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true
3737
container = document.createElement('div')
3838
document.body.appendChild(container)
@@ -78,10 +78,12 @@ describe('workflow preview read-only appearance', () => {
7878
)
7979
)
8080

81-
const preview = container.querySelector('[data-testid="preview"]')!
82-
const previewSwitch = preview.querySelector('[role="switch"]') as HTMLButtonElement
83-
const disabled = container.querySelector('[data-testid="disabled"]')!
84-
const disabledSwitch = disabled.querySelector('[role="switch"]') as HTMLButtonElement
81+
const preview = container.querySelector('[data-testid="preview"]')
82+
const disabled = container.querySelector('[data-testid="disabled"]')
83+
if (!preview || !disabled) throw new Error('Missing preview or disabled section')
84+
const previewSwitch = preview.querySelector<HTMLButtonElement>('[role="switch"]')
85+
const disabledSwitch = disabled.querySelector<HTMLButtonElement>('[role="switch"]')
86+
if (!previewSwitch || !disabledSwitch) throw new Error('Missing preview or disabled switch')
8587

8688
expect(preview.querySelector('[data-preview-readonly]')).not.toBeNull()
8789
expect(previewSwitch.hasAttribute('disabled')).toBe(true)
@@ -90,12 +92,14 @@ describe('workflow preview read-only appearance', () => {
9092
expect(getComputedStyle(previewSwitch).pointerEvents).toBe('none')
9193
const piiTrigger = Array.from(preview.querySelectorAll('button')).find((button) =>
9294
button.textContent?.includes('Configure PII Types')
93-
)!
95+
)
96+
if (!piiTrigger) throw new Error('Missing PII configuration trigger')
9497
expect(piiTrigger.disabled).toBe(true)
9598
expect(piiTrigger.hasAttribute('data-preview-full-opacity')).toBe(true)
9699
const removeButton = Array.from(preview.querySelectorAll('button')).find((button) =>
97100
button.textContent?.includes('Remove file')
98-
)!
101+
)
102+
if (!removeButton) throw new Error('Missing remove file button')
99103
expect(getComputedStyle(removeButton).pointerEvents).toBe('none')
100104
expect(getComputedStyle(removeButton).opacity).toBe('0.5')
101105

‎packages/emcn/src/components/collapsible-card/collapsible-card.test.tsx‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ function mount(children: ReactNode) {
1313
document.body.appendChild(container)
1414
root = createRoot(container)
1515
act(() => root?.render(children))
16+
return container
1617
}
1718

1819
afterEach(() => {
@@ -37,9 +38,11 @@ describe('CollapsibleCard', () => {
3738
</CollapsibleCard>
3839
)
3940
}
40-
mount(<Example />)
41-
const card = container!.querySelector('[data-filter-id="condition-1"]')!
42-
const trigger = card.querySelector<HTMLElement>('[role="button"]')!
41+
const mountedContainer = mount(<Example />)
42+
const card = mountedContainer.querySelector('[data-filter-id="condition-1"]')
43+
if (!card) throw new Error('Missing condition card')
44+
const trigger = card.querySelector<HTMLElement>('[role="button"]')
45+
if (!trigger) throw new Error('Missing collapse trigger')
4346
expect(trigger.getAttribute('aria-expanded')).toBe('false')
4447
expect(card.querySelector('input')).toBeNull()
4548
act(() => trigger.click())
@@ -56,7 +59,7 @@ describe('CollapsibleCard', () => {
5659
const add = vi.fn()
5760
const remove = vi.fn()
5861
const parentClick = vi.fn()
59-
mount(
62+
const mountedContainer = mount(
6063
<CollapsibleCard
6164
title={<span>Long condition name</span>}
6265
badge={<span>Text</span>}
@@ -77,8 +80,9 @@ describe('CollapsibleCard', () => {
7780
Content
7881
</CollapsibleCard>
7982
)
80-
const trigger = container!.querySelector('[role="button"]')!
81-
const [addButton, deleteButton] = container!.querySelectorAll('button')
83+
const trigger = mountedContainer.querySelector('[role="button"]')
84+
const [addButton, deleteButton] = mountedContainer.querySelectorAll('button')
85+
if (!trigger || !addButton || !deleteButton) throw new Error('Missing card actions')
8286
expect(trigger.contains(addButton)).toBe(false)
8387
act(() => {
8488
addButton.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }))

‎packages/emcn/src/components/field-divider/field-divider.dom.test.tsx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ describe('FieldDisclosure', () => {
3939
</form>
4040
)
4141
act(() => root?.render(render(false)))
42-
const button = container.querySelector('button')!
42+
const button = container.querySelector('button')
43+
if (!button) throw new Error('Missing field disclosure button')
4344
expect(button.getAttribute('aria-expanded')).toBe('false')
4445
expect(button.getAttribute('aria-controls')).toBe('additional-fields')
4546
act(() => {

‎scripts/check-unused-exports.baseline.json‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,6 @@
371371
"apps/sim/app/workspace/[workspaceId]/components/index.ts#ResourceCell",
372372
"apps/sim/app/workspace/[workspaceId]/components/index.ts#ResourceCellEditing",
373373
"apps/sim/app/workspace/[workspaceId]/components/index.ts#ResourceChromeFallback",
374-
"apps/sim/app/workspace/[workspaceId]/components/index.ts#ResourceNotFound",
375374
"apps/sim/app/workspace/[workspaceId]/components/index.ts#ResourceRow",
376375
"apps/sim/app/workspace/[workspaceId]/components/index.ts#ResourceRowSelection",
377376
"apps/sim/app/workspace/[workspaceId]/components/index.ts#ResourceTableHandle",

0 commit comments

Comments
 (0)