Skip to content
Open
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
2 changes: 1 addition & 1 deletion frontend/src/components/Background.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ interface BackgroundProps {

export default function Background({ state = 'idle' }: BackgroundProps) {
return (
<div className={`background background--${state}`}>
<div className={`background background--${state}`} aria-hidden="true">
<div className="background-grid" />
<div className="background-scan" />
<div className="background-lines" />
Expand Down
34 changes: 34 additions & 0 deletions frontend/testing/unit/components/Background.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react'
import { render } from '@testing-library/react'
import { describe, it, expect } from 'vitest'
import Background from '../../../src/components/Background'

describe('Background Component', () => {
it('renders without crashing with default props', () => {
const { container } = render(<Background />)
const wrapper = container.querySelector('.background')
expect(wrapper).toBeInTheDocument()
expect(wrapper).toHaveClass('background--idle')
})

it('renders with different state props', () => {
const { container: activeContainer } = render(<Background state="active" />)
expect(activeContainer.querySelector('.background')).toHaveClass('background--active')

const { container: errorContainer } = render(<Background state="error" />)
expect(errorContainer.querySelector('.background')).toHaveClass('background--error')
})

it('asserts decorative container and layers are aria-hidden', () => {
const { container } = render(<Background />)

// The main wrapper should be aria-hidden since it is decorative background
const wrapper = container.querySelector('.background')
expect(wrapper).toHaveAttribute('aria-hidden', 'true')

// Confirm that the decorative internal elements exist as well
expect(container.querySelector('.background-grid')).toBeInTheDocument()
expect(container.querySelector('.background-scan')).toBeInTheDocument()
expect(container.querySelector('.background-lines')).toBeInTheDocument()
})
})
50 changes: 34 additions & 16 deletions testing/backend/unit/test_tls_verification.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,23 @@ def test_env_override_true(self, monkeypatch):
class TestCrawlerVerifySsl:
@pytest.mark.asyncio
async def test_crawl_target_passes_verify_ssl(self):
async def mock_aiter_bytes():
yield b"<html></html>"

mock_response = MagicMock()
mock_response.text = "<html></html>"
mock_response.url = "https://example.com/"
mock_response.status_code = 200
mock_response.headers = {}
mock_response.history = []
mock_response.aiter_bytes = mock_aiter_bytes

mock_stream_ctx = MagicMock()
mock_stream_ctx.__aenter__ = AsyncMock(return_value=mock_response)
mock_stream_ctx.__aexit__ = AsyncMock(return_value=False)

mock_client = AsyncMock()
mock_client.get = AsyncMock(return_value=mock_response)
mock_client.stream = MagicMock(return_value=mock_stream_ctx)
mock_client.__aenter__ = AsyncMock(return_value=mock_client)
mock_client.__aexit__ = AsyncMock(return_value=False)

Expand All @@ -79,15 +87,23 @@ async def test_crawl_target_passes_verify_ssl(self):

@pytest.mark.asyncio
async def test_crawl_target_verify_ssl_false_when_disabled(self):
async def mock_aiter_bytes():
yield b"<html></html>"

mock_response = MagicMock()
mock_response.text = "<html></html>"
mock_response.url = "https://example.com/"
mock_response.status_code = 200
mock_response.headers = {}
mock_response.history = []
mock_response.aiter_bytes = mock_aiter_bytes

mock_stream_ctx = MagicMock()
mock_stream_ctx.__aenter__ = AsyncMock(return_value=mock_response)
mock_stream_ctx.__aexit__ = AsyncMock(return_value=False)

mock_client = AsyncMock()
mock_client.get = AsyncMock(return_value=mock_response)
mock_client.stream = MagicMock(return_value=mock_stream_ctx)
mock_client.__aenter__ = AsyncMock(return_value=mock_client)
mock_client.__aexit__ = AsyncMock(return_value=False)

Expand Down Expand Up @@ -121,14 +137,15 @@ async def test_api_scanner_passes_verify_ssl(self):

with patch("backend.secuscan.scanners.api_scanner.httpx.AsyncClient", return_value=mock_client) as mock_cls:
with patch("backend.secuscan.scanners.api_scanner.settings") as mock_settings:
mock_settings.verify_ssl = True
with patch.object(scanner, "_fetch_spec", return_value=None):
with patch.object(scanner, "_probe_graphql", return_value=([], [])):
await scanner.run("https://example.com", {})
with patch("backend.secuscan.scanners.api_scanner.crawl_target", return_value={"api_hints": []}):
mock_settings.verify_ssl = True
with patch.object(scanner, "_fetch_spec", return_value=None):
with patch.object(scanner, "_probe_graphql", return_value=([], [])):
await scanner.run("https://example.com", {})

mock_cls.assert_called()
_, kwargs = mock_cls.call_args
assert kwargs["verify"] is True
mock_cls.assert_called()
_, kwargs = mock_cls.call_args
assert kwargs["verify"] is True

@pytest.mark.asyncio
async def test_api_scanner_verify_ssl_false_when_disabled(self):
Expand All @@ -143,13 +160,14 @@ async def test_api_scanner_verify_ssl_false_when_disabled(self):

with patch("backend.secuscan.scanners.api_scanner.httpx.AsyncClient", return_value=mock_client) as mock_cls:
with patch("backend.secuscan.scanners.api_scanner.settings") as mock_settings:
mock_settings.verify_ssl = False
with patch.object(scanner, "_fetch_spec", return_value=None):
with patch.object(scanner, "_probe_graphql", return_value=([], [])):
await scanner.run("https://example.com", {})

_, kwargs = mock_cls.call_args
assert kwargs["verify"] is False
with patch("backend.secuscan.scanners.api_scanner.crawl_target", return_value={"api_hints": []}):
mock_settings.verify_ssl = False
with patch.object(scanner, "_fetch_spec", return_value=None):
with patch.object(scanner, "_probe_graphql", return_value=([], [])):
await scanner.run("https://example.com", {})

_, kwargs = mock_cls.call_args
assert kwargs["verify"] is False


# ---------------------------------------------------------------------------
Expand Down
Loading