mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-18 22:36:19 +00:00
fix(git-sources): return 200 for stacks without a Git source (#1294)
The dashboard probes GET /api/stacks/<name>/git-source for every stack to
decide whether to show a Git badge. For a stack with no Git source attached
the endpoint answered 404, so a fleet of unlinked stacks painted a red 404
per stack in the browser console.
Return 200 { linked: false } when the stack exists but has no Git source,
and reserve 404 for the genuine "stack does not exist" case (mirroring the
existence guard the PUT handler already uses). The two consumers that read
this endpoint now treat the { linked: false } sentinel as unlinked rather
than as a configured source.
This commit is contained in:
@@ -221,6 +221,43 @@ describe('StackAnatomyPanel update banner', () => {
|
||||
expect(otherCalls()).toBe(1); // the apply-completion re-check must not fire for "other"
|
||||
});
|
||||
|
||||
it('renders the git badge when a source is attached', async () => {
|
||||
vi.mocked(apiFetch).mockImplementation(async (input: RequestInfo | URL) => {
|
||||
const url = String(input);
|
||||
if (url.includes('/update-preview')) return jsonRes(previewBody(false));
|
||||
if (url.includes('/scan-status')) return jsonRes({ status: 'ok' });
|
||||
if (url.includes('/git-source')) {
|
||||
return jsonRes({ repo_url: 'https://github.com/org/repo.git', branch: 'main', compose_path: 'compose.yaml' });
|
||||
}
|
||||
return jsonRes(null, false);
|
||||
});
|
||||
|
||||
render(panel(false));
|
||||
|
||||
// Positive control: a linked stack shows the "git · host/repo#branch" badge,
|
||||
// which proves the matcher used by the unlinked test below is real.
|
||||
await screen.findByText(/github\.com\/org\/repo#main/);
|
||||
expect(screen.queryByText('local')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('treats a 200 { linked: false } git-source response as unlinked', async () => {
|
||||
vi.mocked(apiFetch).mockImplementation(async (input: RequestInfo | URL) => {
|
||||
const url = String(input);
|
||||
if (url.includes('/update-preview')) return jsonRes(previewBody(true));
|
||||
if (url.includes('/scan-status')) return jsonRes({ status: 'ok' });
|
||||
if (url.includes('/git-source')) return jsonRes({ linked: false }); // 200, no source attached
|
||||
return jsonRes(null, false);
|
||||
});
|
||||
|
||||
render(panel(false));
|
||||
|
||||
// The git-source effect runs before the banner effect, so by the time the
|
||||
// banner renders the git-source response has been applied. An unlinked
|
||||
// stack must keep the "local" label, not flip to a git badge.
|
||||
await screen.findByTestId('update-available-banner');
|
||||
expect(screen.getByText('local')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('ignores a stale re-check that resolves after the stack changed', async () => {
|
||||
let resolveStale!: (r: Response) => void;
|
||||
const stale = new Promise<Response>((r) => { resolveStale = r; });
|
||||
|
||||
Reference in New Issue
Block a user