mirror of
https://github.com/penpot/penpot.git
synced 2026-02-12 14:42:56 +00:00
267 lines
7.5 KiB
JavaScript
267 lines
7.5 KiB
JavaScript
import { test, expect } from "@playwright/test";
|
|
import { WorkspacePage } from "../../pages/WorkspacePage";
|
|
|
|
const setupEmptyTokensFile = async (page, options = {}) => {
|
|
const { flags = [] } = options;
|
|
|
|
const workspacePage = new WorkspacePage(page);
|
|
if (flags.length > 0) {
|
|
await workspacePage.mockConfigFlags(flags);
|
|
}
|
|
|
|
await workspacePage.setupEmptyFile();
|
|
await workspacePage.mockRPC(
|
|
"get-team?id=*",
|
|
"workspace/get-team-tokens.json",
|
|
);
|
|
|
|
await workspacePage.mockRPC(
|
|
"update-file?id=*",
|
|
"workspace/update-file-create-rect.json",
|
|
);
|
|
|
|
await workspacePage.goToWorkspace({
|
|
fileId: "c7ce0794-0992-8105-8004-38f280443849",
|
|
pageId: "66697432-c33d-8055-8006-2c62cc084cad",
|
|
});
|
|
|
|
const tokensTabButton = page.getByRole("tab", { name: "Tokens" });
|
|
await tokensTabButton.click();
|
|
|
|
return {
|
|
workspacePage,
|
|
tokenThemeUpdateCreateModal: workspacePage.tokenThemeUpdateCreateModal,
|
|
tokensUpdateCreateModal: workspacePage.tokensUpdateCreateModal,
|
|
tokenThemesSetsSidebar: workspacePage.tokenThemesSetsSidebar,
|
|
tokenSetItems: workspacePage.tokenSetItems,
|
|
tokensSidebar: workspacePage.tokensSidebar,
|
|
tokenSetGroupItems: workspacePage.tokenSetGroupItems,
|
|
tokenContextMenuForSet: workspacePage.tokenContextMenuForSet,
|
|
};
|
|
};
|
|
|
|
const setupTokensFile = async (page, options = {}) => {
|
|
const {
|
|
file = "workspace/get-file-tokens.json",
|
|
fileFragment = "workspace/get-file-fragment-tokens.json",
|
|
flags = ["enable-feature-token-input"],
|
|
} = options;
|
|
|
|
const workspacePage = new WorkspacePage(page);
|
|
if (flags.length > 0) {
|
|
await workspacePage.mockConfigFlags(flags);
|
|
}
|
|
|
|
await workspacePage.setupEmptyFile();
|
|
await workspacePage.mockRPC(
|
|
"get-team?id=*",
|
|
"workspace/get-team-tokens.json",
|
|
);
|
|
await workspacePage.mockRPC(/get\-file\?/, file);
|
|
await workspacePage.mockRPC(/get\-file\-fragment\?/, fileFragment);
|
|
await workspacePage.mockRPC(
|
|
"update-file?id=*",
|
|
"workspace/update-file-create-rect.json",
|
|
);
|
|
|
|
await workspacePage.goToWorkspace({
|
|
fileId: "c7ce0794-0992-8105-8004-38f280443849",
|
|
pageId: "66697432-c33d-8055-8006-2c62cc084cad",
|
|
});
|
|
|
|
const tokensTabButton = page.getByRole("tab", { name: "Tokens" });
|
|
await tokensTabButton.click();
|
|
|
|
return {
|
|
workspacePage,
|
|
tokensUpdateCreateModal: workspacePage.tokensUpdateCreateModal,
|
|
tokenThemeUpdateCreateModal: workspacePage.tokenThemeUpdateCreateModal,
|
|
tokenThemesSetsSidebar: workspacePage.tokenThemesSetsSidebar,
|
|
tokenSetItems: workspacePage.tokenSetItems,
|
|
tokenSetGroupItems: workspacePage.tokenSetGroupItems,
|
|
tokensSidebar: workspacePage.tokensSidebar,
|
|
tokenContextMenuForToken: workspacePage.tokenContextMenuForToken,
|
|
tokenContextMenuForSet: workspacePage.tokenContextMenuForSet,
|
|
};
|
|
};
|
|
|
|
const setupTypographyTokensFile = async (page, options = {}) => {
|
|
return setupTokensFile(page, {
|
|
file: "workspace/get-file-typography-tokens.json",
|
|
fileFragment: "workspace/get-file-fragment-typography-tokens.json",
|
|
...options,
|
|
});
|
|
};
|
|
|
|
const testTokenCreationFlow = async (
|
|
page,
|
|
{
|
|
tokenLabel,
|
|
namePlaceholder,
|
|
valuePlaceholder,
|
|
validValue,
|
|
invalidValue,
|
|
selfReferenceValue,
|
|
missingReferenceValue,
|
|
secondValidValue,
|
|
resolvedValueText,
|
|
secondResolvedValueText,
|
|
},
|
|
) => {
|
|
const invalidValueError = "Invalid token value";
|
|
const emptyNameError = "Name should be at least 1 character";
|
|
const selfReferenceError = "Token has self reference";
|
|
const missingReferenceError = "Missing token references";
|
|
|
|
const { tokensUpdateCreateModal, tokenThemesSetsSidebar } =
|
|
await setupEmptyTokensFile(page);
|
|
|
|
// Open modal
|
|
const tokensTabPanel = page.getByRole("tabpanel", { name: "tokens" });
|
|
|
|
const addTokenButton = tokensTabPanel.getByRole("button", {
|
|
name: `Add Token: ${tokenLabel}`,
|
|
});
|
|
|
|
await addTokenButton.click();
|
|
await expect(tokensUpdateCreateModal).toBeVisible();
|
|
|
|
// Placeholder checks
|
|
await expect(
|
|
tokensUpdateCreateModal.getByPlaceholder(namePlaceholder),
|
|
).toBeVisible();
|
|
await expect(
|
|
tokensUpdateCreateModal.getByPlaceholder(valuePlaceholder),
|
|
).toBeVisible();
|
|
|
|
const nameField = tokensUpdateCreateModal.getByLabel("Name");
|
|
const valueField = tokensUpdateCreateModal.getByLabel("Value");
|
|
const submitButton = tokensUpdateCreateModal.getByRole("button", {
|
|
name: "Save",
|
|
});
|
|
|
|
// 1. Name filled + empty value → disabled
|
|
await nameField.fill("my-token");
|
|
await expect(submitButton).toBeDisabled();
|
|
|
|
// 2. Invalid value → disabled + error message
|
|
await valueField.fill(invalidValue);
|
|
|
|
const invalidValueErrorNode =
|
|
tokensUpdateCreateModal.getByText(invalidValueError);
|
|
|
|
await expect(invalidValueErrorNode).toBeVisible();
|
|
await expect(submitButton).toBeDisabled();
|
|
|
|
// 3. Empty name → disabled + error message
|
|
await nameField.fill("");
|
|
|
|
const emptyNameErrorNode = tokensUpdateCreateModal.getByText(emptyNameError);
|
|
|
|
await expect(emptyNameErrorNode).toBeVisible();
|
|
await expect(submitButton).toBeDisabled();
|
|
|
|
// 4. Self reference → disabled + error message
|
|
await nameField.fill("my-token");
|
|
await valueField.fill(selfReferenceValue);
|
|
|
|
const selfRefErrorNode =
|
|
tokensUpdateCreateModal.getByText(selfReferenceError);
|
|
|
|
await expect(selfRefErrorNode).toBeVisible();
|
|
await expect(submitButton).toBeDisabled();
|
|
|
|
// 5. Missing reference → disabled + error message
|
|
await valueField.fill(missingReferenceValue);
|
|
|
|
const missingRefErrorNode = tokensUpdateCreateModal.getByText(
|
|
missingReferenceError,
|
|
);
|
|
|
|
await expect(missingRefErrorNode).toBeVisible();
|
|
await expect(submitButton).toBeDisabled();
|
|
|
|
//
|
|
// ------- SUCCESSFUL CREATION -------
|
|
//
|
|
|
|
// 6. Basic valid value → enabled
|
|
await valueField.fill(validValue);
|
|
await expect(
|
|
tokensUpdateCreateModal.getByText(resolvedValueText),
|
|
).toBeVisible();
|
|
await expect(submitButton).toBeEnabled();
|
|
|
|
await submitButton.click();
|
|
|
|
await expect(
|
|
tokensTabPanel.getByRole("button", { name: "my-token" }),
|
|
).toBeEnabled();
|
|
|
|
//
|
|
// ------- SECOND TOKEN WITH VALID REFERENCE -------
|
|
//
|
|
|
|
await addTokenButton.click();
|
|
|
|
await nameField.fill("my-token-2");
|
|
await valueField.fill(secondValidValue);
|
|
|
|
await expect(
|
|
tokensUpdateCreateModal.getByText(secondResolvedValueText),
|
|
).toBeVisible();
|
|
await expect(submitButton).toBeEnabled();
|
|
|
|
await submitButton.click();
|
|
|
|
await expect(
|
|
tokensTabPanel.getByRole("button", { name: "my-token-2" }),
|
|
).toBeEnabled();
|
|
};
|
|
|
|
const unfoldTokenTree = async (tokensTabPanel, type, tokenName) => {
|
|
const tokenSegments = tokenName.split(".");
|
|
const tokenFolderTree = tokenSegments.slice(0, -1);
|
|
const tokenLeafName = tokenSegments.pop();
|
|
|
|
const typeParentWrapper = tokensTabPanel.getByTestId(`section-${type}`);
|
|
const typeSectionButton = typeParentWrapper
|
|
.getByRole("button", {
|
|
name: type,
|
|
})
|
|
.first();
|
|
|
|
const isSectionExpanded =
|
|
await typeSectionButton.getAttribute("aria-expanded");
|
|
|
|
if (isSectionExpanded === "false") {
|
|
await typeSectionButton.click();
|
|
}
|
|
|
|
for (const segment of tokenFolderTree) {
|
|
const segmentButton = typeParentWrapper
|
|
.getByRole("listitem")
|
|
.getByRole("button", { name: segment })
|
|
.first();
|
|
|
|
const isExpanded = await segmentButton.getAttribute("aria-expanded");
|
|
if (isExpanded === "false") {
|
|
await segmentButton.click();
|
|
}
|
|
}
|
|
|
|
await expect(
|
|
typeParentWrapper.getByRole("button", {
|
|
name: tokenLeafName,
|
|
}),
|
|
).toBeEnabled();
|
|
};
|
|
|
|
export {
|
|
setupEmptyTokensFile,
|
|
setupTokensFile,
|
|
setupTypographyTokensFile,
|
|
testTokenCreationFlow,
|
|
unfoldTokenTree,
|
|
};
|