Skip to content

Commit

Permalink
feat: invalid step should stop flow (#33)
Browse files Browse the repository at this point in the history
* feat: invalid step should stop flow

* feat: remove css vendor prefixes

* fix: start based on location

* feat: invalid step error
  • Loading branch information
VojtechVidra authored Feb 29, 2024
1 parent f6acd56 commit 9a48fa7
Show file tree
Hide file tree
Showing 11 changed files with 67 additions and 12 deletions.
2 changes: 2 additions & 0 deletions workspaces/e2e/tests/branch/branch.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
<link rel="stylesheet" href="/node_modules/@flows/js/css.min/flows.css" />
</head>
<body>
<button class="start-flow">Start flow</button>
<button class="enter-1">Variant 1</button>
<button class="enter-2">Variant 2</button>
<div
style="background-color: grey; width: 20px; height: 20px; margin: 40px"
class="target"
></div>
<div class="log"></div>

<script type="module" src="./branch.ts"></script>
</body>
Expand Down
19 changes: 19 additions & 0 deletions workspaces/e2e/tests/branch/branch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,22 @@ test("branch can have multiple steps", async ({ page }) => {
await page.locator(".flows-continue").click();
await expect(page.locator(".flows-tooltip")).toContainText("Last Step");
});
test("should reset flow when entering branch without targetBranch", async ({ page }) => {
await page.goto("/branch/branch.html?hideNext=false&logErrors=true");
await expect(page.locator(".flows-tooltip")).toBeVisible();
await page.locator(".flows-continue").click();
await expect(page.locator(".flows-tooltip")).toBeHidden();
await page.locator(".start-flow").click();
await expect(page.locator(".flows-tooltip")).toBeVisible();
await expect(page.locator("[data-type='invalidStepError']")).toHaveCount(1);
});
test("should reset flow when entering out of bound step", async ({ page }) => {
await page.goto("/branch/branch.html?lastStep=true&logErrors=true");
await page.locator(".enter-1").click();
await page.locator(".flows-continue").click();
await page.locator(".flows-option").click();
await expect(page.locator(".flows-tooltip")).toBeHidden();
await page.locator(".start-flow").click();
await expect(page.locator(".flows-tooltip")).toBeVisible();
await expect(page.locator("[data-type='invalidStepError']")).toHaveCount(1);
});
22 changes: 20 additions & 2 deletions workspaces/e2e/tests/branch/branch.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import type { FlowSteps } from "@flows/js";
import { init } from "@flows/js/core";
import { init, startFlow } from "@flows/js/core";

const lastStep = new URLSearchParams(window.location.search).get("lastStep") === "true";
const hideNext = new URLSearchParams(window.location.search).get("hideNext") !== "false";
const logErrors = new URLSearchParams(window.location.search).get("logErrors") === "true";

const steps: FlowSteps = [
{
targetElement: ".target",
title: "Hello",
hideNext: true,
hideNext,
wait: [
{ clickElement: ".enter-1", targetBranch: 0 },
{ clickElement: ".enter-2", targetBranch: 1 },
Expand Down Expand Up @@ -43,6 +45,7 @@ if (lastStep)
steps.push({
targetElement: ".target",
title: "Last Step",
footerActions: { right: [{ label: "Continue", targetBranch: undefined }] },
});

void init({
Expand All @@ -53,4 +56,19 @@ void init({
steps,
},
],
_debug: async (e) => {
if (logErrors) {
const p = document.createElement("p");
p.classList.add("log-item");
p.dataset.type = e.type;
p.dataset.referenceId = e.referenceId;
p.innerText = JSON.stringify(e);
document.querySelector(".log")?.appendChild(p);
}
return { referenceId: "" };
},
});

document.querySelector(".start-flow")?.addEventListener("click", () => {
startFlow("flow");
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@
<button class="start-flow">Start flow</button>
<div class="log"></div>

<script type="module" src="./error.ts"></script>
<script type="module" src="./tooltip-error.ts"></script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { expect, test } from "@playwright/test";

test("Emits error event", async ({ page }) => {
await page.goto("/error/error.html");
await page.goto("/tooltip-error/tooltip-error.html");
await page.locator(".start-flow").click();
await expect(page.locator("[data-type='tooltipError']")).toHaveCount(1);
await expect(page.locator("[data-type='invalidateTooltipError']")).toHaveCount(0);
});

test("should not emit any error event if it gets invalidates quickly", async ({ page }) => {
await page.goto("/error/error.html");
await page.goto("/tooltip-error/tooltip-error.html");
await page.locator(".start-flow").click();
await expect(page.locator("[data-type='tooltipError']")).toHaveCount(0);
await page.locator(".add-target").click();
Expand All @@ -21,7 +21,7 @@ test("should not emit any error event if it gets invalidates quickly", async ({
test("should emit error and invalidate it if it gets invalidated after a while", async ({
page,
}) => {
await page.goto("/error/error.html");
await page.goto("/tooltip-error/tooltip-error.html");
await page.locator(".start-flow").click();
await expect(page.locator("[data-type='tooltipError']")).toHaveCount(1);
await page.locator(".add-target").click();
Expand Down
File renamed without changes.
3 changes: 0 additions & 3 deletions workspaces/js/css/template.css
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@
left: 0;
width: 100%;
height: 100%;
-webkit-mask: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16px' height='16px' viewBox='0 0 16 16'%3e%3cpath fill='currentColor' d='M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z' /%3e%3c/svg%3e")
50%;
mask: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16px' height='16px' viewBox='0 0 16 16'%3e%3cpath fill='currentColor' d='M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z' /%3e%3c/svg%3e")
50%;
background-color: var(--flows-fg-default);
Expand Down Expand Up @@ -168,7 +166,6 @@
width: var(--flows-size-medium);
height: var(--flows-size-medium);
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
border-radius: var(--flows-borderRadius-xSmall);
}
.flows-arrow-bottom {
Expand Down
18 changes: 18 additions & 0 deletions workspaces/js/src/core/flow-state.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { DebugEvent, Flow, FlowStep, FlowStepIndex, TrackingEvent } from "../types";
import { hash } from "../lib/hash";
import { isModalStep, isTooltipStep } from "../lib/step-type";
import { log } from "../lib/log";
import { render } from "./render";
import type { FlowsContext } from "./flows-context";

Expand Down Expand Up @@ -73,6 +74,10 @@ export class FlowState {
...props,
});
}

/**
* Called when entering a step or when the flow is started or recreated from local storage.
*/
enterStep(): this {
const step = this.currentStep;
if (step && isTooltipStep(step) && !this.tooltipErrorPromise)
Expand All @@ -83,6 +88,19 @@ export class FlowState {
});
}, 1000);

const isFork = Array.isArray(step);
if (isFork) {
log.error("Stopping flow: entered invalid step, make sure to use targetBranch");
void this.debug({ type: "invalidStepError" });
this.destroy();
}
const isOutOfBoundStep = !step && this.flow?._incompleteSteps !== true;
if (isOutOfBoundStep) {
log.error("Stopping flow: entered out of bound step");
void this.debug({ type: "invalidStepError" });
this.destroy();
}

return this;
}

Expand Down
1 change: 1 addition & 0 deletions workspaces/js/src/core/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,4 +176,5 @@ const _init = (options: FlowsInitOptions): void => {
]);

startFlowsBasedOnLocation();
FlowsContext.getInstance().onLocationChange?.(getPathname(), FlowsContext.getInstance());
};
4 changes: 2 additions & 2 deletions workspaces/js/src/core/location-change.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ export const handleLocationChange = (): void => {
});
if (matchingWait) state.nextStep(matchingWait.targetBranch).render();
}

startFlowsBasedOnLocation();
});

startFlowsBasedOnLocation();
};

export const startFlowsBasedOnLocation = (): void => {
Expand Down
2 changes: 1 addition & 1 deletion workspaces/js/src/types/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export interface TrackingEvent {
export type Tracking = (event: TrackingEvent) => void;

export interface DebugEvent extends Omit<TrackingEvent, "type"> {
type: "tooltipError" | "invalidateTooltipError";
type: "tooltipError" | "invalidateTooltipError" | "invalidStepError";
/**
* referenceId of the event that the current event is invalidating.
*/
Expand Down

0 comments on commit 9a48fa7

Please sign in to comment.