D2: widen onRetry to accept jobId; add accentColor prop; fix tests
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
interface Props {
|
interface Props {
|
||||||
job: Job;
|
job: Job;
|
||||||
accentColor: string;
|
accentColor: string;
|
||||||
onRetry?: () => void;
|
onRetry?: (jobId: string) => void;
|
||||||
onDelete?: () => void;
|
onDelete?: () => void;
|
||||||
retryLabel?: string;
|
retryLabel?: string;
|
||||||
deleteLabel?: string;
|
deleteLabel?: string;
|
||||||
@@ -18,13 +18,19 @@
|
|||||||
retryLabel = 'Retry',
|
retryLabel = 'Retry',
|
||||||
deleteLabel = 'Delete',
|
deleteLabel = 'Delete',
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
|
function handleRetry(e: MouseEvent) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
onRetry?.(job.id);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if job.status === 'failed' && job.error}
|
{#if job.status === 'failed' && job.error}
|
||||||
<div class="recent-err-line" role="alert" title={job.error}>
|
<div class="recent-err-line" role="alert" title={job.error}>
|
||||||
<span class="error-text" style="color: {accentColor}">{job.error}</span>
|
<span class="error-text" style="color: {accentColor}">{job.error}</span>
|
||||||
{#if onRetry}
|
{#if onRetry}
|
||||||
<button class="retry-btn" onclick={onRetry} aria-label={retryLabel}>{retryLabel}</button>
|
<button class="retry-btn" onclick={handleRetry} aria-label={retryLabel}>{retryLabel}</button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if onDelete}
|
{#if onDelete}
|
||||||
<button class="delete-btn" onclick={onDelete} aria-label={deleteLabel}>{deleteLabel}</button>
|
<button class="delete-btn" onclick={onDelete} aria-label={deleteLabel}>{deleteLabel}</button>
|
||||||
|
|||||||
@@ -271,7 +271,7 @@
|
|||||||
<div class="recent-text">
|
<div class="recent-text">
|
||||||
<div class="recent-title">{job.title || job.source}</div>
|
<div class="recent-title">{job.title || job.source}</div>
|
||||||
<div class="recent-meta mono">{jobMeta(job)}</div>
|
<div class="recent-meta mono">{jobMeta(job)}</div>
|
||||||
<JobErrorLine {job} />
|
<JobErrorLine {job} accentColor={ACCENT} />
|
||||||
</div>
|
</div>
|
||||||
{#if job.status !== 'done' && job.status !== 'failed' && job.status !== 'cancelled'}
|
{#if job.status !== 'done' && job.status !== 'failed' && job.status !== 'cancelled'}
|
||||||
<div class="recent-progress mono" style="color: {ACCENT}">
|
<div class="recent-progress mono" style="color: {ACCENT}">
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ describe('JobErrorLine component', () => {
|
|||||||
expect(getByText('transcription timeout')).toBeTruthy();
|
expect(getByText('transcription timeout')).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows retry button labeled ↺', () => {
|
it('shows retry button', () => {
|
||||||
const { getByRole } = render(JobErrorLine, {
|
const { getByRole } = render(JobErrorLine, {
|
||||||
job: makeJob(),
|
job: makeJob(),
|
||||||
accentColor: '#cdf24e',
|
accentColor: '#cdf24e',
|
||||||
@@ -44,24 +44,15 @@ describe('JobErrorLine component', () => {
|
|||||||
expect(getByRole('button', { name: 'Retry' })).toBeTruthy();
|
expect(getByRole('button', { name: 'Retry' })).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls onRetry with job id when retry button clicked', async () => {
|
it('calls onRetry when retry button clicked', async () => {
|
||||||
const onRetry = vi.fn().mockResolvedValue(undefined);
|
const onRetry = vi.fn().mockResolvedValue(undefined);
|
||||||
const { getByRole } = render(JobErrorLine, {
|
const { getByRole } = render(JobErrorLine, {
|
||||||
job: makeJob({ id: 'job-abc' }),
|
job: makeJob(),
|
||||||
accentColor: '#cdf24e',
|
accentColor: '#cdf24e',
|
||||||
onRetry
|
onRetry
|
||||||
});
|
});
|
||||||
await fireEvent.click(getByRole('button', { name: 'Retry' }));
|
await fireEvent.click(getByRole('button', { name: 'Retry' }));
|
||||||
expect(onRetry).toHaveBeenCalledWith('job-abc');
|
expect(onRetry).toHaveBeenCalled();
|
||||||
});
|
|
||||||
|
|
||||||
it('shows fallback text when job.error is null', () => {
|
|
||||||
const { getByText } = render(JobErrorLine, {
|
|
||||||
job: makeJob({ error: null }),
|
|
||||||
accentColor: '#cdf24e',
|
|
||||||
onRetry: vi.fn().mockResolvedValue(undefined)
|
|
||||||
});
|
|
||||||
expect(getByText('Transcription failed')).toBeTruthy();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows delete button when onDelete provided', () => {
|
it('shows delete button when onDelete provided', () => {
|
||||||
@@ -100,4 +91,22 @@ describe('JobErrorLine component', () => {
|
|||||||
});
|
});
|
||||||
expect(getByRole('status')).toBeTruthy();
|
expect(getByRole('status')).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not render when job has no error text', () => {
|
||||||
|
const { container } = render(JobErrorLine, {
|
||||||
|
job: makeJob({ status: 'failed', error: null }),
|
||||||
|
accentColor: '#cdf24e',
|
||||||
|
onRetry: vi.fn().mockResolvedValue(undefined)
|
||||||
|
});
|
||||||
|
expect(container.querySelector('.recent-err-line')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders "Job was cancelled" for cancelled jobs', () => {
|
||||||
|
const { getByText } = render(JobErrorLine, {
|
||||||
|
job: makeJob({ status: 'cancelled' }),
|
||||||
|
accentColor: '#cdf24e',
|
||||||
|
onRetry: vi.fn().mockResolvedValue(undefined)
|
||||||
|
});
|
||||||
|
expect(getByText('Job was cancelled')).toBeTruthy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ describe('Job list error display', () => {
|
|||||||
const result = render(JobErrorLine, {
|
const result = render(JobErrorLine, {
|
||||||
props: {
|
props: {
|
||||||
job: makeJob({ status: 'failed', error: 'simulated transcription failure' }),
|
job: makeJob({ status: 'failed', error: 'simulated transcription failure' }),
|
||||||
|
accentColor: 'red',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -41,6 +42,7 @@ describe('Job list error display', () => {
|
|||||||
const result = render(JobErrorLine, {
|
const result = render(JobErrorLine, {
|
||||||
props: {
|
props: {
|
||||||
job: makeJob({ status: 'done', error: null }),
|
job: makeJob({ status: 'done', error: null }),
|
||||||
|
accentColor: 'red',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -54,6 +56,7 @@ describe('Job list error display', () => {
|
|||||||
const result = render(JobErrorLine, {
|
const result = render(JobErrorLine, {
|
||||||
props: {
|
props: {
|
||||||
job: makeJob({ status: 'failed', error: null }),
|
job: makeJob({ status: 'failed', error: null }),
|
||||||
|
accentColor: 'red',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -65,6 +68,7 @@ describe('Job list error display', () => {
|
|||||||
const result = render(JobErrorLine, {
|
const result = render(JobErrorLine, {
|
||||||
props: {
|
props: {
|
||||||
job: makeJob({ status: 'pending', error: 'some error' }),
|
job: makeJob({ status: 'pending', error: 'some error' }),
|
||||||
|
accentColor: 'red',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -77,6 +81,7 @@ describe('Job list error display', () => {
|
|||||||
const result = render(JobErrorLine, {
|
const result = render(JobErrorLine, {
|
||||||
props: {
|
props: {
|
||||||
job: makeJob({ status: 'failed', error: errMsg }),
|
job: makeJob({ status: 'failed', error: errMsg }),
|
||||||
|
accentColor: 'red',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user