Back to Repositories

Testing DNS Monitor Form Condition Management in Uptime Kuma

This test suite validates the monitor form functionality in Uptime Kuma, focusing on DNS monitoring conditions and UI interactions. The tests verify condition management, successful DNS resolution, and failure handling scenarios.

Test Coverage Overview

The test suite provides comprehensive coverage of the monitor form functionality:

  • UI condition management (adding/removing conditions and groups)
  • DNS NS record validation with multiple conditions
  • Error handling for invalid DNS entries
  • Monitor status verification for both success and failure cases

Implementation Analysis

The testing approach utilizes Playwright’s modern testing capabilities with async/await patterns. The implementation leverages custom utility functions for monitor type selection and SQLite snapshot restoration, ensuring consistent test environments.

Key patterns include test isolation through beforeEach hooks, screenshot captures for visual verification, and explicit wait conditions for UI state changes.

Technical Details

  • Testing Framework: Playwright with Jest
  • Utilities: Custom monitor selection helper, login utility, SQLite snapshot restoration
  • Test Data: Example DNS queries using iana-servers.net
  • Assertions: Element visibility, count verification, text content matching

Best Practices Demonstrated

The test suite exemplifies several testing best practices including proper test isolation, clear test case organization, and comprehensive error handling.

  • Modular test helper functions
  • Consistent state management between tests
  • Visual regression testing through screenshots
  • Clear test case descriptions and expectations

louislam/uptime-kuma

test/e2e/specs/monitor-form.spec.js

            
import { expect, test } from "@playwright/test";
import { login, restoreSqliteSnapshot, screenshot } from "../util-test";

/**
 * Selects the monitor type from the dropdown.
 * @param {import('@playwright/test').Page} page - The Playwright page instance.
 * @param {string} monitorType - The monitor type to select (default is "dns").
 * @returns {Promise<void>} - A promise that resolves when the monitor type is selected.
 */
async function selectMonitorType(page, monitorType = "dns") {
    const monitorTypeSelect = page.getByTestId("monitor-type-select");
    await expect(monitorTypeSelect).toBeVisible();
    await monitorTypeSelect.selectOption(monitorType);

    const selectedValue = await monitorTypeSelect.evaluate((select) => select.value);
    expect(selectedValue).toBe(monitorType);
}

test.describe("Monitor Form", () => {
    test.beforeEach(async ({ page }) => {
        await restoreSqliteSnapshot(page);
    });

    test("condition ui", async ({ page }, testInfo) => {
        await page.goto("./add");
        await login(page);
        await screenshot(testInfo, page);
        await selectMonitorType(page);

        await page.getByTestId("add-condition-button").click();
        expect(await page.getByTestId("condition").count()).toEqual(1); // 1 explicitly added

        await page.getByTestId("add-group-button").click();
        expect(await page.getByTestId("condition-group").count()).toEqual(1);
        expect(await page.getByTestId("condition").count()).toEqual(2); // 1 solo conditions + 1 condition in group

        await screenshot(testInfo, page);

        await page.getByTestId("remove-condition").first().click();
        expect(await page.getByTestId("condition").count()).toEqual(1); // 0 solo condition + 1 condition in group

        await page.getByTestId("remove-condition-group").first().click();
        expect(await page.getByTestId("condition-group").count()).toEqual(0);

        await screenshot(testInfo, page);
    });

    test("successful condition", async ({ page }, testInfo) => {
        await page.goto("./add");
        await login(page);
        await screenshot(testInfo, page);
        await selectMonitorType(page);

        const friendlyName = "Example DNS NS";
        await page.getByTestId("friendly-name-input").fill(friendlyName);
        await page.getByTestId("hostname-input").fill("example.com");

        const resolveTypeSelect = page.getByTestId("resolve-type-select");
        await resolveTypeSelect.click();
        await resolveTypeSelect.getByRole("option", { name: "NS" }).click();

        await page.getByTestId("add-condition-button").click();
        expect(await page.getByTestId("condition").count()).toEqual(1); // 1 explicitly added

        await page.getByTestId("add-condition-button").click();
        expect(await page.getByTestId("condition").count()).toEqual(2); // 2 explicitly added

        await page.getByTestId("condition-value").nth(0).fill("a.iana-servers.net");
        await page.getByTestId("condition-and-or").nth(0).selectOption("or");
        await page.getByTestId("condition-value").nth(1).fill("b.iana-servers.net");

        await screenshot(testInfo, page);
        await page.getByTestId("save-button").click();
        await page.waitForURL("/dashboard/*");

        expect(page.getByTestId("monitor-status")).toHaveText("up", { ignoreCase: true });

        await screenshot(testInfo, page);
    });

    test("failing condition", async ({ page }, testInfo) => {
        await page.goto("./add");
        await login(page);
        await screenshot(testInfo, page);
        await selectMonitorType(page);

        const friendlyName = "Example DNS NS";
        await page.getByTestId("friendly-name-input").fill(friendlyName);
        await page.getByTestId("hostname-input").fill("example.com");

        const resolveTypeSelect = page.getByTestId("resolve-type-select");
        await resolveTypeSelect.click();
        await resolveTypeSelect.getByRole("option", { name: "NS" }).click();

        await page.getByTestId("add-condition-button").click();
        expect(await page.getByTestId("condition").count()).toEqual(1); // 1 explicitly added

        await page.getByTestId("condition-value").nth(0).fill("definitely-not.net");

        await screenshot(testInfo, page);
        await page.getByTestId("save-button").click();
        await page.waitForURL("/dashboard/*");

        expect(page.getByTestId("monitor-status")).toHaveText("down", { ignoreCase: true });

        await screenshot(testInfo, page);
    });
});