Merge remote-tracking branch 'origin/main' into refresh
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// @vitest-environment happy-dom
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { emptyLayout, leaves, type Layout } from "./layout.js";
|
||||
import { addTab, emptyLayout, leaves, type Layout } from "./layout.js";
|
||||
import { splitLeaf } from "./layout.js";
|
||||
import { createMultiView, type MultiView } from "./multiview.js";
|
||||
import type { ConnectionPool } from "./connections.js";
|
||||
@@ -333,3 +333,98 @@ describe("openDraft newTab (#100)", () => {
|
||||
expect(leaves(tab.root)).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("multiview closeSession tab cleanup (#137)", () => {
|
||||
beforeEach(() => {
|
||||
stubFetch();
|
||||
document.body.replaceChildren();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it("closes the tab when its last session goes away", () => {
|
||||
const layout = emptyLayout();
|
||||
const first = layout.tabs[0];
|
||||
first.focusedLeafId = splitLeaf(first, "", "s1", "row", true);
|
||||
const second = addTab(layout);
|
||||
second.focusedLeafId = splitLeaf(second, "", "s2", "row", true);
|
||||
const mv = makeMv(layout);
|
||||
document.body.appendChild(mv.el);
|
||||
mv.render();
|
||||
|
||||
mv.closeSession("s2");
|
||||
|
||||
expect(layout.tabs).toHaveLength(1);
|
||||
expect(layout.tabs[0].id).toBe(first.id);
|
||||
expect(layout.activeTabId).toBe(first.id);
|
||||
});
|
||||
|
||||
it("closes a background tab without stealing focus from the active one", () => {
|
||||
const layout = emptyLayout();
|
||||
const background = layout.tabs[0];
|
||||
background.focusedLeafId = splitLeaf(background, "", "s1", "row", true);
|
||||
const active = addTab(layout);
|
||||
active.focusedLeafId = splitLeaf(active, "", "s2", "row", true);
|
||||
const mv = makeMv(layout);
|
||||
document.body.appendChild(mv.el);
|
||||
mv.render();
|
||||
|
||||
mv.closeSession("s1");
|
||||
|
||||
expect(layout.tabs).toHaveLength(1);
|
||||
expect(layout.tabs[0].id).toBe(active.id);
|
||||
expect(layout.activeTabId).toBe(active.id);
|
||||
});
|
||||
|
||||
it("keeps a tab that still holds another pane", () => {
|
||||
const layout = emptyLayout();
|
||||
const tab = layout.tabs[0];
|
||||
const first = splitLeaf(tab, "", "s1", "row", true);
|
||||
tab.focusedLeafId = splitLeaf(tab, first, "s2", "row", true);
|
||||
addTab(layout);
|
||||
layout.activeTabId = tab.id;
|
||||
const mv = makeMv(layout);
|
||||
document.body.appendChild(mv.el);
|
||||
mv.render();
|
||||
|
||||
mv.closeSession("s2");
|
||||
|
||||
expect(layout.tabs).toHaveLength(2);
|
||||
expect(leaves(tab.root)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("keeps a tab holding a draft pane", async () => {
|
||||
const layout = emptyLayout();
|
||||
const tab = layout.tabs[0];
|
||||
const s1 = splitLeaf(tab, "", "s1", "row", true);
|
||||
splitLeaf(tab, s1, null, "row", true);
|
||||
addTab(layout);
|
||||
layout.activeTabId = tab.id;
|
||||
const mv = makeMv(layout);
|
||||
document.body.appendChild(mv.el);
|
||||
mv.render();
|
||||
await flush();
|
||||
|
||||
mv.closeSession("s1");
|
||||
|
||||
expect(layout.tabs).toHaveLength(2);
|
||||
expect(leaves(tab.root)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("never closes the only tab", () => {
|
||||
const layout = emptyLayout();
|
||||
const tab = layout.tabs[0];
|
||||
tab.focusedLeafId = splitLeaf(tab, "", "s1", "row", true);
|
||||
const mv = makeMv(layout);
|
||||
document.body.appendChild(mv.el);
|
||||
mv.render();
|
||||
|
||||
mv.closeSession("s1");
|
||||
|
||||
expect(layout.tabs).toHaveLength(1);
|
||||
expect(layout.tabs[0].root).toBeNull();
|
||||
expect(layout.activeTabId).toBe(tab.id);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -553,6 +553,10 @@ export function createMultiView(opts: MultiViewOptions): MultiView {
|
||||
if (loc.tab.focusedLeafId === loc.leaf.id) {
|
||||
loc.tab.focusedLeafId = leaves(loc.tab.root)[0]?.id ?? null;
|
||||
}
|
||||
// A tab that held nothing but the dead session goes with it (#137): a killed
|
||||
// session should not leave an empty tab behind for the operator to close by
|
||||
// hand. `closeTab` keeps the last tab (emptied) so there is always one.
|
||||
if (!loc.tab.root) closeTab(layout, loc.tab.id);
|
||||
render();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user