Skip to content

Commit

Permalink
test(0.6.1): 完成0.6.1单元测试
Browse files Browse the repository at this point in the history
  • Loading branch information
bailicangdu committed Dec 17, 2021
1 parent e9d4f27 commit acd2507
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 20 deletions.
189 changes: 186 additions & 3 deletions src/__tests__/create_app.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable promise/param-names */
import { commonStartEffect, releaseAllEffect, ports } from './common/initial'
import { appInstanceMap } from '../create_app'
import { appStates } from '../constants'
import { appInstanceMap, unmountApp, unmountAllApps } from '../create_app'
import { appStates, keepAliveStates } from '../constants'
import microApp from '..'

describe('create_app', () => {
Expand Down Expand Up @@ -99,7 +99,7 @@ describe('create_app', () => {
setTimeout(() => {
expect(errorHandle).not.toBeCalled()
reslove(true)
}, 100)
}, 200)
})
})

Expand Down Expand Up @@ -274,4 +274,187 @@ describe('create_app', () => {
// @ts-ignore
delete window.specialUmdMode
})

// 测试 unmountApp 方法
test('test unmountApp method', async () => {
// 场景1: 常规卸载操作
const microAppElement12 = document.createElement('micro-app')
microAppElement12.setAttribute('name', 'test-app12')
microAppElement12.setAttribute('url', `http://127.0.0.1:${ports.create_app}/common`)

appCon.appendChild(microAppElement12)

await new Promise((reslove) => {
microAppElement12.addEventListener('mounted', () => {
unmountApp('test-app12').then(reslove)
})
})

await new Promise((reslove) => {
unmountApp('not-exist').then(() => {
expect(console.warn).toHaveBeenCalledWith('[micro-app] app not-exist does not exist')
reslove(true)
})
})

// 场景2: 卸载已经卸载的应用
const microAppElement13 = document.createElement('micro-app')
microAppElement13.setAttribute('name', 'test-app13')
microAppElement13.setAttribute('url', `http://127.0.0.1:${ports.create_app}/common`)

appCon.appendChild(microAppElement13)

await new Promise((reslove) => {
microAppElement13.addEventListener('mounted', () => {
appCon.removeChild(microAppElement13)
})

// 应用已经卸载后执行unmountApp
microAppElement13.addEventListener('unmount', () => {
// 首次卸载不传 destroy,则直接返回,test-app13依然存在
unmountApp('test-app13').then(() => {
expect(appInstanceMap.has('test-app13')).toBeTruthy()
// 第二次卸载设置destroy,应用被删除
unmountApp('test-app13', {
destroy: true,
}).then(() => {
expect(appInstanceMap.has('test-app13')).toBeFalsy()
reslove(true)
})
})
})
})

// 场景3: 卸载已经推入后台的keep-alive应用
const microAppElement14 = document.createElement('micro-app')
microAppElement14.setAttribute('name', 'test-app14')
microAppElement14.setAttribute('url', `http://127.0.0.1:${ports.create_app}/common`)
microAppElement14.setAttribute('keep-alive', 'true')

appCon.appendChild(microAppElement14)

await new Promise((reslove) => {
microAppElement14.addEventListener('mounted', () => {
appCon.removeChild(microAppElement14)
})

// 应用已隐藏后执行unmountApp
microAppElement14.addEventListener('afterhidden', () => {
// 首次卸载不传 destroy,则直接返回,test-app14安然无恙
unmountApp('test-app14').then(() => {
expect(appInstanceMap.has('test-app14')).toBeTruthy()
// 第二次卸载设置clearAliveState,触发应用卸载操作,应用状态被清除
unmountApp('test-app14', {
clearAliveState: true,
}).then(() => {
expect(appInstanceMap.has('test-app14')).toBeTruthy()
expect(appInstanceMap.get('test-app14')?.getAppState()).toBe(appStates.UNMOUNT)
reslove(true)
})
})
})
})

// 场景4: 强制删除已经推入后台的keep-alive应用
const microAppElement15 = document.createElement('micro-app')
microAppElement15.setAttribute('name', 'test-app15')
microAppElement15.setAttribute('url', `http://127.0.0.1:${ports.create_app}/umd1`)
microAppElement15.setAttribute('keep-alive', 'true')

appCon.appendChild(microAppElement15)

await new Promise((reslove) => {
microAppElement15.addEventListener('mounted', () => {
appCon.removeChild(microAppElement15)
})

// 应用已隐藏后执行unmountApp
microAppElement15.addEventListener('afterhidden', () => {
unmountApp('test-app15', {
destroy: true,
}).then(() => {
expect(appInstanceMap.has('test-app15')).toBeFalsy()
reslove(true)
})
})
})

// 场景5: 强制删除正在运行的app
const microAppElement16 = document.createElement('micro-app')
microAppElement16.setAttribute('name', 'test-app16')
microAppElement16.setAttribute('url', `http://127.0.0.1:${ports.create_app}/common`)
microAppElement16.setAttribute('destroy', 'attr-of-destroy')
microAppElement16.setAttribute('destory', 'attr-of-destory')

appCon.appendChild(microAppElement16)

await new Promise((reslove) => {
microAppElement16.addEventListener('mounted', () => {
unmountApp('test-app16', {
destroy: true,
}).then(() => {
expect(appInstanceMap.has('test-app16')).toBeFalsy()
expect(microAppElement16.getAttribute('destroy')).toBe('attr-of-destroy')
expect(microAppElement16.getAttribute('destory')).toBe('attr-of-destory')
reslove(true)
})
})
})

// 场景6: 卸载正在运行的keep-alive应用并清空状态
const microAppElement17 = document.createElement('micro-app')
microAppElement17.setAttribute('name', 'test-app17')
microAppElement17.setAttribute('url', `http://127.0.0.1:${ports.create_app}/common`)
microAppElement17.setAttribute('keep-alive', 'attr-of-keep-alive')

appCon.appendChild(microAppElement17)

await new Promise((reslove) => {
microAppElement17.addEventListener('mounted', () => {
unmountApp('test-app17', {
clearAliveState: true,
}).then(() => {
expect(appInstanceMap.get('test-app17')?.getAppState()).toBe(appStates.UNMOUNT)
expect(microAppElement17.getAttribute('keep-alive')).toBe('attr-of-keep-alive')
reslove(true)
})
})
})

// 场景7: 正常卸载一个keep-alive应用,保留状态
const microAppElement18 = document.createElement('micro-app')
microAppElement18.setAttribute('name', 'test-app18')
microAppElement18.setAttribute('url', `http://127.0.0.1:${ports.create_app}/common`)
microAppElement18.setAttribute('keep-alive', 'true')

appCon.appendChild(microAppElement18)

await new Promise((reslove) => {
microAppElement18.addEventListener('mounted', () => {
unmountApp('test-app18').then(() => {
expect(appInstanceMap.get('test-app18')?.getKeepAliveState()).toBe(keepAliveStates.KEEP_ALIVE_HIDDEN)
reslove(true)
})
})
})
})

// 测试 unmountAllApps 方法
test('test unmountAllApps method', async () => {
const microAppElement19 = document.createElement('micro-app')
microAppElement19.setAttribute('name', 'test-app19')
microAppElement19.setAttribute('url', `http://127.0.0.1:${ports.create_app}/common`)
microAppElement19.setAttribute('destroy', 'true')

appCon.appendChild(microAppElement19)

await new Promise((reslove) => {
microAppElement19.addEventListener('mounted', () => {
unmountAllApps().then(() => {
expect(appInstanceMap.has('test-app19')).toBeFalsy()
reslove(true)
})
})
})
})
})
11 changes: 11 additions & 0 deletions src/__tests__/demos/common/script1.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,14 @@ Promise.resolve().then(() => {
window.addEventListener("appstate-change", function (e) {
window.keepAliveListener && window.keepAliveListener(e.detail.appState)
})

// 20201.12.17 v0.6.1 new Image兼容测试
const newImg = new Image()
newImg.src = '/static/media/logo.6ce24c58.svg'
document.body.appendChild(newImg)
expect(newImg.__MICRO_APP_NAME__).toBe(window.__MICRO_APP_NAME__)

// 测试 cloneNode
var img2 = newImg.cloneNode(true)
document.body.appendChild(img2)
expect(img2.__MICRO_APP_NAME__).toBe(newImg.__MICRO_APP_NAME__)
33 changes: 17 additions & 16 deletions src/create_app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,6 @@ export default class CreateApp implements AppInterface {
*/
private actionsForUnmount (destroy: boolean, unmountcb?: CallableFunction): void {
this.sandBox?.stop()

if (destroy) {
this.actionsForCompletelyDestory()
} else if (this.umdMode && (this.container as Element).childElementCount) {
Expand Down Expand Up @@ -315,6 +314,16 @@ export default class CreateApp implements AppInterface {

// hidden app when disconnectedCallback called with keep-alive
hiddenKeepAliveApp (): void {
const oldContainer = this.container

cloneContainer(
this.container as Element,
this.keepAliveContainer ? this.keepAliveContainer : (this.keepAliveContainer = document.createElement('div')),
false,
)

this.container = this.keepAliveContainer

this.keepAliveState = keepAliveStates.KEEP_ALIVE_HIDDEN

// event should dispatch before clone node
Expand All @@ -325,18 +334,10 @@ export default class CreateApp implements AppInterface {

// dispatch afterhidden event to base app
dispatchLifecyclesEvent(
this.container!,
oldContainer!,
this.name,
lifeCycles.AFTERHIDDEN,
)

cloneContainer(
this.container as Element,
this.keepAliveContainer ? this.keepAliveContainer : (this.keepAliveContainer = document.createElement('div')),
false,
)

this.container = this.keepAliveContainer
}

// show app when connectedCallback called with keep-alive
Expand Down Expand Up @@ -436,7 +437,7 @@ export interface unmountAppParams {
}

/**
*
* unmount app by appname
* @param appName
* @param options unmountAppParams
* @returns Promise<void>
Expand All @@ -460,13 +461,13 @@ export function unmountApp (appName: string, options?: unmountAppParams): Promis
}
} else {
const container = getRootContainer(app.container!)
function unmountHandler () {
const unmountHandler = () => {
container.removeEventListener('unmount', unmountHandler)
container.removeEventListener('afterhidden', afterhiddenHandler)
reslove()
}

function afterhiddenHandler () {
const afterhiddenHandler = () => {
container.removeEventListener('unmount', unmountHandler)
container.removeEventListener('afterhidden', afterhiddenHandler)
reslove()
Expand All @@ -481,7 +482,7 @@ export function unmountApp (appName: string, options?: unmountAppParams): Promis
container.hasAttribute('destory') && (destoryAttrValue = container.getAttribute('destory'))

container.setAttribute('destroy', 'true')
container.parentNode?.removeChild(container)
container.parentNode!.removeChild(container)
container.removeAttribute('destroy')

typeof destroyAttrValue === 'string' && container.setAttribute('destroy', destroyAttrValue)
Expand All @@ -490,11 +491,11 @@ export function unmountApp (appName: string, options?: unmountAppParams): Promis
const keepAliveAttrValue = container.getAttribute('keep-alive')!

container.removeAttribute('keep-alive')
container.parentNode?.removeChild(container)
container.parentNode!.removeChild(container)

container.setAttribute('keep-alive', keepAliveAttrValue)
} else {
container.parentNode?.removeChild(container)
container.parentNode!.removeChild(container)
}
}
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/sandbox/image.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getCurrentAppName } from '../libs/utils'

const ImageProxy = new Proxy(Image, {
construct: (Target, args): any => {
construct (Target, args): HTMLImageElement {
const elementImage = new Target(...args)
elementImage.__MICRO_APP_NAME__ = getCurrentAppName()
return elementImage
Expand Down

0 comments on commit acd2507

Please sign in to comment.