| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- import { Suspense, createApp, defineComponent, h } from 'vue'
- import { renderToString } from '../src/renderToString'
- import { ssrRenderComponent } from '../src/helpers/ssrRenderComponent'
- import { ssrRenderSuspense } from '../src/helpers/ssrRenderSuspense'
- describe('SSR Suspense', () => {
- const ResolvingAsync = {
- async setup() {
- return () => h('div', 'async')
- },
- }
- const RejectingAsync = {
- setup() {
- return new Promise((_, reject) => reject('foo'))
- },
- }
- test('content', async () => {
- const Comp = {
- render() {
- return h(Suspense, null, {
- default: h(ResolvingAsync),
- fallback: h('div', 'fallback'),
- })
- },
- }
- expect(await renderToString(createApp(Comp))).toBe(`<div>async</div>`)
- })
- test('reject', async () => {
- const Comp = {
- errorCaptured: vi.fn(() => false),
- render() {
- return h(Suspense, null, {
- default: h(RejectingAsync),
- fallback: h('div', 'fallback'),
- })
- },
- }
- expect(await renderToString(createApp(Comp))).toBe(`<!---->`)
- expect(Comp.errorCaptured).toHaveBeenCalledTimes(1)
- expect('missing template').toHaveBeenWarned()
- })
- test('2 components', async () => {
- const Comp = {
- render() {
- return h(Suspense, null, {
- default: h('div', [h(ResolvingAsync), h(ResolvingAsync)]),
- fallback: h('div', 'fallback'),
- })
- },
- }
- expect(await renderToString(createApp(Comp))).toBe(
- `<div><div>async</div><div>async</div></div>`,
- )
- })
- test('resolving component + rejecting component', async () => {
- const Comp = {
- errorCaptured: vi.fn(() => false),
- render() {
- return h(Suspense, null, {
- default: h('div', [h(ResolvingAsync), h(RejectingAsync)]),
- fallback: h('div', 'fallback'),
- })
- },
- }
- expect(await renderToString(createApp(Comp))).toBe(
- `<div><div>async</div><!----></div>`,
- )
- expect(Comp.errorCaptured).toHaveBeenCalledTimes(1)
- expect('missing template or render function').toHaveBeenWarned()
- })
- test('failing suspense in passing suspense', async () => {
- const Comp = {
- errorCaptured: vi.fn(() => false),
- render() {
- return h(Suspense, null, {
- default: h('div', [
- h(ResolvingAsync),
- h(Suspense, null, {
- default: h('div', [h(RejectingAsync)]),
- fallback: h('div', 'fallback 2'),
- }),
- ]),
- fallback: h('div', 'fallback 1'),
- })
- },
- }
- expect(await renderToString(createApp(Comp))).toBe(
- `<div><div>async</div><div><!----></div></div>`,
- )
- expect(Comp.errorCaptured).toHaveBeenCalledTimes(1)
- expect('missing template').toHaveBeenWarned()
- })
- // nuxt/nuxt#28162
- test('propagates sync errors from compiled ssrRenderSuspense default slot', async () => {
- const Throwing = defineComponent({
- ssrRender(_ctx: any, _push: any) {
- throw new TypeError('bang')
- },
- })
- const Root = defineComponent({
- ssrRender(_ctx: any, _push: any, _parent: any) {
- ssrRenderSuspense(_push, {
- default: () => {
- _push(ssrRenderComponent(Throwing, null, null, _parent))
- },
- _: 1,
- } as any)
- },
- })
- await expect(renderToString(createApp(Root))).rejects.toThrow('bang')
- })
- test('passing suspense in failing suspense', async () => {
- const Comp = {
- errorCaptured: vi.fn(() => false),
- render() {
- return h(Suspense, null, {
- default: h('div', [
- h(RejectingAsync),
- h(Suspense, null, {
- default: h('div', [h(ResolvingAsync)]),
- fallback: h('div', 'fallback 2'),
- }),
- ]),
- fallback: h('div', 'fallback 1'),
- })
- },
- }
- expect(await renderToString(createApp(Comp))).toBe(
- `<div><!----><div><div>async</div></div></div>`,
- )
- expect(Comp.errorCaptured).toHaveBeenCalledTimes(1)
- expect('missing template').toHaveBeenWarned()
- })
- })
|