Skip to content

Commit

Permalink
feat(react): add asyncSsrManager prop to FeatureAppLoader (#248)
Browse files Browse the repository at this point in the history
  • Loading branch information
unstubbable authored and clebert committed Jan 11, 2019
1 parent f662c45 commit 92579d9
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 26 deletions.
1 change: 1 addition & 0 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"module": "lib/esm/index.js",
"typings": "lib/cjs/index.d.ts",
"dependencies": {
"@feature-hub/async-ssr-manager": "^0.0.0",
"@feature-hub/core": "^0.11.0"
},
"devDependencies": {
Expand Down
98 changes: 89 additions & 9 deletions packages/react/src/__tests__/feature-app-loader.node.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

// tslint:disable:no-implicit-dependencies

import {AsyncSsrManagerV1} from '@feature-hub/async-ssr-manager';
import {
AsyncValue,
FeatureAppDefinition,
Expand All @@ -13,10 +14,15 @@ import {shallow} from 'enzyme';
import * as React from 'react';
import {FeatureAppLoader} from '..';

interface MockAsyncSsrManager extends AsyncSsrManagerV1 {
rerenderAfter: ((promise: Promise<unknown>) => void) & jest.Mock;
}

describe('FeatureAppLoader (on Node.js)', () => {
let mockFeatureAppManager: FeatureAppManagerLike;
let mockGetAsyncFeatureAppDefinition: jest.Mock;
let mockAsyncFeatureAppDefinition: AsyncValue<FeatureAppDefinition<unknown>>;
let mockAsyncSsrManager: MockAsyncSsrManager;
let spyConsoleError: jest.SpyInstance;

beforeEach(() => {
Expand All @@ -35,6 +41,12 @@ describe('FeatureAppLoader (on Node.js)', () => {
destroy: jest.fn()
};

mockAsyncSsrManager = {
rerenderAfter: jest.fn(),
renderUntilCompleted: jest.fn(),
serverRequest: undefined
};

spyConsoleError = jest.spyOn(console, 'error');
spyConsoleError.mockImplementation(jest.fn());
});
Expand All @@ -50,13 +62,24 @@ describe('FeatureAppLoader (on Node.js)', () => {
featureAppManager={mockFeatureAppManager}
src="example.js"
/>,
{
disableLifecycleMethods: true
}
{disableLifecycleMethods: true}
);

expect(mockGetAsyncFeatureAppDefinition).not.toHaveBeenCalled();
});

it('does not trigger a rerender on the Async SSR Manager', () => {
shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="example.js"
asyncSsrManager={mockAsyncSsrManager}
/>,
{disableLifecycleMethods: true}
);

expect(mockAsyncSsrManager.rerenderAfter).not.toHaveBeenCalled();
});
});

describe('with a serverSrc', () => {
Expand All @@ -67,16 +90,59 @@ describe('FeatureAppLoader (on Node.js)', () => {
src="example.js"
serverSrc="example-node.js"
/>,
{
disableLifecycleMethods: true
}
{disableLifecycleMethods: true}
);

expect(mockGetAsyncFeatureAppDefinition.mock.calls).toEqual([
['example-node.js']
]);
});

it('triggers a rerender on the Async SSR Manager with the feature app definition promise', () => {
shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="example.js"
serverSrc="example-node.js"
asyncSsrManager={mockAsyncSsrManager}
/>,
{disableLifecycleMethods: true}
);

expect(mockAsyncSsrManager.rerenderAfter.mock.calls).toEqual([
[mockAsyncFeatureAppDefinition.promise]
]);
});

describe('when a Feature App definition is synchronously available', () => {
let mockFeatureAppDefinition: FeatureAppDefinition<unknown>;

beforeEach(() => {
mockFeatureAppDefinition = {
id: 'testId',
create: jest.fn()
};

mockAsyncFeatureAppDefinition = new AsyncValue(
Promise.resolve(mockFeatureAppDefinition)
);
});

it('does not trigger a rerender on the Async SSR Manager', () => {
shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="example.js"
serverSrc="example-node.js"
asyncSsrManager={mockAsyncSsrManager}
/>,
{disableLifecycleMethods: true}
);

expect(mockAsyncSsrManager.rerenderAfter).not.toHaveBeenCalled();
});
});

describe('when the async Feature App definition synchronously has an error', () => {
let mockError: Error;

Expand All @@ -94,9 +160,7 @@ describe('FeatureAppLoader (on Node.js)', () => {
serverSrc="example-node.js"
idSpecifier="testIdSpecifier"
/>,
{
disableLifecycleMethods: true
}
{disableLifecycleMethods: true}
)
).toThrowError(mockError);

Expand All @@ -107,6 +171,22 @@ describe('FeatureAppLoader (on Node.js)', () => {
]
]);
});

it('does not trigger a rerender on the Async SSR Manager', () => {
try {
shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="example.js"
serverSrc="example-node.js"
asyncSsrManager={mockAsyncSsrManager}
/>,
{disableLifecycleMethods: true}
);
} catch {}

expect(mockAsyncSsrManager.rerenderAfter).not.toHaveBeenCalled();
});
});
});
});
68 changes: 53 additions & 15 deletions packages/react/src/__tests__/feature-app-loader.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// tslint:disable:no-implicit-dependencies

import {AsyncSsrManagerV1} from '@feature-hub/async-ssr-manager';
import {
AsyncValue,
FeatureAppDefinition,
Expand All @@ -9,10 +10,15 @@ import {shallow} from 'enzyme';
import * as React from 'react';
import {FeatureAppContainer, FeatureAppLoader} from '..';

interface MockAsyncSsrManager extends AsyncSsrManagerV1 {
rerenderAfter: ((promise: Promise<unknown>) => void) & jest.Mock;
}

describe('FeatureAppLoader', () => {
let mockFeatureAppManager: FeatureAppManagerLike;
let mockGetAsyncFeatureAppDefinition: jest.Mock;
let mockAsyncFeatureAppDefinition: AsyncValue<FeatureAppDefinition<unknown>>;
let mockAsyncSsrManager: MockAsyncSsrManager;
let spyConsoleError: jest.SpyInstance;

beforeEach(() => {
Expand All @@ -35,6 +41,12 @@ describe('FeatureAppLoader', () => {
destroy: jest.fn()
};

mockAsyncSsrManager = {
rerenderAfter: jest.fn(),
renderUntilCompleted: jest.fn(),
serverRequest: undefined
};

spyConsoleError = jest.spyOn(console, 'error');
spyConsoleError.mockImplementation(jest.fn());
});
Expand All @@ -55,7 +67,7 @@ describe('FeatureAppLoader', () => {
const wrapper = shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="/test.js"
src="example.js"
/>
);

Expand All @@ -67,7 +79,7 @@ describe('FeatureAppLoader', () => {
shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="/test.js"
src="example.js"
/>
);

Expand All @@ -80,7 +92,7 @@ describe('FeatureAppLoader', () => {
shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="/test.js"
src="example.js"
css={[{href: 'foo.css'}, {href: 'bar.css', media: 'print'}]}
/>
);
Expand All @@ -93,15 +105,15 @@ describe('FeatureAppLoader', () => {
shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="/test.js"
src="example.js"
css={[{href: 'foo.css'}]}
/>
);

shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="/test.js"
src="example.js"
css={[{href: 'foo.css'}]}
/>
);
Expand Down Expand Up @@ -129,7 +141,7 @@ describe('FeatureAppLoader', () => {
const wrapper = shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="/test.js"
src="example.js"
idSpecifier="testIdSpecifier"
/>
);
Expand All @@ -142,6 +154,19 @@ describe('FeatureAppLoader', () => {
/>
);
});

it('does not trigger a rerender on the Async SSR Manager', () => {
shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="example.js"
serverSrc="example-node.js"
asyncSsrManager={mockAsyncSsrManager}
/>
);

expect(mockAsyncSsrManager.rerenderAfter).not.toHaveBeenCalled();
});
});

describe('when the async Feature App definition synchronously has an error', () => {
Expand All @@ -161,7 +186,7 @@ describe('FeatureAppLoader', () => {
const wrapper = shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="/test.js"
src="example.js"
idSpecifier="testIdSpecifier"
/>
);
Expand All @@ -170,7 +195,7 @@ describe('FeatureAppLoader', () => {

expect(spyConsoleError.mock.calls).toEqual([
[
'The Feature App for the src "/test.js" and the ID specifier "testIdSpecifier" could not be rendered.',
'The Feature App for the src "example.js" and the ID specifier "testIdSpecifier" could not be rendered.',
mockError
]
]);
Expand Down Expand Up @@ -198,7 +223,7 @@ describe('FeatureAppLoader', () => {
const wrapper = shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="/test.js"
src="example.js"
/>
);

Expand All @@ -209,7 +234,7 @@ describe('FeatureAppLoader', () => {
const wrapper = shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="/test.js"
src="example.js"
idSpecifier="testIdSpecifier"
/>
);
Expand All @@ -225,12 +250,25 @@ describe('FeatureAppLoader', () => {
);
});

it('does not trigger a rerender on the Async SSR Manager', () => {
shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="example.js"
serverSrc="example-node.js"
asyncSsrManager={mockAsyncSsrManager}
/>
);

expect(mockAsyncSsrManager.rerenderAfter).not.toHaveBeenCalled();
});

describe('when unmounted before loading has finished', () => {
it('renders nothing', async () => {
const wrapper = shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="/test.js"
src="example.js"
/>
);

Expand Down Expand Up @@ -261,7 +299,7 @@ describe('FeatureAppLoader', () => {
const wrapper = shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="/test.js"
src="example.js"
idSpecifier="testIdSpecifier"
/>
);
Expand All @@ -278,7 +316,7 @@ describe('FeatureAppLoader', () => {

expect(spyConsoleError.mock.calls).toEqual([
[
'The Feature App for the src "/test.js" and the ID specifier "testIdSpecifier" could not be rendered.',
'The Feature App for the src "example.js" and the ID specifier "testIdSpecifier" could not be rendered.',
mockError
]
]);
Expand All @@ -289,7 +327,7 @@ describe('FeatureAppLoader', () => {
const wrapper = shallow(
<FeatureAppLoader
featureAppManager={mockFeatureAppManager}
src="/test.js"
src="example.js"
/>
);

Expand All @@ -305,7 +343,7 @@ describe('FeatureAppLoader', () => {

expect(spyConsoleError.mock.calls).toEqual([
[
'The Feature App for the src "/test.js" could not be rendered.',
'The Feature App for the src "example.js" could not be rendered.',
mockError
]
]);
Expand Down
Loading

0 comments on commit 92579d9

Please sign in to comment.