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

feat: implement auto preview on error #87

Merged
merged 23 commits into from
May 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# 0.2.0

## Features

- Auto preview UI whenever a test fails, you don't have to call `preview.debug()` manually.

# 0.1.7

## Fixes
Expand Down
1 change: 1 addition & 0 deletions config/jest/setupTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { jestPreviewConfigure } from '../../dist/index';
jestPreviewConfigure({
externalCss: ['demo/global.css', 'demo/assets/_scss/global-style.scss'],
publicFolder: 'demo/public',
autoPreview: true,
});

window.matchMedia = (query) => ({
Expand Down
12 changes: 9 additions & 3 deletions demo/__tests__/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { render, screen } from '@testing-library/react';

import userEvent from '@testing-library/user-event';
import App from '../App';
import preview from '../../dist/index';
import { debug } from '../../dist/index';

describe('App', () => {
it('should work as expected', () => {
Expand All @@ -17,7 +17,13 @@ describe('App', () => {

// Open http://localhost:3336 to see preview
// Require to run `jest-preview` server before
preview.debug();
expect(screen.getByTestId('count')).toContainHTML('6');
// Execute `preview.debug()` or `debug()` to see the UI in a browser
debug();

// Jest Preview automatically preview failed tests without explicitly calling `debug()`
// Try to comment out the following line to see the count equals to 6
userEvent.click(screen.getByTestId('increase'));

expect(screen.getByTestId('count')).toContainHTML('7');
});
});
2 changes: 2 additions & 0 deletions examples/vite-react/config/jest/setupTests.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// @ts-check
import '@testing-library/jest-dom/extend-expect';
import { jestPreviewConfigure } from 'jest-preview';

jestPreviewConfigure({
externalCss: ['src/index.css', 'src/assets/_scss/global-style.scss'],
autoPreview: true,
});

window.matchMedia = (query) => ({
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jest-preview",
"version": "0.1.7-alpha.0",
"version": "0.2.0",
"description": "Preview your HTML code while using Jest",
"keywords": [
"testing",
Expand All @@ -27,7 +27,7 @@
"transforms"
],
"scripts": {
"docs": "cd website && npm run start",
"docs": "cd website && npm run start -- --port 3001",
"build:docs": "cd website && npm run build",
"dev": "vite",
"types": "tsc src/index.ts --declaration --emitDeclarationOnly --jsx react --esModuleInterop --outDir dist",
Expand Down
2 changes: 1 addition & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function makeBundle({ filePath, dir = 'dist' }) {
format: 'cjs',
},
plugins: [typescript(), terser()],
external: ['path', 'camelcase'],
external: ['path', 'camelcase', 'fs', 'child_process'],
};
}

Expand Down
65 changes: 60 additions & 5 deletions src/configure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,32 @@ import { exec } from 'child_process';

import { CACHE_FOLDER } from './constants';
import { createCacheFolderIfNeeded } from './utils';
import { debug } from './preview';

interface JestPreviewConfigOptions {
externalCss: string[];
externalCss?: string[];
autoPreview?: boolean;
publicFolder?: string;
}

export async function jestPreviewConfigure(
options: JestPreviewConfigOptions = { externalCss: [] },
{
externalCss = [],
autoPreview = false,
publicFolder,
}: JestPreviewConfigOptions = { externalCss: [], autoPreview: false },
) {
if (autoPreview) {
autoRunPreview();
}

if (!fs.existsSync(CACHE_FOLDER)) {
fs.mkdirSync(CACHE_FOLDER, {
recursive: true,
});
}

options.externalCss?.forEach((cssFile) => {
externalCss?.forEach((cssFile) => {
// Avoid name collision
// Example: src/common/styles.css => cache-src___common___styles.css
const delimiter = '___';
Expand Down Expand Up @@ -65,15 +75,60 @@ export async function jestPreviewConfigure(
// }
});

if (options.publicFolder) {
if (publicFolder) {
createCacheFolderIfNeeded();
fs.writeFileSync(
path.join(CACHE_FOLDER, 'cache-public.config'),
options.publicFolder,
publicFolder,
{
encoding: 'utf-8',
flag: 'w',
},
);
}
}

// Omit only, skip, todo, concurrent, each. Couldn't use Omit. Just redeclare for simplicity
type RawIt = (...args: Parameters<jest.It>) => ReturnType<jest.It>;

function patchJestFunction(it: RawIt) {
const originalIt = it;
const itWithPreview: RawIt = (name, callback, timeout) => {
let callbackWithPreview: jest.ProvidesCallback | undefined;
if (!callback) {
callbackWithPreview = undefined;
} else {
callbackWithPreview = async function (
...args: Parameters<jest.ProvidesCallback>
) {
try {
// @ts-expect-error Just forward the args
return await callback(...args);
} catch (error) {
debug();
throw error;
}
};
}
return originalIt(name, callbackWithPreview, timeout);
};
return itWithPreview;
}

function autoRunPreview() {
const originalIt = it;
let itWithPreview = patchJestFunction(it) as jest.It;
itWithPreview.each = originalIt.each;
itWithPreview.only = patchJestFunction(originalIt.only) as jest.It;
thanhsonng marked this conversation as resolved.
Show resolved Hide resolved
itWithPreview.skip = originalIt.skip;
itWithPreview.todo = originalIt.todo;
itWithPreview.concurrent = patchJestFunction(
originalIt.concurrent,
) as jest.It;

// Overwrite global it/ test
// Is there any use cases that `it` and `test` is undefined?
it = itWithPreview;
test = itWithPreview;
fit = itWithPreview.only;
}
24 changes: 24 additions & 0 deletions website/blog/2022-05-03-automatic-mode/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
slug: automatic-mode
title: Introducing Automatic Mode
authors: [nvh95, thanhsonng]
thanhsonng marked this conversation as resolved.
Show resolved Hide resolved
tags: [jest-preview, developer-experience]
image: /img/automatic-mode.png
---

We are so happy to annouce that we are launching Jest Preview **Automatic Mode**. In this mode, you don't have to trigger the `preview.debug()` function by yourself. Jest Preview **AUTOMATICALLY** preview the UI of your app **WHENEVER a Jest test fails**.

![Jest Preview Automatic Mode](https://user-images.githubusercontent.com/8603085/166488340-45cae3bf-42e6-4e29-8031-df923c3ace83.gif)

We believe this is the game changer feature of Jest Preview, which boost the Front end productivity dramatically on writing new tests and debugging existing tests. You don't have to move the `preview.debug()` around by yourself anymore. All you need to do is just one line of code:

```js
// setupTests.ts
jestPreviewConfigure({ autoPreview: true });
```

**Automatic Mode** is in experiement and currently is an opt-in option. We recommend you to start use it now. Automatic Mode expect to be the default mode in Jest Preview 0.3.0.

If you have any trouble with Automatic Mode, let us know at [Jest Preview's GitHub issue](https://github.com/nvh95/jest-preview/issues/new?assignees=&labels=&template=bug_report.md&title=)

Did you use Jest Preview Automatic Mode yet? [Let us know](https://twitter.com/intent/tweet?text=I%20used%20Jest%20Preview%20Automatic%20Mode%20and%20it%27s%20awesome!%20%23jestpreview)!
9 changes: 7 additions & 2 deletions website/docs/api/debug.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@ sidebar_position: 1

# debug()

Preview application's UI when testing with Jest to an external browser. Need to [start the Jest Preview](/docs/getting-started/usage#2-run-the-jest-preview-server) server beforehand.

:::info

[Automatic Mode](/blog/automatic-mode) is now available and is recommended for general use, instead of manually triggering `preview.debug()`
:::

```diff
+import preview from 'jest-preview';

describe('App', () => {
it('should work as expected', () => {
render(<App />);
Expand All @@ -19,7 +25,6 @@ Or:

```diff
+import { debug } from 'jest-preview';

describe('App', () => {
it('should work as expected', () => {
render(<App />);
Expand Down
41 changes: 41 additions & 0 deletions website/docs/api/jestPreviewConfigure.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,44 @@ jestPreviewConfigure({
publicFolder: 'your-public-folder-name',
});
```

## externalCss: string[]

Default: `[]`

CSS files outside your Jest rendered app (e.g: CSS from `src/index.js`, `main.jsx`) should be configured via `externalCss` option. They should be path from root of your project. For example:

```js
jestPreviewConfigure({
// Configure external CSS
externalCss: [
'demo/global.css',
'demo/global.scss', // Sass
'node_modules/@your-design-system/css/dist/index.min.css', // css from node_modules
'node_modules/bootstrap/dist/css/bootstrap.min.css',
],
```

## publicFolder: string

Default: `undefined`.

Name of your public folder from the project root.

You don't have to configure this by yourself if your public folder is `public`. Below you can find a list of public directories which have different names than `public`:

<!-- Thanks msw for the idea https://github.com/mswjs/mswjs.io/blob/9f62d45a3740789cc4308ae1475027598541a007/docs/snippets/public-dir.mdx -->

| Project name | Public directory |
| ------------------------------------ | ---------------- |
| [GatsbyJS](https://www.gatsbyjs.org) | `static` |
| [Angular](https://angular.io/) | `src` |
| [Preact](https://preactjs.com) | `src/static` |

## autoPreview: boolean

Default: `false` (`true` in `v0.3.0`)

Automatically preview the UI in the external browser when the test fails. You don't need to invoke `preview.debug()` by yourself anymore.

Set to `false` if you experience any error or just want to opt-out.
25 changes: 24 additions & 1 deletion website/docs/others/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,27 @@ sidebar_position: 1

# Frequently Asked Questions

TBD
## I can see HTML on my browser, but without any CSS

There are a few reasons that you might not see CSS on the Jest Preview Dashboard (`jest-preview`):

- Jest Preview generally uses [Code Transformation](https://jestjs.io/docs/code-transformation) to process CSS. You might forget to configure the `transform` in your Jest's config. Please see [**Installation**](/docs/getting-started/installation) for more. If you are using [Create React App](https://create-react-app.dev/), you might want to visit [CRA Example](/docs/examples/create-react-app). If you are using [Next.js](https://nextjs.org/), you might want to visit [Next.js example](/docs/examples/next-rust).
- If you already configure CSS transform, there is a very high chance that Jest is caching your CSS files. Please [**delete Jest's cache**](https://jestjs.io/docs/cli#--clearcache) by running `jest --clearCache`.
- You might have some CSS files that are not imported to your current testing component (i.e: `src/index.jsx`, `src/main.jsx`). You can configure external CSS using `jestPreviewConfigure`. See more at [**Installation**](/docs/getting-started/installation#4-optional-configure-external-css).

```js
jestPreviewConfigure({
externalCss: [
'demo/global.css',
'node_modules/@your-design-system/css/dist/index.min.css',
'node_modules/bootstrap/dist/css/bootstrap.min.css',
],
});
```

- Your CSS strategy is not supported by Jest Preview yet. Please see [**Features**](/docs/getting-started/features) for supported CSS strategies. Feel free to [Request a new feature](https://github.com/nvh95/jest-preview/issues/new?assignees=&labels=&template=feature_request.md&title=) if you want Jest Preview supports your use case.
- It might be a bug from Jest Preview. Let us know at [Bug Report](https://github.com/nvh95/jest-preview/issues/new?assignees=&labels=&template=bug_report.md&title=).

## I couldn't use Automatic Mode

Automatic Mode is in experiemental phase. If you are experiencing any issues when using Automatic Mode, please let us know at [Jest Preview's GitHub issue](https://github.com/nvh95/jest-preview/issues/new?assignees=&labels=&template=bug_report.md&title=). We appreciate your feedback and it would be super helpful for us to have a reproducible repository.