Skip to content

Commit 5d5bfeb

Browse files
committed
fix: allow special characters in branch name
1 parent 04fb00e commit 5d5bfeb

File tree

2 files changed

+99
-1
lines changed

2 files changed

+99
-1
lines changed

frontend/pages/sites/$siteId/builds/Build.jsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
IconRebuild,
1818
IconReport,
1919
IconView,
20+
IconIgnore,
2021
} from '@shared/icons';
2122
import CreateScanLink from './CreateScanLink';
2223

@@ -70,6 +71,14 @@ const Build = ({
7071
icon: IconExclamationCircle,
7172
};
7273
break;
74+
case 'invalid':
75+
messageStatusDoneIcon = {
76+
messagePrefix: 'Invalid in ',
77+
status: 'Invalid',
78+
done: true,
79+
icon: IconIgnore,
80+
};
81+
break;
7382
case 'processing':
7483
messageStatusDoneIcon = {
7584
messagePrefix: 'In progress for ',
@@ -165,7 +174,9 @@ const Build = ({
165174
</p>
166175

167176
<p className="logs-link">
168-
{build.startedAt && <BuildLogsLink buildId={build.id} siteId={siteId} />}
177+
{(build.startedAt || build.state === 'invalid') && (
178+
<BuildLogsLink buildId={build.id} siteId={siteId} />
179+
)}
169180
</p>
170181
</div>
171182
</div>
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import '@testing-library/jest-dom';
4+
import Build from '@pages/sites/$siteId/builds/Build';
5+
import { createTestQueryClient } from '@support/queryClient';
6+
7+
// Mocking react-router-dom's <Link> component
8+
// to avoid rendering actual routing elements in tests.
9+
// This prevents warnings when <Link> is used outside a Router
10+
jest.mock('react-router-dom', () => {
11+
const original = jest.requireActual('react-router-dom');
12+
return {
13+
...original,
14+
Link: ({ to, children }) => {
15+
return `Link[to="${to}"] ${children}`;
16+
},
17+
};
18+
});
19+
20+
describe('<Build />', () => {
21+
const props = {
22+
build: { state: '', id: 1 },
23+
containerRef: { current: { offsetTop: 0 } },
24+
latestForBranch: true,
25+
showBuildTasks: true,
26+
site: { id: 123 },
27+
};
28+
29+
const createWrapper = createTestQueryClient();
30+
31+
function testValidBuild(container) {
32+
expect(container.querySelector('.build-info-prefix')).toHaveTextContent('#1');
33+
expect(screen.queryByRole('button', { name: 'Rebuild' })).toBeInTheDocument();
34+
expect(screen.getByText(/View build logs/)).toHaveTextContent(
35+
'Link[to="/sites/123/builds/1/logs"]',
36+
);
37+
}
38+
39+
test('it renders successful build', () => {
40+
const { container } = render(
41+
<Build
42+
{...props}
43+
build={{
44+
...props.build,
45+
state: 'success',
46+
startedAt: 1770775800000,
47+
branch: 'main',
48+
}}
49+
/>,
50+
{ wrapper: createWrapper() },
51+
);
52+
testValidBuild(container);
53+
});
54+
55+
test('it renders failed build', () => {
56+
const { container } = render(
57+
<Build
58+
{...props}
59+
build={{
60+
...props.build,
61+
state: 'error',
62+
startedAt: 1770775800000,
63+
branch: 'main',
64+
}}
65+
/>,
66+
{ wrapper: createWrapper() },
67+
);
68+
testValidBuild(container);
69+
});
70+
71+
test('it renders invalid build', () => {
72+
const { container } = render(
73+
<Build
74+
{...props}
75+
build={{ ...props.build, state: 'invalid', branch: 'invalid branch ~!@#$%^&*()' }}
76+
/>,
77+
{ wrapper: createWrapper() },
78+
);
79+
expect(container.querySelector('.build-info-prefix')).toHaveTextContent('#1');
80+
const logsLink = screen.getByText(/View build logs/);
81+
expect(logsLink).toHaveTextContent('Link[to="/sites/123/builds/1/logs"]');
82+
expect(screen.queryByRole('button', { name: 'Rebuild' })).not.toBeInTheDocument();
83+
const link = screen.getByRole('link', { name: /invalid branch ~!@#\$%\^&\*\(\)/i });
84+
expect(link).toHaveAttribute('href', 'https://github.com/undefined/undefined/tree/invalid%20branch%20~!%40%23%24%25%5E%26*()');
85+
expect(link).toHaveAttribute('title', 'View branch on GitHub');
86+
});
87+
});

0 commit comments

Comments
 (0)