a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
115 lines
3.8 KiB
Go
115 lines
3.8 KiB
Go
package languages
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/zzet/gortex/internal/graph"
|
|
)
|
|
|
|
func TestJSEmitter_NamedHandlerAttributedToHandler(t *testing.T) {
|
|
// A bare emitter (no `events` import) with a named handler: the listen
|
|
// edge attributes to the handler node, not the .on call's enclosing
|
|
// function, so the resolver's synthesized call lands on onReady.
|
|
src := `function onReady() {}
|
|
|
|
function boot(emitter) {
|
|
emitter.on('ready', onReady);
|
|
emitter.emit('ready');
|
|
}
|
|
`
|
|
fix := runJSExtractFixture(t, "app.js", src)
|
|
|
|
events := fix.nodesByKind[graph.KindEvent]
|
|
if len(events) != 1 || events[0].ID != "event::emitter::emitter::ready" {
|
|
t.Fatalf("want 1 emitter topic event::emitter::emitter::ready, got %+v", events)
|
|
}
|
|
if tr, _ := events[0].Meta["transport"].(string); tr != "emitter" {
|
|
t.Errorf("topic transport = %q (want emitter)", tr)
|
|
}
|
|
|
|
listens := fix.edgesByKind[graph.EdgeListensOn]
|
|
if len(listens) != 1 {
|
|
t.Fatalf("want 1 EdgeListensOn, got %d", len(listens))
|
|
}
|
|
if listens[0].From != "app.js::onReady" {
|
|
t.Errorf("listen From = %q (want app.js::onReady — the handler, not the enclosing fn)", listens[0].From)
|
|
}
|
|
|
|
emits := fix.edgesByKind[graph.EdgeEmits]
|
|
if len(emits) != 1 {
|
|
t.Fatalf("want 1 EdgeEmits, got %d", len(emits))
|
|
}
|
|
if emits[0].From != "app.js::boot" {
|
|
t.Errorf("emit From = %q (want app.js::boot — the enclosing fn)", emits[0].From)
|
|
}
|
|
}
|
|
|
|
func TestJSEmitter_AnonymousHandlerFallsBackToEnclosingFn(t *testing.T) {
|
|
// An inline arrow handler has no named node, so the listen edge falls
|
|
// back to the enclosing function — and the topic node still appears.
|
|
src := `function boot(emitter) {
|
|
emitter.on('tick', () => { doWork(); });
|
|
}
|
|
`
|
|
fix := runJSExtractFixture(t, "a.js", src)
|
|
if got := len(fix.nodesByKind[graph.KindEvent]); got != 1 {
|
|
t.Fatalf("anonymous-handler emitter should still produce 1 topic node, got %d", got)
|
|
}
|
|
listens := fix.edgesByKind[graph.EdgeListensOn]
|
|
if len(listens) != 1 {
|
|
t.Fatalf("want 1 EdgeListensOn, got %d", len(listens))
|
|
}
|
|
if listens[0].From != "a.js::boot" {
|
|
t.Errorf("anon handler listen From = %q (want enclosing fn a.js::boot)", listens[0].From)
|
|
}
|
|
}
|
|
|
|
func TestJSEmitter_ImportGatedPathStillWins(t *testing.T) {
|
|
// With the `events` import the import-gated pub/sub path classifies the
|
|
// call, so the emitter-literal fallback must NOT also fire (one node).
|
|
src := `const EventEmitter = require('events');
|
|
|
|
function boot(emitter) {
|
|
emitter.on('ready', onReady);
|
|
emitter.emit('ready');
|
|
}
|
|
`
|
|
fix := runJSExtractFixture(t, "g.js", src)
|
|
events := fix.nodesByKind[graph.KindEvent]
|
|
if len(events) != 1 {
|
|
t.Fatalf("want exactly 1 topic node (no fallback double-emit), got %d: %+v", len(events), events)
|
|
}
|
|
if events[0].ID != "event::pubsub::eventemitter::ready" {
|
|
t.Errorf("topic id = %q (want the import-gated pubsub node)", events[0].ID)
|
|
}
|
|
}
|
|
|
|
func TestJSEmitter_TemplateLiteralEventSkipped(t *testing.T) {
|
|
// A computed / template-literal event name has no stable literal, so
|
|
// no emitter topic node is produced.
|
|
src := "function boot(emitter) {\n emitter.on(`evt-${id}`, cb);\n}\n"
|
|
fix := runJSExtractFixture(t, "t.js", src)
|
|
if got := len(fix.nodesByKind[graph.KindEvent]); got != 0 {
|
|
t.Errorf("template-literal event must produce no topic node, got %d", got)
|
|
}
|
|
}
|
|
|
|
func TestTSEmitter_LiteralFallback(t *testing.T) {
|
|
src := `function boot(bus: any) {
|
|
bus.on('open', onOpen);
|
|
bus.emit('open');
|
|
}
|
|
|
|
function onOpen() {}
|
|
`
|
|
fix := runTSExtractFixture(t, "ws.ts", src)
|
|
events := fix.nodesByKind[graph.KindEvent]
|
|
if len(events) != 1 || events[0].ID != "event::emitter::bus::open" {
|
|
t.Fatalf("want event::emitter::bus::open, got %+v", events)
|
|
}
|
|
listens := fix.edgesByKind[graph.EdgeListensOn]
|
|
if len(listens) != 1 || listens[0].From != "ws.ts::onOpen" {
|
|
t.Errorf("listen From = %v (want ws.ts::onOpen)", listens)
|
|
}
|
|
}
|