diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 2f4bdaecd..c6f33954b 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -19,3 +19,4 @@ - CLI: Watch mode uses correct backlinks (`_` usages) [#2058](https://github.com/terrastruct/d2/pull/2058) - Vars: Spread variables are inserted in place instead of appending to end of scope [#2062](https://github.com/terrastruct/d2/pull/2062) - Imports: fix local icon imports from files that are imported [#2066](https://github.com/terrastruct/d2/pull/2066) +- CLI: fixes edge case of watch mode links to nested board that had more nested boards not working [#2070](https://github.com/terrastruct/d2/pull/2070) diff --git a/d2cli/watch.go b/d2cli/watch.go index 1dfbb5b9e..61b236348 100644 --- a/d2cli/watch.go +++ b/d2cli/watch.go @@ -521,6 +521,7 @@ func (w *watcher) handleRoot(hw http.ResponseWriter, r *http.Request) { boardPath = boardPath[:idx] } // if path is "/index", we just want "/" + boardPath = strings.TrimSuffix(boardPath, "/index") if boardPath == "index" { boardPath = "" } diff --git a/e2etests-cli/main_test.go b/e2etests-cli/main_test.go index d051530fa..d58629912 100644 --- a/e2etests-cli/main_test.go +++ b/e2etests-cli/main_test.go @@ -1045,8 +1045,72 @@ layers: { aRE := regexp.MustCompile(`href=\\"([^\"]*)\\"`) match := aRE.FindSubmatch(msg) assert.Equal(t, 2, len(match)) - assert.Equal(t, "index.svg", string(match[1])) + link := string(match[1]) + + err = getWatchPage(ctx, t, fmt.Sprintf("http://%s/%s", watchURL, link)) + assert.Success(t, err) + _, _, err = c.Read(ctx) + assert.Success(t, err) + successRE := regexp.MustCompile(`broadcasting update to 1 client`) + _, err = waitLogs(ctx, stderr, successRE) + assert.Success(t, err) + }, + }, + { + name: "watch-nested-layer-link", + serial: true, + run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) { + writeFile(t, dir, "index.d2", ` +a: { + link: layers.b +} + +layers: { + b: { + hi + + layers: { + hey: { + hey + } + } + } +}`) + stderr := &stderrWrapper{} + tms := testMain(dir, env, "--watch", "--browser=0", "index.d2") + tms.Stderr = stderr + + tms.Start(t, ctx) + defer func() { + // Manually close, since watcher is daemon + err := tms.Signal(ctx, os.Interrupt) + assert.Success(t, err) + }() + + // Wait for watch server to spin up and listen + urlRE := regexp.MustCompile(`127.0.0.1:([0-9]+)`) + watchURL, err := waitLogs(ctx, stderr, urlRE) + assert.Success(t, err) + + stderr.Reset() + + // Start a client + c, _, err := websocket.Dial(ctx, fmt.Sprintf("ws://%s/watch", watchURL), nil) + assert.Success(t, err) + defer c.CloseNow() + + // Get the link + _, msg, err := c.Read(ctx) + aRE := regexp.MustCompile(`href=\\"([^\"]*)\\"`) + match := aRE.FindSubmatch(msg) + assert.Equal(t, 2, len(match)) + link := string(match[1]) + + err = getWatchPage(ctx, t, fmt.Sprintf("http://%s/%s", watchURL, link)) + assert.Success(t, err) + _, _, err = c.Read(ctx) + assert.Success(t, err) successRE := regexp.MustCompile(`broadcasting update to 1 client`) _, err = waitLogs(ctx, stderr, successRE) assert.Success(t, err)