feat: migrate static pages to native tabbar
This commit is contained in:
34
tests/ai-page-render.test.js
Normal file
34
tests/ai-page-render.test.js
Normal file
@@ -0,0 +1,34 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
describe('ai page compatibility', () => {
|
||||
test('renders tab panels with compatible layout primitives', () => {
|
||||
const wxml = fs.readFileSync(path.join(process.cwd(), 'pages/ai/index.wxml'), 'utf8')
|
||||
const wxss = fs.readFileSync(path.join(process.cwd(), 'pages/ai/index.wxss'), 'utf8')
|
||||
|
||||
expect(wxml).not.toContain('placeholder-page')
|
||||
expect(wxml).toContain('ai-page')
|
||||
expect(wxml).toContain('ai-page__title')
|
||||
expect(wxml).toContain('wx:for="{{tabs}}"')
|
||||
expect(wxml).toContain('bindtap="handleTabTap"')
|
||||
expect(wxml).toContain('{{currentPanel.badge}}')
|
||||
expect(wxml).toContain('{{currentPanel.heading}}')
|
||||
expect(wxml).toContain('wx:for="{{currentPanel.highlights}}"')
|
||||
expect(wxml).toContain('wx:for="{{currentPanel.examples}}"')
|
||||
expect(wxml).toContain('wx:if="{{currentPanel.formType === \'qa\'}}"')
|
||||
expect(wxml).toContain('wx:if="{{currentPanel.formType === \'analysis\'}}"')
|
||||
expect(wxml).toContain('wx:if="{{currentPanel.formType === \'constitution\'}}"')
|
||||
expect(wxml).toContain('bindtap="handleActionTap"')
|
||||
expect(wxml).toContain('wx:for="{{secondaryEntries}}"')
|
||||
expect(wxml).toContain('bindtap="handleSecondaryEntryTap"')
|
||||
|
||||
expect(wxss).not.toContain('display: grid')
|
||||
expect(wxss).not.toContain('gap:')
|
||||
expect(wxss).toContain('.ai-page__tabs')
|
||||
expect(wxss).toContain('.ai-page__tab--active')
|
||||
expect(wxss).toContain('.panel-card')
|
||||
expect(wxss).toContain('.action-card')
|
||||
expect(wxss).toContain('.example-chip')
|
||||
expect(wxss).toContain('.ai-page__secondary-list')
|
||||
})
|
||||
})
|
||||
170
tests/ai-page.test.js
Normal file
170
tests/ai-page.test.js
Normal file
@@ -0,0 +1,170 @@
|
||||
describe('ai page', () => {
|
||||
afterEach(() => {
|
||||
delete global.Page
|
||||
delete global.wx
|
||||
jest.resetModules()
|
||||
})
|
||||
|
||||
test('exposes AI assistant tabs and default QA panel data', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
const aiPageModule = require('../pages/ai/index')
|
||||
const pageData =
|
||||
typeof aiPageModule.createAiPageData === 'function'
|
||||
? aiPageModule.createAiPageData()
|
||||
: capturedPageConfig?.data
|
||||
|
||||
expect(aiPageModule.createAiPageData).toEqual(expect.any(Function))
|
||||
expect(pageData.title).toBe('AI助手')
|
||||
expect(pageData.historyText).toBe('历史')
|
||||
expect(pageData.activeTabKey).toBe('qa')
|
||||
expect(pageData.tabs).toEqual([
|
||||
expect.objectContaining({ key: 'qa', label: 'AI答疑' }),
|
||||
expect.objectContaining({ key: 'analysis', label: '辨证分析' }),
|
||||
expect.objectContaining({ key: 'constitution', label: '体质检测' })
|
||||
])
|
||||
expect(pageData.currentPanel).toEqual(
|
||||
expect.objectContaining({
|
||||
key: 'qa',
|
||||
badge: 'AI答疑',
|
||||
heading: '您好,我是中医学习助手',
|
||||
actionButtonText: '发送'
|
||||
})
|
||||
)
|
||||
expect(pageData.currentPanel.examples).toHaveLength(3)
|
||||
})
|
||||
|
||||
test('switches panel content when another tab is tapped', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
require('../pages/ai/index')
|
||||
|
||||
const pageInstance = {
|
||||
data: {
|
||||
...(capturedPageConfig.data || {})
|
||||
},
|
||||
setData(update) {
|
||||
this.data = {
|
||||
...this.data,
|
||||
...update
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
capturedPageConfig.handleTabTap.call(pageInstance, {
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
tabKey: 'analysis'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(pageInstance.data.activeTabKey).toBe('analysis')
|
||||
expect(pageInstance.data.currentPanel).toEqual(
|
||||
expect.objectContaining({
|
||||
key: 'analysis',
|
||||
badge: '辨证分析',
|
||||
heading: '先整理症状,再查看学习型辨证分析',
|
||||
actionButtonText: '开始分析'
|
||||
})
|
||||
)
|
||||
|
||||
capturedPageConfig.handleTabTap.call(pageInstance, {
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
tabKey: 'constitution'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(pageInstance.data.activeTabKey).toBe('constitution')
|
||||
expect(pageInstance.data.currentPanel).toEqual(
|
||||
expect.objectContaining({
|
||||
key: 'constitution',
|
||||
badge: '体质检测',
|
||||
heading: '体质检测即将开放',
|
||||
actionButtonText: '查看其它待开放能力'
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
test('shows a toast for history and action placeholders', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
global.wx = {
|
||||
showToast: jest.fn()
|
||||
}
|
||||
|
||||
require('../pages/ai/index')
|
||||
|
||||
capturedPageConfig.handleHistoryTap()
|
||||
capturedPageConfig.handleActionTap()
|
||||
|
||||
expect(global.wx.showToast).toHaveBeenCalledTimes(2)
|
||||
expect(global.wx.showToast).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
expect.objectContaining({
|
||||
title: '功能建设中',
|
||||
icon: 'none'
|
||||
})
|
||||
)
|
||||
expect(global.wx.showToast).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
expect.objectContaining({
|
||||
title: '功能建设中',
|
||||
icon: 'none'
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
test('adds a visible interpret entry and routes history to the tcm history page', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
global.wx = {
|
||||
navigateTo: jest.fn(),
|
||||
showToast: jest.fn()
|
||||
}
|
||||
|
||||
const aiPageModule = require('../pages/ai/index')
|
||||
const pageData = aiPageModule.createAiPageData()
|
||||
|
||||
expect(pageData.secondaryEntries).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ key: 'ai-history', title: 'AI历史' }),
|
||||
expect.objectContaining({ key: 'mingli-interpret', title: '命理解读' })
|
||||
])
|
||||
)
|
||||
|
||||
capturedPageConfig.handleHistoryTap()
|
||||
capturedPageConfig.handleSecondaryEntryTap({
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
route: '/packages/mingli/pages/interpret/index'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(global.wx.navigateTo).toHaveBeenNthCalledWith(1, {
|
||||
url: '/packages/tcm/pages/ai-history/index'
|
||||
})
|
||||
expect(global.wx.navigateTo).toHaveBeenNthCalledWith(2, {
|
||||
url: '/packages/mingli/pages/interpret/index'
|
||||
})
|
||||
})
|
||||
})
|
||||
72
tests/home-page-render.test.js
Normal file
72
tests/home-page-render.test.js
Normal file
@@ -0,0 +1,72 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
describe('home page compatibility', () => {
|
||||
test('avoids fragile WXSS layout features for the native miniprogram renderer', () => {
|
||||
const wxss = fs.readFileSync(path.join(process.cwd(), 'pages/home/index.wxss'), 'utf8')
|
||||
|
||||
expect(wxss).not.toContain('display: grid')
|
||||
expect(wxss).not.toContain('width: fit-content')
|
||||
expect(wxss).not.toContain('gap:')
|
||||
})
|
||||
|
||||
test('renders existing sections and the new wellness/classics blocks with compatible layouts', () => {
|
||||
const wxml = fs.readFileSync(path.join(process.cwd(), 'pages/home/index.wxml'), 'utf8')
|
||||
const wxss = fs.readFileSync(path.join(process.cwd(), 'pages/home/index.wxss'), 'utf8')
|
||||
|
||||
expect(wxml).not.toContain('quick-links')
|
||||
expect(wxml).not.toContain('floating-actions')
|
||||
expect(wxml).not.toContain('home-page__corner')
|
||||
expect(wxml).not.toContain('home-page__header')
|
||||
expect(wxml).toContain('{{wellnessTitle}}')
|
||||
expect(wxml).toContain('{{classicsTitle}}')
|
||||
expect(wxml).toContain('{{classicsActionText}}')
|
||||
expect(wxml).toContain('bindtap="handleSearchTap"')
|
||||
expect(wxml).toContain('bindtap="handleEncyclopediaTap"')
|
||||
expect(wxml).toContain('bindtap="handleToolTap"')
|
||||
expect(wxml).toContain('bindtap="handleWellnessTap"')
|
||||
expect(wxml).toContain('bindtap="handleClassicActionTap"')
|
||||
expect(wxml).toContain('bindtap="handleClassicTap"')
|
||||
expect(wxml).toContain('feature-grid feature-grid--three')
|
||||
expect(wxml.match(/feature-grid feature-grid--four/g)).toHaveLength(3)
|
||||
expect(wxml.match(/feature-grid feature-grid--three/g)).toHaveLength(1)
|
||||
expect(wxml).toContain('section-card__header')
|
||||
expect(wxml).toContain('feature-card__book')
|
||||
|
||||
expect(wxss).toContain('.feature-grid--four .feature-card')
|
||||
expect(wxss).toContain('.feature-grid--three .feature-grid__item')
|
||||
expect(wxss).toContain('.section-card__header')
|
||||
expect(wxss).toContain('.section-card__action')
|
||||
expect(wxss).toContain('.feature-card__book')
|
||||
expect(wxss).not.toContain('.home-page__corner')
|
||||
expect(wxss).not.toContain('.home-page__header')
|
||||
expect(wxss).toContain('padding: 12rpx 18rpx 36rpx;')
|
||||
expect(wxss).toContain('padding: 24rpx 18rpx 16rpx;')
|
||||
expect(wxss).toContain('font-size: 60rpx;')
|
||||
expect(wxss).toContain('font-size: 42rpx;')
|
||||
expect(wxss).toContain('min-height: 152rpx;')
|
||||
})
|
||||
|
||||
test('renders the portal section without forbidden grid or gap styles', () => {
|
||||
const wxml = fs.readFileSync(path.join(process.cwd(), 'pages/home/index.wxml'), 'utf8')
|
||||
const wxss = fs.readFileSync(path.join(process.cwd(), 'pages/home/index.wxss'), 'utf8')
|
||||
|
||||
expect(wxml).toContain('{{portalTitle}}')
|
||||
expect(wxml).toContain('portal-grid')
|
||||
expect(wxml).toContain('bindtap="handlePortalTap"')
|
||||
expect(wxss).toContain('.portal-grid')
|
||||
expect(wxss).toContain('.portal-card')
|
||||
expect(wxss).not.toContain('display: grid')
|
||||
expect(wxss).not.toContain('gap:')
|
||||
})
|
||||
|
||||
test('renders encyclopedia section before the learning portal section', () => {
|
||||
const wxml = fs.readFileSync(path.join(process.cwd(), 'pages/home/index.wxml'), 'utf8')
|
||||
const encyclopediaIndex = wxml.indexOf('{{encyclopediaTitle}}')
|
||||
const portalIndex = wxml.indexOf('{{portalTitle}}')
|
||||
|
||||
expect(encyclopediaIndex).toBeGreaterThan(-1)
|
||||
expect(portalIndex).toBeGreaterThan(-1)
|
||||
expect(encyclopediaIndex).toBeLessThan(portalIndex)
|
||||
})
|
||||
})
|
||||
169
tests/home-page.test.js
Normal file
169
tests/home-page.test.js
Normal file
@@ -0,0 +1,169 @@
|
||||
describe('home page', () => {
|
||||
afterEach(() => {
|
||||
delete global.Page
|
||||
delete global.wx
|
||||
jest.resetModules()
|
||||
})
|
||||
|
||||
test('exposes static home sections without custom bottom navigation data', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
const homePageModule = require('../pages/home/index')
|
||||
const pageData =
|
||||
typeof homePageModule.createHomePageData === 'function'
|
||||
? homePageModule.createHomePageData()
|
||||
: capturedPageConfig?.data
|
||||
|
||||
expect(homePageModule.createHomePageData).toEqual(expect.any(Function))
|
||||
expect(pageData.brandName).toBe('玄知中医')
|
||||
expect(pageData.quickLinks).toBeUndefined()
|
||||
expect(pageData.floatingActions).toBeUndefined()
|
||||
expect(pageData.encyclopediaTitle).toBe('中医百科')
|
||||
expect(pageData.toolsTitle).toBe('学习工具')
|
||||
expect(pageData.wellnessTitle).toBe('养生调理')
|
||||
expect(pageData.classicsTitle).toBe('热门典籍')
|
||||
expect(pageData.classicsActionText).toBe('进入书城')
|
||||
expect(pageData.encyclopediaCards).toHaveLength(3)
|
||||
expect(pageData.toolCards).toHaveLength(4)
|
||||
expect(pageData.wellnessCards).toHaveLength(3)
|
||||
expect(pageData.classicsBooks).toHaveLength(4)
|
||||
expect(pageData.bottomNavItems).toBeUndefined()
|
||||
})
|
||||
|
||||
test('adds direct portal cards for tcm, mingli, bazi and learning routes', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
global.wx = {
|
||||
switchTab: jest.fn(),
|
||||
navigateTo: jest.fn()
|
||||
}
|
||||
|
||||
const homePageModule = require('../pages/home/index')
|
||||
const pageData = homePageModule.createHomePageData()
|
||||
|
||||
expect(pageData.portalTitle).toBe('学习入口')
|
||||
expect(pageData.portalCards).toEqual([
|
||||
expect.objectContaining({ key: 'tcm-library', title: '中医馆' }),
|
||||
expect.objectContaining({ key: 'mingli-hall', title: '易学阁' }),
|
||||
expect.objectContaining({ key: 'bazi', title: '八字排盘' }),
|
||||
expect.objectContaining({ key: 'learning-center', title: '学习中心' })
|
||||
])
|
||||
|
||||
capturedPageConfig.handlePortalTap({
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
route: '/pages/library/index'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
capturedPageConfig.handlePortalTap({
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
route: '/packages/mingli/pages/hall/index'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(global.wx.switchTab).toHaveBeenCalledWith({
|
||||
url: '/pages/library/index'
|
||||
})
|
||||
expect(global.wx.navigateTo).toHaveBeenCalledWith({
|
||||
url: '/packages/mingli/pages/hall/index'
|
||||
})
|
||||
})
|
||||
|
||||
test('wires search, feature cards and classics interactions to route-first actions', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
global.wx = {
|
||||
switchTab: jest.fn(),
|
||||
navigateTo: jest.fn(),
|
||||
showToast: jest.fn()
|
||||
}
|
||||
|
||||
const homePageModule = require('../pages/home/index')
|
||||
const pageData = homePageModule.createHomePageData()
|
||||
|
||||
expect(pageData.searchRoute).toBe('/packages/tcm/pages/search-books/index')
|
||||
expect(pageData.encyclopediaCards).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ key: 'classic', route: '/pages/library/index' })
|
||||
])
|
||||
)
|
||||
expect(pageData.classicsBooks).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
key: 'huangdi-neijing-suwen',
|
||||
route: '/packages/tcm/pages/book-detail/index?scene=classic-a'
|
||||
})
|
||||
])
|
||||
)
|
||||
|
||||
capturedPageConfig.handleSearchTap()
|
||||
capturedPageConfig.handleEncyclopediaTap({
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
route: '/pages/library/index',
|
||||
title: '经典书城'
|
||||
}
|
||||
}
|
||||
})
|
||||
capturedPageConfig.handleToolTap({
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
route: '/pages/ai/index',
|
||||
title: 'AI问答'
|
||||
}
|
||||
}
|
||||
})
|
||||
capturedPageConfig.handleWellnessTap({
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
title: '药膳'
|
||||
}
|
||||
}
|
||||
})
|
||||
capturedPageConfig.handleClassicActionTap()
|
||||
capturedPageConfig.handleClassicTap({
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
route: '/packages/tcm/pages/book-detail/index?scene=classic-a',
|
||||
title: '黄帝内经素问'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(global.wx.navigateTo).toHaveBeenNthCalledWith(1, {
|
||||
url: '/packages/tcm/pages/search-books/index'
|
||||
})
|
||||
expect(global.wx.switchTab).toHaveBeenNthCalledWith(1, {
|
||||
url: '/pages/library/index'
|
||||
})
|
||||
expect(global.wx.switchTab).toHaveBeenNthCalledWith(2, {
|
||||
url: '/pages/ai/index'
|
||||
})
|
||||
expect(global.wx.showToast).toHaveBeenCalledWith({
|
||||
title: '药膳待开放',
|
||||
icon: 'none'
|
||||
})
|
||||
expect(global.wx.switchTab).toHaveBeenNthCalledWith(3, {
|
||||
url: '/pages/library/index'
|
||||
})
|
||||
expect(global.wx.navigateTo).toHaveBeenNthCalledWith(2, {
|
||||
url: '/packages/tcm/pages/book-detail/index?scene=classic-a'
|
||||
})
|
||||
})
|
||||
})
|
||||
29
tests/library-page-render.test.js
Normal file
29
tests/library-page-render.test.js
Normal file
@@ -0,0 +1,29 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
describe('library page compatibility', () => {
|
||||
test('renders category navigation and book cards with compatible layout primitives', () => {
|
||||
const wxml = fs.readFileSync(path.join(process.cwd(), 'pages/library/index.wxml'), 'utf8')
|
||||
const wxss = fs.readFileSync(path.join(process.cwd(), 'pages/library/index.wxss'), 'utf8')
|
||||
|
||||
expect(wxml).not.toContain('placeholder-page')
|
||||
expect(wxml).toContain('library-page__sidebar')
|
||||
expect(wxml).toContain('library-page__category')
|
||||
expect(wxml).toContain('wx:for="{{categories}}"')
|
||||
expect(wxml).toContain('bindtap="handleCategoryTap"')
|
||||
expect(wxml).toContain('{{currentCategoryName}}')
|
||||
expect(wxml).toContain('wx:for="{{visibleBooks}}"')
|
||||
expect(wxml).toContain('book-card__cover-char')
|
||||
expect(wxml).toContain('bindtap="handleSearchTap"')
|
||||
expect(wxml).toContain('{{domainBridge.title}}')
|
||||
expect(wxml).toContain('bindtap="handleDomainBridgeTap"')
|
||||
|
||||
expect(wxss).not.toContain('display: grid')
|
||||
expect(wxss).not.toContain('gap:')
|
||||
expect(wxss).toContain('.library-page__sidebar')
|
||||
expect(wxss).toContain('.library-page__category--active')
|
||||
expect(wxss).toContain('.book-card')
|
||||
expect(wxss).toContain('.book-card__meta')
|
||||
expect(wxss).toContain('.library-page__bridge')
|
||||
})
|
||||
})
|
||||
145
tests/library-page.test.js
Normal file
145
tests/library-page.test.js
Normal file
@@ -0,0 +1,145 @@
|
||||
describe('library page', () => {
|
||||
afterEach(() => {
|
||||
delete global.Page
|
||||
delete global.wx
|
||||
jest.resetModules()
|
||||
})
|
||||
|
||||
test('exposes mock categories and featured books by default', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
const libraryPageModule = require('../pages/library/index')
|
||||
const pageData =
|
||||
typeof libraryPageModule.createLibraryPageData === 'function'
|
||||
? libraryPageModule.createLibraryPageData()
|
||||
: capturedPageConfig?.data
|
||||
|
||||
expect(libraryPageModule.createLibraryPageData).toEqual(expect.any(Function))
|
||||
expect(pageData.title).toBe('典籍')
|
||||
expect(pageData.searchButtonText).toBe('搜索')
|
||||
expect(pageData.activeCategoryId).toBe('featured')
|
||||
expect(pageData.currentCategoryName).toBe('精选')
|
||||
expect(pageData.categories).toHaveLength(9)
|
||||
expect(pageData.categories.map(item => item.name)).toEqual([
|
||||
'精选',
|
||||
'注解',
|
||||
'经论',
|
||||
'伤寒金匮',
|
||||
'医方',
|
||||
'本草',
|
||||
'针灸',
|
||||
'医案',
|
||||
'综合'
|
||||
])
|
||||
expect(pageData.visibleBooks).toHaveLength(6)
|
||||
expect(pageData.visibleBooks[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
id: 'huangdi-neijing-suwen',
|
||||
title: '黄帝内经素问',
|
||||
author: '王冰次',
|
||||
dynasty: '唐',
|
||||
period: '公元762年'
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
test('switches visible books when another category is selected', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
require('../pages/library/index')
|
||||
|
||||
const pageInstance = {
|
||||
data: {
|
||||
...(capturedPageConfig.data || {})
|
||||
},
|
||||
setData(update) {
|
||||
this.data = {
|
||||
...this.data,
|
||||
...update
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
capturedPageConfig.handleCategoryTap.call(pageInstance, {
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
categoryId: 'annotation'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(pageInstance.data.activeCategoryId).toBe('annotation')
|
||||
expect(pageInstance.data.currentCategoryName).toBe('注解')
|
||||
expect(pageInstance.data.visibleBooks).toEqual([
|
||||
expect.objectContaining({
|
||||
title: '黄帝内经素问集注'
|
||||
}),
|
||||
expect.objectContaining({
|
||||
title: '神农本草经辑注'
|
||||
}),
|
||||
expect.objectContaining({
|
||||
title: '难经集注'
|
||||
})
|
||||
])
|
||||
})
|
||||
|
||||
test('shows a toast while search is still mocked', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
global.wx = {
|
||||
showToast: jest.fn()
|
||||
}
|
||||
|
||||
require('../pages/library/index')
|
||||
|
||||
capturedPageConfig.handleSearchTap()
|
||||
|
||||
expect(global.wx.showToast).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
title: '搜索功能暂未开放',
|
||||
icon: 'none'
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
test('adds a visible mingli-hall bridge entry to the library tab', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
global.wx = {
|
||||
navigateTo: jest.fn(),
|
||||
showToast: jest.fn()
|
||||
}
|
||||
|
||||
const libraryPageModule = require('../pages/library/index')
|
||||
const pageData = libraryPageModule.createLibraryPageData()
|
||||
|
||||
expect(pageData.domainBridge).toEqual(
|
||||
expect.objectContaining({
|
||||
title: '进入易学阁',
|
||||
route: '/packages/mingli/pages/hall/index'
|
||||
})
|
||||
)
|
||||
|
||||
capturedPageConfig.handleDomainBridgeTap()
|
||||
|
||||
expect(global.wx.navigateTo).toHaveBeenCalledWith({
|
||||
url: '/packages/mingli/pages/hall/index'
|
||||
})
|
||||
})
|
||||
})
|
||||
22
tests/login-page-render.test.js
Normal file
22
tests/login-page-render.test.js
Normal file
@@ -0,0 +1,22 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
describe('login page compatibility', () => {
|
||||
test('renders a static login layout with action list only', () => {
|
||||
const wxml = fs.readFileSync(path.join(process.cwd(), 'pages/login/index.wxml'), 'utf8')
|
||||
const wxss = fs.readFileSync(path.join(process.cwd(), 'pages/login/index.wxss'), 'utf8')
|
||||
|
||||
expect(wxml).toContain('login-page')
|
||||
expect(wxml).toContain('{{title}}')
|
||||
expect(wxml).toContain('{{subtitle}}')
|
||||
expect(wxml).toContain('wx:for="{{actions}}"')
|
||||
expect(wxml).toContain('bindtap="handleActionTap"')
|
||||
expect(wxml).not.toContain('handleMockLogin')
|
||||
expect(wxml).not.toContain('t-input')
|
||||
expect(wxml).not.toContain('app-button')
|
||||
|
||||
expect(wxss).toContain('.login-page')
|
||||
expect(wxss).toContain('.login-page__hero')
|
||||
expect(wxss).toContain('.login-page__action')
|
||||
})
|
||||
})
|
||||
75
tests/login-page.test.js
Normal file
75
tests/login-page.test.js
Normal file
@@ -0,0 +1,75 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
describe('login page', () => {
|
||||
afterEach(() => {
|
||||
delete global.Page
|
||||
delete global.wx
|
||||
jest.resetModules()
|
||||
})
|
||||
|
||||
test('renders a static login surface without session-store wiring', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
const loginPageModule = require('../pages/login/index')
|
||||
const pageData = loginPageModule.createLoginPageData()
|
||||
const source = fs.readFileSync(path.join(process.cwd(), 'pages/login/index.js'), 'utf8')
|
||||
|
||||
expect(capturedPageConfig.data).toEqual(expect.objectContaining({ title: '欢迎来到玄志' }))
|
||||
expect(pageData.title).toBe('欢迎来到玄志')
|
||||
expect(pageData.actions).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ key: 'wechat', title: '微信授权登录' }),
|
||||
expect.objectContaining({ key: 'browse', title: '先看看静态页面' })
|
||||
])
|
||||
)
|
||||
expect(source).not.toContain('sessionStore')
|
||||
expect(source).not.toContain('handleMockLogin')
|
||||
})
|
||||
|
||||
test('switches to home for browse action and keeps wechat action as static toast', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
global.wx = {
|
||||
switchTab: jest.fn(),
|
||||
showToast: jest.fn()
|
||||
}
|
||||
|
||||
require('../pages/login/index')
|
||||
|
||||
capturedPageConfig.handleActionTap({
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
actionType: 'route',
|
||||
route: '/pages/home/index'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
capturedPageConfig.handleActionTap({
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
actionType: 'toast'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(global.wx.switchTab).toHaveBeenCalledWith({
|
||||
url: '/pages/home/index'
|
||||
})
|
||||
expect(global.wx.showToast).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
title: '登录功能建设中',
|
||||
icon: 'none'
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
33
tests/mingli-bazi-page-render.test.js
Normal file
33
tests/mingli-bazi-page-render.test.js
Normal file
@@ -0,0 +1,33 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
describe('mingli bazi page compatibility', () => {
|
||||
test('renders larger hero, form and result sections with native-compatible layout', () => {
|
||||
const wxml = fs.readFileSync(
|
||||
path.join(process.cwd(), 'packages/mingli/pages/bazi/index.wxml'),
|
||||
'utf8'
|
||||
)
|
||||
const wxss = fs.readFileSync(
|
||||
path.join(process.cwd(), 'packages/mingli/pages/bazi/index.wxss'),
|
||||
'utf8'
|
||||
)
|
||||
|
||||
expect(wxml).toContain('hero-card__eyebrow')
|
||||
expect(wxml).toContain('hero-card__meta')
|
||||
expect(wxml).toContain('panel-header')
|
||||
expect(wxml).toContain('field-block__value')
|
||||
expect(wxml).toContain('result-card__grid')
|
||||
|
||||
expect(wxss).toContain('.hero-card__eyebrow')
|
||||
expect(wxss).toContain('.hero-card__meta')
|
||||
expect(wxss).toContain('.panel-header__title')
|
||||
expect(wxss).toContain('.field-block__value')
|
||||
expect(wxss).toContain('.result-card__grid')
|
||||
expect(wxss).toContain('padding: 36rpx 24rpx 96rpx;')
|
||||
expect(wxss).toContain('padding: 34rpx 28rpx;')
|
||||
expect(wxss).toContain('font-size: 46rpx;')
|
||||
expect(wxss).toContain('font-size: 34rpx;')
|
||||
expect(wxss).not.toContain('display: grid')
|
||||
expect(wxss).not.toContain('gap:')
|
||||
})
|
||||
})
|
||||
29
tests/mingli-learning-pages.test.js
Normal file
29
tests/mingli-learning-pages.test.js
Normal file
@@ -0,0 +1,29 @@
|
||||
describe('mingli and learning pages', () => {
|
||||
afterEach(() => {
|
||||
delete global.Page
|
||||
delete global.wx
|
||||
jest.resetModules()
|
||||
})
|
||||
|
||||
test('hall, bazi, interpret and learning center pages expose static route-first surfaces', () => {
|
||||
global.Page = () => {}
|
||||
|
||||
const hallModule = require('../packages/mingli/pages/hall/index')
|
||||
const baziModule = require('../packages/mingli/pages/bazi/index')
|
||||
const interpretModule = require('../packages/mingli/pages/interpret/index')
|
||||
const learningModule = require('../packages/learning/pages/center/index')
|
||||
|
||||
expect(hallModule.createMingliHallPageData()).toEqual(
|
||||
expect.objectContaining({ title: '易学阁' })
|
||||
)
|
||||
expect(baziModule.createMingliBaziPageData('result')).toEqual(
|
||||
expect.objectContaining({ scene: 'result', title: '八字排盘' })
|
||||
)
|
||||
expect(interpretModule.createMingliInterpretPageData('result')).toEqual(
|
||||
expect.objectContaining({ scene: 'result', title: '命理解读' })
|
||||
)
|
||||
expect(learningModule.createLearningCenterPageData()).toEqual(
|
||||
expect.objectContaining({ title: '学习中心' })
|
||||
)
|
||||
})
|
||||
})
|
||||
83
tests/miniprogram-compatibility.test.js
Normal file
83
tests/miniprogram-compatibility.test.js
Normal file
@@ -0,0 +1,83 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const PROJECT_ROOT = process.cwd()
|
||||
const IGNORED_SEGMENTS = ['node_modules', 'miniprogram_npm', 'coverage', '.worktrees']
|
||||
|
||||
function shouldIgnore(filePath) {
|
||||
return IGNORED_SEGMENTS.some(segment => filePath.includes(`${path.sep}${segment}${path.sep}`))
|
||||
}
|
||||
|
||||
function getProjectFiles(extension) {
|
||||
const pendingDirs = [PROJECT_ROOT]
|
||||
const collectedFiles = []
|
||||
|
||||
while (pendingDirs.length) {
|
||||
const currentDir = pendingDirs.pop()
|
||||
const entries = fs.readdirSync(currentDir, { withFileTypes: true })
|
||||
|
||||
entries.forEach(entry => {
|
||||
const absolutePath = path.join(currentDir, entry.name)
|
||||
|
||||
if (shouldIgnore(absolutePath)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
pendingDirs.push(absolutePath)
|
||||
return
|
||||
}
|
||||
|
||||
if (entry.isFile() && absolutePath.endsWith(extension)) {
|
||||
collectedFiles.push(absolutePath)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return collectedFiles
|
||||
}
|
||||
|
||||
function getDirectoryImportViolations() {
|
||||
const requirePattern = /require\((['"])(\.[^'"]+)\1\)/g
|
||||
|
||||
return getProjectFiles('.js').flatMap(filePath => {
|
||||
const source = fs.readFileSync(filePath, 'utf8')
|
||||
const violations = []
|
||||
let match = requirePattern.exec(source)
|
||||
|
||||
while (match) {
|
||||
const specifier = match[2]
|
||||
const targetPath = path.resolve(path.dirname(filePath), specifier)
|
||||
|
||||
if (fs.existsSync(targetPath) && fs.statSync(targetPath).isDirectory()) {
|
||||
violations.push({
|
||||
filePath: path.relative(PROJECT_ROOT, filePath),
|
||||
specifier
|
||||
})
|
||||
}
|
||||
|
||||
match = requirePattern.exec(source)
|
||||
}
|
||||
|
||||
return violations
|
||||
})
|
||||
}
|
||||
|
||||
function getImportTarget(wxssPath, importPath) {
|
||||
return path.resolve(path.dirname(wxssPath), importPath)
|
||||
}
|
||||
|
||||
describe('miniprogram compatibility', () => {
|
||||
test('avoids directory-level require paths that the miniprogram runtime cannot resolve reliably', () => {
|
||||
expect(getDirectoryImportViolations()).toEqual([])
|
||||
})
|
||||
|
||||
test('app.wxss imports the generated TDesign style entry that exists in the project', () => {
|
||||
const appWxssPath = path.join(PROJECT_ROOT, 'app.wxss')
|
||||
const appWxss = fs.readFileSync(appWxssPath, 'utf8')
|
||||
const match = appWxss.match(/@import ['"]([^'"]+)['"];/)
|
||||
|
||||
expect(match).not.toBeNull()
|
||||
expect(fs.existsSync(getImportTarget(appWxssPath, match[1]))).toBe(true)
|
||||
})
|
||||
})
|
||||
24
tests/profile-page-render.test.js
Normal file
24
tests/profile-page-render.test.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
describe('profile page compatibility', () => {
|
||||
test('renders the five static profile sections with route-first shortcuts', () => {
|
||||
const wxml = fs.readFileSync(path.join(process.cwd(), 'pages/profile/index.wxml'), 'utf8')
|
||||
const wxss = fs.readFileSync(path.join(process.cwd(), 'pages/profile/index.wxss'), 'utf8')
|
||||
|
||||
expect(wxml).not.toContain('placeholder-page')
|
||||
expect(wxml).toContain('profile-page')
|
||||
expect(wxml).toContain('{{userCard.title}}')
|
||||
expect(wxml).toContain('{{vipCard.title}}')
|
||||
expect(wxml).toContain('wx:for="{{assetItems}}"')
|
||||
expect(wxml).toContain('bindtap="handleAssetTap"')
|
||||
expect(wxml).toContain('{{recentRecord.emptyTitle}}')
|
||||
expect(wxml).toContain('wx:for="{{moreItems}}"')
|
||||
expect(wxml).toContain('bindtap="handleMoreTap"')
|
||||
|
||||
expect(wxss).toContain('.profile-page')
|
||||
expect(wxss).toContain('.profile-header')
|
||||
expect(wxss).toContain('.asset-grid')
|
||||
expect(wxss).toContain('.menu-list')
|
||||
})
|
||||
})
|
||||
43
tests/profile-page.test.js
Normal file
43
tests/profile-page.test.js
Normal file
@@ -0,0 +1,43 @@
|
||||
describe('profile page', () => {
|
||||
afterEach(() => {
|
||||
delete global.Page
|
||||
delete global.wx
|
||||
jest.resetModules()
|
||||
})
|
||||
|
||||
test('exposes static profile sections and navigable shortcuts', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
global.wx = {
|
||||
navigateTo: jest.fn()
|
||||
}
|
||||
|
||||
const profilePageModule = require('../pages/profile/index')
|
||||
const pageData = profilePageModule.createProfilePageData()
|
||||
|
||||
expect(pageData.userCard.title).toBe('点击登录')
|
||||
expect(pageData.assetItems).toHaveLength(4)
|
||||
expect(pageData.moreItems).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ key: 'learning-center', title: '学习中心' }),
|
||||
expect.objectContaining({ key: 'ai-history', title: 'AI历史' })
|
||||
])
|
||||
)
|
||||
|
||||
capturedPageConfig.handleMoreTap({
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
route: '/packages/learning/pages/center/index'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(global.wx.navigateTo).toHaveBeenCalledWith({
|
||||
url: '/packages/learning/pages/center/index'
|
||||
})
|
||||
})
|
||||
})
|
||||
82
tests/project-config.test.js
Normal file
82
tests/project-config.test.js
Normal file
@@ -0,0 +1,82 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
function readJson(fileName) {
|
||||
return JSON.parse(
|
||||
fs.readFileSync(path.join(process.cwd(), fileName), {
|
||||
encoding: 'utf8'
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
describe('project config', () => {
|
||||
test('declares an explicit project name and base library version in root config', () => {
|
||||
const projectConfig = readJson('project.config.json')
|
||||
|
||||
expect(projectConfig.projectname).toEqual(expect.any(String))
|
||||
expect(projectConfig.projectname.trim()).not.toBe('')
|
||||
expect(projectConfig.libVersion).toMatch(/^\d+\.\d+\.\d+$/)
|
||||
})
|
||||
|
||||
test('registers native tab pages and matching tabBar items in app config', () => {
|
||||
const appConfig = readJson('app.json')
|
||||
const expectedTabPages = [
|
||||
'pages/home/index',
|
||||
'pages/library/index',
|
||||
'pages/ai/index',
|
||||
'pages/profile/index'
|
||||
]
|
||||
|
||||
expect(appConfig.pages).toEqual(
|
||||
expect.arrayContaining([...expectedTabPages, 'pages/login/index'])
|
||||
)
|
||||
expect(appConfig.tabBar).toEqual(
|
||||
expect.objectContaining({
|
||||
list: expect.arrayContaining(
|
||||
expectedTabPages.map(pagePath =>
|
||||
expect.objectContaining({
|
||||
pagePath
|
||||
})
|
||||
)
|
||||
)
|
||||
})
|
||||
)
|
||||
expect(appConfig.tabBar.list).toHaveLength(4)
|
||||
})
|
||||
|
||||
test('registers static migration subpackages in app config', () => {
|
||||
const appConfig = readJson('app.json')
|
||||
|
||||
expect(appConfig.subPackages).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
root: 'packages/tcm',
|
||||
pages: expect.arrayContaining([
|
||||
'pages/ai-history/index',
|
||||
'pages/assets/index',
|
||||
'pages/bianzheng/index',
|
||||
'pages/book-detail/index',
|
||||
'pages/search-books/index',
|
||||
'pages/section/index',
|
||||
'pages/placeholder/index'
|
||||
])
|
||||
}),
|
||||
expect.objectContaining({
|
||||
root: 'packages/mingli',
|
||||
pages: expect.arrayContaining([
|
||||
'pages/hall/index',
|
||||
'pages/bazi/index',
|
||||
'pages/book-detail/index',
|
||||
'pages/search-books/index',
|
||||
'pages/section/index',
|
||||
'pages/interpret/index'
|
||||
])
|
||||
}),
|
||||
expect.objectContaining({
|
||||
root: 'packages/learning',
|
||||
pages: ['pages/center/index']
|
||||
})
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
const { createRequester, RequestError } = require('../services/request')
|
||||
const { createRequester, RequestError } = require('../services/request/index')
|
||||
|
||||
describe('createRequester', () => {
|
||||
test('normalizes successful responses', async () => {
|
||||
|
||||
46
tests/static-ux-domain-data.test.js
Normal file
46
tests/static-ux-domain-data.test.js
Normal file
@@ -0,0 +1,46 @@
|
||||
const {
|
||||
createTcmHomeHubCards,
|
||||
createTcmAssetPageData
|
||||
} = require('../utils/static-ux/tcm')
|
||||
const {
|
||||
createMingliHallPageData,
|
||||
createBaziPageData
|
||||
} = require('../utils/static-ux/mingli')
|
||||
const { createLearningCenterPageData } = require('../utils/static-ux/learning')
|
||||
|
||||
describe('static domain factories', () => {
|
||||
test('returns scene-safe static data for tcm, mingli and learning domains', () => {
|
||||
expect(createTcmHomeHubCards()).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ key: 'tcm-library', title: '中医馆' }),
|
||||
expect.objectContaining({ key: 'mingli-hall', title: '易学阁' })
|
||||
])
|
||||
)
|
||||
|
||||
expect(createTcmAssetPageData('notes')).toEqual(
|
||||
expect.objectContaining({
|
||||
title: '学习资产',
|
||||
activeKind: 'notes'
|
||||
})
|
||||
)
|
||||
|
||||
expect(createMingliHallPageData()).toEqual(
|
||||
expect.objectContaining({
|
||||
title: '易学阁'
|
||||
})
|
||||
)
|
||||
|
||||
expect(createBaziPageData('result')).toEqual(
|
||||
expect.objectContaining({
|
||||
title: '八字排盘',
|
||||
scene: 'result'
|
||||
})
|
||||
)
|
||||
|
||||
expect(createLearningCenterPageData()).toEqual(
|
||||
expect.objectContaining({
|
||||
title: '学习中心'
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
26
tests/static-ux-navigation.test.js
Normal file
26
tests/static-ux-navigation.test.js
Normal file
@@ -0,0 +1,26 @@
|
||||
const { isTabRoute, openStaticRoute } = require('../utils/static-ux/route-map')
|
||||
|
||||
describe('static ux navigation', () => {
|
||||
test('recognizes tab routes by page path', () => {
|
||||
expect(isTabRoute('/pages/home/index')).toBe(true)
|
||||
expect(isTabRoute('/pages/home/index?from=portal')).toBe(true)
|
||||
expect(isTabRoute('/packages/tcm/pages/assets/index?kind=history')).toBe(false)
|
||||
})
|
||||
|
||||
test('uses switchTab for tab routes and navigateTo for non-tab routes', () => {
|
||||
const wxApi = {
|
||||
switchTab: jest.fn(),
|
||||
navigateTo: jest.fn()
|
||||
}
|
||||
|
||||
expect(openStaticRoute('/pages/library/index', wxApi)).toBe(true)
|
||||
expect(openStaticRoute('/packages/tcm/pages/assets/index?kind=history', wxApi)).toBe(true)
|
||||
|
||||
expect(wxApi.switchTab).toHaveBeenCalledWith({
|
||||
url: '/pages/library/index'
|
||||
})
|
||||
expect(wxApi.navigateTo).toHaveBeenCalledWith({
|
||||
url: '/packages/tcm/pages/assets/index?kind=history'
|
||||
})
|
||||
})
|
||||
})
|
||||
12
tests/static-ux-route-map.test.js
Normal file
12
tests/static-ux-route-map.test.js
Normal file
@@ -0,0 +1,12 @@
|
||||
const { ROUTES } = require('../utils/static-ux/route-map')
|
||||
|
||||
describe('static route map', () => {
|
||||
test('exposes full route paths for all static migration pages', () => {
|
||||
expect(ROUTES.tabs.home).toBe('/pages/home/index')
|
||||
expect(ROUTES.tcm.aiHistory).toBe('/packages/tcm/pages/ai-history/index')
|
||||
expect(ROUTES.tcm.section).toBe('/packages/tcm/pages/section/index')
|
||||
expect(ROUTES.mingli.hall).toBe('/packages/mingli/pages/hall/index')
|
||||
expect(ROUTES.mingli.interpret).toBe('/packages/mingli/pages/interpret/index')
|
||||
expect(ROUTES.learning.center).toBe('/packages/learning/pages/center/index')
|
||||
})
|
||||
})
|
||||
25
tests/tcm-reading-pages.test.js
Normal file
25
tests/tcm-reading-pages.test.js
Normal file
@@ -0,0 +1,25 @@
|
||||
describe('tcm reading pages', () => {
|
||||
afterEach(() => {
|
||||
delete global.Page
|
||||
delete global.wx
|
||||
jest.resetModules()
|
||||
})
|
||||
|
||||
test('book detail, search and section pages use static scenes instead of business ids', () => {
|
||||
global.Page = () => {}
|
||||
|
||||
const bookDetailModule = require('../packages/tcm/pages/book-detail/index')
|
||||
const searchModule = require('../packages/tcm/pages/search-books/index')
|
||||
const sectionModule = require('../packages/tcm/pages/section/index')
|
||||
|
||||
expect(bookDetailModule.createTcmBookDetailPageData('classic-a')).toEqual(
|
||||
expect.objectContaining({ scene: 'classic-a', title: '典籍详情' })
|
||||
)
|
||||
expect(searchModule.createTcmSearchBooksPageData('keyword-demo')).toEqual(
|
||||
expect.objectContaining({ keyword: 'keyword-demo', title: '搜索典籍' })
|
||||
)
|
||||
expect(sectionModule.createTcmSectionPageData('reader-a')).toEqual(
|
||||
expect.objectContaining({ scene: 'reader-a', title: '典籍阅读' })
|
||||
)
|
||||
})
|
||||
})
|
||||
99
tests/tcm-support-pages.test.js
Normal file
99
tests/tcm-support-pages.test.js
Normal file
@@ -0,0 +1,99 @@
|
||||
describe('tcm support pages', () => {
|
||||
afterEach(() => {
|
||||
delete global.Page
|
||||
delete global.wx
|
||||
jest.resetModules()
|
||||
})
|
||||
|
||||
test('assets page switches by static kind and keeps route-only navigation', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
const assetsPageModule = require('../packages/tcm/pages/assets/index')
|
||||
const pageData = assetsPageModule.createTcmAssetsPageData('favorites')
|
||||
|
||||
expect(capturedPageConfig.data).toEqual(expect.objectContaining({ activeKind: 'notes' }))
|
||||
expect(pageData.activeKind).toBe('favorites')
|
||||
expect(pageData.title).toBe('学习资产')
|
||||
expect(pageData.filterItems).toHaveLength(4)
|
||||
})
|
||||
|
||||
test('routes TCM asset history items back to the AI tab with switchTab', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
global.wx = {
|
||||
switchTab: jest.fn(),
|
||||
navigateTo: jest.fn()
|
||||
}
|
||||
|
||||
const assetsPageModule = require('../packages/tcm/pages/assets/index')
|
||||
const pageData = assetsPageModule.createTcmAssetsPageData('history')
|
||||
|
||||
capturedPageConfig.handleEntryTap({
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
route: pageData.items[0].route
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(global.wx.switchTab).toHaveBeenCalledWith({
|
||||
url: '/pages/ai/index'
|
||||
})
|
||||
expect(global.wx.navigateTo).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('ai history, bianzheng and placeholder pages expose scene-driven static data', () => {
|
||||
global.Page = () => {}
|
||||
|
||||
const aiHistoryModule = require('../packages/tcm/pages/ai-history/index')
|
||||
const bianzhengModule = require('../packages/tcm/pages/bianzheng/index')
|
||||
const placeholderModule = require('../packages/tcm/pages/placeholder/index')
|
||||
|
||||
expect(aiHistoryModule.createTcmAiHistoryPageData('empty')).toEqual(
|
||||
expect.objectContaining({ scene: 'empty', title: 'AI对话历史' })
|
||||
)
|
||||
expect(bianzhengModule.createTcmBianzhengPageData('result')).toEqual(
|
||||
expect.objectContaining({ scene: 'result', title: '辨证分析' })
|
||||
)
|
||||
expect(placeholderModule.createTcmPlaceholderPageData('membership')).toEqual(
|
||||
expect.objectContaining({ kind: 'membership' })
|
||||
)
|
||||
})
|
||||
|
||||
test('routes AI history items targeting the AI tab with switchTab', () => {
|
||||
let capturedPageConfig
|
||||
|
||||
global.Page = config => {
|
||||
capturedPageConfig = config
|
||||
}
|
||||
|
||||
global.wx = {
|
||||
switchTab: jest.fn(),
|
||||
navigateTo: jest.fn()
|
||||
}
|
||||
|
||||
const aiHistoryModule = require('../packages/tcm/pages/ai-history/index')
|
||||
const pageData = aiHistoryModule.createTcmAiHistoryPageData('default')
|
||||
|
||||
capturedPageConfig.handleHistoryTap({
|
||||
currentTarget: {
|
||||
dataset: {
|
||||
route: pageData.groups[0].items[0].route
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(global.wx.switchTab).toHaveBeenCalledWith({
|
||||
url: '/pages/ai/index'
|
||||
})
|
||||
expect(global.wx.navigateTo).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user