Skip to content

Instantly share code, notes, and snippets.

@miketamis
Created October 3, 2019 23:00
Show Gist options
  • Save miketamis/069403c7b253ad26959f03206f0997d7 to your computer and use it in GitHub Desktop.
Save miketamis/069403c7b253ad26959f03206f0997d7 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
function testOnPage(className) {
return async ({ rendered }) => {
await wait(() => expect(rendered.container.querySelector(className)).toBeInTheDocument());
};
}
async function testLoading({ rendered: { container, getByText, history, debug } }) {
await wait(() => expect(getByText('Loading...')).toBeInTheDocument(), { container });
}
const journeyMachine = Machine(
{
id: 'journey',
initial: 'IDLE',
context: {},
states: {
IDLE: {
on: {
DEEP_LINK: {
target: 'LOADING_CUSTOMER',
actions: assign(
(_context, { deepLink }) =>
deepLink && {
deepLink,
},
),
},
},
},
LOADING_CUSTOMER: {
meta: {
test: testLoading,
},
onExit: assign((_context, { customer }) => ({
customer,
})),
on: {
LOADED_CUSTOMER: [
{
target: 'LOADING_SERVICEPLANS',
cond: 'isPlanSelectorDeepLinked',
},
{
target: 'CHANGE',
cond: 'isChangeDeepLinked',
},
{
target: 'LOGIN',
cond: 'isLoginDeepLinkedAndUnauthenticated',
},
{
target: 'MOVE_ADDRESS_SEARCH',
cond: 'isMoveDeepLinked',
},
{
target: 'MOVE_OR_CHANGE',
cond: 'isBroadbandCustomer',
},
{
target: 'LANDING_PAGE',
},
],
},
},
SORRY: {
meta: {
test: testOnPage('.SorryContainer'),
},
},
CHANGE: {
entry: assign({ journeyType: 'CHANGE' }),
on: {
'': [
{
target: 'LOGIN',
cond: 'isUnauthenticated',
},
{
target: 'CHANGE_ADDRESS_SEARCH',
cond: 'customerElidUnavalibe',
},
{
target: 'LOADING_SERVICEPLANS',
},
],
},
},
LANDING_PAGE: {
meta: {
test: testOnPage('.landing-container'),
},
on: {
LOGIN_CLICK: {
target: 'LOGIN',
cond: 'isUnauthenticated',
},
ADDRESS_ENTERED: {
target: 'LOADING_SERVICEPLANS',
},
},
},
LOGIN: {
meta: {
test: testOnPage('.LoginContainer'),
},
on: {
LOGIN: {
target: 'LOADING_CUSTOMER',
},
},
},
MOVE_OR_CHANGE: {
meta: {
test: testOnPage('.MoveOrChange'),
},
on: {
MOVE_CLICKED: 'MOVE_ADDRESS_SEARCH',
CHANGE_CLICKED: 'CHANGE',
},
},
CHANGE_ADDRESS_SEARCH: {
meta: {
test: testOnPage('.MoveOrChange'),
},
on: {
ADDRESS_ENTERED: {
target: 'LOADING_SERVICEPLANS',
},
},
},
MOVE_ADDRESS_SEARCH: {
meta: {
test: testOnPage('.MoveAddress__container'),
},
entry: assign({ journeyType: 'CHANGE' }),
on: {
'': {
target: 'LOGIN',
cond: 'isUnauthenticated',
},
ADDRESS_ENTERED: {
target: 'LOADING_SERVICEPLANS',
},
},
},
LOADING_SERVICEPLANS: {
meta: {
test: testLoading,
},
onExit: assign((context, { plans }) => ({
plans,
})),
on: {
LOADED: [
{
target: 'NO_PLAN',
cond: 'noPlansAvalible',
},
{
target: 'QUESTIONS',
cond: 'needsQuestions',
},
{
target: 'PLAN_SELECTOR',
},
],
},
},
NO_PLAN: {
meta: {
test: testOnPage('.NoPlanOptions'),
},
},
PLAN_SELECTOR: {
meta: {
test: testOnPage('.configurator-wrapper'),
},
on: {
ADDRESS_ENTERED: {
target: 'LOADING_SERVICEPLANS',
},
},
},
QUESTIONS: {
meta: {
test: testOnPage('.QuestionsContainer'),
},
on: {
USAGE_SUBMITED: {
target: 'PLAN_SELECTOR',
},
},
},
},
},
{
guards: {
isNotBroadbandCustomer: withCustomer(customer => !customer.isBroadbandCustomer),
isBroadbandCustomer: withCustomer(customer => customer.isBroadbandCustomer),
isMoveDeepLinked: (context, event) => context.deepLink === 'MOVE' || context.journeyType === 'MOVE',
isPlanSelectorDeepLinked: (context, event) => context.deepLink === 'PLAN_SELECTOR',
isChangeDeepLinked: (context, event) => context.deepLink === 'CHANGE' || context.journeyType === 'CHANGE',
isUnauthenticated: withCustomer(customer => !customer.isAuthenticated),
isLoginDeepLinkedAndUnauthenticated: withCustomer(
(customer, context) => !customer.isAuthenticated && context.deepLink === 'LOGIN',
),
isAuthenticated: withCustomer(customer => customer.isAuthenticated),
noPlansAvalible: withPlans(plans => plans.noPlansAvalible),
needsQuestions: withPlans(plans => plans.needsQuestions),
customerElidUnavalibe: withCustomer(customer => !customer.elid),
},
},
);
function withCustomer(predicate) {
return (context, event) => {
const customer = event.customer || context.customer;
return !!customer && predicate(customer, context, event);
};
}
function withPlans(predicate) {
return (context, event) => {
const plans = event.plans || context.plans;
return !!plans && predicate(plans);
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment