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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Remix Example #99

Merged
merged 14 commits into from
Jun 12, 2022
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/nextjs-babel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Enable Jest Preview inside `jest.config.js`. Note that the Jest config object re
}
```

Configure Jest Preview inside `jest.setup.js` (or any setup files) specified in your `setupFilesAfterEnv` config, so Jest Preview knows which global CSS file to load.
Configure Jest Preview inside `jest.setup.js` (or any setup files specified in your `setupFilesAfterEnv` config), so Jest Preview knows which global CSS file to load.

```js
import { jestPreviewConfigure } from 'jest-preview';
Expand Down
2 changes: 1 addition & 1 deletion examples/nextjs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Enable Jest Preview inside `jest.config.js`. Note that the Jest config object re
+ module.exports = configureNextJestPreview(createJestConfig(customJestConfig));
```

Configure Jest Preview inside `jest.setup.js` (or any setup files) specified in your `setupFilesAfterEnv` config, so Jest Preview knows which global CSS file to load.
Configure Jest Preview inside `jest.setup.js` (or any setup files specified in your `setupFilesAfterEnv` config), so Jest Preview knows which global CSS file to load.

```js
import { jestPreviewConfigure } from 'jest-preview';
Expand Down
3 changes: 3 additions & 0 deletions examples/remix/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["@remix-run/eslint-config", "@remix-run/eslint-config/node"]
}
6 changes: 6 additions & 0 deletions examples/remix/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules

/.cache
/build
/public/build
.env
31 changes: 31 additions & 0 deletions examples/remix/.swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"tsx": true,
"decorators": false,
"dynamicImport": false
},
"transform": {
"react": {
"pragma": "React.createElement",
"pragmaFrag": "React.Fragment",
"throwIfNamespace": true,
"development": false,
"useBuiltins": false,
"runtime": "automatic"
},
"hidden": {
"jest": true
}
}
},
"module": {
"type": "commonjs",
"strict": false,
"strictMode": true,
"lazy": false,
"noInterop": false
}
}
53 changes: 53 additions & 0 deletions examples/remix/README-REMIX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Welcome to Remix!

- [Remix Docs](https://remix.run/docs)

## Development

From your terminal:

```sh
npm run dev
```

This starts your app in development mode, rebuilding assets on file changes.

## Deployment

First, build your app for production:

```sh
npm run build
```

Then run the app in production mode:

```sh
npm start
```

Now you'll need to pick a host to deploy it to.

### DIY

If you're familiar with deploying node applications, the built-in Remix app server is production-ready.

Make sure to deploy the output of `remix build`

- `build/`
- `public/build/`

### Using a Template

When you ran `npx create-remix@latest` there were a few choices for hosting. You can run that again to create a new project, then copy over your `app/` folder to the new project that's pre-configured for your target server.

```sh
cd ..
# create a new project, and pick a pre-configured host
npx create-remix@latest
cd my-new-remix-app
# remove the new project's app (not the old one!)
rm -rf app
# copy your app over
cp -R ../my-old-remix-app/app app
```
200 changes: 200 additions & 0 deletions examples/remix/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
# Use with Remix

This example demonstrates how to use `jest-preview` with [`Remix`](https://remix.run/), bootstrapped using [`create-remix`](https://remix.run/docs/en/v1#getting-started) (without using any built-in templates/stacks).
nvh95 marked this conversation as resolved.
Show resolved Hide resolved

🚧 This example only demonstrates the simplest use of CSS in a Remix app (global stylesheet). Remix supports [many different ways of styling](https://remix.run/docs/en/v1/guides/styling). Example of more complex ways to style is coming.

## Install Jest

<!-- TODO: Add Son's Setup Jest blog post here -->

You have to manually install Jest in your Remix app.

First, install `jest` itself. If you are using `jest` version 28 or later, you must install `jest-environment-jsdom` too ([reference](https://jestjs.io/docs/upgrading-to-jest28#jsdom)).

```bash
npm install --save-dev jest jest-environment-jsdom
```

Install [SWC](https://swc.rs)

```bash
npm install --save-dev @swc/core @swc/jest
```

Config [SWC](https://swc.rs) inside `.swcrc`

```js
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"tsx": true,
"decorators": false,
"dynamicImport": false
},
"transform": {
"react": {
"pragma": "React.createElement",
"pragmaFrag": "React.Fragment",
"throwIfNamespace": true,
"development": false,
"useBuiltins": false,
"runtime": "automatic"
},
"hidden": {
"jest": true
}
}
},
"module": {
"type": "commonjs",
"strict": false,
"strictMode": true,
"lazy": false,
"noInterop": false
}
}
```

Next, install your favorite testing libraries. This example uses `react-testing-library`, at version 12 specifically ([version 13 wouldn't work](https://stackoverflow.com/questions/71713405/cannot-find-module-react-dom-client-from-node-modules-testing-library-react)). Optionally, you can install its companion [`jest-dom`](https://testing-library.com/docs/ecosystem-jest-dom/) package to add some useful matchers to Jest.

```bash
npm install --save-dev @testing-library/react@12 @testing-library/jest-dom
```

## Install & configure Jest Preview

Install Jest Preview

```bash
npm install --save-dev jest-preview
```

Enable Jest Preview inside `jest.config.js`. The config options are largely up to you, but remember to remove/add the highlighted options as followed so Jest Preview could work properly.

```js
module.exports = {
collectCoverageFrom: [
'**/*.{js,jsx,ts,tsx}',
'!**/*.d.ts',
'!**/node_modules/**',
],
moduleNameMapper: {
// Handle absolute imports in Remix
'~/(.*)': '<rootDir>/app/$1',
},
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
testPathIgnorePatterns: [
'<rootDir>/node_modules/',
'<rootDir>/.cache/',
'<rootDir>/build/',
],
testEnvironment: 'jsdom',
transform: {
// Use @swc/jest to transpile tests
// https://jestjs.io/docs/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object
'^.+\\.(js|jsx|ts|tsx)$': '@swc/jest',
'^.+\\.(css|scss|sass)$': 'jest-preview/transforms/css',
'^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)':
'jest-preview/transforms/file',
},
transformIgnorePatterns: ['/node_modules/'],
};
```

Configure Jest Preview inside `jest.setup.js` (or any setup files specified in your `setupFilesAfterEnv` config), so Jest Preview knows which global CSS file to load. You can even set `autoPreview` to `true` so your failed test gets a preview automatically! 🤯

```js
import { jestPreviewConfigure } from 'jest-preview';
import './app/styles/global.css';

jestPreviewConfigure({
// Enable autoPreview so Jest Preview runs automatically
// whenever your test fails, without you having to do anything!
autoPreview: true,
});
```

## Done

That's it! Now you can use Jest Preview in your test. Say we have `app/__tests__/index.test.tsx` as follow...

```tsx
import { render, screen } from '@testing-library/react';
import { debug } from 'jest-preview';
import Index from '../routes/index';
import '@testing-library/jest-dom'; // So we can use toBeInTheDocument assertion

it('should show welcome message', () => {
render(<Index />);

debug(); // Remove this line if you have enabled autoPreview in jest.setup.js

expect(
screen.getByRole('heading', { name: /welcome to remix/i }),
).toBeInTheDocument();
});
```

...and an `app/styles/global.css` like this:

```css
html {
max-width: 38rem;
padding: 2rem;
margin: auto;
line-height: 1.5rem;
font-size: 24px;
}
```

To run this test with Jest Preview, you must keep the `jest-preview` server running in parallel. See the result at `http://locahost:3336`.

```bash
./node_modules/.bin/jest-preview

./node_modules/.bin/jest --watch
```

You might as well add some NPM scripts for convenience:

```diff
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
+ "test": "jest --watch",
+ "jest-preview": "jest-preview"
},
```

```bash
npm run jest-preview

npm run test
```

You may even install `npm-run-all` to simplify this further:

```bash
npm install --save-dev npm-run-all
```

```diff
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"test": "jest --watch",
"jest-preview": "jest-preview",
+ "test:preview": "npm-run-all -p test jest-preview"
},
```

```bash
npm run test:preview
```
12 changes: 12 additions & 0 deletions examples/remix/app/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { render, screen } from '@testing-library/react'
import { debug } from 'jest-preview';
import Index from '../routes/index'
import '@testing-library/jest-dom' // So we can use toBeInTheDocument assertion

it('should show welcome message', () => {
render(<Index />);

debug(); // Remove this line if you have enabled autoPreview in jest.setup.js

expect(screen.getByRole('heading', { name: /welcome to remix/i })).toBeInTheDocument();
});
Binary file added examples/remix/app/assets/remix.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions examples/remix/app/entry.client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { RemixBrowser } from "@remix-run/react";
import { hydrate } from "react-dom";

hydrate(<RemixBrowser />, document);
21 changes: 21 additions & 0 deletions examples/remix/app/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { EntryContext } from "@remix-run/node";
import { RemixServer } from "@remix-run/react";
import { renderToString } from "react-dom/server";

export default function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext
) {
let markup = renderToString(
<RemixServer context={remixContext} url={request.url} />
);

responseHeaders.set("Content-Type", "text/html");

return new Response("<!DOCTYPE html>" + markup, {
status: responseStatusCode,
headers: responseHeaders,
});
}
37 changes: 37 additions & 0 deletions examples/remix/app/root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { LinksFunction, MetaFunction } from "@remix-run/node";
import {
Links,
LiveReload,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from "@remix-run/react";
import styles from '~/styles/global.css';

export const meta: MetaFunction = () => ({
charset: "utf-8",
title: "New Remix App",
viewport: "width=device-width,initial-scale=1",
});

export const links: LinksFunction = () => ([
{ rel: 'stylesheet', href: styles },
]);

export default function App() {
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body>
<Outlet />
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
);
}
Loading