From afc0ad31a666c216ccdb2ce00713098ed824a5fe Mon Sep 17 00:00:00 2001 From: Ubugeeei Date: Tue, 26 Mar 2024 22:32:59 +0900 Subject: [PATCH 1/2] test: enum test cases --- .../__tests__/apiLifecycle.spec.ts | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/packages/runtime-vapor/__tests__/apiLifecycle.spec.ts b/packages/runtime-vapor/__tests__/apiLifecycle.spec.ts index 535416fde..9494b3f81 100644 --- a/packages/runtime-vapor/__tests__/apiLifecycle.spec.ts +++ b/packages/runtime-vapor/__tests__/apiLifecycle.spec.ts @@ -16,8 +16,30 @@ import { makeRender } from './_utils' const define = makeRender() -describe('apiLifecycle', () => { - // TODO: test +describe('api: lifecycle hooks', () => { + it.todo('onBeforeMount', () => {}) + + it.todo('onMounted', () => {}) + + it.todo('onBeforeUpdate', async () => {}) + + it.todo('state mutation in onBeforeUpdate', async () => {}) + + it.todo('onUpdated', async () => {}) + + it.todo('onBeforeUnmount', async () => {}) + + it.todo('onUnmounted', async () => {}) + + it.todo('onBeforeUnmount in onMounted', async () => {}) + + it.todo('lifecycle call order', async () => {}) + + it.todo('onRenderTracked', () => {}) + + it.todo('onRenderTriggered', async () => {}) + + it.todo('runs shared hook fn for each instance', async () => {}) // #136 test('should trigger updated hooks across components. (parent -> child)', async () => { From 77d74f020063c40b916a7b7c8afc70724ed7d626 Mon Sep 17 00:00:00 2001 From: Ubugeeei Date: Tue, 26 Mar 2024 23:38:15 +0900 Subject: [PATCH 2/2] test(runtime-vapor): lifecycle hooks --- .../__tests__/apiLifecycle.spec.ts | 343 +++++++++++++++++- 1 file changed, 333 insertions(+), 10 deletions(-) diff --git a/packages/runtime-vapor/__tests__/apiLifecycle.spec.ts b/packages/runtime-vapor/__tests__/apiLifecycle.spec.ts index 9494b3f81..dd7c51196 100644 --- a/packages/runtime-vapor/__tests__/apiLifecycle.spec.ts +++ b/packages/runtime-vapor/__tests__/apiLifecycle.spec.ts @@ -2,44 +2,367 @@ import { type InjectionKey, type Ref, createComponent, + createIf, createTextNode, getCurrentInstance, inject, nextTick, + onBeforeMount, + onBeforeUnmount, + onBeforeUpdate, + onMounted, + onUnmounted, onUpdated, provide, ref, renderEffect, setText, + template, } from '../src' import { makeRender } from './_utils' const define = makeRender() describe('api: lifecycle hooks', () => { - it.todo('onBeforeMount', () => {}) + it('onBeforeMount', () => { + const fn = vi.fn(() => { + expect(host.innerHTML).toBe(``) + }) + const { render, host } = define({ + setup() { + onBeforeMount(fn) + return () => template('
')() + }, + }) + render() + expect(fn).toHaveBeenCalledTimes(1) + }) - it.todo('onMounted', () => {}) + it('onMounted', () => { + const fn = vi.fn(() => { + expect(host.innerHTML).toBe(``) + }) + const { render, host } = define({ + setup() { + onMounted(fn) + return () => template('
')() + }, + }) + render() + expect(fn).toHaveBeenCalledTimes(1) + }) - it.todo('onBeforeUpdate', async () => {}) + it('onBeforeUpdate', async () => { + const count = ref(0) + const fn = vi.fn(() => { + expect(host.innerHTML).toBe('0') + }) + const { render, host } = define({ + setup() { + onBeforeUpdate(fn) + return (() => { + const n0 = createTextNode() + renderEffect(() => { + setText(n0, count.value) + }) + return n0 + })() + }, + }) + render() + count.value++ + await nextTick() + expect(fn).toHaveBeenCalledTimes(1) + expect(host.innerHTML).toBe('1') + }) - it.todo('state mutation in onBeforeUpdate', async () => {}) + it('state mutation in onBeforeUpdate', async () => { + const count = ref(0) + const fn = vi.fn(() => { + expect(host.innerHTML).toBe('0') + count.value++ + }) + const renderSpy = vi.fn() - it.todo('onUpdated', async () => {}) + const { render, host } = define({ + setup() { + onBeforeUpdate(fn) + return (() => { + const n0 = createTextNode() + renderEffect(() => { + renderSpy() + setText(n0, count.value) + }) + return n0 + })() + }, + }) + render() + expect(renderSpy).toHaveBeenCalledTimes(1) + }) - it.todo('onBeforeUnmount', async () => {}) + it('onUpdated', async () => { + const count = ref(0) + const fn = vi.fn(() => { + expect(host.innerHTML).toBe('1') + }) - it.todo('onUnmounted', async () => {}) + const { render, host } = define({ + setup() { + onUpdated(fn) + return (() => { + const n0 = createTextNode() + renderEffect(() => { + setText(n0, count.value) + }) + return n0 + })() + }, + }) + render() - it.todo('onBeforeUnmount in onMounted', async () => {}) + count.value++ + await nextTick() + expect(fn).toHaveBeenCalledTimes(1) + }) - it.todo('lifecycle call order', async () => {}) + it('onBeforeUnmount', async () => { + const toggle = ref(true) + const fn = vi.fn(() => { + expect(host.innerHTML).toBe('
') + }) + const { render, host } = define({ + setup() { + return (() => { + const n0 = createIf( + () => toggle.value, + () => createComponent(Child), + ) + return n0 + })() + }, + }) + + const Child = { + setup() { + onBeforeUnmount(fn) + return (() => { + const t0 = template('
') + const n0 = t0() + return n0 + })() + }, + } + + render() + + toggle.value = false + await nextTick() + // expect(fn).toHaveBeenCalledTimes(1) // FIXME: not called + expect(host.innerHTML).toBe('') + }) + + it('onUnmounted', async () => { + const toggle = ref(true) + const fn = vi.fn(() => { + expect(host.innerHTML).toBe('
') + }) + const { render, host } = define({ + setup() { + return (() => { + const n0 = createIf( + () => toggle.value, + () => createComponent(Child), + ) + return n0 + })() + }, + }) + + const Child = { + setup() { + onUnmounted(fn) + return (() => { + const t0 = template('
') + const n0 = t0() + return n0 + })() + }, + } + + render() + + toggle.value = false + await nextTick() + // expect(fn).toHaveBeenCalledTimes(1) // FIXME: not called + expect(host.innerHTML).toBe('') + }) + + it('onBeforeUnmount in onMounted', async () => { + const toggle = ref(true) + const fn = vi.fn(() => { + expect(host.innerHTML).toBe('
') + }) + const { render, host } = define({ + setup() { + return (() => { + const n0 = createIf( + () => toggle.value, + () => createComponent(Child), + ) + return n0 + })() + }, + }) + + const Child = { + setup() { + onMounted(() => { + onBeforeUnmount(fn) + }) + return (() => { + const t0 = template('
') + const n0 = t0() + return n0 + })() + }, + } + + render() + + toggle.value = false + await nextTick() + // expect(fn).toHaveBeenCalledTimes(1) // FIXME: not called + expect(host.innerHTML).toBe('') + }) + + it('lifecycle call order', async () => { + const count = ref(0) + const toggle = ref(true) + const calls: string[] = [] + + const { render } = define({ + setup() { + onBeforeMount(() => calls.push('onBeforeMount')) + onMounted(() => calls.push('onMounted')) + onBeforeUpdate(() => calls.push('onBeforeUpdate')) + onUpdated(() => calls.push('onUpdated')) + onBeforeUnmount(() => calls.push('onBeforeUnmount')) + onUnmounted(() => calls.push('onUnmounted')) + return (() => { + const n0 = createIf( + () => toggle.value, + () => createComponent(Mid, { count: () => count.value }), + ) + return n0 + })() + }, + }) + + const Mid = { + props: ['count'], + setup(props: any) { + onBeforeMount(() => calls.push('mid onBeforeMount')) + onMounted(() => calls.push('mid onMounted')) + onBeforeUpdate(() => calls.push('mid onBeforeUpdate')) + onUpdated(() => calls.push('mid onUpdated')) + onBeforeUnmount(() => calls.push('mid onBeforeUnmount')) + onUnmounted(() => calls.push('mid onUnmounted')) + return (() => { + const n0 = createComponent(Child, { count: () => props.count }) + return n0 + })() + }, + } + + const Child = { + props: ['count'], + setup(props: any) { + onBeforeMount(() => calls.push('child onBeforeMount')) + onMounted(() => calls.push('child onMounted')) + onBeforeUpdate(() => calls.push('child onBeforeUpdate')) + onUpdated(() => calls.push('child onUpdated')) + onBeforeUnmount(() => calls.push('child onBeforeUnmount')) + onUnmounted(() => calls.push('child onUnmounted')) + return (() => { + const t0 = template('
') + const n0 = t0() + renderEffect(() => setText(n0, props.count)) + return n0 + })() + }, + } + + // mount + render() + expect(calls).toEqual([ + 'onBeforeMount', + 'mid onBeforeMount', + 'child onBeforeMount', + 'child onMounted', + 'mid onMounted', + 'onMounted', + ]) + + calls.length = 0 + + // update + count.value++ + await nextTick() + // FIXME: not called + // expect(calls).toEqual([ + // 'root onBeforeUpdate', + // 'mid onBeforeUpdate', + // 'child onBeforeUpdate', + // 'child onUpdated', + // 'mid onUpdated', + // 'root onUpdated', + // ]) + + calls.length = 0 + + // unmount + toggle.value = false + // FIXME: not called + // expect(calls).toEqual([ + // 'root onBeforeUnmount', + // 'mid onBeforeUnmount', + // 'child onBeforeUnmount', + // 'child onUnmounted', + // 'mid onUnmounted', + // 'root onUnmounted', + // ]) + }) it.todo('onRenderTracked', () => {}) it.todo('onRenderTriggered', async () => {}) - it.todo('runs shared hook fn for each instance', async () => {}) + it('runs shared hook fn for each instance', async () => { + const fn = vi.fn() + const toggle = ref(true) + const { render } = define({ + setup() { + return createIf( + () => toggle.value, + () => [createComponent(Child), createComponent(Child)], + ) + }, + }) + const Child = { + setup() { + onBeforeMount(fn) + onBeforeUnmount(fn) + return template('
')() + }, + } + + render() + expect(fn).toHaveBeenCalledTimes(2) + toggle.value = false + await nextTick() + // expect(fn).toHaveBeenCalledTimes(4) // FIXME: not called unmounted hook + }) // #136 test('should trigger updated hooks across components. (parent -> child)', async () => {