Skip to content
This repository was archived by the owner on Apr 8, 2020. It is now read-only.

Commit b35b448

Browse files
committed
Refractor state
1 parent 2a372e2 commit b35b448

6 files changed

+176
-235
lines changed

src/csstransition.spec.tsx

+19-36
Original file line numberDiff line numberDiff line change
@@ -50,40 +50,23 @@ describe("csstransition.tsx", () => {
5050
});
5151

5252
describe("componentDidMount", () => {
53-
describe("with transitionAppear=false", () => {
54-
const state = { id: 0, style: {} };
55-
let reducer: SinonSpy;
56-
before(() => {
57-
reducer = spy(() => ({ state }));
58-
wrapper = getWrapper({ children: <span /> }, reducer);
59-
reducer.reset();
60-
(wrapper.instance() as any).componentDidMount();
61-
});
62-
63-
it("should not dispatch action", () => {
64-
assert.isFalse(reducer.called);
65-
});
53+
const initialState = { id: 0, style: {} };
54+
const state = { id: 1, style: {} };
55+
let reducer: SinonSpy;
56+
before(() => {
57+
reducer = spy(createReducer({ state: initialState }, { state }));
58+
wrapper = getWrapper({ transitionAppear: true, active: true, children: <span /> }, reducer);
59+
reducer.reset();
60+
(wrapper.instance() as any).componentDidMount();
6661
});
6762

68-
describe("with transitionAppear=true", () => {
69-
const initialState = { id: 0, style: {} };
70-
const state = { id: 1, style: {} };
71-
let reducer: SinonSpy;
72-
before(() => {
73-
reducer = spy(createReducer({ state: initialState }, { state }));
74-
wrapper = getWrapper({ transitionAppear: true, active: true, children: <span /> }, reducer);
75-
reducer.reset();
76-
(wrapper.instance() as any).componentDidMount();
77-
});
78-
79-
it("should dispatch TransitionTrigger", () => {
80-
assert.isTrue(reducer.calledOnce);
81-
assert.isTrue(reducer.calledWith(initialState, ActionID.TransitionTrigger));
82-
});
63+
it("should dispatch ActionID.Mount", () => {
64+
assert.isTrue(reducer.calledOnce);
65+
assert.isTrue(reducer.calledWith(initialState, ActionID.Mount));
66+
});
8367

84-
it("should set state", () => {
85-
assert.deepEqual(wrapper.state(), state);
86-
});
68+
it("should set state", () => {
69+
assert.deepEqual(wrapper.state(), state);
8770
});
8871
});
8972

@@ -98,7 +81,7 @@ describe("csstransition.tsx", () => {
9881
wrapper.setProps({ active: true });
9982
});
10083

101-
it("should dispatch TransitionTrigger", () => {
84+
it("should dispatch ActionID.TransitionTrigger", () => {
10285
assert.isTrue(reducer.calledOnce);
10386
assert.isTrue(reducer.calledWith(initialState, ActionID.TransitionTrigger));
10487
});
@@ -119,7 +102,7 @@ describe("csstransition.tsx", () => {
119102
wrapper.find("TransitionObserver").simulate("transitionBegin");
120103
});
121104

122-
it("should dispatch TransitionStart", () => {
105+
it("should dispatch ActionID.TransitionStart", () => {
123106
assert.isTrue(reducer.calledOnce);
124107
assert.isTrue(reducer.calledWith(initialState, ActionID.TransitionStart));
125108
});
@@ -140,7 +123,7 @@ describe("csstransition.tsx", () => {
140123
wrapper.find("TransitionObserver").simulate("transitionComplete");
141124
});
142125

143-
it("should dispatch TransitionComplete", () => {
126+
it("should dispatch ActionID.TransitionComplete", () => {
144127
assert.isTrue(reducer.calledOnce);
145128
assert.isTrue(reducer.calledWith(initialState, ActionID.TransitionComplete));
146129
});
@@ -163,13 +146,13 @@ describe("csstransition.tsx", () => {
163146
wrapper.setProps({ active: true });
164147
});
165148

166-
it("should dispatch TransitionTrigger", () => {
149+
it("should dispatch ActionID.TransitionTrigger", () => {
167150
assert.isTrue(reducer.calledOnce);
168151
assert.isTrue(reducer.calledWith(initialState, ActionID.TransitionTrigger));
169152
reducer.reset();
170153
});
171154

172-
it("should dispatch TransitionStart in 2nd frame", (done) => {
155+
it("should dispatch ActionID.TransitionStart in 2nd frame", (done) => {
173156
runInFrame(1, () => {
174157
assert.isTrue(reducer.calledOnce);
175158
assert.isTrue(reducer.calledWith(pendingState, ActionID.TransitionStart));

src/csstransition.tsx

+3-5
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ import {
1414

1515
import { ActionID, CSSTransitionState, reduce } from "./csstransitionstate";
1616
import { TransitionObserver } from "./transitionobserver";
17-
import { TransitionDelay, runInFrame } from "./utils";
17+
import { runInFrame } from "./utils";
1818

19-
export type CSSTransitionDelay = TransitionDelay;
19+
export type CSSTransitionDelay = number | { appear?: number; enter?: number; leave?: number };
2020
export type CSSTransitionEventHandler = () => void;
2121

2222
export interface CSSTransitionProps
@@ -52,9 +52,7 @@ export function createCSSTransition(reducer: typeof reduce): ComponentClass<CSST
5252
}
5353

5454
public componentDidMount(): void {
55-
if (this.props.transitionAppear && this.props.active) {
56-
this.dispatch(ActionID.TransitionTrigger);
57-
}
55+
this.dispatch(ActionID.Mount);
5856
}
5957

6058
public componentWillUnmount(): void {

src/csstransitionstate.spec.ts

+98-47
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import { spy } from "sinon";
1212
import { CSSTransitionProps } from "./csstransition";
1313
import { transit } from "./transit";
1414
import {
15-
reduce, StateID, StateIDList, ActionID, CSSTransitionState,
16-
getAppearStyle, getAppearPendingStyle, getEnterPendingStyle, getLeavePendingStyle,
15+
reduce, StateID, StateIDList, ActionID, CSSTransitionState, getState,
16+
getDelay, transitionNames,
1717
defaultInitState, activeInitState, appearInitState,
1818
defaultState, activeState,
1919
appearPendingState, enterPendingState, leavePendingState,
@@ -22,48 +22,79 @@ import {
2222
} from "./csstransitionstate";
2323

2424
describe("csstransitionstate.ts", () => {
25-
describe("getAppearStyle()", () => {
26-
it("should return appearStyle", () => {
27-
const props: any = { appearStyle: {} };
28-
assert.strictEqual(getAppearStyle(props), props.appearStyle);
25+
describe("getDelay()", () => {
26+
it("should process number", () => {
27+
transitionNames.forEach((name) => assert.strictEqual(getDelay(name, 200), 200));
2928
});
30-
it("should fallback to enterStyle", () => {
31-
const props: any = { enterStyle: {} };
32-
assert.strictEqual(getAppearStyle(props), props.enterStyle);
29+
30+
it("should process object", () => {
31+
transitionNames.forEach((name) => assert.strictEqual(getDelay(name, { [name]: 100 }), 100));
3332
});
3433
});
35-
describe("getEnterPendingStyle()", () => {
36-
it("should return enterInitStyle", () => {
37-
const props: any = { enterInitStyle: {} };
38-
assert.strictEqual(getEnterPendingStyle(props), props.enterInitStyle);
39-
});
40-
it("should fallback to defaultStyle", () => {
41-
const props: any = { defaultStyle: {} };
42-
assert.strictEqual(getEnterPendingStyle(props), props.defaultStyle);
34+
describe("getState()", () => {
35+
it("should return active / default state", () => {
36+
["active", "default"].forEach((name) => {
37+
const id = StateID.Active;
38+
const style = { left: "0px" };
39+
assert.deepEqual(
40+
getState(id, name, { [name + "Style"]: style }), {
41+
id,
42+
style,
43+
});
44+
});
4345
});
44-
});
45-
describe("getLeavePendingStyle()", () => {
46-
it("should return leaveInitStyle", () => {
47-
const props: any = { leaveInitStyle: {} };
48-
assert.strictEqual(getLeavePendingStyle(props), props.leaveInitStyle);
46+
it("should return transition state", () => {
47+
transitionNames.forEach((name) => {
48+
const id = StateID.EnterStarted;
49+
const style = { top: transit("5px", 120) };
50+
const styleProcessed = { top: "5px", transition: "top 120ms ease 0ms" };
51+
assert.deepEqual(
52+
getState(id, name, { [name + "Style"]: style }), {
53+
id,
54+
style: styleProcessed,
55+
});
56+
});
4957
});
50-
it("should fallback to activeStyle", () => {
51-
const props: any = { activeStyle: {} };
52-
assert.strictEqual(getLeavePendingStyle(props), props.activeStyle);
58+
it("should return transition init state", () => {
59+
transitionNames.forEach((name) => {
60+
const id = StateID.EnterStarted;
61+
const style = { left: "0px" };
62+
assert.deepEqual(
63+
getState(id, name, { [name + "InitStyle"]: style, [name + "Style"]: {} }, { init: true }), {
64+
id,
65+
style,
66+
});
67+
});
5368
});
54-
});
55-
describe("getAppearPendingStyle()", () => {
56-
it("should return appearInitStyle", () => {
57-
const props: any = { appearInitStyle: {}, appearStyle: {} };
58-
assert.strictEqual(getAppearPendingStyle(props), props.appearInitStyle);
69+
it("should return transition init fallback state", () => {
70+
transitionNames.forEach((name) => {
71+
const fallbackName = name === "leave" ? "active" : "default";
72+
const id = StateID.EnterStarted;
73+
const style = { left: "0px" };
74+
assert.deepEqual(
75+
getState(id, name, { [fallbackName + "Style"]: style, [name + "Style"]: {} }, { init: true }), {
76+
id,
77+
style,
78+
});
79+
});
5980
});
60-
it("should fallback to enterInitStyle", () => {
61-
const props: any = { enterInitStyle: {} };
62-
assert.strictEqual(getAppearPendingStyle(props), props.enterInitStyle);
81+
it("should fallback to enter for appear", () => {
82+
const id = StateID.AppearInit;
83+
const style = { left: "0px" };
84+
assert.deepEqual(
85+
getState(id, "appear", { enterStyle: style }), {
86+
id,
87+
style,
88+
});
6389
});
64-
it("should fallback to defaultStyle", () => {
65-
const props: any = { defaultStyle: {} };
66-
assert.strictEqual(getAppearPendingStyle(props), props.defaultStyle);
90+
it("should fallback to enterInit for appearInit", () => {
91+
const id = StateID.AppearInit;
92+
const style = { left: "0px" };
93+
assert.deepEqual(
94+
getState(id, "appear", { enterInitStyle: style }, { init: true }), {
95+
id,
96+
style,
97+
});
6798
});
6899
});
69100
describe("states", () => {
@@ -77,7 +108,7 @@ describe("csstransitionstate.ts", () => {
77108
);
78109
describe(
79110
"appearInitState",
80-
testState(StateID.AppearInit, "defaultStyle", (props) => appearInitState(props)),
111+
testState(StateID.AppearInit, "appearInitStyle", (props) => appearInitState(props)),
81112
);
82113
describe(
83114
"defaultState",
@@ -89,15 +120,15 @@ describe("csstransitionstate.ts", () => {
89120
);
90121
describe(
91122
"appearPendingState",
92-
testState(StateID.AppearPending, "defaultStyle", (props) => appearPendingState(props)),
123+
testState(StateID.AppearPending, "appearInitStyle", (props) => appearPendingState(props)),
93124
);
94125
describe(
95126
"enterPendingState",
96-
testState(StateID.EnterPending, "defaultStyle", (props) => enterPendingState(props)),
127+
testState(StateID.EnterPending, "enterInitStyle", (props) => enterPendingState(props)),
97128
);
98129
describe(
99130
"leavePendingState",
100-
testState(StateID.LeavePending, "activeStyle", (props) => leavePendingState(props)),
131+
testState(StateID.LeavePending, "leaveInitStyle", (props) => leavePendingState(props)),
101132
);
102133
describe(
103134
"appearTriggeredState",
@@ -125,7 +156,7 @@ describe("csstransitionstate.ts", () => {
125156
);
126157
});
127158
describe("actions", () => {
128-
describe("ActionInit", () => {
159+
describe("Init", () => {
129160
const actionID = ActionID.Init;
130161

131162
it("should fail when state is already initialized", () => {
@@ -147,6 +178,19 @@ describe("csstransitionstate.ts", () => {
147178
assert.strictEqual(state.id, StateID.AppearInit);
148179
});
149180
});
181+
describe("Mount", () => {
182+
const actionID = ActionID.Mount;
183+
it("should become AppearPending", () => {
184+
const id = StateID.AppearInit;
185+
const {state, pending} = reduce({ id }, actionID, { active: true, transitionAppear: true });
186+
assert.strictEqual(pending, ActionID.TransitionTrigger);
187+
assert.strictEqual(state.id, StateID.AppearPending);
188+
});
189+
190+
it("should do nothing", () => {
191+
assert.isNull(reduce({ id: StateID.Active }, actionID, {}));
192+
});
193+
});
150194
describe("TransitionInit", () => {
151195
const actionID = ActionID.TransitionInit;
152196
const validOrigin = [
@@ -335,37 +379,44 @@ describe("csstransitionstate.ts", () => {
335379

336380
function testState(id: StateID, styleName: string, state: (props: CSSTransitionProps) => CSSTransitionState) {
337381
return () => {
382+
const extraProps = ["appearStyle", "appearInitStyle"].indexOf(styleName) > -1 ? { appearStyle: {} } : {};
338383
it("should return id", () => {
339384
assert.strictEqual(state({}).id, id);
340385
});
341-
if (["enterStyle", "leaveStyle"].indexOf(styleName) < 0) {
386+
if (["appearStyle", "enterStyle", "leaveStyle"].indexOf(styleName) < 0) {
342387
it("should return style", () => {
343388
const style = { top: "0px" };
344-
assert.deepEqual(state({ [styleName]: style }).style, style);
389+
assert.deepEqual(state({ ...extraProps, [styleName]: style }).style, style);
345390
});
346391
it("should return combined style", () => {
347392
const style = { top: "0px" };
348393
const baseStyle = { left: "0px" };
349-
assert.deepEqual(state({ style: baseStyle, [styleName]: style }).style, { ...baseStyle, ...style });
394+
assert.deepEqual(
395+
state({ ...extraProps, style: baseStyle, [styleName]: style }).style,
396+
{ ...baseStyle, ...style },
397+
);
350398
});
351399
} else {
352400
it("should return transition style", () => {
353401
const style = { top: transit("5px", 120) };
354402
const styleProcessed = { top: "5px", transition: "top 120ms ease 0ms" };
355-
assert.deepEqual(state({ [styleName]: style }).style, styleProcessed);
403+
assert.deepEqual(state({ ...extraProps, [styleName]: style }).style, styleProcessed);
356404
});
357405

358406
it("should return combined style", () => {
359407
const style = { top: transit("5px", 120) };
360408
const styleProcessed = { top: "5px", transition: "top 120ms ease 0ms" };
361409
const baseStyle = { left: "0px" };
362-
assert.deepEqual(state({ style: baseStyle, [styleName]: style }).style, { ...baseStyle, ...styleProcessed });
410+
assert.deepEqual(
411+
state({ ...extraProps, style: baseStyle, [styleName]: style }).style,
412+
{ ...baseStyle, ...styleProcessed },
413+
);
363414
});
364415

365416
it("should return transition style with extra delay", () => {
366417
const style = { top: transit("5px", 120, "ease", 10) };
367418
const styleProcessed = { top: "5px", transition: "top 120ms ease 30ms" };
368-
assert.deepEqual(state({ [styleName]: style, transitionDelay: 20 }).style, styleProcessed);
419+
assert.deepEqual(state({ ...extraProps, [styleName]: style, transitionDelay: 20 }).style, styleProcessed);
369420
});
370421
}
371422
};

0 commit comments

Comments
 (0)