This is an automated email from the ASF dual-hosted git repository.

voidmatcha pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git


The following commit(s) were added to refs/heads/master by this push:
     new d7f24c1801 [ZEPPELIN-6703] Fix Angular shell test typecheck errors
d7f24c1801 is described below

commit d7f24c1801c644f4a2d39a2440393ecc630ebb08
Author: Minho Jang <[email protected]>
AuthorDate: Thu Nov 12 00:12:23 2026 +0900

    [ZEPPELIN-6703] Fix Angular shell test typecheck errors
    
    ### What is this PR for?
    Fix TypeScript errors across 10 files in the Angular shell test compilation.
    
    This PR:
    - Includes declarations for Vite raw imports and DOM iteration.
    - Corrects test fixtures and lifecycle state assertions to match existing 
contracts.
    - Adds test-only declarations for G2 APIs missing from its bundled types.
    
    ### What type of PR is it?
    Bug Fix
    
    ### What is the Jira issue?
    * https://issues.apache.org/jira/browse/ZEPPELIN-6703
    
    ### How should this be tested?
    From `zeppelin-web-angular`, build the internal libraries and check the 
shell test compilation:
    
    ```bash
    npm run build:projects
    npx tsc -p src/tsconfig.spec.json --noEmit
    ```
    
    Run the existing shell unit tests to check for regressions:
    
    ```bash
    npm run test:shell
    ```
    
    ### Questions:
    * Does the license files need to update? No.
    * Is there breaking changes for older versions? No.
    * Does this needs documentation? No.
    
    Closes #5611 from miinhho/ZEPPELIN-6703-shell-monaco-types.
    
    Signed-off-by: YONGJAE LEE <[email protected]>
---
 zeppelin-web-angular/eslint.config.js              |  1 +
 .../app/core/paragraph-base/paragraph-base.spec.ts |  2 +-
 .../core-read/notebook-core-read-host.spec.ts      | 10 ++---
 .../notebook-core-read.component.testbed.spec.ts   |  5 ++-
 .../workspace/notebook/notebook.component.spec.ts  | 30 ++++++++++----
 .../scatter-chart-visualization.component.spec.ts  | 46 ++++++++++++++++------
 zeppelin-web-angular/src/tsconfig.spec.json        |  5 ++-
 .../test/g2-dependency-compatibility.spec.ts       |  2 +-
 zeppelin-web-angular/test/g2-test-types.d.ts       | 36 +++++++++++++++++
 9 files changed, 109 insertions(+), 28 deletions(-)

diff --git a/zeppelin-web-angular/eslint.config.js 
b/zeppelin-web-angular/eslint.config.js
index 7b7c9d5bde..8ad647b990 100644
--- a/zeppelin-web-angular/eslint.config.js
+++ b/zeppelin-web-angular/eslint.config.js
@@ -189,6 +189,7 @@ module.exports = tseslint.config(
       'src/**/*.spec.ts',
       'projects/zeppelin-{notebook-core,sdk,visualization}/**/*.spec.ts',
       'test/**/*.spec.ts',
+      'test/**/*.d.ts',
       'test/test-setup.ts',
       'test/notebook-core/**/*.ts',
       'vitest.notebook-core.config.mts',
diff --git 
a/zeppelin-web-angular/src/app/core/paragraph-base/paragraph-base.spec.ts 
b/zeppelin-web-angular/src/app/core/paragraph-base/paragraph-base.spec.ts
index 201085ae0a..9f0c179f19 100644
--- a/zeppelin-web-angular/src/app/core/paragraph-base/paragraph-base.spec.ts
+++ b/zeppelin-web-angular/src/app/core/paragraph-base/paragraph-base.spec.ts
@@ -92,7 +92,7 @@ describe('ParagraphBase streaming state isolation', () => {
     component.ngOnDestroy();
   });
 
-  it.each(['FINISHED', 'ERROR', 'ABORT', 'RUNNING', 'PENDING'])(
+  it.each(['FINISHED', 'ERROR', 'ABORT', 'RUNNING', 'PENDING'] as const)(
     'keeps accumulating output when another paragraph becomes %s',
     status => {
       const component = new TestParagraph(paragraph('A'));
diff --git 
a/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read-host.spec.ts
 
b/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read-host.spec.ts
index 8ed06cb0a1..83cf363d27 100644
--- 
a/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read-host.spec.ts
+++ 
b/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read-host.spec.ts
@@ -113,18 +113,18 @@ describe('NotebookCoreReadHost', () => {
     expect(states[states.length - 1]).toMatchObject({ connected: true, 
snapshot: { status: 'loading' } });
 
     replyNote('A');
-    expect(host.port.getSnapshot().status).toBe('ready');
+    expect(states[states.length - 1].snapshot.status).toBe('ready');
     expect(new Set(states.map(({ snapshot }) => 
snapshot)).size).toBe(states.length);
   });
 
   it('ignores a reply that arrives after the connection dropped', () => {
-    const { host, received, connectedStatus$, sent } = setup();
+    const { host, received, connectedStatus$, sent, states } = setup();
     host.open({ kind: 'note', noteId: 'A' });
 
     connectedStatus$.next(false);
     received.next({ op: OP.NOTE, data: { note: note('A') }, msgId: 
`msg-${sent.length}` } as Envelope);
 
-    expect(host.port.getSnapshot().status).toBe('failed');
+    expect(states[states.length - 1].snapshot.status).toBe('failed');
   });
 
   it('reads the current target again on retry', () => {
@@ -137,7 +137,7 @@ describe('NotebookCoreReadHost', () => {
   });
 
   it('tears down exactly once and ignores everything afterwards', () => {
-    const { host, received, connectedStatus$, sent, replyNote, completions } = 
setup();
+    const { host, received, connectedStatus$, sent, replyNote, states, 
completions } = setup();
     host.open({ kind: 'note', noteId: 'A' });
 
     host.dispose();
@@ -148,7 +148,7 @@ describe('NotebookCoreReadHost', () => {
     connectedStatus$.next(false);
     connectedStatus$.next(true);
 
-    expect(host.port.getSnapshot().status).toBe('disposed');
+    expect(states[states.length - 1].snapshot.status).toBe('disposed');
     expect(completions()).toBe(1);
     expect(sent).toEqual(['GET_NOTE A']);
     expect(received.observed).toBe(false);
diff --git 
a/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read.component.testbed.spec.ts
 
b/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read.component.testbed.spec.ts
index 780d3afc37..ec114871d3 100644
--- 
a/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read.component.testbed.spec.ts
+++ 
b/zeppelin-web-angular/src/app/pages/workspace/notebook/core-read/notebook-core-read.component.testbed.spec.ts
@@ -26,6 +26,7 @@ import { TicketService } from 
'@zeppelin/services/ticket.service';
 
 import { NotebookCoreReadComponent } from './notebook-core-read.component';
 import template from './notebook-core-read.component.html?raw';
+import { NotebookCoreReadState } from './notebook-core-read-host';
 
 @Component({
   selector: 'zeppelin-notebook-paragraph-result',
@@ -142,6 +143,8 @@ describe('NotebookCoreReadComponent', () => {
     reply(noteMessage('A', lastMsgId()));
     const { host } = fixture.componentInstance;
     const dispose = vi.spyOn(host, 'dispose');
+    const states: NotebookCoreReadState[] = [];
+    host.state$.subscribe(state => states.push(state));
     const sentBefore = sent.length;
 
     fixture.destroy();
@@ -149,7 +152,7 @@ describe('NotebookCoreReadComponent', () => {
     messageService.connectedStatus$.next(true);
 
     expect(dispose).toHaveBeenCalledTimes(1);
-    expect(host.port.getSnapshot().status).toBe('disposed');
+    expect(states[states.length - 1].snapshot.status).toBe('disposed');
     expect(sent).toHaveLength(sentBefore);
   });
 });
diff --git 
a/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.spec.ts
 
b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.spec.ts
index 1d8f07926f..f646ac5cea 100644
--- 
a/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.spec.ts
+++ 
b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.spec.ts
@@ -87,12 +87,12 @@ describe('NotebookComponent', () => {
   it('ignores stale interpreter bindings replies', () => {
     const { component } = createComponent();
 
-    const originalBindings = [{ id: 'existing', selected: true }];
-    component.interpreterBindings = originalBindings as typeof 
component.interpreterBindings;
+    const originalBindings = [{ id: 'existing', name: 'Existing', selected: 
true, interpreters: [] }];
+    component.interpreterBindings = originalBindings;
 
     const data: MessageReceiveDataTypeMap[OP.INTERPRETER_BINDINGS] = {
       noteId: 'note-a',
-      interpreterBindings: [{ id: 'stale', selected: false }]
+      interpreterBindings: [{ id: 'stale', name: 'Stale', selected: false, 
interpreters: [] }]
     };
 
     component.loadInterpreterBindings(data);
@@ -136,12 +136,14 @@ describe('NotebookComponent', () => {
 
     const data: MessageReceiveDataTypeMap[OP.INTERPRETER_BINDINGS] = {
       noteId: 'note-b',
-      interpreterBindings: [{ id: 'current', selected: true }]
+      interpreterBindings: [{ id: 'current', name: 'Current', selected: true, 
interpreters: [] }]
     };
 
     component.loadInterpreterBindings(data);
 
-    expect(component.interpreterBindings).toEqual([{ id: 'current', selected: 
true }]);
+    expect(component.interpreterBindings).toEqual([
+      { id: 'current', name: 'Current', selected: true, interpreters: [] }
+    ]);
   });
 
   it('applies revision history for the active note', () => {
@@ -179,8 +181,22 @@ describe('NotebookComponent', () => {
     const { component, messageService } = createComponent();
 
     component.note = {
-      paragraphs: []
-    } as typeof component.note;
+      id: 'note-b',
+      name: 'Notebook',
+      path: '/Notebook',
+      defaultInterpreterGroup: 'spark',
+      paragraphs: [],
+      noteParams: {},
+      noteForms: {},
+      angularObjects: {},
+      config: {
+        releaseresource: false,
+        isZeppelinNotebookCronEnable: false,
+        looknfeel: 'default',
+        personalizedMode: 'false'
+      },
+      info: {}
+    };
 
     const message: WebSocketMessage<MessageReceiveDataTypeMap, 
OP.PARAGRAPH_ADDED> = {
       op: OP.PARAGRAPH_ADDED,
diff --git 
a/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.spec.ts
 
b/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.spec.ts
index a0cda74b8d..f870c9d742 100644
--- 
a/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.spec.ts
+++ 
b/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.spec.ts
@@ -73,19 +73,43 @@ const createChart = (): ScatterFixture => {
 
   const chart = new G2.Chart({ container, width: 600, height: 400, renderer: 
'svg', animate: false });
   component.chart = chart;
-  const points = (): MappedPoint[] =>
-    chart
-      .get('geoms')[0]
-      .get('dataArray')
+  const points = (): MappedPoint[] => {
+    const dataArray = chart.get('geoms')[0].get('dataArray');
+    if (!dataArray) {
+      throw new Error('Expected rendered scatter data');
+    }
+    return dataArray
       .flat()
+      .map(point => {
+        const { x, y, color, size } = point;
+        if (
+          typeof x !== 'number' ||
+          typeof y !== 'number' ||
+          typeof color !== 'string' ||
+          (size !== undefined && typeof size !== 'number')
+        ) {
+          throw new Error('Expected a mapped scatter point with scalar 
positions, color and optional size');
+        }
+        return { x, y, color, size };
+      })
       .sort((a: MappedPoint, b: MappedPoint) => a.x - b.x);
-  const radii = (): number[] =>
-    chart
-      .get('geoms')[0]
-      .get('shapeContainer')
+  };
+  const radii = (): number[] => {
+    const shapeContainer = chart.get('geoms')[0].get('shapeContainer');
+    if (!shapeContainer) {
+      throw new Error('Expected a rendered scatter shape container');
+    }
+    return shapeContainer
       .get('children')
-      .map((shape: { attr: (name: string) => number }) => shape.attr('radius'))
+      .map(shape => {
+        const radius = shape.attr('radius');
+        if (typeof radius !== 'number') {
+          throw new Error('Expected a rendered scatter marker with a numeric 
radius');
+        }
+        return radius;
+      })
       .sort((a: number, b: number) => a - b);
+  };
 
   const selectSize = (name?: string) => {
     config.setting.scatterChart!.size = name ? field(name, 
table.columns.indexOf(name)) : undefined;
@@ -144,9 +168,7 @@ describe('ScatterChartVisualizationComponent point sizes', 
() => {
             .map((item: { name: string; value: string }) => ({ name: 
item.name, value: item.value }))
         );
     const legendItems = () => {
-      const legends: Record<string, Array<{ get: (name: string) => unknown }>> 
= fixture.chart.get(
-        'legendController'
-      ).legends;
+      const legends = fixture.chart.get('legendController').legends;
       return Object.values(legends)
         .flat()
         .map(legend => legend.get('items'));
diff --git a/zeppelin-web-angular/src/tsconfig.spec.json 
b/zeppelin-web-angular/src/tsconfig.spec.json
index 07cf05eef6..60953fc6d0 100644
--- a/zeppelin-web-angular/src/tsconfig.spec.json
+++ b/zeppelin-web-angular/src/tsconfig.spec.json
@@ -2,14 +2,17 @@
   "extends": "./tsconfig.json",
   "compilerOptions": {
     "outDir": "../out-tsc/spec",
-    "types": ["mathjax", "node"]
+    "types": ["mathjax", "node"],
+    "lib": ["es2018", "dom", "dom.iterable"]
   },
+  "files": ["../node_modules/vite/client.d.ts"],
   "include": [
     "**/*.spec.ts",
     "../projects/zeppelin-notebook-core/**/*.spec.ts",
     "../projects/zeppelin-sdk/**/*.spec.ts",
     "../projects/zeppelin-visualization/**/*.spec.ts",
     "../test/**/*.spec.ts",
+    "../test/**/*.d.ts",
     "../test/test-setup.ts",
     "../vitest.notebook-core.config.mts",
     "../vitest.shell.config.mts"
diff --git a/zeppelin-web-angular/test/g2-dependency-compatibility.spec.ts 
b/zeppelin-web-angular/test/g2-dependency-compatibility.spec.ts
index 370ed1af96..1f98593c18 100644
--- a/zeppelin-web-angular/test/g2-dependency-compatibility.spec.ts
+++ b/zeppelin-web-angular/test/g2-dependency-compatibility.spec.ts
@@ -28,7 +28,7 @@ describe('G2 dependency compatibility', () => {
       chart.interval().position('category*value').color('category');
       chart.render();
       expect(container.querySelector('svg')).not.toBeNull();
-      
expect(chart.get('geoms')[0].get('shapeContainer').get('children')).toHaveLength(2);
+      
expect(chart.get('geoms')[0].get('shapeContainer')?.get('children')).toHaveLength(2);
     } finally {
       chart.destroy();
       container.remove();
diff --git a/zeppelin-web-angular/test/g2-test-types.d.ts 
b/zeppelin-web-angular/test/g2-test-types.d.ts
new file mode 100644
index 0000000000..e3190cf9af
--- /dev/null
+++ b/zeppelin-web-angular/test/g2-test-types.d.ts
@@ -0,0 +1,36 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import type { TooltipItem } from '@antv/g2';
+
+// G2 3.5.x ships declarations validated against 3.0.4. These runtime APIs
+// are used by the shell tests but are absent from those declarations.
+declare module '@antv/g2' {
+  interface ChartProps {
+    renderer: 'canvas' | 'svg';
+  }
+
+  interface Chart {
+    get(name: 'geoms'): Geom[];
+    get(name: 'legendController'): {
+      legends: Record<string, Array<{ get(name: 'items'): unknown }>>;
+    };
+    getTooltipItems(point: { x: number; y: number }): Array<Pick<TooltipItem, 
'name' | 'value'>>;
+  }
+
+  interface Geom {
+    get(name: 'dataArray'): Array<Array<Record<string, unknown>>> | undefined;
+    get(name: 'shapeContainer'): {
+      get(name: 'children'): Array<{ attr(name: 'radius'): unknown }>;
+    } | null;
+  }
+}

Reply via email to