diff --git a/scenario/arkui/MyNews/entry/src/main/ets/pages/Index.ets b/scenario/arkui/MyNews/entry/src/main/ets/pages/Index.ets index e8ca73ffa8a379177b764461959ffbdb61876391..17aff0a74ec36a58b6457a4cfde9dde4b1d125a9 100644 --- a/scenario/arkui/MyNews/entry/src/main/ets/pages/Index.ets +++ b/scenario/arkui/MyNews/entry/src/main/ets/pages/Index.ets @@ -15,12 +15,23 @@ import { HomePage } from '../view/HomePage'; -import { MallPageBuilder } from '../view/MallPage' +import { MallPageBuilder } from '../view/MallPage'; import { ProfilePageBuilder } from '../view/ProfilePage'; import { TaskPageBuilder } from '../view/TaskPage'; import { VideoPageBuilder } from '../view/VideoPage'; import { IndexBottomNavItem } from '../viewmodel/IndexBottomNavItem'; -import { SearchPage } from '../view/SearchPage' + +// import { SearchPage } from '../view/SearchPage'; + + +/* 定义通用无底色、无按压效果按钮样式 */ +@Extend(Button) +function commonBtnStyle(handler?: (event: ClickEvent) => void) { + .type(ButtonType.Normal) + .stateEffect(false) + .backgroundColor(Color.Transparent) + .onClick(handler) +} /** @@ -29,36 +40,42 @@ import { SearchPage } from '../view/SearchPage' const bottomNavItemList: IndexBottomNavItem[] = [{ title: '首页', normalIcon: $r('app.media.ic_public_home'), - selectedIcon: $r('app.media.ic_public_home_filled') + selectedIcon: $r('app.media.ic_public_home_filled'), + btnId: 'indexHomePageBtn' }, { title: '视频', normalIcon: $r('app.media.ic_public_video'), - selectedIcon: $r('app.media.ic_public_video_filled') + selectedIcon: $r('app.media.ic_public_video_filled'), + btnId: 'indexVideoPageBtn' }, { title: '任务', normalIcon: $r('app.media.ic_public_calendar'), - selectedIcon: $r('app.media.ic_public_calendar_filled') + selectedIcon: $r('app.media.ic_public_calendar_filled'), + btnId: 'indexTaskPageBtn' }, { title: '商城', normalIcon: $r('app.media.ic_public_appstore'), - selectedIcon: $r('app.media.ic_public_appstore_filled') + selectedIcon: $r('app.media.ic_public_appstore_filled'), + btnId: 'indexMallPageBtn' }, { title: '个人', normalIcon: $r('app.media.ic_public_contacts'), - selectedIcon: $r('app.media.ic_public_contacts_filled') + selectedIcon: $r('app.media.ic_public_contacts_filled'), + btnId: 'indexProfilePageBtn' }] @Entry @Component struct Index { - @State currentIndex: number = 0 + @State curNavIdx: number = 0 private tabsController: TabsController = new TabsController() build() { - if(1) - SearchPage() - else + // TODO: 搜索页开发用 + // if (1) + // SearchPage() + // else Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) { ForEach(bottomNavItemList, (item: IndexBottomNavItem, itemIndex: number) => { TabContent() { @@ -86,7 +103,7 @@ struct Index { .width('100%') .height('100%') .align(Alignment.Top) - .tabBar(this.TabBuilder(item.title, itemIndex, item.normalIcon, item.selectedIcon)) + .tabBar(this.TabBuilder(item.title, itemIndex, item.normalIcon, item.selectedIcon, item.btnId)) }) } .width('100%') @@ -101,22 +118,25 @@ struct Index { * 底部导航栏中自定义按钮样式(图标+文字) */ @Builder - TabBuilder(title: string, targetIndex: number, normalIcon: Resource, selectedIcon: Resource) { - Column() { - // 当被选中时变色,图标变为填充型 - Image(this.currentIndex === targetIndex ? selectedIcon : normalIcon) - .size({ width: 20, height: 20 }) - .fillColor(this.currentIndex === targetIndex ? $r('app.color.primary') : $r('app.color.light_fg')) - Text(title) - .fontSize(8) - .fontColor(this.currentIndex === targetIndex ? $r('app.color.primary') : $r('app.color.light_fg')) + TabBuilder(title: string, targetIndex: number, normalIcon: Resource, selectedIcon: Resource, btnId: string) { + Button() { + Column() { + // 当被选中时变色,图标变为填充型 + Image(this.curNavIdx === targetIndex ? selectedIcon : normalIcon) + .size({ width: 20, height: 20 }) + .fillColor(this.curNavIdx === targetIndex ? $r('app.color.primary') : $r('app.color.light_fg')) + Text(title) + .fontSize(8) + .fontColor(this.curNavIdx === targetIndex ? $r('app.color.primary') : $r('app.color.light_fg')) + } + .width('100%') + .height('100%') + .justifyContent(FlexAlign.Center) } - .width('100%') - .height('100%') - .justifyContent(FlexAlign.Center) - .onClick(() => { + .id(btnId) + .commonBtnStyle(() => { this.tabsController.changeIndex(targetIndex) - this.currentIndex = targetIndex + this.curNavIdx = targetIndex }) } diff --git a/scenario/arkui/MyNews/entry/src/main/ets/view/PublishPage.ets b/scenario/arkui/MyNews/entry/src/main/ets/pages/PublishPage.ets similarity index 87% rename from scenario/arkui/MyNews/entry/src/main/ets/view/PublishPage.ets rename to scenario/arkui/MyNews/entry/src/main/ets/pages/PublishPage.ets index 4fd06376f3c28f4e038a03142d52aac681485eaa..34aa8af7b83bd5ed425ba2e02ad17acbcaba42aa 100644 --- a/scenario/arkui/MyNews/entry/src/main/ets/view/PublishPage.ets +++ b/scenario/arkui/MyNews/entry/src/main/ets/pages/PublishPage.ets @@ -17,6 +17,16 @@ import router from '@ohos.router'; +/* 定义通用无底色、无按压效果按钮样式 */ +@Extend(Button) +function commonBtnStyle(handler?: (event: ClickEvent) => void) { + .type(ButtonType.Normal) + .stateEffect(false) + .backgroundColor(Color.Transparent) + .onClick(handler) +} + + /** * All the items in the bottom tab bar. * 页面底部所有选项卡。 @@ -58,6 +68,7 @@ struct PublishPage { .tabBar(this.TabBuilder(item, itemIndex)) }) } + .id('publishPage') .width('100%') .height('100%') .barHeight(64) @@ -104,13 +115,17 @@ struct Article { Column() { /* Tool bar. */ Row() { - Text('取消') - .margin({ left: 20 }) - .fontSize(18) - .fontColor($r('app.color.light_fg')) - .onClick(() => { - router.back() - }) + Button() { + Text('取消') + .margin({ left: 20 }) + .fontSize(18) + .fontColor($r('app.color.light_fg')) + } + .id('publishPageReturnBtn') + .commonBtnStyle(() => { + router.back() + }) + Row({ space: 20 }) { Text('预览') .fontSize(18) diff --git a/scenario/arkui/MyNews/entry/src/main/ets/view/SearchPage.ets b/scenario/arkui/MyNews/entry/src/main/ets/pages/SearchPage.ets similarity index 93% rename from scenario/arkui/MyNews/entry/src/main/ets/view/SearchPage.ets rename to scenario/arkui/MyNews/entry/src/main/ets/pages/SearchPage.ets index 3002c7d2db5c474418f8f153764ac9e1ce41673c..4f7bb7088efb0fe67eebf37ee2545f20e42532bb 100644 --- a/scenario/arkui/MyNews/entry/src/main/ets/view/SearchPage.ets +++ b/scenario/arkui/MyNews/entry/src/main/ets/pages/SearchPage.ets @@ -19,6 +19,16 @@ import { HotBoardClass, HotBoardItem } from '../viewmodel/HotBoard'; import { HotBoardItemList } from '../../mock/HotBoardData'; +/* 定义通用无底色、无按压效果按钮样式 */ +@Extend(Button) +function commonBtnStyle(handler?: (event: ClickEvent) => void) { + .type(ButtonType.Normal) + .stateEffect(false) + .backgroundColor(Color.Transparent) + .onClick(handler) +} + + /** * 中部选项卡内容 */ @@ -29,6 +39,7 @@ const tabItemList: string[] = [ '品牌榜' ] + /** * `搜索` 页面内容。 */ @@ -36,7 +47,6 @@ const tabItemList: string[] = [ @Component export struct SearchPage { @State isPrivacyModeOn: boolean = false - private scroller: Scroller = new Scroller() build() { Column() { @@ -105,6 +115,7 @@ export struct SearchPage { /* 无痕搜索模式开关栏 */ PrivacyModeToggleBar({ isPrivacyModeOn: this.isPrivacyModeOn }) } + .id('searchPage') .width('100%') .height('100%') .justifyContent(FlexAlign.SpaceBetween) @@ -125,12 +136,16 @@ struct TopBar { build() { Row() { /* 返回按钮 */ - Image($r('app.media.ic_public_arrow_left')) - .size({ width: 30, height: 30 }) - .fillColor($r('app.color.light_fg')) - .onClick(() => { - router.back() - }) + Button() { + Image($r('app.media.ic_public_arrow_left')) + .size({ width: 30, height: 30 }) + .fillColor($r('app.color.light_fg')) + } + .id('searchPageReturnBtn') + .commonBtnStyle(() => { + router.back() + }) + /* 搜索框 */ Search({ placeholder: '示例热搜词条' }) .width(0) @@ -140,14 +155,18 @@ struct TopBar { .placeholderFont({ size: 13 }) .borderRadius(999) .backgroundColor($r('app.color.index_tab_bg')) + /* 搜索按钮 */ - Text('搜索') - .margin({ left: 10 }) - .fontSize(14) - .fontColor($r('app.color.primary')) - .onClick(() => { - // TODO: 用户输入内容->搜索该内容 or 无输入->搜索当前词条 - }) + Button() { + Text('搜索') + .margin({ left: 10 }) + .fontSize(14) + .fontColor($r('app.color.primary')) + } + .id('searchPageSearchBtn') + .commonBtnStyle(() => { + // TODO: 用户输入内容->搜索该内容 or 无输入->搜索当前词条 + }) } .width('100%') .height(60) diff --git a/scenario/arkui/MyNews/entry/src/main/ets/view/HomePage.ets b/scenario/arkui/MyNews/entry/src/main/ets/view/HomePage.ets index 990b5fdd1764471e0861487433049cce12781fc5..bf674106fcbf5891cf48e36391e3276e8f69a48f 100644 --- a/scenario/arkui/MyNews/entry/src/main/ets/view/HomePage.ets +++ b/scenario/arkui/MyNews/entry/src/main/ets/view/HomePage.ets @@ -19,6 +19,16 @@ import { FollowingTabContent } from './HomePageFollowingTab'; import { RecommendationTabContent } from './HomePageRecommendationTab'; +/* 定义通用无底色、无按压效果按钮样式 */ +@Extend(Button) +function commonBtnStyle(handler?: (event: ClickEvent) => void) { + .type(ButtonType.Normal) + .stateEffect(false) + .backgroundColor(Color.Transparent) + .onClick(handler) +} + + /** * 上部选项卡内容 */ @@ -46,7 +56,7 @@ const tabItemList: string[] = [ */ @Component export struct HomePage { - @State currentTabIndex: number = 1 + @State curTabIdx: number = 1 build() { Column() { @@ -54,27 +64,28 @@ export struct HomePage { TopBar() /* 可左右滑动的选项卡+按钮 */ - TabSelector({ curIdx: this.currentTabIndex }) + TabSelector({ curIdx: this.curTabIdx }) Divider().strokeWidth(1).color($r('app.color.light_border')) /* 下方页面内容 */ Column() { - if (this.currentTabIndex === 0) { + if (this.curTabIdx === 0) { FollowingTabContent() // 默认显示推荐页 } - else if (this.currentTabIndex === 1) { + else if (this.curTabIdx === 1) { RecommendationTabContent() } // TODO: 添加其他选项卡对应的页面 else { - Text(this.currentTabIndex.toString()) + Text(this.curTabIdx.toString()) } } .width('100%') .height(0) .flexGrow(1) } + .id('homePage') .width('100%') .height('100%') } @@ -87,66 +98,76 @@ export struct HomePage { @Component struct TopBar { @State handleLeftBtnClk: boolean = false - @State curSearchTermIdx: number = 0 build() { Row({ space: 4 }) { - /* 左侧按钮 */ - Stack() { - Image($r('app.media.ic_public_appstore_filled')) - .padding(5) - .size({ width: 34, height: 34 }) - .fillColor($r('app.color.primary')) - .backgroundColor($r('app.color.primary_fg')) - .borderRadius(999) - Text('阅读赚金币') - .padding({ left: 2, right: 2, top: 1, bottom: 1 }) - .fontSize(7) - .fontColor($r('app.color.light_fg')) - .backgroundColor('#ffcc00') - .borderRadius(999) + /* 左侧奖励按钮 */ + Button() { + Stack() { + Image($r('app.media.ic_public_appstore_filled')) + .padding(5) + .size({ width: 34, height: 34 }) + .fillColor($r('app.color.primary')) + .backgroundColor($r('app.color.primary_fg')) + .borderRadius(999) + Text('阅读赚金币') + .padding({ left: 2, right: 2, top: 1, bottom: 1 }) + .fontSize(7) + .fontColor($r('app.color.light_fg')) + .backgroundColor('#ffcc00') + .borderRadius(999) + } + .height('100%') + .align(Alignment.Bottom) } - .height('100%') - .align(Alignment.Bottom) - .onClick(() => { + .id('homePageTopBarRewardBtn') + .commonBtnStyle(() => { // TODO: 按钮点击事件处理 - this.handleLeftBtnClk = !this.handleLeftBtnClk + this.handleLeftBtnClk = false + this.handleLeftBtnClk = true }) .bindPopup(this.handleLeftBtnClk, { message: 'TODO: 按钮点击事件处理', }) /* 搜索框 */ - Row() { - Image($r('app.media.ic_public_input_search')) - .margin({ left: 10 }) - .size({ width: 16, height: 16 }) - .fillColor($r('app.color.light_fg_shallow')) - Text() // TODO: 添加滚动热搜词条 + Button() { + Row() { + Image($r('app.media.ic_public_input_search')) + .margin({ left: 10 }) + .size({ width: 16, height: 16 }) + .fillColor($r('app.color.light_fg_shallow')) + Text() // TODO: 添加滚动热搜词条 + } + .width('100%') + .height('100%') + .borderRadius(999) + .backgroundColor($r('app.color.primary_fg')) } + .id('homePageTopBarSearchBox') .width(0) - .height('100%') .flexGrow(1) - .borderRadius(999) - .backgroundColor($r('app.color.primary_fg')) - .onClick(() => { + .commonBtnStyle(() => { // 将搜索页压入页面栈 - router.pushUrl({ url: 'view/SearchPage' }) + router.pushUrl({ url: 'pages/SearchPage' }) }) /* 右侧发布按钮 */ - Column() { - Image($r("app.media.ic_public_add_norm_filled")) - .size({ width: 20, height: 20 }) - .fillColor($r("app.color.primary_fg")) - Text('发布').fontSize(9).fontColor($r("app.color.primary_fg")) + Button() { + Column() { + Image($r('app.media.ic_public_add_norm_filled')) + .size({ width: 20, height: 20 }) + .fillColor($r('app.color.primary_fg')) + Text('发布').fontSize(9).fontColor($r('app.color.primary_fg')) + } + .height('90%') + .margin({ left: 4, right: 4 }) + .justifyContent(FlexAlign.SpaceBetween) } - .height('90%') - .margin({ left: 4, right: 4 }) - .justifyContent(FlexAlign.SpaceBetween) - .onClick(() => { + .id('homePageTopBarPublishBtn') + .commonBtnStyle(() => { // 将发布页压入页面栈 - router.pushUrl({ url: 'view/PublishPage' }) + router.pushUrl({ url: 'pages/PublishPage' }) }) } .width('100%') @@ -154,7 +175,7 @@ struct TopBar { .padding({ top: 18, bottom: 6, left: 10, right: 10 }) .alignItems(VerticalAlign.Bottom) .justifyContent(FlexAlign.SpaceBetween) - .backgroundColor($r("app.color.primary")) + .backgroundColor($r('app.color.primary')) } } @@ -164,6 +185,8 @@ struct TopBar { */ @Component struct TabSelector { + @State handleFilterBtnClk: boolean = false + @State handleEarphoneBtnClk: boolean = false @Link curIdx: number private scroller: Scroller = new Scroller() @@ -174,30 +197,33 @@ struct TabSelector { /* 可左右滑动的选项卡栏 */ Row({ space: 3 }) { ForEach(tabItemList, (item: string, itemIdx: number) => { - Column({ space: 4 }) { - Text(item) - .fontSize(14) - .fontWeight(this.curIdx === itemIdx ? FontWeight.Bold : FontWeight.Normal) - .fontColor(this.curIdx === itemIdx ? $r('app.color.primary') : $r('app.color.light_fg')) - - /* 文字下方线条 */ - Line() - .startPoint([0, 0]) - .endPoint([16, 0]) - .stroke(this.curIdx === itemIdx ? $r('app.color.primary') : Color.Transparent) - .strokeLineCap(LineCapStyle.Round) - .strokeWidth(2) + Button() { + Column({ space: 4 }) { + /* 选项卡文字 */ + Text(item) + .fontSize(14) + .fontWeight(this.curIdx === itemIdx ? FontWeight.Bold : FontWeight.Normal) + .fontColor(this.curIdx === itemIdx ? $r('app.color.primary') : $r('app.color.light_fg')) + /* 文字下方线条 */ + Line() + .startPoint([0, 0]) + .endPoint([16, 0]) + .stroke(this.curIdx === itemIdx ? $r('app.color.primary') : Color.Transparent) + .strokeLineCap(LineCapStyle.Round) + .strokeWidth(2) + } + .height('100%') + .padding({ left: 14, bottom: 1 }) + .justifyContent(FlexAlign.End) } - .height('100%') - .padding({ left: 14, bottom: 1 }) - .justifyContent(FlexAlign.End) - .onClick(() => { + .commonBtnStyle(() => { this.curIdx = itemIdx }) }) } .height('100%') } + .id('homePageTabSelector') .width('100%') .height('100%') .scrollable(ScrollDirection.Horizontal) @@ -217,12 +243,20 @@ struct TabSelector { .flexGrow(1) .alignContent(Alignment.End) - /* 右侧的按钮 */ Row({ space: 8 }) { - Image($r("app.media.ic_public_view_list")) - .size({ width: 14, height: 14 }) - .fillColor($r('app.color.light_fg')) + Button() { + Image($r('app.media.ic_public_view_list')) + .size({ width: 14, height: 14 }) + .fillColor($r('app.color.light_fg')) + } + .commonBtnStyle(() => { + this.handleFilterBtnClk = false + this.handleFilterBtnClk = true + }) + .bindPopup(this.handleFilterBtnClk, { + message: 'TODO: 按钮点击事件处理' + }) Divider() .strokeWidth(2) @@ -230,9 +264,18 @@ struct TabSelector { .vertical(true) .color($r('app.color.light_border')) - Image($r("app.media.ic_device_earphone")) - .size({ width: 14, height: 14 }) - .fillColor($r('app.color.light_fg')) + Button() { + Image($r('app.media.ic_device_earphone')) + .size({ width: 14, height: 14 }) + .fillColor($r('app.color.light_fg')) + } + .commonBtnStyle(() => { + this.handleEarphoneBtnClk = false + this.handleEarphoneBtnClk = true + }) + .bindPopup(this.handleEarphoneBtnClk, { + message: 'TODO: 按钮点击事件处理' + }) } .height('100%') .padding({ left: 4, right: 14 }) diff --git a/scenario/arkui/MyNews/entry/src/main/ets/view/MallPage.ets b/scenario/arkui/MyNews/entry/src/main/ets/view/MallPage.ets index a9567d23d6b864051f92ceb16e7ab277e564321b..6751dfd24508754a6348b42671088a3c2f6f20a4 100644 --- a/scenario/arkui/MyNews/entry/src/main/ets/view/MallPage.ets +++ b/scenario/arkui/MyNews/entry/src/main/ets/view/MallPage.ets @@ -20,4 +20,5 @@ export function MallPageBuilder() { Column() { Text('商城页面内容') } + .id('mallPage') } diff --git a/scenario/arkui/MyNews/entry/src/main/ets/view/ProfilePage.ets b/scenario/arkui/MyNews/entry/src/main/ets/view/ProfilePage.ets index dc4acadf0cdd0e19100d70a1a6e3668c012cf3e3..43a409e9f38c5a01b8d14ad5dc134045f843344f 100644 --- a/scenario/arkui/MyNews/entry/src/main/ets/view/ProfilePage.ets +++ b/scenario/arkui/MyNews/entry/src/main/ets/view/ProfilePage.ets @@ -20,4 +20,5 @@ export function ProfilePageBuilder() { Column() { Text('个人页面内容') } + .id('profilePage') } diff --git a/scenario/arkui/MyNews/entry/src/main/ets/view/TaskPage.ets b/scenario/arkui/MyNews/entry/src/main/ets/view/TaskPage.ets index b08b8625e37590c8f4883488789eaba68783d41c..6b922995c950f6d44c23b4736200fe2dd7b124f2 100644 --- a/scenario/arkui/MyNews/entry/src/main/ets/view/TaskPage.ets +++ b/scenario/arkui/MyNews/entry/src/main/ets/view/TaskPage.ets @@ -20,4 +20,5 @@ export function TaskPageBuilder() { Column() { Text('任务页面内容') } + .id('taskPage') } diff --git a/scenario/arkui/MyNews/entry/src/main/ets/view/VideoPage.ets b/scenario/arkui/MyNews/entry/src/main/ets/view/VideoPage.ets index 26bfefc18d88a31a9f25b12e70f9892079251bc6..a9ed5128129c77772cbcae0aea1eb091264960e0 100644 --- a/scenario/arkui/MyNews/entry/src/main/ets/view/VideoPage.ets +++ b/scenario/arkui/MyNews/entry/src/main/ets/view/VideoPage.ets @@ -20,4 +20,5 @@ export function VideoPageBuilder() { Column() { Text('视频页面内容') } + .id('videoPage') } diff --git a/scenario/arkui/MyNews/entry/src/main/ets/viewmodel/IndexBottomNavItem.ets b/scenario/arkui/MyNews/entry/src/main/ets/viewmodel/IndexBottomNavItem.ets index f0ddf5a4f17c4a02b07bc650cca9b698a0ce19de..4f1388ff545ccff8a7b69384f937454ffb6a5621 100644 --- a/scenario/arkui/MyNews/entry/src/main/ets/viewmodel/IndexBottomNavItem.ets +++ b/scenario/arkui/MyNews/entry/src/main/ets/viewmodel/IndexBottomNavItem.ets @@ -15,14 +15,15 @@ /** - * Type definition for the items in the bottom navigation bar. - * 应用底部导航栏中项的类型定义。 + * 应用底部导航栏中项的类型定义 */ export interface IndexBottomNavItem { - /* Text under the icon. */ + /* 图标下方文字 */ title: string - /* Display outlined icons when not clicked. */ + /* 未被选中时显示为轮廓型图标 */ normalIcon: Resource - /* Display filled icons after clicked. */ + /* 被选中时替换为填充型图标 */ selectedIcon: Resource + /* 对应的按钮id(测试用例中使用) */ + btnId: string } diff --git a/scenario/arkui/MyNews/entry/src/main/resources/base/profile/main_pages.json b/scenario/arkui/MyNews/entry/src/main/resources/base/profile/main_pages.json index 6dce140ee632e781f4305c8bf5d75c6c10295ab3..64148a785467616e13f2d0413e819b6f771f8f31 100644 --- a/scenario/arkui/MyNews/entry/src/main/resources/base/profile/main_pages.json +++ b/scenario/arkui/MyNews/entry/src/main/resources/base/profile/main_pages.json @@ -1,7 +1,7 @@ { "src": [ "pages/Index", - "view/PublishPage", - "view/SearchPage" + "pages/PublishPage", + "pages/SearchPage" ] } \ No newline at end of file diff --git a/scenario/arkui/MyNews/entry/src/ohosTest/ets/test/Ability.test.ets b/scenario/arkui/MyNews/entry/src/ohosTest/ets/test/Ability.test.ets deleted file mode 100644 index f974452cec608befe257cfe0555b00a808156fd6..0000000000000000000000000000000000000000 --- a/scenario/arkui/MyNews/entry/src/ohosTest/ets/test/Ability.test.ets +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2023 Southeast University. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -import hilog from '@ohos.hilog'; -import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from '@ohos/hypium'; - -export default function abilityTest() { - describe('ActsAbilityTest', () => { - // Defines a test suite. Two parameters are supported: test suite name and test suite function. - beforeAll(() => { - // Presets an action, which is performed only once before all test cases of the test suite start. - // This API supports only one parameter: preset action function. - }) - beforeEach(() => { - // Presets an action, which is performed before each unit test case starts. - // The number of execution times is the same as the number of test cases defined by **it**. - // This API supports only one parameter: preset action function. - }) - afterEach(() => { - // Presets a clear action, which is performed after each unit test case ends. - // The number of execution times is the same as the number of test cases defined by **it**. - // This API supports only one parameter: clear action function. - }) - afterAll(() => { - // Presets a clear action, which is performed after all test cases of the test suite end. - // This API supports only one parameter: clear action function. - }) - it('assertContain', 0, () => { - // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. - hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); - let a = 'abc'; - let b = 'b'; - // Defines a variety of assertion methods, which are used to declare expected boolean conditions. - expect(a).assertContain(b); - expect(a).assertEqual(a); - }) - }) -} \ No newline at end of file diff --git a/scenario/arkui/MyNews/entry/src/ohosTest/ets/test/HomePage.test.ets b/scenario/arkui/MyNews/entry/src/ohosTest/ets/test/HomePage.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..5d8e20dd9d28ace2baae42db93431825deb65e63 --- /dev/null +++ b/scenario/arkui/MyNews/entry/src/ohosTest/ets/test/HomePage.test.ets @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2023 Southeast University. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import hilog from '@ohos.hilog'; +import { describe, expect, it } from '@ohos/hypium'; +import abilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { Component, Driver, ON } from '@ohos.UiTest'; +import Want from '@ohos.app.ability.Want'; + +const TAG: string = '[Scenario_MyNews_HomePageTest]' +const DOMAIN: number = 0xF811 +const BUNDLE: string = 'MyNews_' + +let delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator() +let driver: Driver = Driver.create() + +/* 通过id验证按钮是否存在,若存在则执行一次点击操作,返回按钮对象供后续操作 */ +const checkBtnIdAndClk = async (btnId: string): Promise => { + await driver.assertComponentExist(ON.type('Button').id(btnId)) + let btn: Component = await driver.findComponent(ON.type('Button').id(btnId)) + await btn.click() + await driver.delayMs(1000) +} + +export default function HomePageTest() { + describe('HomePageTest', () => { + /** + * 拉起应用,进入首页 + */ + it('StartAbility_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 begin') + const want: Want = { + bundleName: 'com.samples.mynews', + abilityName: 'EntryAbility' + } + try { + await delegator.startAbility(want) + await driver.delayMs(1000) + await checkBtnIdAndClk('indexHomePageBtn') + await driver.assertComponentExist(ON.id('homePage')) + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 entered home page') + done() + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `StartAbility_001 exception = ${JSON.stringify(exception)}`) + expect().assertFail() + done() + } + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 end') + }) + + /** + * 顶栏按钮功能测试 + */ + it('HomePageTopBarBtnFunction_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'HomePageTopBarBtnFunction_001 begin') + /* 依次测试顶栏按钮功能 */ + // [0]:待查找、点击的按钮ID;[1]:点击后用于判断按钮功能是否正常的组件ID;[2]:返回首页的按钮ID + const btnList: string[][] = [ + // ['homePageTopBarRewardBtn', '', ''], // `阅读奖励`,暂未添加点击事件处理 + ['homePageTopBarSearchBox', 'searchPage', 'searchPageReturnBtn'], // `搜索框` + ['homePageTopBarPublishBtn', 'publishPage', 'publishPageReturnBtn']// `发布` + ] + try { + for (let i = 0; i < btnList.length; i++) { + await checkBtnIdAndClk(btnList[i][0]) // 检查按钮是否存在并点击 + hilog.info(DOMAIN, TAG, BUNDLE + `HomePageTopBarBtnFunction_001 button ${btnList[i][0]} is found and clicked`) + await driver.assertComponentExist(ON.id(btnList[i][1])) // 检查所跳转的页面内容是否匹配 + hilog.info(DOMAIN, TAG, BUNDLE + `HomePageTopBarBtnFunction_001 button ${btnList[i][0]} function test passed`) + await checkBtnIdAndClk(btnList[i][2]) // 返回首页 + } + done() + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `HomePageTopBarBtnFunction_001 exception = ${JSON.stringify(exception)}`) + expect().assertFail() + done() + } + hilog.info(DOMAIN, TAG, BUNDLE + 'HomePageTopBarBtnFunction_001 end') + }) + + /** + * 选项卡栏功能测试(是否正确加载及是否可滑动) + */ + it('HomePageTabSelectorFunction_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'HomePageTabSelectorFunction_001 begin') + /* 检查选项卡是否正确加载,测试左右滑动功能 */ + try { + await driver.assertComponentExist(ON.id('homePageTabSelector')) + let tabSelector = await driver.findComponent(ON.id('homePageTabSelector')) // 获取选项卡栏对象 + hilog.info(DOMAIN, TAG, BUNDLE + `HomePageTabSelectorFunction_001 tab selector is found`) + expect(await tabSelector.isScrollable()).assertTrue() // 检查是否可滑动(左右滑动没有提供API) + hilog.info(DOMAIN, TAG, BUNDLE + `HomePageTabSelectorFunction_001 tab selector is scrollable`) + done() + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `HomePageTabSelectorFunction_001 exception = ${JSON.stringify(exception)}`) + expect().assertFail() + done() + } + hilog.info(DOMAIN, TAG, BUNDLE + 'HomePageTabSelectorFunction_001 end') + }) + + /** + * 选项卡栏功能测试(页面切换功能) + */ + it('HomePageTabSelectorFunction_002', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'HomePageTabSelectorFunction_002 begin') + /* 检查选项卡是否正确加载,测试下方内容切换功能 */ + try { + await driver.assertComponentExist(ON.id('homePageTabSelector')) + let tabSelector = await driver.findComponent(ON.id('homePageTabSelector')) // 获取选项卡栏对象 + hilog.info(DOMAIN, TAG, BUNDLE + `HomePageTabSelectorFunction_002 tab selector is found`) + // TODO: 测试下方内容切换功能 + done() + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `HomePageTabSelectorFunction_002 exception = ${JSON.stringify(exception)}`) + expect().assertFail() + done() + } + hilog.info(DOMAIN, TAG, BUNDLE + 'HomePageTabSelectorFunction_002 end') + }) + }) +} diff --git a/scenario/arkui/MyNews/entry/src/ohosTest/ets/test/Index.test.ets b/scenario/arkui/MyNews/entry/src/ohosTest/ets/test/Index.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..e340d7beb26a9feb48c463f38e94b3a50a66f275 --- /dev/null +++ b/scenario/arkui/MyNews/entry/src/ohosTest/ets/test/Index.test.ets @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2023 Southeast University. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import hilog from '@ohos.hilog'; +import { describe, expect, it } from '@ohos/hypium'; +import abilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { Component, Driver, ON } from '@ohos.UiTest'; +import Want from '@ohos.app.ability.Want'; + + +const TAG: string = '[Scenario_MyNews_IndexTest]' +const DOMAIN: number = 0xF811 +const BUNDLE: string = 'MyNews_' + +let delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator() +let driver: Driver = Driver.create() + +/* 通过id验证按钮是否存在,若存在则执行一次点击操作,返回按钮对象供后续操作 */ +const checkBtnIdAndClk = async (btnId: string): Promise => { + await driver.assertComponentExist(ON.type('Button').id(btnId)) + let btn: Component = await driver.findComponent(ON.type('Button').id(btnId)) + await btn.click() + await driver.delayMs(1000) +} + +export default function indexTest() { + describe('IndexTest', () => { + /** + * 拉起应用 + */ + it('StartAbility_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 begin') + const want: Want = { + bundleName: 'com.samples.mynews', + abilityName: 'EntryAbility' + } + try { + await delegator.startAbility(want) + await driver.delayMs(1000) + done() + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `StartAbility_001 exception = ${JSON.stringify(exception)}`) + expect().assertFail() + done() + } + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 end') + }) + + /** + * 底部导航栏按钮功能测试 + */ + it('IndexNavBtnFunction_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'IndexNavBtnFunction_001 begin') + /* 从右到左,依次测试底部导航栏按钮功能 */ + // [0]: 待查找、点击的按钮ID;[1]: 点击后用于判断按钮功能是否正常的组件ID + const btnList: string[][] = [ + ['indexProfilePageBtn', 'profilePage'], // `个人` + ['indexMallPageBtn', 'mallPage'], // `商城` + ['indexTaskPageBtn', 'taskPage'], // `任务` + ['indexVideoPageBtn', 'videoPage'], // `视频` + ['indexHomePageBtn', 'homePage']// `首页` + ] + try { + for (let i = 0; i < btnList.length; i++) { + await checkBtnIdAndClk(btnList[i][0]) // 检查按钮是否存在并点击 + hilog.info(DOMAIN, TAG, BUNDLE + `IndexNavBtnFunction_001 button ${btnList[i][0]} is found and clicked`) + await driver.assertComponentExist(ON.id(btnList[i][1])) // 检查所跳转的页面内容是否匹配 + hilog.info(DOMAIN, TAG, BUNDLE + `IndexNavBtnFunction_001 button ${btnList[i][0]} function test passed`) + } + done() + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `IndexNavBtnFunction_001 exception = ${JSON.stringify(exception)}`) + expect().assertFail() + done() + } + hilog.info(DOMAIN, TAG, BUNDLE + 'IndexNavBtnFunction_001 end') + }) + }) +} diff --git a/scenario/arkui/MyNews/entry/src/ohosTest/ets/test/List.test.ets b/scenario/arkui/MyNews/entry/src/ohosTest/ets/test/List.test.ets index e59c8e4798c7ea7500dda3989e02a5f09e8c7392..b73bfd553b12d0d1000cbe3c047b7eed01c2bae7 100644 --- a/scenario/arkui/MyNews/entry/src/ohosTest/ets/test/List.test.ets +++ b/scenario/arkui/MyNews/entry/src/ohosTest/ets/test/List.test.ets @@ -1,3 +1,4 @@ +import HomePageTest from './HomePage.test' /* * Copyright (c) 2023 Southeast University. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,8 +15,10 @@ */ -import abilityTest from './Ability.test'; +import indexTest from './Index.test' + export default function testsuite() { - abilityTest(); + indexTest() + HomePageTest() } \ No newline at end of file