From 432af48e3eda0ad530344b868984a251f47e0289 Mon Sep 17 00:00:00 2001 From: SHA-4 Date: Thu, 5 Mar 2020 15:47:07 -0500 Subject: [PATCH 1/7] Flush promises to handle async React lifecycle methods --- src/tester.tsx | 6 ++++-- src/utils.ts | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/tester.tsx b/src/tester.tsx index 3a4a87a..825d2d4 100644 --- a/src/tester.tsx +++ b/src/tester.tsx @@ -1,6 +1,7 @@ import React, { Fragment } from 'react'; import { + flushPromises, getInstance, getValue, isString, @@ -201,8 +202,9 @@ class Tester { } if (mountOpts.async) { - await this.sleep(); - this.update(); + // See https://github.com/enzymejs/enzyme/issues/1587 + await flushPromises(); + await this.refresh(); } return this; diff --git a/src/utils.ts b/src/utils.ts index a09b4a2..c454462 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -22,3 +22,7 @@ export function capitalize (string: string) { export function isString (value: unknown): value is string { return typeof value === 'string' || value instanceof String; } + +export function flushPromises () { + return new Promise((resolve, _reject) => setImmediate(resolve)); +} From 2895a011ee6311bdae62edb98bf1edfa90ab6daa Mon Sep 17 00:00:00 2001 From: SHA-4 Date: Thu, 5 Mar 2020 15:54:02 -0500 Subject: [PATCH 2/7] Mount components with async by default --- src/tester.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tester.tsx b/src/tester.tsx index 825d2d4..8c6c9ea 100644 --- a/src/tester.tsx +++ b/src/tester.tsx @@ -201,7 +201,7 @@ class Tester { this.createShallowWrapper(); } - if (mountOpts.async) { + if (mountOpts.async !== false) { // See https://github.com/enzymejs/enzyme/issues/1587 await flushPromises(); await this.refresh(); From 11f700405de01d7a779f644a75bfa17c5be80d2f Mon Sep 17 00:00:00 2001 From: SHA-4 Date: Thu, 5 Mar 2020 16:48:26 -0500 Subject: [PATCH 3/7] Await componentDidMount method by default --- src/tester.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tester.tsx b/src/tester.tsx index 8c6c9ea..595813d 100644 --- a/src/tester.tsx +++ b/src/tester.tsx @@ -202,6 +202,8 @@ class Tester { } if (mountOpts.async !== false) { + await this.instance.componentDidMount(); + // See https://github.com/enzymejs/enzyme/issues/1587 await flushPromises(); await this.refresh(); From af05d9991052c06511b60834b33dc923b76c2913 Mon Sep 17 00:00:00 2001 From: SHA-4 Date: Thu, 5 Mar 2020 17:01:39 -0500 Subject: [PATCH 4/7] Handle null instance in mount --- src/tester.tsx | 4 +++- src/utils.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tester.tsx b/src/tester.tsx index 595813d..663e6eb 100644 --- a/src/tester.tsx +++ b/src/tester.tsx @@ -202,7 +202,9 @@ class Tester { } if (mountOpts.async !== false) { - await this.instance.componentDidMount(); + if (this.instance) { + await this.instance.componentDidMount(); + } // See https://github.com/enzymejs/enzyme/issues/1587 await flushPromises(); diff --git a/src/utils.ts b/src/utils.ts index c454462..76e1e34 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -4,7 +4,7 @@ export function getInstance (component: any) { const instance = component.instance(); - return instance.wrappedInstance || instance; + return instance && (instance.wrappedInstance || instance); } export function getValue (tester: any, value: unknown) { From e90de594a521419985ddf1b868ae9d0fc952ceaf Mon Sep 17 00:00:00 2001 From: SHA-4 Date: Thu, 5 Mar 2020 17:18:18 -0500 Subject: [PATCH 5/7] Add test for async componentDidMount --- test/tester.test.tsx | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/test/tester.test.tsx b/test/tester.test.tsx index a6b5338..87286f7 100644 --- a/test/tester.test.tsx +++ b/test/tester.test.tsx @@ -1,13 +1,35 @@ /* global it, describe, expect */ -import React from 'react'; +import React, { Component } from 'react'; import { Tester } from '../src'; +import { sleep } from '../src/utils'; const COMPONENT_ID = 'testing-component'; const MyTestingComponent = (props: any) =>
; -describe('Tester', () => { +class AsyncComponent extends Component { + public constructor (props: object) { + super(props); + this.state = { status: 'loading' }; + } + + public async componentDidMount () { + await sleep(10); + this.setState({ + status: 'done', + }); + } + public render () { + return ( +
+ {this.state.status} +
+ ); + } +} + +describe('Tester', () => { it('Init tests', async () => { const tester = await new Tester(MyTestingComponent).mount(); expect(tester.wrapper).toBeTruthy(); @@ -19,4 +41,10 @@ describe('Tester', () => { expect(tester.wrapper).toBeTruthy(); expect(tester.wrapper.html()).toContain('test-hook-component'); }); + + it('Awaits async componentDidMount', async () => { + const tester = await new Tester(AsyncComponent).mount(); + expect(tester.wrapper.text()).toContain('done'); + }); + }); From 15e9ae85abbe6a6388c8c02b1c37d354f9460fce Mon Sep 17 00:00:00 2001 From: SHA-4 Date: Thu, 5 Mar 2020 17:32:43 -0500 Subject: [PATCH 6/7] Update test to use text helper function --- test/tester.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/tester.test.tsx b/test/tester.test.tsx index 87286f7..dc7b842 100644 --- a/test/tester.test.tsx +++ b/test/tester.test.tsx @@ -44,7 +44,7 @@ describe('Tester', () => { it('Awaits async componentDidMount', async () => { const tester = await new Tester(AsyncComponent).mount(); - expect(tester.wrapper.text()).toContain('done'); + expect(tester.text()).toContain('done'); }); }); From af55bcafc2cbf2aed2fc343e0bcfb3e708e9eacf Mon Sep 17 00:00:00 2001 From: SHA-4 Date: Thu, 5 Mar 2020 17:42:50 -0500 Subject: [PATCH 7/7] Make flushPromises util async --- src/utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 76e1e34..6f28e76 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -23,6 +23,6 @@ export function isString (value: unknown): value is string { return typeof value === 'string' || value instanceof String; } -export function flushPromises () { - return new Promise((resolve, _reject) => setImmediate(resolve)); +export async function flushPromises () { + return new Promise((resolve, _reject) => setImmediate(resolve)); }