Skip to content

Commit 2caf8f6

Browse files
committed
Refactor props structure
Signed-off-by: Milos Dzepina <milos@aragon.org>
1 parent 769de3f commit 2caf8f6

3 files changed

Lines changed: 78 additions & 51 deletions

File tree

src/modules/components/proposal/proposalActionSimulationStructure/proposalActionSimulationStructure.stories.tsx

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ type Story = StoryObj<typeof ProposalActionSimulationStructure>;
2424
export const Success: Story = {
2525
args: {
2626
totalActions: 3,
27-
lastSimulation: DateTime.now().minus({ seconds: 10 }),
28-
status: 'success',
29-
tenderlyUrl: 'https://dashboard.tenderly.co/simulation/12345',
27+
lastSimulation: {
28+
timestamp: DateTime.now().minus({ seconds: 10 }).toMillis(),
29+
url: 'https://dashboard.tenderly.co/simulation/12345',
30+
status: 'success',
31+
},
3032
},
3133
};
3234

@@ -36,9 +38,11 @@ export const Success: Story = {
3638
export const Failure: Story = {
3739
args: {
3840
totalActions: 2,
39-
lastSimulation: DateTime.now().minus({ seconds: 10 }),
40-
status: 'failure',
41-
tenderlyUrl: 'https://dashboard.tenderly.co/simulation/12345',
41+
lastSimulation: {
42+
timestamp: DateTime.now().minus({ seconds: 10 }).toMillis(),
43+
url: 'https://dashboard.tenderly.co/simulation/12345',
44+
status: 'failure',
45+
},
4246
},
4347
};
4448

@@ -48,7 +52,6 @@ export const Failure: Story = {
4852
export const Loading: Story = {
4953
args: {
5054
totalActions: 5,
51-
status: 'unknown',
5255
isSimulating: true,
5356
},
5457
};
@@ -59,7 +62,6 @@ export const Loading: Story = {
5962
export const NoPreviousSimulation: Story = {
6063
args: {
6164
totalActions: 1,
62-
status: 'unknown',
6365
},
6466
};
6567

@@ -69,8 +71,11 @@ export const NoPreviousSimulation: Story = {
6971
export const WithErrorMessage: Story = {
7072
args: {
7173
totalActions: 2,
72-
lastSimulation: DateTime.now().minus({ weeks: 2 }),
73-
status: 'success',
74+
lastSimulation: {
75+
timestamp: DateTime.now().minus({ weeks: 2 }).toMillis(),
76+
url: 'https://dashboard.tenderly.co/simulation/12345',
77+
status: 'success',
78+
},
7479
error: 'Simulation failed to run. Please try again.',
7580
},
7681
};
@@ -81,8 +86,11 @@ export const WithErrorMessage: Story = {
8186
export const RecentSimulation: Story = {
8287
args: {
8388
totalActions: 7,
84-
lastSimulation: DateTime.now().minus({ minutes: 5 }),
85-
status: 'success',
89+
lastSimulation: {
90+
timestamp: DateTime.now().minus({ minutes: 5 }).toMillis(),
91+
url: 'https://dashboard.tenderly.co/simulation/12345',
92+
status: 'success',
93+
},
8694
},
8795
};
8896

@@ -92,8 +100,11 @@ export const RecentSimulation: Story = {
92100
export const OldSimulation: Story = {
93101
args: {
94102
totalActions: 2,
95-
lastSimulation: DateTime.now().minus({ weeks: 2 }),
96-
status: 'success',
103+
lastSimulation: {
104+
timestamp: DateTime.now().minus({ weeks: 2 }).toMillis(),
105+
url: 'https://dashboard.tenderly.co/simulation/12345',
106+
status: 'success',
107+
},
97108
},
98109
};
99110

@@ -103,10 +114,12 @@ export const OldSimulation: Story = {
103114
export const NotSimulatable: Story = {
104115
args: {
105116
totalActions: 3,
106-
lastSimulation: DateTime.now().minus({ hours: 2 }),
107-
status: 'success',
117+
lastSimulation: {
118+
timestamp: DateTime.now().minus({ hours: 2 }).toMillis(),
119+
url: 'https://dashboard.tenderly.co/simulation/12345',
120+
status: 'success',
121+
},
108122
isSimulatable: false,
109-
tenderlyUrl: 'https://dashboard.tenderly.co/simulation/12345',
110123
},
111124
};
112125

src/modules/components/proposal/proposalActionSimulationStructure/proposalActionSimulationStructure.test.tsx

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ describe('<ProposalActionSimulationStructure /> component', () => {
88
const createTestComponent = (props?: Partial<IProposalActionSimulationStructureProps>) => {
99
const completeProps: IProposalActionSimulationStructureProps = {
1010
totalActions: 3,
11-
status: 'success',
1211
...props,
1312
};
1413

@@ -44,29 +43,62 @@ describe('<ProposalActionSimulationStructure /> component', () => {
4443

4544
it('renders relative time for recent simulation', () => {
4645
const recentTime = DateTime.now().minus({ days: 2 });
47-
render(createTestComponent({ lastSimulation: recentTime }));
46+
render(createTestComponent({
47+
lastSimulation: {
48+
timestamp: recentTime.toMillis(),
49+
url: 'https://dashboard.tenderly.co/simulation/12345',
50+
status: 'success'
51+
}
52+
}));
4853
expect(screen.getByText('2 days ago')).toBeInTheDocument();
4954
});
5055

5156
it('renders "Now" for very recent simulation', () => {
5257
const veryRecentTime = DateTime.now().minus({ seconds: 30 });
53-
render(createTestComponent({ lastSimulation: veryRecentTime }));
58+
render(createTestComponent({
59+
lastSimulation: {
60+
timestamp: veryRecentTime.toMillis(),
61+
url: 'https://dashboard.tenderly.co/simulation/12345',
62+
status: 'success'
63+
}
64+
}));
5465
expect(screen.getByText('Now')).toBeInTheDocument();
5566
});
5667

5768
it('renders the execution status label', () => {
5869
render(
5970
createTestComponent({
60-
status: 'success',
71+
lastSimulation: {
72+
timestamp: DateTime.now().toMillis(),
73+
url: 'https://dashboard.tenderly.co/simulation/12345',
74+
status: 'success'
75+
}
6176
}),
6277
);
6378
expect(screen.getByText('Likely to succeed')).toBeInTheDocument();
6479
});
6580

81+
it('renders failure status label', () => {
82+
render(
83+
createTestComponent({
84+
lastSimulation: {
85+
timestamp: DateTime.now().toMillis(),
86+
url: 'https://dashboard.tenderly.co/simulation/12345',
87+
status: 'failure'
88+
}
89+
}),
90+
);
91+
expect(screen.getByText('Likely to fail')).toBeInTheDocument();
92+
});
93+
94+
it('renders unknown status when no lastSimulation is provided', () => {
95+
render(createTestComponent());
96+
expect(screen.getByText('Unknown')).toBeInTheDocument();
97+
});
98+
6699
it('renders loading state when execution status is loading', () => {
67100
render(
68101
createTestComponent({
69-
status: 'unknown',
70102
isSimulating: true,
71103
}),
72104
);

src/modules/components/proposal/proposalActionSimulationStructure/proposalActionSimulationStructure.tsx

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ export interface IProposalActionSimulationStructureProps {
1919
*/
2020
totalActions: number;
2121
/**
22-
* Last simulation date.
22+
* Last simulation data including timestamp, URL, and status.
2323
*/
24-
lastSimulation?: DateTime;
24+
lastSimulation?: { timestamp: number; url: string; status: 'success' | 'failure' };
2525
/**
2626
* Whether simulation is currently running.
2727
*/
@@ -30,18 +30,10 @@ export interface IProposalActionSimulationStructureProps {
3030
* Whether the proposal can be simulated.
3131
*/
3232
isSimulatable?: boolean;
33-
/**
34-
* Simulation status result.
35-
*/
36-
status: 'success' | 'failure' | 'unknown';
3733
/**
3834
* Callback when simulate again button is clicked.
3935
*/
4036
onSimulate?: () => void;
41-
/**
42-
* URL for tenderly simulation.
43-
*/
44-
tenderlyUrl?: string;
4537
/**
4638
* Additional class names applied to the wrapper div.
4739
*/
@@ -54,23 +46,13 @@ export interface IProposalActionSimulationStructureProps {
5446
}
5547

5648
export const ProposalActionSimulationStructure: React.FC<IProposalActionSimulationStructureProps> = (props) => {
57-
const {
58-
totalActions,
59-
lastSimulation,
60-
isSimulating,
61-
isSimulatable = true,
62-
status,
63-
onSimulate,
64-
tenderlyUrl,
65-
className,
66-
error,
67-
} = props;
49+
const { totalActions, lastSimulation, isSimulating, isSimulatable = true, onSimulate, className, error } = props;
6850

6951
const { copy } = useGukModulesContext();
7052
const simulationCopy = copy.proposalActionSimulationStructure;
7153

7254
const statusConfig = useMemo(() => {
73-
switch (status) {
55+
switch (lastSimulation?.status) {
7456
case 'success':
7557
return {
7658
icon: IconType.CHECKMARK,
@@ -85,7 +67,6 @@ export const ProposalActionSimulationStructure: React.FC<IProposalActionSimulati
8567
textColor: 'text-critical-800',
8668
variant: 'critical' as const,
8769
};
88-
case 'unknown':
8970
default:
9071
return {
9172
icon: IconType.INFO,
@@ -94,13 +75,14 @@ export const ProposalActionSimulationStructure: React.FC<IProposalActionSimulati
9475
variant: 'neutral' as const,
9576
};
9677
}
97-
}, [simulationCopy, status]);
78+
}, [simulationCopy, lastSimulation?.status]);
9879

99-
const formatSimulationDate = (date?: DateTime) => {
100-
if (!date) {
80+
const formatSimulationDate = (timestamp?: number) => {
81+
if (!timestamp) {
10182
return copy.proposalActionSimulationStructure.never;
10283
}
10384

85+
const date = DateTime.fromMillis(timestamp);
10486
const now = DateTime.now();
10587
const diffInMinutes = now.diff(date, 'minutes').minutes;
10688
const diffInDays = now.diff(date, 'days').days;
@@ -128,7 +110,7 @@ export const ProposalActionSimulationStructure: React.FC<IProposalActionSimulati
128110
{simulationCopy.simulating}
129111
</span>
130112
) : (
131-
formatSimulationDate(lastSimulation)
113+
formatSimulationDate(lastSimulation?.timestamp)
132114
)}
133115
</DefinitionList.Item>
134116

@@ -173,8 +155,8 @@ export const ProposalActionSimulationStructure: React.FC<IProposalActionSimulati
173155
<Button
174156
variant="tertiary"
175157
size="md"
176-
disabled={!tenderlyUrl}
177-
href={tenderlyUrl}
158+
disabled={!lastSimulation?.url}
159+
href={lastSimulation?.url}
178160
target="_blank"
179161
iconRight={IconType.LINK_EXTERNAL}
180162
>

0 commit comments

Comments
 (0)