Skip to content

Commit b7bc58b

Browse files
authored
Merge pull request #58 from getditto/pv/async-setup
feat: add support for async setup functions
2 parents 35c29d4 + c80458e commit b7bc58b

File tree

2 files changed

+68
-2
lines changed

2 files changed

+68
-2
lines changed

src/DittoProvider.spec.tsx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,4 +241,56 @@ describe('Ditto Provider Tests', () => {
241241
expect(setup).to.have.been.calledOnce
242242
expect(init).to.have.been.calledOnce
243243
})
244+
245+
it('should work with an async setup function', async () => {
246+
const config = testIdentity()
247+
const renderFn = sinon.stub()
248+
renderFn.withArgs(sinon.match({ loading: false })).returns('loaded')
249+
250+
root.render(
251+
<DittoProvider
252+
setup={async () => {
253+
const ditto = new Ditto(config.identity, config.path)
254+
await new Promise((resolve) => setTimeout(resolve, 10))
255+
return ditto
256+
}}
257+
>
258+
{renderFn}
259+
</DittoProvider>,
260+
)
261+
262+
await waitFor(() => container.textContent === 'loaded')
263+
expect(renderFn).to.have.been.calledTwice
264+
})
265+
266+
it(`should provide an error when the setup function doesn't return a ditto instance`, async () => {
267+
const setup = sinon.stub().returns(null)
268+
269+
root.render(
270+
<DittoProvider setup={setup}>
271+
{({ loading, error }) => !loading && error?.message}
272+
</DittoProvider>,
273+
)
274+
275+
await waitFor(
276+
() =>
277+
container.textContent ===
278+
'expected a Ditto instance to be returned by the setup function, but got null',
279+
)
280+
})
281+
282+
it('should provide an error when the setup function doesn’t return an array of ditto instances', async () => {
283+
const setup = sinon.stub().returns([null])
284+
root.render(
285+
<DittoProvider setup={setup}>
286+
{({ loading, error }) => !loading && error?.message}
287+
</DittoProvider>,
288+
)
289+
290+
await waitFor(
291+
() =>
292+
container.textContent ===
293+
'expected an array of Ditto instances to be returned by the setup function, but at least one element is not a Ditto instance (got null)',
294+
)
295+
})
244296
})

src/DittoProvider.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export interface DittoProviderProps {
2020
*
2121
* Returns a single Ditto instance or an array of instances.
2222
*/
23-
setup: () => Ditto | Ditto[]
23+
setup: () => Ditto | Ditto[] | Promise<Ditto | Ditto[]>
2424
render?: RenderFunction
2525
children?: RenderFunction
2626
}
@@ -65,16 +65,30 @@ export const DittoProvider: React.FunctionComponent<DittoProviderProps> = (
6565
hasMountEffectStarted.current = true
6666
try {
6767
await init(props.initOptions)
68-
const setupReturnValue: Ditto | Ditto[] = props.setup()
68+
const setupReturnValue: Ditto | Ditto[] = await props.setup()
6969
if (Array.isArray(setupReturnValue)) {
7070
const dittoHash: DittoHash = {}
7171
const dittos: Ditto[] = setupReturnValue
7272
for (const ditto of dittos) {
73+
if (!(ditto instanceof Ditto)) {
74+
throw new Error(
75+
// Type is `never` because correct use never reaches this point
76+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
77+
`expected an array of Ditto instances to be returned by the setup function, but at least one element is not a Ditto instance (got ${ditto})`,
78+
)
79+
}
7380
dittoHash[ditto.persistenceDirectory] = ditto
7481
}
7582
setDittoHash(dittoHash)
7683
} else {
7784
const ditto = setupReturnValue
85+
if (!(ditto instanceof Ditto)) {
86+
throw new Error(
87+
// Type is `never` because correct use never reaches this point
88+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
89+
`expected a Ditto instance to be returned by the setup function, but got ${ditto}`,
90+
)
91+
}
7892
const dittoHash: DittoHash = {}
7993
dittoHash[ditto.persistenceDirectory] = ditto
8094
setDittoHash(dittoHash)

0 commit comments

Comments
 (0)