* init * fix type * fix a re-render infinite loop because of missing readOnly (╯°□°)╯︵ ┻━┻) * further fixes * improvement * fix expiry datetime check * remove unnecessary prismaMock def * revert * fix test * add test ids * remove unit tests in favor of e2e * e2e test update * fix e2e * fix e2e * remove unnecessary change * abstract into injectable object * further improvements * fix label not selecting radio * fix type * code improvement * DI implementation * fix type * fix quick copy * code improvement and a few fixes * further improvements and NITS * further into DI * select * improve link list sorting * prep for easier conflict resolution * add back translations * using useCopy instead * improvement * add index to update salt and have different hash generation * fix private link description * fix increment regression in expiry logic * fixes * address feedback * use extractHostTimezone in event type listing * remove unused function * remove translationBundler * -_- * address feedback * further changes * address more feedback * NIT * address improvement suggestions * use extractHostTimezone * remove console log * pre update * code improvement * further fixes * cleanup * -_-
198 lines
8.5 KiB
TypeScript
198 lines
8.5 KiB
TypeScript
import { expect } from "@playwright/test";
|
|
|
|
import { test } from "./lib/fixtures";
|
|
import {
|
|
bookTimeSlot,
|
|
selectFirstAvailableTimeSlotNextMonth,
|
|
submitAndWaitForResponse,
|
|
} from "./lib/testUtils";
|
|
|
|
test.describe.configure({ mode: "serial" });
|
|
|
|
test.describe("private links creation and usage", () => {
|
|
test.beforeEach(async ({ users }) => {
|
|
const user = await users.create();
|
|
await user.apiLogin();
|
|
});
|
|
test.afterEach(async ({ users }) => {
|
|
await users.deleteAll();
|
|
});
|
|
test("generate private link and make a booking with it", async ({ page }) => {
|
|
await page.goto("/event-types");
|
|
// We wait until loading is finished
|
|
await Promise.all([
|
|
page.waitForURL("**/event-types"),
|
|
page.getByTestId("event-types").locator("li a").first().click(),
|
|
]);
|
|
|
|
await expect(page.locator("[data-testid=event-title]")).toBeVisible();
|
|
|
|
// We wait for the page to load
|
|
await page.locator("[data-testid=vertical-tab-event_advanced_tab_title]").click();
|
|
|
|
const hashedLinkCheck = page.locator('[data-testid="multiplePrivateLinksCheck"]');
|
|
await expect(hashedLinkCheck).toBeVisible();
|
|
|
|
// ignore if it is already checked, and click if unchecked
|
|
if (!(await hashedLinkCheck.isChecked())) {
|
|
await hashedLinkCheck.click();
|
|
}
|
|
|
|
// Wait for the private link URL input to be visible and get its value
|
|
const $url = await page.locator('[data-testid="private-link-url"]').inputValue();
|
|
|
|
// click update
|
|
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
|
|
action: () => page.locator("[data-testid=update-eventtype]").click(),
|
|
});
|
|
// book using generated url hash
|
|
await page.goto($url);
|
|
await selectFirstAvailableTimeSlotNextMonth(page);
|
|
await bookTimeSlot(page);
|
|
// Make sure we're navigated to the success page
|
|
const successPage = page.getByTestId("success-page");
|
|
await expect(successPage).toBeVisible();
|
|
|
|
// hash regenerates after successful booking (only for usage-based links)
|
|
await page.goto("/event-types");
|
|
await page.waitForSelector('[data-testid="event-types"]');
|
|
await page.reload(); // ensure fresh state
|
|
|
|
await page.locator("ul[data-testid=event-types] > li a").first().click();
|
|
// We wait for the page to load
|
|
await page.locator("[data-testid=vertical-tab-event_advanced_tab_title]").click();
|
|
|
|
// After booking with a usage-based private link, the link should be expired
|
|
await expect(page.locator('[data-testid="private-link-description"]')).toContainText(
|
|
"Usage limit reached"
|
|
);
|
|
|
|
// Ensure that private URL is enabled after modifying the event type.
|
|
// Additionally, if the slug is changed, ensure that the private URL is updated accordingly.
|
|
await page.getByTestId("vertical-tab-event_setup_tab_title").click();
|
|
await page.locator("[data-testid=event-title]").first().fill("somethingrandom");
|
|
await page.locator("[data-testid=event-slug]").first().fill("somethingrandom");
|
|
await expect(page.locator('[data-testid="event-slug"]').first()).toHaveValue("somethingrandom");
|
|
|
|
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
|
|
action: () => page.locator("[data-testid=update-eventtype]").click(),
|
|
});
|
|
await page.locator("[data-testid=vertical-tab-event_advanced_tab_title]").click();
|
|
|
|
// Wait for the private link URL input to be visible and get its value
|
|
const $url2 = await page.locator('[data-testid="private-link-url"]').inputValue();
|
|
expect($url2.includes("somethingrandom")).toBeTruthy();
|
|
});
|
|
|
|
test("generate private link with future expiration date and make a booking with it", async ({ page }) => {
|
|
await page.goto("/event-types");
|
|
// We wait until loading is finished
|
|
await Promise.all([
|
|
page.waitForURL("**/event-types"),
|
|
page.getByTestId("event-types").locator("li a").first().click(),
|
|
]);
|
|
|
|
await expect(page.locator("[data-testid=event-title]")).toBeVisible();
|
|
|
|
// We wait for the page to load
|
|
await page.locator("[data-testid=vertical-tab-event_advanced_tab_title]").click();
|
|
|
|
const privateLinkCheck = page.locator('[data-testid="multiplePrivateLinksCheck"]');
|
|
await expect(privateLinkCheck).toBeVisible();
|
|
|
|
// ignore if it is already checked, and click if unchecked
|
|
if (!(await privateLinkCheck.isChecked())) {
|
|
await privateLinkCheck.click();
|
|
}
|
|
|
|
// Wait for the private link URL input to be visible and get its value
|
|
const $url = await page.locator('[data-testid="private-link-url"]').inputValue();
|
|
await page.locator('[data-testid="private-link-settings"]').click();
|
|
await expect(page.locator('[data-testid="private-link-radio-group"]')).toBeVisible();
|
|
await page.locator('[data-testid="private-link-time"]').click();
|
|
await page.locator('[data-testid="private-link-expiration-settings-save"]').click();
|
|
await page.waitForLoadState("networkidle");
|
|
// click update
|
|
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
|
|
action: () => page.locator("[data-testid=update-eventtype]").click(),
|
|
});
|
|
// book using generated url hash
|
|
await page.goto($url);
|
|
await selectFirstAvailableTimeSlotNextMonth(page);
|
|
await bookTimeSlot(page);
|
|
// Make sure we're navigated to the success page
|
|
await expect(page.getByTestId("success-page")).toBeVisible();
|
|
|
|
// hash regenerates after successful booking (only for usage-based links)
|
|
await page.goto("/event-types");
|
|
await page.waitForSelector('[data-testid="event-types"]');
|
|
await page.reload(); // ensure fresh state
|
|
|
|
await page.locator("ul[data-testid=event-types] > li a").first().click();
|
|
// We wait for the page to load
|
|
await page.locator("[data-testid=vertical-tab-event_advanced_tab_title]").click();
|
|
|
|
// After booking with a expiration date based private link, the link should still be valid
|
|
await expect(page.locator('[data-testid="private-link-expired"]')).toBeHidden();
|
|
});
|
|
test("generate private link with 2 usages and make 2 bookings with it", async ({ page }) => {
|
|
await page.goto("/event-types");
|
|
// We wait until loading is finished
|
|
await Promise.all([
|
|
page.waitForURL("**/event-types"),
|
|
page.getByTestId("event-types").locator("li a").first().click(),
|
|
]);
|
|
|
|
await expect(page.locator("[data-testid=event-title]")).toBeVisible();
|
|
|
|
// We wait for the page to load
|
|
await page.locator("[data-testid=vertical-tab-event_advanced_tab_title]").click();
|
|
|
|
const privateLinkCheck = page.locator('[data-testid="multiplePrivateLinksCheck"]');
|
|
await expect(privateLinkCheck).toBeVisible();
|
|
|
|
// ignore if it is already checked, and click if unchecked
|
|
if (!(await privateLinkCheck.isChecked())) {
|
|
await privateLinkCheck.click();
|
|
}
|
|
|
|
// Wait for the private link URL input to be visible and get its value
|
|
const $url = await page.locator('[data-testid="private-link-url"]').inputValue();
|
|
await page.locator('[data-testid="private-link-settings"]').click();
|
|
await expect(page.locator('[data-testid="private-link-radio-group"]')).toBeVisible();
|
|
await page.locator('[data-testid="private-link-usage-count"]').fill("2");
|
|
await page.locator('[data-testid="private-link-expiration-settings-save"]').click();
|
|
await page.waitForLoadState("networkidle");
|
|
// click update
|
|
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
|
|
action: () => page.locator("[data-testid=update-eventtype]").click(),
|
|
});
|
|
// book using generated url hash
|
|
await page.goto($url);
|
|
await selectFirstAvailableTimeSlotNextMonth(page);
|
|
await bookTimeSlot(page);
|
|
// Make sure we're navigated to the success page
|
|
await expect(page.getByTestId("success-page")).toBeVisible();
|
|
|
|
// book again using generated url hash
|
|
await page.goto($url);
|
|
await selectFirstAvailableTimeSlotNextMonth(page);
|
|
await bookTimeSlot(page);
|
|
// Make sure we're navigated to the success page
|
|
await expect(page.getByTestId("success-page")).toBeVisible();
|
|
|
|
await page.goto("/event-types");
|
|
await page.waitForSelector('[data-testid="event-types"]');
|
|
await page.reload(); // ensure fresh state
|
|
|
|
await page.locator("ul[data-testid=event-types] > li a").first().click();
|
|
// We wait for the page to load
|
|
await page.locator("[data-testid=vertical-tab-event_advanced_tab_title]").click();
|
|
|
|
// After booking twice with a 2 usages based private link, the link should be expired
|
|
await expect(page.locator('[data-testid="private-link-description"]')).toContainText(
|
|
"Usage limit reached"
|
|
);
|
|
});
|
|
});
|