vorteil/direktiv

View on GitHub
ui/e2e/settings/index.spec.ts

Summary

Maintainability
A
2 hrs
Test Coverage
import { createNamespace, deleteNamespace } from "../utils/namespace";
import { expect, test } from "@playwright/test";

import { createRegistries } from "../utils/registries";
import { createSecrets } from "../utils/secrets";
import { createVariables } from "../utils/variables";
import { decode } from "js-base64";
import { faker } from "@faker-js/faker";
import { radixClick } from "../utils/testutils";
import { waitForSuccessToast } from "../explorer/workflow/utils";

let namespace = "";

test.beforeEach(async () => {
  namespace = await createNamespace();
});

test.afterEach(async () => {
  await deleteNamespace(namespace);
  namespace = "";
});

test("it renders secrets, variables and registries", async ({ page }) => {
  const secrets = await createSecrets(namespace, 6);
  const registries = await createRegistries(namespace, 4);
  const variables = await createVariables(namespace);

  await page.goto(`/n/${namespace}/settings`);

  await expect(
    page
      .getByTestId("secrets-section")
      .getByRole("heading", { name: "Secrets" })
  ).toBeVisible();

  await expect(
    page.getByTestId("secrets-section").getByTestId("item-name")
  ).toHaveCount(secrets.length);

  await expect(
    page
      .getByTestId("registries-section")
      .getByRole("heading", { name: "Registries" })
  ).toBeVisible();

  await expect(
    page.getByTestId("registries-section").getByTestId("item-name")
  ).toHaveCount(registries.length);

  await expect(
    page
      .getByTestId("variables-section")
      .getByRole("heading", { name: "Variables" })
  ).toBeVisible();

  await expect(
    page.getByTestId("variables-section").getByTestId("item-name")
  ).toHaveCount(variables.length);
});

test("it is possible to create and delete secrets", async ({ page }) => {
  const secrets = await createSecrets(namespace, 3);
  const firstSecretName = secrets[0]?.data.name;
  const secretToDelete = secrets[1];

  // avoid typescript errors below
  if (!secretToDelete || !firstSecretName) throw "error setting up test data";

  await page.goto(`/n/${namespace}/settings`);
  await page.getByTestId("secret-create").click();
  const newSecret = {
    name: faker.internet.domainWord(),
    value: faker.random.alphaNumeric(20),
  };

  await page.getByPlaceholder("secret-name").type(firstSecretName);
  await page.locator("textarea").type(newSecret.value);
  await page.getByRole("button", { name: "Create" }).click();

  await expect(
    page.getByText("The name already exists"),
    "it renders an error message when using a name that already exists"
  ).toBeVisible();

  await page.getByPlaceholder("secret-name").type(newSecret.name);
  await page.getByRole("button", { name: "Create" }).click();

  await waitForSuccessToast(page);

  const secretElements = page.getByTestId("item-name");
  await expect(secretElements, "number of secrets should be 4").toHaveCount(4);

  await page
    .getByTestId(`dropdown-trg-item-${secretToDelete.data.name}`)
    .click();

  await page.getByTestId("dropdown-actions-delete").click();
  await page.getByRole("button", { name: "Delete" }).click();

  await waitForSuccessToast(page);
  await expect(secretElements, "number of secrets should be 3").toHaveCount(3);

  await expect(
    secretElements.filter({ hasText: newSecret.name }),
    "there should remain the newly created secret in the list"
  ).toBeVisible();
  await expect(
    secretElements.filter({ hasText: `${secretToDelete.data.name}` }),
    "the deleted item shouldn't be in the list"
  ).toBeHidden();
});

test("it is possible to create and delete registries", async ({ page }) => {
  const registries = await createRegistries(namespace, 3);
  const registryToDelete = registries[2];

  // avoid typescript errors below
  if (!registryToDelete) throw "error setting up test data";

  await page.goto(`/n/${namespace}/settings`);
  await page.getByTestId("registry-create").click();

  const newRegistry = {
    url: faker.internet.url(),
    user: faker.internet.userName(),
    password: faker.internet.password(),
  };

  await page.getByTestId("new-registry-url").type(newRegistry.url);
  await page.getByTestId("new-registry-pwd").type(newRegistry.password);
  await page.getByTestId("new-registry-user").type(newRegistry.user);

  await page.getByTestId("registry-create-submit").click();
  await waitForSuccessToast(page);

  const registryElements = page.getByTestId("item-name");
  await expect(
    registryElements,
    "number of registry elements rendered should be 4"
  ).toHaveCount(4);

  await page.getByTestId(`dropdown-trg-item-${registryToDelete.url}`).click();
  await page.getByTestId("dropdown-actions-delete").click();
  await page.getByTestId("registry-delete-confirm").click();

  await waitForSuccessToast(page);
  await expect(
    registryElements,
    "number of registry elements rendered should be 3"
  ).toHaveCount(3);

  await expect(
    registryElements.filter({ hasText: newRegistry.url }),
    "there should remain the newly created registry in the list"
  ).toHaveCount(1);
  await expect(
    registryElements.filter({ hasText: registryToDelete.url }),
    "the deleted item shouldn't be in the list"
  ).toHaveCount(0);
});

test("it is possible to create and delete variables", async ({
  page,
  browserName,
}) => {
  /* set up test data */
  const variables = await createVariables(namespace, 3);
  const variableToDelete = variables[2];

  if (!variableToDelete) throw "error setting up test data";

  /* visit page and edit variable*/
  await page.goto(`/n/${namespace}/settings`);
  await page.getByTestId("variable-create").click();

  await page.getByTestId("variable-name").type("awesome-variable");

  await page.locator(".view-lines").click();
  await page.locator(".view-lines").type("<div>Hello world</div>");
  await page.getByLabel("Mimetype").click();
  await page.getByLabel("HTML").click();
  await page.getByRole("button", { name: "create" }).click();
  await waitForSuccessToast(page);

  /* reload and make sure changes have been persisted */
  await page.reload({
    waitUntil: "networkidle",
  });

  await page.getByTestId("dropdown-trg-item-awesome-variable").click();
  await page.getByTestId("dropdown-actions-edit").click();

  await expect(
    page.locator(".view-lines"),
    "the variable's content is loaded into the editor"
  ).toContainText("<div>Hello world</div>");

  await expect(
    page.locator("select"),
    "MimeTypeSelect is set to the subject's mimeType"
  ).toHaveValue("text/html");

  const cancelButton = page.getByRole("button", { name: "Cancel" });
  await radixClick(browserName, cancelButton);

  /* delete one variable */
  await expect(
    page.getByTestId("item-name"),
    "there are 4 variables"
  ).toHaveCount(4);

  await page
    .getByTestId(`dropdown-trg-item-${variableToDelete.data.name}`)
    .click();
  await page.getByTestId("dropdown-actions-delete").click();
  await page.getByTestId("registry-delete-confirm").click();

  await waitForSuccessToast(page);
  await expect(
    page.getByTestId("item-name"),
    "after deleting a variable, there are 3 variables left"
  ).toHaveCount(3);

  await expect(
    page
      .getByTestId("item-name")
      .filter({ hasText: variableToDelete.data.name }),
    "the deleted variable is no longer in the list"
  ).toHaveCount(0);

  await expect(
    page.getByTestId("item-name").filter({ hasText: "awesome-variable" }),
    "the new variable is still in the list"
  ).toHaveCount(1);
});

test("it is possible to edit variables", async ({ page }) => {
  /* set up test data */
  const variables = await createVariables(namespace, 3);
  const subject = variables[2];

  const newName = "new-name";

  if (!subject) throw "There was an error setting up test data";

  /* visit page and edit variable */
  await page.goto(`/n/${namespace}/settings`);
  await page.getByTestId(`dropdown-trg-item-${subject.data.name}`).click();
  await page.getByRole("button", { name: "edit" }).click();

  const textArea = page
    .getByTestId("variable-editor-card")
    .getByRole("textbox");

  await expect
    .poll(
      async () => await textArea.inputValue(),
      "the variable's content is loaded into the editor"
    )
    .toBe(decode(subject.content));

  await page.getByTestId("variable-name").fill(newName);

  await expect(
    page.locator("select"),
    "MimeTypeSelect is set to the subject's mimeType"
  ).toHaveValue(subject.data.mimeType);

  await page.locator(".view-lines").click();
  await page.locator(".view-lines").click();

  /* delete and replace existing content */
  for (let i = 0; i < subject.content.length; i++) {
    await page.locator(".view-lines").press("Backspace");
  }

  await page.locator(".view-lines").type("data: this is supposed to be YAML");
  await page.getByLabel("Mimetype").click();
  await page.getByLabel("YAML").click();

  await page.getByRole("button", { name: "save" }).click();
  await waitForSuccessToast(page);

  /* reload and make sure changes have been persisted */
  await page.reload({
    waitUntil: "networkidle",
  });

  await page.getByTestId(`dropdown-trg-item-${newName}`).click();
  await page.getByRole("button", { name: "edit" }).click();

  await expect
    .poll(
      async () => await textArea.inputValue(),
      "the updated variable content is loaded into the editor"
    )
    .toBe("data: this is supposed to be YAML");

  await expect(
    await page.getByTestId("variable-name").inputValue(),
    "the updated variable name is shown in the name input"
  ).toBe(newName);

  await expect(
    page.locator("select"),
    "MimeTypeSelect is set to the updated mimeType"
  ).toHaveValue("application/yaml");
});

test("it is not possible to create a variable with a name that already exists", async ({
  page,
}) => {
  /* set up test data */
  const variables = await createVariables(namespace, 3);
  const reservedName = variables[0]?.data.name ?? "";

  await page.goto(`/n/${namespace}/settings`);
  await page.getByTestId("variable-create").click();

  page.getByTestId("variable-name").fill(reservedName);

  await page.getByRole("button", { name: "Create" }).click();

  await expect(
    page.getByText("The name already exists"),
    "it renders an error message"
  ).toBeVisible();
});

test("it is not possible to set a variables name to a name that already exists", async ({
  page,
}) => {
  /* set up test data */
  const variables = await createVariables(namespace, 3);
  const subject = variables[2];

  if (!subject) throw "There was an error setting up test data";

  const reservedName = variables[0]?.data.name ?? "";

  await page.goto(`/n/${namespace}/settings`);
  await page.getByTestId(`dropdown-trg-item-${subject.data.name}`).click();
  await page.getByRole("button", { name: "edit" }).click();

  page.getByTestId("variable-name").fill(reservedName);

  await page.getByRole("button", { name: "Save" }).click();

  await expect(
    page.getByText("The name already exists"),
    "it renders an error message"
  ).toBeVisible();
});