// @vitest-environment jsdom
import { describe, it, expect, vi, afterEach } from 'vitest';
import { render, screen, cleanup, fireEvent } from '@testing-library/react';
import SaveBar, { type SaveStatus } from '../components/SaveBar';
/**
* The first component test in the project, and deliberately a small one: it is
* here to show the shape (`// @vitest-environment jsdom` on the first line,
* render, assert, cleanup) as much as to cover SaveBar.
*
* SaveBar earns it though. It used to decide whether an outcome read as
* success or failure by testing whether the message happened to start with
* "Error"; #600 replaced that with a typed state, pinned below.
*/
afterEach(cleanup);
const props = {
dirty: false,
saving: false,
status: null as SaveStatus,
onSave: () => {},
label: 'Save',
};
describe('SaveBar', () => {
it('stays out of the way when there is nothing to act on', () => {
const { container } = render();
// It is pinned over the page, so rendering it with nothing to say would
// cover content for no reason.
expect(container.firstChild).toBeNull();
});
it('announces unsaved changes', () => {
render();
expect(screen.getByText('Unsaved changes')).toBeTruthy();
});
it('only offers saving when there is something to save', () => {
const { rerender } = render(
,
);
expect(screen.getByRole('button', { name: 'Save' })).toHaveProperty('disabled', true);
rerender();
expect(screen.getByRole('button', { name: 'Save' })).toHaveProperty('disabled', false);
});
it('blocks a second save while one is in flight', () => {
render();
const button = screen.getByRole('button', { name: 'Saving...' });
expect(button).toHaveProperty('disabled', true);
});
it('calls onSave when clicked', () => {
const onSave = vi.fn();
render();
fireEvent.click(screen.getByRole('button', { name: 'Save' }));
expect(onSave).toHaveBeenCalledOnce();
});
it('styles the outcome by its kind, not by its wording', () => {
// #600: the bar used to call a message an error when it started with
// "Error", so this third message was shown as a success.
const { rerender } = render(
,
);
expect(screen.getByText('Error: Failed to save').className).toContain('error');
rerender();
expect(screen.getByText('Saved!').className).toContain('success');
rerender(
,
);
expect(screen.getByText('Could not reach the server').className).toContain('error');
});
it('offers the preview link only where it belongs', () => {
const { rerender } = render();
expect(screen.queryByRole('link')).toBeNull();
rerender();
// `?fresh=1` is what bypasses the cache, so the preview shows the save.
expect(screen.getByRole('link')).toHaveProperty('href', expect.stringContaining('/?fresh=1'));
});
});