Yicong-Huang commented on code in PR #5170:
URL: https://github.com/apache/texera/pull/5170#discussion_r3294120800


##########
frontend/TESTING.md:
##########
@@ -0,0 +1,340 @@
+# Frontend testing guide
+
+Canonical reference for writing, running, and maintaining unit tests in 
`frontend/`. Written for both human contributors and AI agents — read it on 
demand when [`AGENTS.md`](AGENTS.md)'s rules need a deeper recipe, the mental 
model behind a constraint, or troubleshooting steps.
+
+For repo-wide testing philosophy (TDD, characterization tests, "every test 
must cover a specific failure mode") see [`../AGENTS.md`](../AGENTS.md) "Tests 
come first".
+
+## Contents
+
+1. [The stack](#the-stack)
+2. [Running tests](#running-tests)
+3. [Why `detectChanges()` is the coverage 
switch](#why-detectchanges-is-the-coverage-switch)
+4. [Recipes](#recipes)
+5. [Standalone components](#standalone-components)
+6. [jsdom vs browser mode](#jsdom-vs-browser-mode)
+7. [Mocking](#mocking)
+8. [Anti-patterns](#anti-patterns)
+9. [Coverage troubleshooting](#coverage-troubleshooting)
+10. [References](#references)
+
+## The stack
+
+| Layer                    | Choice                                            
                                                                                
     |
+| ------------------------ | 
--------------------------------------------------------------------------------------------------------------------------------------
 |
+| Test framework           | Vitest                                            
                                                                                
     |
+| Angular test integration | `@angular/build:unit-test` builder (two targets 
in `angular.json`: `gui:test` and `gui:test-browser`)                           
       |
+| Default DOM              | jsdom                                             
                                                                                
     |
+| Real-browser DOM         | `@vitest/browser` + Playwright (Chromium, 
headless)                                                                       
             |
+| Coverage                 | `@vitest/coverage-v8`                             
                                                                                
     |
+| Test setup               | `src/test-zone-setup.ts` wraps `it`/`test` in an 
Angular ProxyZone (Vitest does not provide one and Angular's `fakeAsync` 
requires it) |
+| Globals                  | `globals: true` in `vitest.config.ts`, so 
`describe / it / expect / vi / beforeEach` come from the runtime — no per-file 
imports       |
+
+`src/main.test.ts` is intentionally a near-empty `export {}`. The `unit-test` 
builder uses `buildTarget`'s `main` to seed the bundle graph; if it pointed at 
the real `main.ts`, every component declared in `AppModule` would be 
type-checked for every spec, surfacing template errors for components no active 
spec touches. Keeping `main.test.ts` empty narrows the graph to what each spec 
actually imports.
+
+## Running tests
+
+```bash
+# default — jsdom, watch off
+yarn test
+
+# the same, with coverage in lcov form (CI shape)
+yarn test:ci
+
+# only the specs routed to real browser DOM (Playwright Chromium)
+ng run gui:test-browser
+
+# coverage report you can open in a browser
+yarn test -- --coverage --coverage.reporter=html
+# then open coverage/index.html
+```
+
+Single-file and watch loops use Vitest's own filtering:
+
+```bash
+ng test --test-file 
src/app/workspace/component/workflow-editor/mini-map/mini-map.component.spec.ts
+```
+
+## Why `detectChanges()` is the coverage switch
+
+Angular's Ivy compiler turns each component template into a TypeScript 
function:
+
+```ts
+function MiniMapComponent_Template(rf, ctx) {
+  if (rf & 1) {
+    // creation pass
+    ɵɵelementStart(0, "div");
+    ɵɵlistener("click", () => ctx.onClick());
+    ɵɵtext(1);
+    ɵɵelementEnd();
+  }
+  if (rf & 2) {
+    // update pass
+    ɵɵadvance(1);
+    ɵɵtextInterpolate(ctx.label);
+  }
+}
+```
+
+This function is **not** invoked by the component constructor; it runs only 
during change detection. The Vite build emits source maps that map each `ɵɵ…` 
call back to the `.html` line that produced it, and v8 coverage records hits 
against that source-mapped location.
+
+Consequences:
+
+- `TestBed.createComponent(C)` alone covers the constructor but leaves the 
template at 0 %.
+- A single `fixture.detectChanges()` runs the creation pass and the first 
update pass; most ordinary `.component.html` files jump to 70 – 90 % from this 
one call.
+- Branches gated by `*ngIf="cond"` need a second `detectChanges()` with `cond` 
toggled to cover the other side. The same applies to `*ngFor` over an empty vs 
non-empty array, and to `[ngSwitch]` cases.
+
+If `.component.html` shows 0 % after your spec runs, you almost certainly hit 
one of the [anti-patterns](#anti-patterns) — most often the constructor 
compiled and "should create" passed but `detectChanges` was never reached.
+
+## Recipes
+
+### A. Minimum viable spec
+
+Use this as the starting point for any new component. It already covers the 
template's creation pass.
+
+```ts
+import { ComponentFixture, TestBed } from "@angular/core/testing";
+import { HttpClientTestingModule } from "@angular/common/http/testing";
+import { commonTestProviders } from "../../../common/testing/test-utils";
+import { MyComponent } from "./my.component";
+
+describe("MyComponent", () => {
+  let fixture: ComponentFixture<MyComponent>;
+  let component: MyComponent;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [MyComponent, HttpClientTestingModule],
+      providers: [...commonTestProviders],
+    }).compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(MyComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it("should create", () => {
+    expect(component).toBeTruthy();
+  });
+});
+```
+
+Working reference: 
`src/app/workspace/component/workflow-editor/mini-map/mini-map.component.spec.ts`
 (63 lines, achieves ~87 % template coverage off this pattern alone).

Review Comment:
   Thanks. I think we can delete this line as it is not necessary. 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to