Skip to content

Commit 137b48e

Browse files
committed
Add custom request and watch
1 parent 0366dcc commit 137b48e

File tree

2 files changed

+130
-7
lines changed

2 files changed

+130
-7
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* This file contains tests only for custom geolocation providers.
3+
* e2e-tests for built-in browser navigator.geolocation in apps/web-api-demo/test/geolocation.spec.ts
4+
*/
5+
6+
import { allSettled, createStore, fork } from 'effector';
7+
import { trackGeolocation } from 'geolocation';
8+
import { describe, expect, test } from 'vitest';
9+
10+
describe('trackGeolocation', () => {
11+
test('request', async () => {
12+
let lat = 41.890221;
13+
let lon = 12.492348;
14+
const myCustomProvider = () => ({
15+
async getCurrentPosition() {
16+
return {
17+
coords: { latitude: lat, longitude: lon },
18+
timestamp: Date.now(),
19+
};
20+
},
21+
watchPosition(success: any, error: any) {
22+
return () => {};
23+
},
24+
});
25+
26+
const geo = trackGeolocation({ providers: [myCustomProvider] });
27+
28+
const scope = fork();
29+
30+
expect(scope.getState(geo.$location)).toMatchInlineSnapshot(`null`);
31+
32+
await allSettled(geo.request, { scope });
33+
expect(scope.getState(geo.$location)).toMatchInlineSnapshot(`
34+
{
35+
"latitude": 41.890221,
36+
"longitude": 12.492348,
37+
}
38+
`);
39+
40+
lat = 42.890221;
41+
lon = 13.492348;
42+
43+
await allSettled(geo.request, { scope });
44+
expect(scope.getState(geo.$location)).toMatchInlineSnapshot(`
45+
{
46+
"latitude": 42.890221,
47+
"longitude": 13.492348,
48+
}
49+
`);
50+
});
51+
52+
test('watching', async () => {
53+
const $externalLocation: any = createStore({
54+
latitude: 41.890221,
55+
longitude: 12.492348,
56+
});
57+
58+
const myCustomProvider = () => ({
59+
async getCurrentPosition() {
60+
return {
61+
coords: $externalLocation.getState(),
62+
timestamp: Date.now(),
63+
};
64+
},
65+
watchPosition(success: any, error: any) {
66+
return $externalLocation.watch((location: any) =>
67+
success({
68+
coords: location,
69+
timestamp: Date.now(),
70+
})
71+
);
72+
},
73+
});
74+
75+
const geo = trackGeolocation({ providers: [myCustomProvider] });
76+
77+
const scope = fork();
78+
79+
expect(scope.getState(geo.$location)).toMatchInlineSnapshot(`null`);
80+
81+
await allSettled(geo.watching.start, { scope });
82+
expect(scope.getState(geo.$location)).toMatchInlineSnapshot(`
83+
{
84+
"latitude": 41.890221,
85+
"longitude": 12.492348,
86+
}
87+
`);
88+
89+
$externalLocation.setState({ latitude: 42.890221, longitude: 13.492348 });
90+
expect(scope.getState(geo.$location)).toMatchInlineSnapshot(`
91+
{
92+
"latitude": 42.890221,
93+
"longitude": 13.492348,
94+
}
95+
`);
96+
97+
await allSettled(geo.watching.stop, { scope });
98+
$externalLocation.setState({ latitude: 43.890221, longitude: 14.492348 });
99+
expect(scope.getState(geo.$location)).toMatchInlineSnapshot(`
100+
{
101+
"latitude": 42.890221,
102+
"longitude": 13.492348,
103+
}
104+
`);
105+
});
106+
});

packages/web-api/src/geolocation.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
createStore,
88
createEffect,
99
sample,
10-
restore,
1110
attach,
1211
scopeBind,
1312
} from 'effector';
@@ -53,7 +52,7 @@ type Unsubscribe = () => void;
5352

5453
type CustomProvider = (params: GeolocationParams) => {
5554
getCurrentPosition: () => Promise<CustomGeolocationPosition>;
56-
watchPosition?: (
55+
watchPosition: (
5756
successCallback: (position: CustomGeolocationPosition) => void,
5857
errorCallback: (error: CustomGeolocationError) => void
5958
) => Unsubscribe;
@@ -139,14 +138,19 @@ export function trackGeolocation(
139138
CustomGeolocationPosition | globalThis.GeolocationPosition,
140139
CustomGeolocationError | globalThis.GeolocationPositionError
141140
>(async () => {
142-
let geolocation: GeolocationPosition | null = null;
141+
let geolocation:
142+
| globalThis.GeolocationPosition
143+
| CustomGeolocationPosition
144+
| null = null;
143145

144146
for (const provider of providres) {
145147
if (isDefaultProvider(provider)) {
146148
geolocation = await new Promise<GeolocationPosition>(
147149
(resolve, rejest) =>
148150
provider.getCurrentPosition(resolve, rejest, params)
149151
);
152+
} else {
153+
geolocation = await provider(params).getCurrentPosition();
150154
}
151155
}
152156

@@ -175,7 +179,8 @@ export function trackGeolocation(
175179
const boundNewPosition = scopeBind(newPosition, { safe: true });
176180
const boundFailed = scopeBind(failed, { safe: true });
177181

178-
const unwatchMap = new Map<(id: number) => void, number>();
182+
const defaultUnwatchMap = new Map<(id: number) => void, number>();
183+
const customUnwatchSet = new Set<Unsubscribe>();
179184

180185
for (const provider of providres) {
181186
if (isDefaultProvider(provider)) {
@@ -185,14 +190,26 @@ export function trackGeolocation(
185190
params
186191
);
187192

188-
unwatchMap.set((id: number) => provider.clearWatch(id), watchId);
193+
defaultUnwatchMap.set((id: number) => provider.clearWatch(id), watchId);
194+
} else {
195+
const unwatch = provider(params).watchPosition(
196+
boundNewPosition,
197+
boundFailed
198+
);
199+
200+
customUnwatchSet.add(unwatch);
189201
}
190202
}
191203

192204
return () => {
193-
for (const [unwatch, id] of unwatchMap) {
205+
for (const [unwatch, id] of defaultUnwatchMap) {
194206
unwatch(id);
195-
unwatchMap.delete(unwatch);
207+
defaultUnwatchMap.delete(unwatch);
208+
}
209+
210+
for (const unwatch of customUnwatchSet) {
211+
unwatch();
212+
customUnwatchSet.delete(unwatch);
196213
}
197214
};
198215
});

0 commit comments

Comments
 (0)