Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

馃悰 no longer clobber koa context #879

Merged
merged 3 commits into from Aug 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -157,6 +157,11 @@ describe('create-mock-context', () => {
expect(context.headers.referrer).toBe(headers.referrer);
});

it('returns custom headers when requested through ctx.get', () => {
const context = createContext({headers: {test: 'value'}});
expect(context.get('test')).toBe('value');
});

it('includes custom state', () => {
const state = {
productName: 'Fabulous robot',
Expand Down
Expand Up @@ -69,11 +69,10 @@ export class ReactServerPlugin {
import {createServer} from '@shopify/react-server';
import App from './index';
const render = (ctx) =>
React.createElement(App, {
server: true,
locale: ctx.locale,
location: ctx.request.url,
});
React.createElement(App, {
server: true,
location: ctx.request.url,
});

const app = createServer({
port: ${port ? port : 'process.env.REACT_SERVER_PORT || 8081'},
Expand Down
6 changes: 6 additions & 0 deletions packages/react-server/CHANGELOG.md
Expand Up @@ -11,6 +11,12 @@ and adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

- Added `Options` object as the second argument to `createRender()` allowing passed in values for `afterEachPass` and `betweenEachPass` [#911](https://github.com/Shopify/quilt/pull/911)

## 0.2.0

### Changed

- `createRender` now passses the unchanged `Koa.Context` object.

## [0.1.6] - 2019-08-20

- actually passes in the headers from koa context into `NetworkManager`
Expand Down
7 changes: 3 additions & 4 deletions packages/react-server/README.md
Expand Up @@ -26,12 +26,11 @@ To begin using this package, Node apps only require a server entry point that ca

```tsx
import React from 'react';
import {createServer, RenderContext} from '@shopify/react-server';

import {createServer} from '@shopify/react-server';
import App from '../app';

const app = createServer({
render: (ctx: RenderContext) => <App location={ctx.request.url} />,
render: ctx => <App location={ctx.request.url} />,
});
```

Expand Down Expand Up @@ -71,7 +70,7 @@ interface Options {
assetPrefix?: string;
// any additional Koa middleware to mount on the server
serverMiddleware?: compose.Middleware<Context>[];
// a function of `(ctx: Koa.Context) => React.ReactNode`
// a function of `(ctx: Context, data: {locale: string}): React.ReactElement<any>`
render: RenderFunction;
// whether to run in debug mode
debug?: boolean;
Expand Down
2 changes: 1 addition & 1 deletion packages/react-server/src/index.ts
@@ -1,3 +1,3 @@
export {createServer} from './server';
export {createRender, RenderContext} from './render';
export {createRender, Context} from './render';
export {createLogger} from './logger';
2 changes: 1 addition & 1 deletion packages/react-server/src/render/index.ts
@@ -1 +1 @@
export {createRender, RenderContext, RenderFunction} from './render';
export {createRender, Context, RenderFunction} from './render';
19 changes: 6 additions & 13 deletions packages/react-server/src/render/render.tsx
Expand Up @@ -22,10 +22,10 @@ import {Header, StatusCode} from '@shopify/react-network';
import {getAssets} from '@shopify/sewing-kit-koa';
import {getLogger} from '../logger';

export type RenderContext = Context & {
locale: string;
};
export type RenderFunction = (ctx: RenderContext) => React.ReactElement<any>;
export {Context};
export interface RenderFunction {
(ctx: Context): React.ReactElement<any>;
}

type Options = Pick<
NonNullable<ArgumentAtIndex<typeof extract, 1>>,
Expand All @@ -45,11 +45,9 @@ export function createRender(render: RenderFunction, options: Options = {}) {
});
const htmlManager = new HtmlManager();
const asyncAssetManager = new AsyncAssetManager();
const acceptsLanguages = ctx.acceptsLanguages && ctx.acceptsLanguages();
const locale = Array.isArray(acceptsLanguages) ? acceptsLanguages[0] : 'en';

try {
const app = render({...ctx, locale});
const app = render(ctx);
await extract(app, {
decorate(app) {
return (
Expand Down Expand Up @@ -86,12 +84,7 @@ export function createRender(render: RenderFunction, options: Options = {}) {
]);

const response = stream(
<Html
locale={locale}
manager={htmlManager}
styles={styles}
scripts={scripts}
>
<Html manager={htmlManager} styles={styles} scripts={scripts}>
<HtmlContext.Provider value={htmlManager}>{app}</HtmlContext.Provider>
</Html>,
);
Expand Down
18 changes: 14 additions & 4 deletions packages/react-server/src/render/test/render.test.tsx
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import {createMockContext} from '@shopify/jest-koa-mocks';
import withEnv from '@shopify/with-env';
import {Effect} from '@shopify/react-effect/server';
import {createRender, RenderContext} from '../render';
import {createRender} from '../render';

jest.mock('@shopify/sewing-kit-koa', () => ({
getAssets() {
Expand All @@ -25,14 +25,24 @@ describe('createRender', () => {
const ctx = createMockContext();

const renderFunction = createRender(() => <>{myCoolApp}</>);
await renderFunction(ctx as RenderContext);
await renderFunction(ctx);

expect(await readStream(ctx.body)).toContain(myCoolApp);
});

it('does not clobber proxies in the context object', async () => {
const headerValue = 'some-value';
const ctx = createMockContext({headers: {'some-header': headerValue}});

const renderFunction = createRender(ctx => <>{ctx.get('some-header')}</>);
await renderFunction(ctx);

expect(await readStream(ctx.body)).toContain(headerValue);
});

it('in development the body contains a meaningful error messages', () => {
withEnv('development', async () => {
const ctx = {...createMockContext(), locale: ''};
const ctx = createMockContext();

const renderFunction = createRender(() => <BrokenApp />);
await renderFunction(ctx);
Expand All @@ -43,7 +53,7 @@ describe('createRender', () => {

it('in production it throws a 500 with a meaninful error message', () => {
withEnv('production', async () => {
const ctx = {...createMockContext(), locale: ''};
const ctx = createMockContext();
const throwSpy = jest.spyOn(ctx, 'throw').mockImplementation(() => null);

const renderFunction = createRender(() => <BrokenApp />);
Expand Down
3 changes: 1 addition & 2 deletions packages/react-server/src/server/test/server.test.tsx
Expand Up @@ -41,13 +41,12 @@ describe('createServer()', () => {
it('starts a server that responds with markup', async () => {
const response = await request(`${ip}:${port}`)
.get('/')
.set({'accept-language': 'fr'})
.then((resp: request.Response) => {
return resp;
});

expect(response.text).toBe(
`<!DOCTYPE html><html lang="fr"><head><meta charSet="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="referrer" content="never"/></head><body><div id="app"><div>markup</div></div></body></html>`,
`<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="referrer" content="never"/></head><body><div id="app"><div>markup</div></div></body></html>`,
);
});
});
4 changes: 2 additions & 2 deletions yarn.lock
Expand Up @@ -250,7 +250,7 @@
call-me-maybe "^1.0.1"
glob-to-regexp "^0.3.0"

"@shopify/app-bridge-react@^1.6.7":
"@shopify/app-bridge-react@>=1.5.0", "@shopify/app-bridge-react@^1.6.7":
version "1.6.7"
resolved "https://registry.yarnpkg.com/@shopify/app-bridge-react/-/app-bridge-react-1.6.7.tgz#d94a5510a1f88a46b10f8e231f6f2d23e5ba0c20"
integrity sha512-xWIikfRzJk2gB/wkBRgLVMZlC2zWvHatHpe6gkIP+kCxdK426hxtx8BEhLR4xP84mYH+Z1Ha/99voYwuzyKMCw==
Expand Down Expand Up @@ -644,7 +644,7 @@
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.8.tgz#8ae4e0ea205fe95c3901a5a1df7f66495e3a56ce"
integrity sha512-3AQoUxQcQtLHsK25wtTWIoIpgYjH3vSDroZOUr7PpCHw/jLY1RB9z9E8dBT/OSmwStVgkRNvdh+ZHNiomRieaw==

"@types/react-dom@^16.0.11", "@types/react-dom@^16.8.3":
"@types/react-dom@16.8.3", "@types/react-dom@^16.0.11", "@types/react-dom@^16.8.3":
version "16.8.3"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.8.3.tgz#6131b7b6158bc7ed1925a3374b88b7c00481f0cb"
integrity sha512-HF5hD5YR3z9Mn6kXcW1VKe4AQ04ZlZj1EdLBae61hzQ3eEWWxMgNLUbIxeZp40BnSxqY1eAYLsH9QopQcxzScA==
Expand Down