jupyterlab_claude_code_extension 1.1.15 → 1.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jupyterlab_claude_code_extension",
3
- "version": "1.1.15",
3
+ "version": "1.1.17",
4
4
  "description": "Browse, resume, and manage your Claude Code CLI sessions from a JupyterLab side panel. One click reactivates the right terminal - no duplicate tabs, live remote-control indicator, and favourites for the projects you keep coming back to.",
5
5
  "keywords": [
6
6
  "jupyter",
@@ -1,3 +1,10 @@
1
+ declare const __dirname: string;
2
+ declare function require(name: string): any;
3
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
4
+ const fs: { readFileSync: (p: string, enc: string) => string } = require('fs');
5
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
6
+ const path: { join: (...args: string[]) => string } = require('path');
7
+
1
8
  import type { ISession } from '../types';
2
9
 
3
10
  const session = (over: Partial<ISession> = {}): ISession => ({
@@ -61,3 +68,29 @@ describe('session sorting', () => {
61
68
  expect(recent[9].project_path).toBe('p15');
62
69
  });
63
70
  });
71
+
72
+ /**
73
+ * Regression guard for 1.1.13 -> 1.1.14: the launch-spinner Dialog is
74
+ * constructed with ``buttons: []`` so ``Dialog.resolve()`` has no button
75
+ * to "click" and silently no-ops, leaving the modal stuck over the
76
+ * panel. The dismiss call in ``_doResumeInTerminal``'s ``finally`` MUST
77
+ * be ``spinner.dispose()``. These are source-level invariants - cheap,
78
+ * deterministic, and exactly the contract that broke in 1.1.13.
79
+ */
80
+ describe('launch spinner dismiss contract', () => {
81
+ const widgetSrc: string = fs.readFileSync(
82
+ path.join(__dirname, '..', 'widget.ts'),
83
+ 'utf-8'
84
+ );
85
+
86
+ it('_doResumeInTerminal dismisses spinner via dispose(), not resolve()', () => {
87
+ expect(widgetSrc).toMatch(/spinner\.dispose\(\)/);
88
+ expect(widgetSrc).not.toMatch(/spinner\.resolve\(\)/);
89
+ });
90
+
91
+ it('_showLaunchSpinner constructs Dialog with buttons:[]', () => {
92
+ // The empty buttons array is the reason resolve() no-ops; if this
93
+ // ever becomes non-empty, the dismiss call can revisit resolve().
94
+ expect(widgetSrc).toMatch(/_showLaunchSpinner[\s\S]*?buttons:\s*\[\]/);
95
+ });
96
+ });