Skip to content

Commit 4397b27

Browse files
fix: prettier
1 parent e578860 commit 4397b27

File tree

2 files changed

+77
-63
lines changed

2 files changed

+77
-63
lines changed

gui/src/components/StyledMarkdownPreview/SecureImageComponent.test.tsx

Lines changed: 68 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -10,53 +10,67 @@ describe("SecureImageComponent", () => {
1010
describe("Default blocking behavior", () => {
1111
it("should block images by default and show warning message", () => {
1212
render(<SecureImageComponent src="https://example.com/image.jpg" />);
13-
14-
expect(screen.getByText(/Image blocked for security/)).toBeInTheDocument();
13+
14+
expect(
15+
screen.getByText(/Image blocked for security/),
16+
).toBeInTheDocument();
1517
expect(screen.getByText("Load Image")).toBeInTheDocument();
1618
expect(screen.queryByRole("img")).not.toBeInTheDocument();
1719
});
1820

1921
it("should display the image URL", () => {
2022
const testUrl = "https://example.com/test-image.png";
2123
render(<SecureImageComponent src={testUrl} />);
22-
24+
2325
expect(screen.getByText(testUrl)).toBeInTheDocument();
2426
});
2527

2628
it("should handle invalid src prop", () => {
2729
render(<SecureImageComponent src={undefined} />);
28-
29-
expect(screen.getByText("[Invalid image: no source]")).toBeInTheDocument();
30+
31+
expect(
32+
screen.getByText("[Invalid image: no source]"),
33+
).toBeInTheDocument();
3034
expect(screen.queryByText("Load Image")).not.toBeInTheDocument();
3135
});
3236
});
3337

3438
describe("Query parameter detection", () => {
3539
it("should detect and display query parameters", () => {
36-
render(<SecureImageComponent src="https://example.com/image.jpg?user=123&token=abc" />);
37-
38-
expect(screen.getByText(/Warning: URL contains query parameters/)).toBeInTheDocument();
40+
render(
41+
<SecureImageComponent src="https://example.com/image.jpg?user=123&token=abc" />,
42+
);
43+
44+
expect(
45+
screen.getByText(/Warning: URL contains query parameters/),
46+
).toBeInTheDocument();
3947
expect(screen.getByText(/"user": "123"/)).toBeInTheDocument();
4048
expect(screen.getByText(/"token": "abc"/)).toBeInTheDocument();
4149
});
4250

4351
it("should not show query parameter warning for URLs without parameters", () => {
4452
render(<SecureImageComponent src="https://example.com/image.jpg" />);
45-
46-
expect(screen.queryByText(/Warning: URL contains query parameters/)).not.toBeInTheDocument();
53+
54+
expect(
55+
screen.queryByText(/Warning: URL contains query parameters/),
56+
).not.toBeInTheDocument();
4757
});
4858

4959
it("should handle relative URLs with query parameters", () => {
50-
render(<SecureImageComponent src="/images/test.jpg?id=456&session=xyz" />);
51-
52-
expect(screen.getByText(/Warning: URL contains query parameters/)).toBeInTheDocument();
60+
render(
61+
<SecureImageComponent src="/images/test.jpg?id=456&session=xyz" />,
62+
);
63+
64+
expect(
65+
screen.getByText(/Warning: URL contains query parameters/),
66+
).toBeInTheDocument();
5367
expect(screen.getByText(/"id": "456"/)).toBeInTheDocument();
5468
expect(screen.getByText(/"session": "xyz"/)).toBeInTheDocument();
5569
});
5670

5771
it("should handle malformed URLs gracefully", () => {
5872
render(<SecureImageComponent src="not-a-valid-url://image" />);
59-
73+
6074
// Should still display the URL even if it can't be parsed
6175
expect(screen.getByText("not-a-valid-url://image")).toBeInTheDocument();
6276
expect(screen.getByText("Load Image")).toBeInTheDocument();
@@ -67,63 +81,65 @@ describe("SecureImageComponent", () => {
6781
it("should show image when Load Image button is clicked", () => {
6882
const testUrl = "https://example.com/image.jpg";
6983
render(<SecureImageComponent src={testUrl} alt="Test image" />);
70-
84+
7185
// Initially no image
7286
expect(screen.queryByRole("img")).not.toBeInTheDocument();
73-
87+
7488
// Click load button
7589
const loadButton = screen.getByText("Load Image");
7690
fireEvent.click(loadButton);
77-
91+
7892
// Image should now be displayed (query by tag since it might be role="presentation")
7993
const image = screen.getByAltText("Test image");
8094
expect(image).toBeInTheDocument();
8195
expect(image).toHaveAttribute("src", testUrl);
8296
expect(image).toHaveAttribute("alt", "Test image");
83-
97+
8498
// Warning message should be gone
85-
expect(screen.queryByText(/Image blocked for security/)).not.toBeInTheDocument();
99+
expect(
100+
screen.queryByText(/Image blocked for security/),
101+
).not.toBeInTheDocument();
86102
});
87103

88104
it("should handle image load errors", async () => {
89105
const testUrl = "https://example.com/broken-image.jpg";
90106
render(<SecureImageComponent src={testUrl} alt="broken image" />);
91-
107+
92108
// Click load button
93109
const loadButton = screen.getByText("Load Image");
94110
fireEvent.click(loadButton);
95-
111+
96112
// Simulate image error (query by alt text since role might be presentation)
97113
const image = screen.getByAltText("broken image");
98114
fireEvent.error(image);
99-
115+
100116
// Should show error message and hide image
101117
await waitFor(() => {
102118
expect(screen.getByText(/Failed to load image/)).toBeInTheDocument();
103119
expect(screen.queryByAltText("broken image")).not.toBeInTheDocument();
104120
});
105-
121+
106122
// Load button should be available again
107123
expect(screen.getByText("Load Image")).toBeInTheDocument();
108124
});
109125

110126
it("should pass through title and className props", () => {
111127
render(
112-
<SecureImageComponent
113-
src="https://example.com/image.jpg"
128+
<SecureImageComponent
129+
src="https://example.com/image.jpg"
114130
alt="test image"
115131
title="Image title"
116132
className="custom-class"
117-
/>
133+
/>,
118134
);
119-
135+
120136
// Click load button
121137
fireEvent.click(screen.getByText("Load Image"));
122-
138+
123139
// Check image has title (query by alt text)
124140
const image = screen.getByAltText("test image");
125141
expect(image).toHaveAttribute("title", "Image title");
126-
142+
127143
// Check container has className
128144
const container = image.parentElement;
129145
expect(container).toHaveClass("custom-class");
@@ -133,14 +149,14 @@ describe("SecureImageComponent", () => {
133149
describe("Security features", () => {
134150
it("should display query parameters as JSON for transparency", () => {
135151
render(
136-
<SecureImageComponent
137-
src="https://malicious.com/[email protected]&id=12345&action=view"
138-
/>
152+
<SecureImageComponent src="https://malicious.com/[email protected]&id=12345&action=view" />,
139153
);
140-
154+
141155
// Should show all parameters clearly
142-
expect(screen.getByText(/Warning: URL contains query parameters/)).toBeInTheDocument();
143-
156+
expect(
157+
screen.getByText(/Warning: URL contains query parameters/),
158+
).toBeInTheDocument();
159+
144160
// Check JSON is properly formatted
145161
const preElement = screen.getByText(/"email": "user@example.com"/);
146162
expect(preElement).toBeInTheDocument();
@@ -150,49 +166,49 @@ describe("SecureImageComponent", () => {
150166

151167
it("should handle encoded query parameters", () => {
152168
render(
153-
<SecureImageComponent
154-
src="https://example.com/img.png?data=%7B%22user%22%3A%22test%22%7D"
155-
/>
169+
<SecureImageComponent src="https://example.com/img.png?data=%7B%22user%22%3A%22test%22%7D" />,
156170
);
157-
171+
158172
// Should decode and display the parameter
159-
expect(screen.getByText(/Warning: URL contains query parameters/)).toBeInTheDocument();
173+
expect(
174+
screen.getByText(/Warning: URL contains query parameters/),
175+
).toBeInTheDocument();
160176
// The decoded value should be shown in the pre element
161-
const preElement = document.querySelector('pre');
177+
const preElement = document.querySelector("pre");
162178
expect(preElement).toBeTruthy();
163179
// Check that the JSON contains the decoded data
164180
expect(preElement?.textContent).toContain('"data"');
165181
// The value is decoded as a string containing JSON
166182
expect(preElement?.textContent).toContain('"{');
167-
expect(preElement?.textContent).toContain('user');
168-
expect(preElement?.textContent).toContain('test');
183+
expect(preElement?.textContent).toContain("user");
184+
expect(preElement?.textContent).toContain("test");
169185
});
170186
});
171187

172188
describe("Alt text handling", () => {
173189
it("should use empty string for alt when not provided", () => {
174190
render(<SecureImageComponent src="https://example.com/image.jpg" />);
175-
191+
176192
fireEvent.click(screen.getByText("Load Image"));
177-
193+
178194
// Query by tag name since empty alt makes it role="presentation"
179-
const images = document.querySelectorAll('img');
195+
const images = document.querySelectorAll("img");
180196
expect(images.length).toBe(1);
181197
expect(images[0]).toHaveAttribute("alt", "");
182198
});
183199

184200
it("should use provided alt text", () => {
185201
render(
186-
<SecureImageComponent
187-
src="https://example.com/image.jpg"
202+
<SecureImageComponent
203+
src="https://example.com/image.jpg"
188204
alt="Description of image"
189-
/>
205+
/>,
190206
);
191-
207+
192208
fireEvent.click(screen.getByText("Load Image"));
193-
209+
194210
const image = screen.getByAltText("Description of image");
195211
expect(image).toHaveAttribute("alt", "Description of image");
196212
});
197213
});
198-
});
214+
});

gui/src/components/StyledMarkdownPreview/SecureImageComponent.tsx

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ const LoadButton = styled.button`
6969
const ImageContainer = styled.div`
7070
max-width: 100%;
7171
display: inline-block;
72-
72+
7373
img {
7474
max-width: 100%;
7575
height: auto;
@@ -100,7 +100,7 @@ export const SecureImageComponent: React.FC<SecureImageComponentProps> = ({
100100
// Parse URL to check for query parameters
101101
let queryParams: Record<string, string> = {};
102102
let hasQueryParams = false;
103-
103+
104104
try {
105105
const url = new URL(src, window.location.href);
106106
const params = new URLSearchParams(url.search);
@@ -110,7 +110,7 @@ export const SecureImageComponent: React.FC<SecureImageComponentProps> = ({
110110
});
111111
} catch (e) {
112112
// If URL parsing fails, treat src as a relative path
113-
const queryIndex = src.indexOf('?');
113+
const queryIndex = src.indexOf("?");
114114
if (queryIndex > -1) {
115115
hasQueryParams = true;
116116
const params = new URLSearchParams(src.substring(queryIndex));
@@ -141,11 +141,11 @@ export const SecureImageComponent: React.FC<SecureImageComponentProps> = ({
141141
<WarningText>
142142
Image blocked for security. Click to load if you trust the source.
143143
</WarningText>
144-
144+
145145
<UrlDisplay>
146146
<strong>URL:</strong> {src}
147147
</UrlDisplay>
148-
148+
149149
{hasQueryParams && (
150150
<QueryParamsDisplay>
151151
<strong>Warning: URL contains query parameters:</strong>
@@ -154,16 +154,14 @@ export const SecureImageComponent: React.FC<SecureImageComponentProps> = ({
154154
</pre>
155155
</QueryParamsDisplay>
156156
)}
157-
157+
158158
{imageError && (
159159
<div style={{ color: lightGray, fontSize: "12px", marginTop: "8px" }}>
160160
Failed to load image. The URL may be invalid or inaccessible.
161161
</div>
162162
)}
163-
164-
<LoadButton onClick={() => setShowImage(true)}>
165-
Load Image
166-
</LoadButton>
163+
164+
<LoadButton onClick={() => setShowImage(true)}>Load Image</LoadButton>
167165
</ImagePlaceholder>
168166
);
169-
};
167+
};

0 commit comments

Comments
 (0)