Skip to content
This repository was archived by the owner on Nov 3, 2025. It is now read-only.

Commit 80ae9f6

Browse files
committed
✨ (createCanal) Use declarative syntax to show pages
1 parent 31054fe commit 80ae9f6

5 files changed

Lines changed: 238 additions & 64 deletions

File tree

example/src/canals/SignIn/SignIn.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,24 @@ import React from 'react';
22
import { createCanal } from 'react-gondola';
33
import { FirstName } from './FirstName';
44
import { LastName } from './LastName';
5+
import { Observer } from 'mobx-react/native';
6+
import { fromStream } from 'mobx-utils';
7+
import { interval } from 'rxjs';
8+
import { map } from 'rxjs/operators';
59

610
// @ts-ignore
7-
const SignInCanal = createCanal(
11+
const SignInCanal = createCanal([
812
{ name: 'firstName', Component: FirstName },
913
{ name: 'lastName', Component: LastName }
10-
);
14+
]);
1115

1216
export const SignIn = () => {
13-
return <SignInCanal />;
17+
const delayedAuth = fromStream(
18+
interval(1000).pipe(map(tick => tick % 2 === 0))
19+
);
20+
return (
21+
<Observer>
22+
{() => <SignInCanal firstName lastName={delayedAuth.current} />}
23+
</Observer>
24+
);
1425
};

jest/setup.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { configure } from 'mobx';
22

33
configure({
4-
enforceActions: 'always',
4+
enforceActions: 'observed',
55
});
66

77
Date.now = jest.fn(() => 0);

src/__tests__/__snapshots__/createCanal.test.tsx.snap

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,95 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3-
exports[`createCanal renders the first page when mounted 1`] = `
3+
exports[`createCanal renders nothing if no authorization is passed 1`] = `
4+
<View
5+
style={
6+
Object {
7+
"bottom": 0,
8+
"left": 0,
9+
"position": "absolute",
10+
"right": 0,
11+
"top": 0,
12+
}
13+
}
14+
/>
15+
`;
16+
17+
exports[`createCanal renders only the first page if all authorizations are given but the one for the second page 1`] = `
18+
<View
19+
style={
20+
Object {
21+
"bottom": 0,
22+
"left": 0,
23+
"position": "absolute",
24+
"right": 0,
25+
"top": 0,
26+
}
27+
}
28+
>
29+
<View
30+
style={
31+
Object {
32+
"bottom": 0,
33+
"left": 0,
34+
"position": "absolute",
35+
"right": 0,
36+
"top": 0,
37+
}
38+
}
39+
>
40+
<Text>
41+
a
42+
</Text>
43+
</View>
44+
</View>
45+
`;
46+
47+
exports[`createCanal renders the all pages if all authorizations are given 1`] = `
48+
<View
49+
style={
50+
Object {
51+
"bottom": 0,
52+
"left": 0,
53+
"position": "absolute",
54+
"right": 0,
55+
"top": 0,
56+
}
57+
}
58+
>
59+
<View
60+
style={
61+
Object {
62+
"bottom": 0,
63+
"left": 0,
64+
"position": "absolute",
65+
"right": 0,
66+
"top": 0,
67+
}
68+
}
69+
>
70+
<Text>
71+
a
72+
</Text>
73+
</View>
74+
<View
75+
style={
76+
Object {
77+
"bottom": 0,
78+
"left": 0,
79+
"position": "absolute",
80+
"right": 0,
81+
"top": 0,
82+
}
83+
}
84+
>
85+
<Text>
86+
b
87+
</Text>
88+
</View>
89+
</View>
90+
`;
91+
92+
exports[`createCanal renders the first page if authorization for first page is given 1`] = `
493
<View
594
style={
695
Object {
@@ -23,7 +112,9 @@ exports[`createCanal renders the first page when mounted 1`] = `
23112
}
24113
}
25114
>
26-
<View />
115+
<Text>
116+
a
117+
</Text>
27118
</View>
28119
</View>
29120
`;

src/__tests__/createCanal.test.tsx

Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
1-
import React from 'react';
2-
import { View } from 'react-native';
1+
import React, { ComponentType } from 'react';
2+
import { View, Text } from 'react-native';
33
import TestRenderer from 'react-test-renderer';
44

55
import { createCanal } from '../createCanal';
6-
import { Navigation } from '../Navigation.store';
7-
import { Canal } from '../Canal';
6+
7+
const stopCreator = <T extends string>(
8+
name: T
9+
): { name: T; Component: ComponentType } => {
10+
const Component = () => <Text>{name}</Text>;
11+
return { name, Component };
12+
};
813

914
describe('createCanal', () => {
1015
it('throws an error if first arg is not a Component', () => {
1116
try {
1217
// @ts-ignore
13-
createCanal({ name: 'a', Component: 'aaa' });
18+
createCanal([{ name: 'a', Component: 'aaa' }]);
1419
} catch (error) {
1520
expect(error.message).toBe(
1621
'`createCanal` could not find a valid `Component` key for argument 1. Received: {"name":"a","Component":"aaa"}'
@@ -19,16 +24,52 @@ describe('createCanal', () => {
1924
expect.assertions(1);
2025
});
2126

22-
it('renders the first page when mounted', () => {
23-
const Transitioner = createCanal({ name: 'a', Component: View });
24-
const testRenderer = TestRenderer.create(<Transitioner />);
27+
it('renders nothing if no authorization is passed', () => {
28+
const Canal = createCanal([stopCreator('a')]);
29+
const testRenderer = TestRenderer.create(<Canal />);
30+
expect(testRenderer.toJSON()).toMatchSnapshot();
31+
});
32+
33+
it('renders the first page if authorization for first page is given', () => {
34+
const Canal = createCanal([stopCreator('a')]);
35+
const testRenderer = TestRenderer.create(<Canal a />);
36+
expect(testRenderer.toJSON()).toMatchSnapshot();
37+
});
38+
39+
it('renders the all pages if all authorizations are given', () => {
40+
const Canal = createCanal([stopCreator('a'), stopCreator('b')]);
41+
const testRenderer = TestRenderer.create(<Canal a b />);
42+
expect(testRenderer.toJSON()).toMatchSnapshot();
43+
});
44+
45+
it('renders only the first page if all authorizations are given but the one for the second page', () => {
46+
const Canal = createCanal([
47+
stopCreator('a'),
48+
stopCreator('b'),
49+
stopCreator('c')
50+
]);
51+
const testRenderer = TestRenderer.create(<Canal a c />);
2552
expect(testRenderer.toJSON()).toMatchSnapshot();
2653
});
2754

55+
it('only rerender if style was modified', () => {
56+
const Canal = createCanal([
57+
stopCreator('a'),
58+
stopCreator('b'),
59+
stopCreator('c')
60+
]);
61+
const testRenderer = TestRenderer.create(<Canal a />);
62+
const renderSpy = jest.spyOn(testRenderer.root.instance, 'render');
63+
testRenderer.update(<Canal a={false} />);
64+
expect(renderSpy).not.toHaveBeenCalled();
65+
testRenderer.update(<Canal a={false} style={{}} />);
66+
expect(renderSpy).toHaveBeenCalled();
67+
});
68+
2869
it('throws an error if any arg is not a Component', () => {
2970
try {
3071
// @ts-ignore
31-
createCanal({ name: 'a', Component: View }, { name: 'b', Component: 'aaa' });
72+
createCanal([stopCreator('a'), { name: 'b', Component: 'aaa' }]);
3273
} catch (error) {
3374
expect(error.message).toBe(
3475
'`createCanal` could not find a valid `Component` key for argument 2. Received: {"name":"b","Component":"aaa"}'
@@ -37,30 +78,10 @@ describe('createCanal', () => {
3778
expect.assertions(1);
3879
});
3980

40-
it('emits the new canal to the navigation store', () => {
41-
const PageOne = () => <View />;
42-
const PageTwo = () => <View />;
43-
const Transitioner = createCanal(
44-
{ name: 'pageOne', Component: PageOne },
45-
{ name: 'pageTwo', Component: PageTwo }
46-
);
47-
const expectedCanal = new Canal([
48-
{ name: 'pageOne', Component: PageOne },
49-
{ name: 'pageTwo', Component: PageTwo },
50-
]);
51-
Navigation.getInstance().canalsSubject.subscribe({
52-
next: canal => {
53-
expect(canal).toEqual(expectedCanal);
54-
},
55-
});
56-
TestRenderer.create(<Transitioner />);
57-
expect.assertions(1);
58-
});
59-
6081
it('throws an error if name is missing', () => {
6182
try {
6283
// @ts-ignore
63-
createCanal({ Component: View });
84+
createCanal([{ Component: View }]);
6485
} catch (error) {
6586
expect(error.message).toBe(
6687
'`createCanal` could not find a valid `name` key for argument 1. Received: {}'
@@ -73,9 +94,11 @@ describe('createCanal', () => {
7394
xit('throws an error some names are duplicated', () => {
7495
try {
7596
// @ts-ignore
76-
createCanal({ name: 'a', Component: View }, { name: 'a', Component: View });
97+
createCanal([stopCreator('a'), stopCreator('a')]);
7798
} catch (error) {
78-
expect(error.message).toBe('`createCanal` found duplicated `name: a` key.');
99+
expect(error.message).toBe(
100+
'`createCanal` found duplicated `name: a` key.'
101+
);
79102
}
80103
expect.assertions(1);
81104
});

0 commit comments

Comments
 (0)