Skip to content

Commit

Permalink
Only build react-html in experimental channel
Browse files Browse the repository at this point in the history
Even though the whole package is private right now. Once we publish it,
it'll likely be just the experimental channel first before upgrading to
stable.
  • Loading branch information
sebmarkbage committed Jun 28, 2024
1 parent 0d1fdb5 commit 04a3efd
Show file tree
Hide file tree
Showing 5 changed files with 313 additions and 252 deletions.
11 changes: 11 additions & 0 deletions packages/react-html/src/ReactHTMLClient.stable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

// eslint-disable-next-line react-internal/prod-error-codes
throw new Error('react-html should not get built in stable');
11 changes: 11 additions & 0 deletions packages/react-html/src/ReactHTMLServer.stable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

// eslint-disable-next-line react-internal/prod-error-codes
throw new Error('react-html should not get built in stable');
253 changes: 132 additions & 121 deletions packages/react-html/src/__tests__/ReactHTMLClient-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,141 +12,152 @@
let React;
let ReactHTML;

describe('ReactHTML', () => {
beforeEach(() => {
jest.resetModules();
React = require('react');
ReactHTML = require('react-html');
if (!__EXPERIMENTAL__) {
it('should not be built in stable', () => {
try {
require('react-html');
} catch (x) {
return;
}
throw new Error('Expected react-html not to exist in stable.');
});
} else {
describe('ReactHTML', () => {
beforeEach(() => {
jest.resetModules();
React = require('react');
ReactHTML = require('react-html');
});

it('should be able to render a simple component', async () => {
function Component() {
return <div>hello world</div>;
}
it('should be able to render a simple component', async () => {
function Component() {
return <div>hello world</div>;
}

const html = await ReactHTML.renderToMarkup(<Component />);
expect(html).toBe('<div>hello world</div>');
});
const html = await ReactHTML.renderToMarkup(<Component />);
expect(html).toBe('<div>hello world</div>');
});

it('should prefix html tags with a doctype', async () => {
const html = await ReactHTML.renderToMarkup(
<html>
<body>hello</body>
</html>,
);
expect(html).toBe(
'<!DOCTYPE html><html><head></head><body>hello</body></html>',
);
});
it('should prefix html tags with a doctype', async () => {
const html = await ReactHTML.renderToMarkup(
<html>
<body>hello</body>
</html>,
);
expect(html).toBe(
'<!DOCTYPE html><html><head></head><body>hello</body></html>',
);
});

it('should error on useState', async () => {
function Component() {
const [state] = React.useState('hello');
return <div>{state}</div>;
}
it('should error on useState', async () => {
function Component() {
const [state] = React.useState('hello');
return <div>{state}</div>;
}

await expect(async () => {
await ReactHTML.renderToMarkup(<Component />);
}).rejects.toThrow();
});
await expect(async () => {
await ReactHTML.renderToMarkup(<Component />);
}).rejects.toThrow();
});

it('should error on refs passed to host components', async () => {
function Component() {
const ref = React.createRef();
return <div ref={ref} />;
}
it('should error on refs passed to host components', async () => {
function Component() {
const ref = React.createRef();
return <div ref={ref} />;
}

await expect(async () => {
await ReactHTML.renderToMarkup(<Component />);
}).rejects.toThrow();
});
await expect(async () => {
await ReactHTML.renderToMarkup(<Component />);
}).rejects.toThrow();
});

it('should error on callbacks passed to event handlers', async () => {
function Component() {
function onClick() {
// This won't be able to be called.
it('should error on callbacks passed to event handlers', async () => {
function Component() {
function onClick() {
// This won't be able to be called.
}
return <div onClick={onClick} />;
}
return <div onClick={onClick} />;
}

await expect(async () => {
await ReactHTML.renderToMarkup(<Component />);
}).rejects.toThrow();
});
await expect(async () => {
await ReactHTML.renderToMarkup(<Component />);
}).rejects.toThrow();
});

it('supports the useId Hook', async () => {
function Component() {
const firstNameId = React.useId();
const lastNameId = React.useId();
return React.createElement(
'div',
null,
React.createElement(
'h2',
{
id: firstNameId,
},
'First',
),
React.createElement(
'p',
{
'aria-labelledby': firstNameId,
},
'Sebastian',
),
React.createElement(
'h2',
{
id: lastNameId,
},
'Last',
),
React.createElement(
'p',
{
'aria-labelledby': lastNameId,
},
'Smith',
),
);
}
it('supports the useId Hook', async () => {
function Component() {
const firstNameId = React.useId();
const lastNameId = React.useId();
return React.createElement(
'div',
null,
React.createElement(
'h2',
{
id: firstNameId,
},
'First',
),
React.createElement(
'p',
{
'aria-labelledby': firstNameId,
},
'Sebastian',
),
React.createElement(
'h2',
{
id: lastNameId,
},
'Last',
),
React.createElement(
'p',
{
'aria-labelledby': lastNameId,
},
'Smith',
),
);
}

const html = await ReactHTML.renderToMarkup(<Component />);
const container = document.createElement('div');
container.innerHTML = html;

expect(container.getElementsByTagName('h2')[0].id).toBe(
container.getElementsByTagName('p')[0].getAttribute('aria-labelledby'),
);
expect(container.getElementsByTagName('h2')[1].id).toBe(
container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),
);

// It's not the same id between them.
expect(container.getElementsByTagName('h2')[0].id).not.toBe(
container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),
);
});
const html = await ReactHTML.renderToMarkup(<Component />);
const container = document.createElement('div');
container.innerHTML = html;

// @gate disableClientCache
it('does NOT support cache yet because it is a client component', async () => {
let counter = 0;
const getCount = React.cache(() => {
return counter++;
});
function Component() {
const a = getCount();
const b = getCount();
return (
<div>
{a}
{b}
</div>
expect(container.getElementsByTagName('h2')[0].id).toBe(
container.getElementsByTagName('p')[0].getAttribute('aria-labelledby'),
);
}
expect(container.getElementsByTagName('h2')[1].id).toBe(
container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),
);

// It's not the same id between them.
expect(container.getElementsByTagName('h2')[0].id).not.toBe(
container.getElementsByTagName('p')[1].getAttribute('aria-labelledby'),
);
});

// @gate disableClientCache
it('does NOT support cache yet because it is a client component', async () => {
let counter = 0;
const getCount = React.cache(() => {
return counter++;
});
function Component() {
const a = getCount();
const b = getCount();
return (
<div>
{a}
{b}
</div>
);
}

const html = await ReactHTML.renderToMarkup(<Component />);
expect(html).toBe('<div>01</div>');
const html = await ReactHTML.renderToMarkup(<Component />);
expect(html).toBe('<div>01</div>');
});
});
});
}
Loading

0 comments on commit 04a3efd

Please sign in to comment.