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

rahulvats pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new e6cdee07f54 Feat : Verify DAG source codetab functionality(#59546) 
(#62290)
e6cdee07f54 is described below

commit e6cdee07f54ffe9e7a5300d4976424cce1332ea7
Author: Harsh Thakur <[email protected]>
AuthorDate: Wed Feb 25 12:25:44 2026 +0530

    Feat : Verify DAG source codetab functionality(#59546) (#62290)
---
 .../src/airflow/ui/tests/e2e/pages/DagCodePage.ts  | 102 +++++++++++++++++++++
 .../ui/tests/e2e/specs/dag-code-tab.spec.ts        |  49 ++++++++++
 2 files changed, 151 insertions(+)

diff --git a/airflow-core/src/airflow/ui/tests/e2e/pages/DagCodePage.ts 
b/airflow-core/src/airflow/ui/tests/e2e/pages/DagCodePage.ts
new file mode 100644
index 00000000000..7895b4ceb78
--- /dev/null
+++ b/airflow-core/src/airflow/ui/tests/e2e/pages/DagCodePage.ts
@@ -0,0 +1,102 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 { expect, type Locator, type Page } from "@playwright/test";
+import { BasePage } from "tests/e2e/pages/BasePage";
+
+export class DagCodePage extends BasePage {
+  public readonly editorContainer: Locator;
+  public readonly editorScrollable: Locator;
+  public readonly lineNumbers: Locator;
+  public readonly syntaxTokens: Locator;
+
+  public constructor(page: Page) {
+    super(page);
+    this.editorContainer = page.locator('[role="code"]');
+    this.lineNumbers = page.locator(".monaco-editor .line-numbers");
+    this.editorScrollable = page.locator(".monaco-scrollable-element");
+    this.syntaxTokens = page.locator(".monaco-editor .view-line span span");
+  }
+
+  public async navigateToCodeTab(dagId: string): Promise<void> {
+    await this.navigateTo(`/dags/${dagId}/code`);
+    await this.waitForCodeReady();
+  }
+  public async verifyCodeIsScrollable(): Promise<void> {
+    await this.waitForCodeReady();
+
+    const scrollable = this.editorScrollable.first();
+
+    await expect(scrollable).toBeVisible({ timeout: 30_000 });
+
+    // For a sufficiently long file the scroll-height exceeds the client-height
+    const isScrollable = await scrollable.evaluate((el) => el.scrollHeight > 
el.clientHeight);
+
+    expect(isScrollable).toBe(true);
+  }
+
+  public async verifyLineNumbersDisplayed(): Promise<void> {
+    await this.waitForCodeReady();
+
+    await expect(this.lineNumbers.first()).toBeVisible({ timeout: 30_000 });
+
+    const lineNumberCount = await this.lineNumbers.count();
+
+    expect(lineNumberCount).toBeGreaterThan(0);
+
+    const firstLineText = await this.lineNumbers.first().textContent();
+
+    expect(firstLineText?.trim()).toBe("1");
+  }
+
+  public async verifySourceCodeDisplayed(): Promise<void> {
+    await this.waitForCodeReady();
+
+    const viewLines = this.page.locator(".monaco-editor .view-line");
+
+    await expect(viewLines.first()).toBeVisible({ timeout: 30_000 });
+
+    const lineCount = await viewLines.count();
+
+    expect(lineCount).toBeGreaterThan(0);
+  }
+
+  public async verifySyntaxHighlighting(): Promise<void> {
+    await this.waitForCodeReady();
+
+    const tokens = this.syntaxTokens;
+
+    await expect(tokens.first()).toBeVisible({ timeout: 30_000 });
+
+    const tokenCount = await tokens.count();
+
+    expect(tokenCount).toBeGreaterThan(1);
+
+    const classNames = await tokens.first().getAttribute("class");
+
+    expect(classNames).toMatch(/mtk\d+/);
+  }
+
+  private async waitForCodeReady(): Promise<void> {
+    await this.editorContainer.waitFor({ state: "visible", timeout: 60_000 });
+
+    const viewLines = this.page.locator(".monaco-editor .view-line");
+
+    await viewLines.first().waitFor({ state: "visible", timeout: 30_000 });
+  }
+}
diff --git a/airflow-core/src/airflow/ui/tests/e2e/specs/dag-code-tab.spec.ts 
b/airflow-core/src/airflow/ui/tests/e2e/specs/dag-code-tab.spec.ts
new file mode 100644
index 00000000000..f4577873e42
--- /dev/null
+++ b/airflow-core/src/airflow/ui/tests/e2e/specs/dag-code-tab.spec.ts
@@ -0,0 +1,49 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 { test } from "@playwright/test";
+import { testConfig } from "playwright.config";
+
+import { DagCodePage } from "../pages/DagCodePage";
+
+test.describe("DAG Code Tab", () => {
+  test.setTimeout(60_000);
+  const dagId = testConfig.testDag.id;
+  let codePage: DagCodePage;
+
+  test.beforeEach(async ({ page }) => {
+    codePage = new DagCodePage(page);
+    await codePage.navigateToCodeTab(dagId);
+  });
+
+  test("Verify DAG source code is displayed", async () => {
+    await codePage.verifySourceCodeDisplayed();
+  });
+
+  test("Verify syntax highlighting is applied", async () => {
+    await codePage.verifySyntaxHighlighting();
+  });
+
+  test("Verify code is scrollable for long files", async () => {
+    await codePage.verifyCodeIsScrollable();
+  });
+
+  test("Verify line numbers are displayed", async () => {
+    await codePage.verifyLineNumbersDisplayed();
+  });
+});

Reply via email to