chore: refactor tests to improve clarity and reliability

- Removed unnecessary test.skip() calls in various test files, replacing them with comments for clarity.
- Enhanced retry logic in TestDataManager for API requests to handle rate limiting more gracefully.
- Updated security helper functions to include retry mechanisms for fetching security status and setting module states.
- Improved loading completion checks to handle page closure scenarios.
- Adjusted WebKit-specific tests to run in all browsers, removing the previous skip logic.
- General cleanup and refactoring across multiple test files to enhance readability and maintainability.
This commit is contained in:
GitHub Actions
2026-02-08 00:02:09 +00:00
parent 5054a334f2
commit aa85c911c0
71 changed files with 22475 additions and 3241 deletions

View File

@@ -923,7 +923,13 @@ export default function CrowdSecConfig() {
</div>
</div>
<p className="text-sm text-gray-400">{t('crowdsecConfig.packages.description')}</p>
<input type="file" onChange={(e) => setFile(e.target.files?.[0] ?? null)} data-testid="import-file" accept=".tar.gz,.zip" />
<input
type="file"
onChange={(e) => setFile(e.target.files?.[0] ?? null)}
data-testid="import-file"
accept=".tar.gz,.zip"
aria-label={t('crowdsecConfig.packages.selectFile') || "Select CrowdSec package"}
/>
</div>
</Card>
@@ -940,6 +946,7 @@ export default function CrowdSecConfig() {
<input
type="text"
placeholder={t('crowdsecConfig.presets.searchPlaceholder')}
aria-label={t('crowdsecConfig.presets.searchPlaceholder')}
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-full bg-gray-900 border border-gray-700 rounded-lg pl-9 pr-3 py-2 text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500"
@@ -947,6 +954,7 @@ export default function CrowdSecConfig() {
</div>
<select
value={sortBy}
aria-label={t('crowdsecConfig.presets.sortBy') || "Sort presets"}
onChange={(e) => setSortBy(e.target.value as 'alpha' | 'type' | 'source')}
className="bg-gray-900 border border-gray-700 rounded-lg px-3 py-2 text-white"
>
@@ -961,7 +969,16 @@ export default function CrowdSecConfig() {
<div
key={preset.slug}
onClick={() => setSelectedPresetSlug(preset.slug)}
className={`p-3 cursor-pointer hover:bg-gray-800 border-b border-gray-800 last:border-0 ${
role="button"
tabIndex={0}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
setSelectedPresetSlug(preset.slug)
}
}}
aria-pressed={selectedPresetSlug === preset.slug}
className={`p-3 cursor-pointer hover:bg-gray-800 border-b border-gray-800 last:border-0 outline-none focus-visible:bg-gray-800 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500 ${
selectedPresetSlug === preset.slug ? 'bg-blue-900/20 border-l-2 border-l-blue-500' : 'border-l-2 border-l-transparent'
}`}
>
@@ -1092,6 +1109,7 @@ export default function CrowdSecConfig() {
value={selectedPath ?? ''}
onChange={(e) => handleReadFile(e.target.value)}
data-testid="crowdsec-file-select"
aria-label={t('crowdsecConfig.files.selectFile')}
>
<option value="">{t('crowdsecConfig.files.selectFile')}</option>
{listMutation.data?.files?.map((f) => (
@@ -1100,7 +1118,13 @@ export default function CrowdSecConfig() {
</select>
<Button variant="secondary" onClick={() => listMutation.refetch()}>{t('crowdsecConfig.files.refresh')}</Button>
</div>
<textarea value={fileContent ?? ''} onChange={(e) => setFileContent(e.target.value)} rows={12} className="w-full bg-gray-900 border border-gray-700 rounded-lg p-3 text-white" />
<textarea
value={fileContent ?? ''}
onChange={(e) => setFileContent(e.target.value)}
rows={12}
className="w-full bg-gray-900 border border-gray-700 rounded-lg p-3 text-white"
aria-label={t('crowdsecConfig.files.content') || "File content"}
/>
<div className="flex gap-2">
<Button onClick={handleSaveFile} isLoading={writeMutation.isPending || backupMutation.isPending}>{t('common.save')}</Button>
<Button variant="secondary" onClick={() => { setSelectedPath(null); setFileContent(null) }}>{t('common.close')}</Button>
@@ -1150,7 +1174,11 @@ export default function CrowdSecConfig() {
</thead>
<tbody>
{decisionsQuery.data.decisions.map((decision) => (
<tr key={decision.id} className="border-b border-gray-800 hover:bg-gray-800/50">
<tr
key={decision.id}
className="border-b border-gray-800 hover:bg-gray-800/50 focus:outline-none focus-visible:bg-gray-800 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500"
tabIndex={0}
>
<td className="py-2 px-3 font-mono text-white">{decision.ip}</td>
<td className="py-2 px-3 text-gray-300">{decision.reason || '-'}</td>
<td className="py-2 px-3 text-gray-300">{decision.duration}</td>
@@ -1180,15 +1208,30 @@ export default function CrowdSecConfig() {
{/* Ban IP Modal */}
{showBanModal && (
<>
<div
className="fixed inset-0 z-50 flex items-center justify-center"
role="dialog"
aria-modal="true"
aria-labelledby="ban-modal-title"
>
{/* Layer 1: Background overlay (z-40) */}
<div className="fixed inset-0 bg-black/60 z-40" onClick={() => setShowBanModal(false)} />
{/* Layer 2: Form container (z-50, pointer-events-none) */}
<div className="fixed inset-0 flex items-center justify-center pointer-events-none z-50">
<div
className="absolute inset-0 bg-black/60"
onClick={() => setShowBanModal(false)}
role="button"
tabIndex={-1}
aria-label={t('common.close')}
/>
{/* Layer 3: Form content (pointer-events-auto) */}
<div className="bg-dark-card rounded-lg p-6 w-[480px] max-w-full pointer-events-auto">
<h3 className="text-xl font-semibold text-white mb-4 flex items-center gap-2">
{/* Layer 3: Form content (pointer-events-auto) */}
<div
className="relative bg-dark-card rounded-lg p-6 w-[480px] max-w-full shadow-xl"
onKeyDown={(e) => {
if (e.key === 'Escape') setShowBanModal(false)
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) banMutation.mutate()
}}
>
<h3 id="ban-modal-title" className="text-xl font-semibold text-white mb-4 flex items-center gap-2">
<ShieldOff className="h-5 w-5 text-red-400" />
{t('crowdsecConfig.banModal.title')}
</h3>
@@ -1199,14 +1242,22 @@ export default function CrowdSecConfig() {
placeholder="192.168.1.100"
value={banForm.ip}
onChange={(e) => setBanForm({ ...banForm, ip: e.target.value })}
autoFocus
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault()
if (banForm.ip.trim()) banMutation.mutate()
}
}}
/>
<div>
<label className="block text-sm font-medium text-gray-300 mb-1.5" htmlFor="ban-duration">{t('crowdsecConfig.banModal.durationLabel')}</label>
<select
id="ban-duration"
className="w-full bg-gray-900 border border-gray-700 rounded-lg px-4 py-2 text-white"
className="w-full bg-gray-900 border border-gray-700 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
value={banForm.duration}
onChange={(e) => setBanForm({ ...banForm, duration: e.target.value })}
aria-label={t('crowdsecConfig.banModal.durationLabel')}
>
<option value="1h">{t('crowdsecConfig.banModal.duration1h')}</option>
<option value="4h">{t('crowdsecConfig.banModal.duration4h')}</option>
@@ -1225,6 +1276,13 @@ export default function CrowdSecConfig() {
rows={3}
value={banForm.reason}
onChange={(e) => setBanForm({ ...banForm, reason: e.target.value })}
onKeyDown={(e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault()
if (banForm.ip.trim()) banMutation.mutate()
}
}}
aria-label={t('crowdsecConfig.banModal.reasonLabel')}
/>
</div>
</div>
@@ -1243,20 +1301,40 @@ export default function CrowdSecConfig() {
</div>
</div>
</div>
</>
)}
{/* Unban Confirmation Modal */}
{confirmUnban && (
<div className="fixed inset-0 z-50 flex items-center justify-center">
<div className="absolute inset-0 bg-black/60" onClick={() => setConfirmUnban(null)} />
<div className="relative bg-dark-card rounded-lg p-6 w-[400px] max-w-full">
<h3 className="text-xl font-semibold text-white mb-4">{t('crowdsecConfig.unbanModal.title')}</h3>
<div
className="fixed inset-0 z-50 flex items-center justify-center"
role="dialog"
aria-modal="true"
aria-labelledby="unban-modal-title"
>
<div
className="absolute inset-0 bg-black/60"
onClick={() => setConfirmUnban(null)}
role="button"
tabIndex={-1}
aria-label={t('common.close')}
/>
<div
className="relative bg-dark-card rounded-lg p-6 w-[400px] max-w-full shadow-xl"
onKeyDown={(e) => {
if (e.key === 'Escape') setConfirmUnban(null)
if (e.key === 'Enter') unbanMutation.mutate(confirmUnban.ip)
}}
>
<h3 id="unban-modal-title" className="text-xl font-semibold text-white mb-4">{t('crowdsecConfig.unbanModal.title')}</h3>
<p className="text-gray-300 mb-6">
{t('crowdsecConfig.unbanModal.confirm')} <span className="font-mono text-white">{confirmUnban.ip}</span>?
</p>
<div className="flex gap-3 justify-end">
<Button variant="secondary" onClick={() => setConfirmUnban(null)}>
<Button
variant="secondary"
onClick={() => setConfirmUnban(null)}
autoFocus
>
{t('common.cancel')}
</Button>
<Button