Skip to content

Commit

Permalink
test(0.6.0): 完成0.6.0单元测试
Browse files Browse the repository at this point in the history
  • Loading branch information
bailicangdu committed Dec 10, 2021
1 parent 13c2d56 commit 45fee76
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 43 deletions.
3 changes: 3 additions & 0 deletions src/__tests__/common/initial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ declare global {
interface Element {
ssrUrl: string
}
interface Window {
keepAliveListener: (...rest: any[]) => void
}
}

export const ports = {
Expand Down
5 changes: 5 additions & 0 deletions src/__tests__/demos/common/script1.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,8 @@ window.dispatchEvent(new CustomEvent('unmount-me'))
Promise.resolve().then(() => {
window.microApp && window.microApp.dispatch({ unmountMeAsync: true })
})

// 监听keep-alive模式下的app状态
window.addEventListener("appstate-change", function (e) {
window.keepAliveListener && window.keepAliveListener(e.detail.appState)
})
12 changes: 5 additions & 7 deletions src/__tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ describe('main process', () => {
microappElement3.setAttribute('url', `http://127.0.0.1:${ports.main}/ssr-render`)
}, 500)
} else {
expect(appInstanceMap.size).toBe(prefetchAppNum + 2)
// 预加载app test-app3,设置了destroy,name切换时被彻底删除
expect(appInstanceMap.size).toBe(3)
reslove(true)
}
}, false)
Expand All @@ -226,7 +227,8 @@ describe('main process', () => {
await new Promise((reslove) => {
microappElement3.addEventListener('unmount', () => {
defer(() => {
expect(appInstanceMap.size).toBe(prefetchAppNum + 1)
// test-app1也被删除
expect(appInstanceMap.size).toBe(2)
reslove(true)
})
}, false)
Expand All @@ -240,7 +242,6 @@ describe('main process', () => {
* 预加载: false
* 执行前: appInstanceMap => [
* {name: 'test-app5'},
* {name: 'test-app3'},
* {name: 'test-app2'},
* ]
*/
Expand All @@ -263,7 +264,6 @@ describe('main process', () => {
* 预加载: false
* 执行前: appInstanceMap => [
* {name: 'test-app5'},
* {name: 'test-app3'},
* {name: 'test-app2'},
* ]
*
Expand Down Expand Up @@ -311,7 +311,6 @@ describe('main process', () => {
* 预加载: false
* 执行前: appInstanceMap => [
* {name: 'test-app5'},
* {name: 'test-app3'},
* {name: 'test-app2'},
* {name: 'test-app6'},
* ]
Expand Down Expand Up @@ -356,7 +355,6 @@ describe('main process', () => {
* 卸载所有应用
* 卸载前:appInstanceMap => [
* {name: 'test-app5'},
* {name: 'test-app3'},
* {name: 'test-app2'},
* {name: 'test-app6'},
* {name: 'test-app7'},
Expand All @@ -365,6 +363,6 @@ describe('main process', () => {
test('clear all apps', () => {
appCon.innerHTML = ''
// test-app5为预加载,test-app2不强制删除,所以卸载后还有2个应用
expect(appInstanceMap.size).toBe(5)
expect(appInstanceMap.size).toBe(4)
})
})
142 changes: 131 additions & 11 deletions src/__tests__/micro_app_element.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ describe('micro_app_element', () => {
beforeAll(() => {
commonStartEffect(ports.micro_app_element)
appCon = document.querySelector('#app-container')!
window.keepAliveListener = jest.fn()

microApp.start({
preFetchApps: [
Expand Down Expand Up @@ -64,7 +65,7 @@ describe('micro_app_element', () => {

appCon.appendChild(microappElement4)

expect(console.error).toHaveBeenCalledWith('[micro-app] app test-app2: an app named test-app2 already exists')
expect(console.error).toHaveBeenCalledWith('[micro-app] app test-app2: app name conflict, an app named test-app2 is running')
})

// 非法url
Expand All @@ -88,7 +89,7 @@ describe('micro_app_element', () => {

await new Promise((reslove) => {
defer(() => {
expect(console.error).toBeCalledWith('[micro-app] app test-app6: an app named test-app2 already exists')
expect(console.error).toBeCalledWith('[micro-app] app test-app6: app name conflict, an app named test-app2 is running')
expect(microappElement6.getAttribute('name')).toBe('test-app6')
reslove(true)
})
Expand Down Expand Up @@ -171,10 +172,8 @@ describe('micro_app_element', () => {
microappElement10.setAttribute('baseurl', '/baseurl')

appCon.appendChild(microappElement10)
let mountCount = 0
await new Promise((reslove) => {
microappElement10.addEventListener('mounted', () => {
mountCount++
reslove(true)
}, false)
})
Expand All @@ -183,13 +182,6 @@ describe('micro_app_element', () => {

appCon.appendChild(microappElement10)

await new Promise((reslove) => {
setTimeout(() => {
expect(mountCount).toBe(2) // 渲染2次
reslove(true)
}, 200)
})

// 分支覆盖
const microappElement11 = document.createElement('micro-app')
microappElement11.setAttribute('name', 'test-app11')
Expand Down Expand Up @@ -363,4 +355,132 @@ describe('micro_app_element', () => {
})
})
})

// test keep-alive 场景1: 正常渲染、隐藏、重新渲染
test('normal process of keep-alive', async () => {
const microappElement22 = document.createElement('micro-app')
microappElement22.setAttribute('name', 'test-app22')
microappElement22.setAttribute('url', `http://127.0.0.1:${ports.micro_app_element}/common/`)
microappElement22.setAttribute('keep-alive', 'true')

appCon.appendChild(microappElement22)

await new Promise((reslove) => {
microappElement22.addEventListener('mounted', () => {
reslove(true)
})
})

const beforeShowListener = jest.fn()
const afterShowListener = jest.fn()
const afterHiddenListener = jest.fn()

microappElement22.addEventListener('beforeshow', beforeShowListener)
microappElement22.addEventListener('aftershow', afterShowListener)
microappElement22.addEventListener('afterhidden', afterHiddenListener)

appCon.removeChild(microappElement22)
// dispatch event afterhidden to base app and micro app
expect(afterHiddenListener).toBeCalledWith(expect.any(CustomEvent))
expect(window.keepAliveListener).toBeCalledWith('afterhidden')

appCon.appendChild(microappElement22)

defer(() => {
// dispatch event beforeshow to base app and micro app
expect(beforeShowListener).toBeCalledWith(expect.any(CustomEvent))
expect(window.keepAliveListener).toBeCalledWith('beforeshow')

// dispatch event aftershow to base app and micro app
expect(afterShowListener).toBeCalledWith(expect.any(CustomEvent))
expect(window.keepAliveListener).toBeCalledWith('aftershow')
})

// 分支覆盖之 keep-alive 模式下开启 shadowRoot
appCon.removeChild(microappElement22)
microappElement22.setAttribute('shadowDom', 'true')
appCon.appendChild(microappElement22)
})

// test keep-alive 场景2: 二次渲染时,url冲突,卸载旧应用,重新渲染
test('url conflict when remount of keep-alive', async () => {
const microappElement23 = document.createElement('micro-app')
microappElement23.setAttribute('name', 'test-app23')
microappElement23.setAttribute('url', `http://127.0.0.1:${ports.micro_app_element}/common/`)
microappElement23.setAttribute('keep-alive', 'true')

appCon.appendChild(microappElement23)

await new Promise((reslove) => {
microappElement23.addEventListener('mounted', () => {
reslove(true)
})
})

appCon.removeChild(microappElement23)

const microappElement24 = document.createElement('micro-app')
microappElement24.setAttribute('name', 'test-app23')
microappElement24.setAttribute('url', `http://127.0.0.1:${ports.micro_app_element}/dynamic/`)

appCon.appendChild(microappElement24)

expect(console.error).toHaveBeenCalledWith('[micro-app] app test-app23: app name conflict, an app named test-app23 is running')
})

// test keep-alive 场景3: 修改micro-app name、url属性相关操作
test('url conflict when remount of keep-alive', async () => {
const microappElement25 = document.createElement('micro-app')
microappElement25.setAttribute('name', 'test-app25')
microappElement25.setAttribute('url', `http://127.0.0.1:${ports.micro_app_element}/dynamic/`)
microappElement25.setAttribute('keep-alive', 'true')

appCon.appendChild(microappElement25)

await new Promise((reslove) => {
microappElement25.addEventListener('mounted', () => {
reslove(true)
})
})

// afterhidden事件指向test-app25
const afterHiddenListenerForTestApp25 = jest.fn()
microappElement25.addEventListener('afterhidden', afterHiddenListenerForTestApp25)

// beforeshow和aftershow事件指向test-app23
const beforeShowListenerForTestApp23 = jest.fn()
const afterShowListenerForTestApp23 = jest.fn()
microappElement25.addEventListener('beforeshow', beforeShowListenerForTestApp23)
microappElement25.addEventListener('aftershow', afterShowListenerForTestApp23)

// 修改name和url
microappElement25.setAttribute('name', 'test-app23')
microappElement25.setAttribute('url', `http://127.0.0.1:${ports.micro_app_element}/common/`)

await new Promise((reslove) => {
// name和url的修改是异步的,这里放在定时器中执行
setTimeout(() => {
// dispatch event afterhidden to base app
expect(afterHiddenListenerForTestApp25).toBeCalledWith(expect.any(CustomEvent))

// dispatch event beforeshow to base app
expect(beforeShowListenerForTestApp23).toBeCalledWith(expect.any(CustomEvent))

// dispatch event aftershow to base app
expect(afterShowListenerForTestApp23).toBeCalledWith(expect.any(CustomEvent))

reslove(true)
}, 50)
})

// 修改name为test-app25,test-app25为隐藏状态,但url没有修改,此时url冲突,keep-alive报错
microappElement25.setAttribute('name', 'test-app25')

await new Promise((reslove) => {
defer(() => {
expect(console.error).toHaveBeenCalledWith('[micro-app] app test-app25: app name conflict, an app named test-app25 is running')
reslove(true)
})
})
})
})
4 changes: 2 additions & 2 deletions src/create_app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ export default class CreateApp implements AppInterface {
appInstanceMap.delete(this.name)
}

// hidden app when disconnectedCallback with keep-alive
// hidden app when disconnectedCallback called with keep-alive
hiddenKeepAliveApp (): void {
this.keepAliveState = keepAliveStates.KEEP_ALIVE_HIDDEN

Expand All @@ -336,7 +336,7 @@ export default class CreateApp implements AppInterface {
this.container = this.keepAliveContainer
}

// show app when connectedCallback with keep-alive
// show app when connectedCallback called with keep-alive
showKeepAliveApp (container: HTMLElement | ShadowRoot): void {
// dispatch beforeshow event to micro-app
dispatchCustomEventToMicroApp('appstate-change', this.name, {
Expand Down
35 changes: 12 additions & 23 deletions src/micro_app_element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,21 +175,13 @@ export function defineElement (tagName: string): void {
const app = appInstanceMap.get(this.appName)!
const existAppUrl = app.ssrUrl || app.url
const activeAppUrl = this.ssrUrl || this.appUrl
// keep-alive app
if (app.getKeepAliveState() === keepAliveStates.KEEP_ALIVE_HIDDEN) {
// keep-alive don't care about ssrUrl
if (app.url === this.appUrl) {
this.handleShowKeepAliveApp(app)
} else {
/**
* The priority of the app which pushed into the background is the lowest
* make sure the app render correctly, if url different
*/
logWarn(`the keep-alive app with url: ${app.url} is replaced by a new app`, this.appName)
this.handleUnmount(true, () => {
this.handleCreateApp()
})
}
// keep-alive don't care about ssrUrl
// Even if the keep-alive app is pushed into the background, it is still active and cannot be replaced. Otherwise, it is difficult for developers to troubleshoot in case of conflict and will leave developers at a loss
if (
app.getKeepAliveState() === keepAliveStates.KEEP_ALIVE_HIDDEN &&
app.url === this.appUrl
) {
this.handleShowKeepAliveApp(app)
} else if (
existAppUrl === activeAppUrl && (
app.isPrefetch ||
Expand Down Expand Up @@ -270,7 +262,7 @@ export function defineElement (tagName: string): void {
this.ssrUrl = ''
}

this.appName = formatAttrName as string
this.appName = formatAttrName
this.appUrl = formatAttrUrl
;(this.shadowRoot ?? this).innerHTML = ''
if (formatAttrName !== this.getAttribute('name')) {
Expand All @@ -290,11 +282,8 @@ export function defineElement (tagName: string): void {
if (existApp.url === this.appUrl) {
this.handleShowKeepAliveApp(existApp)
} else {
// make sure the app render correctly, if url conflict
logWarn(`the keep-alive app with url: ${existApp.url} is replaced by a new app`, this.appName)
this.handleUnmount(true, () => {
this.handleCreateApp()
})
// the hidden keep-alive app is still active
logError(`app name conflict, an app named ${this.appName} is running`, this.appName)
}
} else if (existApp.url === this.appUrl && existApp.ssrUrl === this.ssrUrl) {
// mount app
Expand Down Expand Up @@ -375,7 +364,7 @@ export function defineElement (tagName: string): void {
) app.unmount(destroy, unmountcb)
}

// hidden app when disconnectedCallback with keep-alive
// hidden app when disconnectedCallback called with keep-alive
private handleHiddenKeepAliveApp () {
const app = appInstanceMap.get(this.appName)
if (
Expand All @@ -385,7 +374,7 @@ export function defineElement (tagName: string): void {
) app.hiddenKeepAliveApp()
}

// show app when connectedCallback with keep-alive
// show app when connectedCallback called with keep-alive
private handleShowKeepAliveApp (app: AppInterface) {
// must be asnyc
defer(() => app.showKeepAliveApp(this.shadowRoot ?? this))
Expand Down

0 comments on commit 45fee76

Please sign in to comment.