Skip to content

Commit

Permalink
[v15] refactor(app-shell): use react-apollo v3 (#801)
Browse files Browse the repository at this point in the history
* chore: update to react@16.9 (#966)

* chore: update to react@16.9

* fix: update lifecyle methods

* chore: temporary resolution for react

* chore(deps): update dependency @testing-library/react to v9.1.1 (#956)

* chore(deps): update dependency @testing-library/react to v8.0.9

* chore: update testing library to 9.1.1

* fix: remove cleanup-after-each hook (automatical now)

* refactor: to remove path for act

* refactor(app-shell): use react-apollo v3, use more hooks

* refactor(app-shell): do not render hooks conditionally

* chore: update react deps consistently

* refactor(authenticated): do not render hook conditionally

* chore: patch jest setup to avoid logging certain warnings on CI

* fix: missing prop ref

* fix(navbar): missing prop

* refactor(app-connectors): to useQuery for fetching image regex setting

* refactor(app-shell): connectors to useQuery

* test(app-shell): fix setup

* chore: regenerate lockfile

* chore: update react-apollo to 3.0.1

* refactor(connectors): image regex tests to RTL

* fix: query mocks for project suspended

* fix: pin react-test-renderer to 16.9

* fix(quick-access): update state unless component is unmounting

* refactor: componentWillUnmount is not a deprecated lifecycle method

* test: cleanup

* refactor: renaming based on feedback
  • Loading branch information
emmenko committed Aug 28, 2019
1 parent c49e84b commit 02b06b2
Show file tree
Hide file tree
Showing 39 changed files with 1,339 additions and 1,246 deletions.
4 changes: 2 additions & 2 deletions application-templates/starter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"@commercetools-frontend/ui-kit": "10.1.2",
"prop-types": "15.7.2",
"react": "16.9.0",
"react-apollo": "2.5.8",
"react-apollo": "3.0.1",
"react-dom": "16.9.0",
"react-intl": "3.1.11",
"react-redux": "7.1.1",
Expand All @@ -33,7 +33,7 @@
"devDependencies": {
"@commercetools-frontend/jest-preset-mc-app": "14.6.0",
"@commercetools-frontend/mc-scripts": "14.6.0",
"@testing-library/react": "9.1.1",
"@testing-library/react": "9.1.2",
"enzyme": "3.10.0",
"jest": "24.9.0"
}
Expand Down
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"@percy/cypress": "2.0.0",
"@percy/puppeteer": "1.0.8",
"@testing-library/cypress": "4.1.1",
"@testing-library/react": "9.1.1",
"@testing-library/react": "9.1.2",
"@types/common-tags": "1.8.0",
"@types/enzyme": "3.10.3",
"@types/graphql": "14.2.3",
Expand Down Expand Up @@ -146,7 +146,10 @@
},
"resolutions": {
"@types/react": "16.9.2",
"react": "16.9.0"
"react": "16.9.0",
"**/react": "16.9.0",
"react-test-renderer": "16.9.0",
"**/react-test-renderer": "16.9.0"
},
"engines": {
"node": ">=8.9",
Expand Down
6 changes: 4 additions & 2 deletions packages/application-shell-connectors/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"dependencies": {
"@babel/runtime-corejs3": "7.5.5",
"@commercetools-frontend/constants": "14.6.0",
"@commercetools-frontend/sentry": "14.6.0",
"apollo-cache-inmemory": "1.6.3",
"apollo-client": "2.6.4",
"apollo-link-http": "1.5.15",
Expand All @@ -51,12 +52,13 @@
"prop-types": "15.7.2"
},
"devDependencies": {
"@apollo/react-testing": "3.0.1",
"react": "16.9.0",
"react-apollo": "2.5.8"
"react-apollo": "3.0.1"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-apollo": "2.x"
"react-apollo": "3.x"
},
"engines": {
"node": ">=8",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,76 +1,149 @@
import React from 'react';
import { shallow, ShallowWrapper } from 'enzyme';
import { ProjectExtensionProviderForImageRegex } from './project-extension-image-regex';
import {
render,
RenderResult,
waitForElementToBeRemoved,
} from '@testing-library/react';
import {
MockedProvider as ApolloMockProvider,
MockedProviderProps,
} from '@apollo/react-testing';
import { reportErrorToSentry } from '@commercetools-frontend/sentry';
import {
ProjectExtensionProviderForImageRegex,
GetProjectExtensionImageRegex,
TImageRegex,
} from './project-extension-image-regex';
import FetchProjectExtensionImageRegex from './fetch-project-extension-image-regex.graphql';
import { GRAPHQL_TARGETS } from '@commercetools-frontend/constants';

jest.mock('@commercetools-frontend/sentry');

type TestProps = {
imageRegex: TImageRegex;
};
const TestComponent = (props: TestProps) => (
<>
<div>
{props.imageRegex &&
props.imageRegex.small &&
props.imageRegex.small.replace}
</div>
<div>
{props.imageRegex &&
props.imageRegex.thumb &&
props.imageRegex.thumb.replace}
</div>
</>
);

const renderComponent = (mocks: MockedProviderProps['mocks']) =>
render(
<ApolloMockProvider mocks={mocks} addTypename={true}>
<ProjectExtensionProviderForImageRegex>
<div>
<GetProjectExtensionImageRegex
render={imageRegexContext => {
if (imageRegexContext.isLoading) {
return <div>{'Loading...'}</div>;
}
if (!imageRegexContext.imageRegex) {
return <div>{'Not found'}</div>;
}
return (
<TestComponent imageRegex={imageRegexContext.imageRegex} />
);
}}
/>
</div>
</ProjectExtensionProviderForImageRegex>
</ApolloMockProvider>
);

describe('rendering', () => {
let wrapper: ShallowWrapper;
let rendered: RenderResult;

describe('Provider', () => {
describe('when data is not defined yet', () => {
beforeEach(() => {
wrapper = shallow(
<ProjectExtensionProviderForImageRegex>
<div />
</ProjectExtensionProviderForImageRegex>
).renderProp('children')({ loading: true, data: undefined });
});
it('should pass value object with "isLoading" state "true" to Provider', () => {
expect(wrapper).toHaveProp(
'value',
expect.objectContaining({ isLoading: true })
);
});
it('should pass value object with "imageRegex" undefined to Provider', () => {
expect(wrapper).toHaveProp(
'value',
expect.objectContaining({ imageRegex: undefined })
);
});
});
describe('when data is defined', () => {
beforeEach(() => {
wrapper = shallow(
<ProjectExtensionProviderForImageRegex>
<div />
</ProjectExtensionProviderForImageRegex>
).renderProp('children')({
loading: false,
data: {
projectExtension: {
imageRegex: {
thumb: {
flag: 'gi',
replace: '-thumb.jpg',
search: '.[^.]+$',
describe('when image regex is defined', () => {
beforeEach(() => {
rendered = renderComponent([
{
request: {
query: FetchProjectExtensionImageRegex,
variables: {
target: GRAPHQL_TARGETS.SETTINGS_SERVICE,
},
},
result: {
data: {
projectExtension: {
__typename: 'ProjectExtension',
id: 'p1',
imageRegex: {
__typename: 'ImageRegex',
thumb: {
__typename: 'ImageRegexOptions',
flag: 'gi',
replace: '-thumb.jpg',
search: '.[^.]+$',
},
small: null,
},
},
},
},
});
});
it('should pass value object with "isLoading" state "false" to Provider', () => {
expect(wrapper).toHaveProp(
'value',
expect.objectContaining({ isLoading: false })
);
});
it('should pass value object with "imageRegex" to Provider', () => {
expect(wrapper).toHaveProp(
'value',
expect.objectContaining({
imageRegex: {
thumb: {
flag: 'gi',
replace: '-thumb.jpg',
search: '.[^.]+$',
},
]);
});
it('should render regex info', async () => {
await waitForElementToBeRemoved(() => rendered.getByText('Loading...'));
expect(rendered.queryByText('-thumb.jpg')).toBeInTheDocument();
});
});
describe('when image regex is not defined', () => {
beforeEach(() => {
rendered = renderComponent([
{
request: {
query: FetchProjectExtensionImageRegex,
variables: {
target: GRAPHQL_TARGETS.SETTINGS_SERVICE,
},
},
result: {
data: {
projectExtension: {
__typename: 'ProjectExtension',
id: 'p1',
imageRegex: null,
},
},
})
);
});
},
},
]);
});
it('should not render regex info', async () => {
await waitForElementToBeRemoved(() => rendered.getByText('Loading...'));
expect(rendered.queryByText('Not found')).toBeInTheDocument();
});
});
describe('when request fails', () => {
beforeEach(() => {
rendered = renderComponent([
{
request: {
query: FetchProjectExtensionImageRegex,
variables: {
target: GRAPHQL_TARGETS.SETTINGS_SERVICE,
},
},
error: new Error('Oops'),
},
]);
});
it('should report error to sentry', async () => {
await waitForElementToBeRemoved(() => rendered.getByText('Loading...'));
expect(rendered.queryByText('Not found')).toBeInTheDocument();
expect(reportErrorToSentry).toHaveBeenCalled();
});
});
// TODO: we can write some functional tests using mount
// as soon as the new changes of the enzyme adapter are released.
// https://github.com/airbnb/enzyme/pull/1513
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import { Query } from 'react-apollo';
import { useQuery } from 'react-apollo';
import { GRAPHQL_TARGETS } from '@commercetools-frontend/constants';
import { reportErrorToSentry } from '@commercetools-frontend/sentry';
import getDisplayName from '../../utils/get-display-name';
import FetchProjectExtensionImageRegex from './fetch-project-extension-image-regex.graphql';

Expand All @@ -9,50 +10,52 @@ type TImageRegexOptions = {
replace: string;
search: string;
};
type TImageRegex = {
export type TImageRegex = {
thumb?: TImageRegexOptions;
small?: TImageRegexOptions;
};
type TImageRegexContext = {
isLoading: boolean;
imageRegex: TImageRegex | null;
imageRegex?: TImageRegex;
};
type ProviderProps = {
children: React.ReactNode;
};
type ConsumerProps = {
render: (imageRegex: TImageRegexContext | {}) => React.ReactNode;
render: (imageRegex: TImageRegexContext) => React.ReactNode;
children?: never;
};

const Context = React.createContext<TImageRegexContext | {}>({});
const Context = React.createContext<TImageRegexContext>({ isLoading: true });

const ProjectExtensionProviderForImageRegex = (props: ProviderProps) => (
<Query<
const ProjectExtensionProviderForImageRegex = (props: ProviderProps) => {
const { loading, data } = useQuery<
{ projectExtension?: { imageRegex?: TImageRegex } },
{ target: string }
>
query={FetchProjectExtensionImageRegex}
variables={{ target: GRAPHQL_TARGETS.SETTINGS_SERVICE }}
>
{({ loading, data }) => (
<Context.Provider
value={{
isLoading: loading,
imageRegex:
data && data.projectExtension && data.projectExtension.imageRegex,
}}
>
{props.children}
</Context.Provider>
)}
</Query>
);
{ target: typeof GRAPHQL_TARGETS.SETTINGS_SERVICE }
>(FetchProjectExtensionImageRegex, {
onError: reportErrorToSentry,
variables: { target: GRAPHQL_TARGETS.SETTINGS_SERVICE },
});

return (
<Context.Provider
value={{
isLoading: loading,
imageRegex:
data && data.projectExtension && data.projectExtension.imageRegex,
}}
>
{props.children}
</Context.Provider>
);
};
ProjectExtensionProviderForImageRegex.displayName =
'ProjectExtensionProviderForImageRegex';

const GetProjectExtensionImageRegex = (props: ConsumerProps) => (
<Context.Consumer>{imageRegex => props.render(imageRegex)}</Context.Consumer>
<Context.Consumer>
{imageRegexContext => props.render(imageRegexContext)}
</Context.Consumer>
);
GetProjectExtensionImageRegex.displayName = 'GetProjectExtensionImageRegex';

Expand Down
7 changes: 4 additions & 3 deletions packages/application-shell/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"build:test-utils:cjs": "cross-env NODE_ENV=development rollup -c ../../rollup.config.js -f cjs ./src/test-utils/index.js --o ./test-utils/index.js"
},
"dependencies": {
"@apollo/react-testing": "3.0.1",
"@commercetools-frontend/actions-global": "14.6.0",
"@commercetools-frontend/application-components": "14.6.0",
"@commercetools-frontend/application-shell-connectors": "14.6.0",
Expand Down Expand Up @@ -95,9 +96,9 @@
},
"devDependencies": {
"@commercetools-frontend/ui-kit": "10.1.2",
"@testing-library/react": "9.1.1",
"@testing-library/react": "9.1.2",
"react": "16.9.0",
"react-apollo": "2.5.8",
"react-apollo": "3.0.1",
"react-dom": "16.9.0",
"react-intl": "3.1.11",
"react-redux": "7.1.1",
Expand All @@ -110,7 +111,7 @@
"@commercetools-frontend/ui-kit": "10.x",
"@testing-library/react": "8.x",
"react": ">=16.8.0",
"react-apollo": "2.x",
"react-apollo": "3.x",
"react-dom": ">=16.8.0",
"react-intl": "3.x",
"react-redux": "7.x",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { setIsAuthenticated } from '../authenticated';
import { getBrowserLocale } from './utils';
import ApplicationShellProvider from './application-shell-provider';

jest.mock('@commercetools-frontend/sentry');
jest.mock('../authenticated');
jest.mock('./utils');

Expand Down
Loading

0 comments on commit 02b06b2

Please sign in to comment.