Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88730dbec9 |
@@ -0,0 +1,24 @@
|
|||||||
|
import { test as base } from '@playwright/test'
|
||||||
|
import { HomePage } from './models/HomePage'
|
||||||
|
import { ListsPage } from './models/ListsPage'
|
||||||
|
import { SearchPage } from './models/SearchPage'
|
||||||
|
import { ThreadPage } from './models/ThreadPage'
|
||||||
|
import { UserPage } from './models/UserPage'
|
||||||
|
|
||||||
|
type Fixtures = {
|
||||||
|
homePage: HomePage
|
||||||
|
listsPage: ListsPage
|
||||||
|
searchPage: SearchPage
|
||||||
|
threadPage: ThreadPage
|
||||||
|
userPage: UserPage
|
||||||
|
}
|
||||||
|
|
||||||
|
export const test = base.extend<Fixtures>({
|
||||||
|
homePage: ({ page }, use) => use(new HomePage(page)),
|
||||||
|
listsPage: ({ page }, use) => use(new ListsPage(page)),
|
||||||
|
searchPage: ({ page }, use) => use(new SearchPage(page)),
|
||||||
|
threadPage: ({ page }, use) => use(new ThreadPage(page)),
|
||||||
|
userPage: ({ page }, use) => use(new UserPage(page)),
|
||||||
|
})
|
||||||
|
|
||||||
|
export { expect } from '@playwright/test'
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { expect, type Locator, type Page } from '@playwright/test'
|
||||||
|
|
||||||
|
export class Base {
|
||||||
|
readonly ambientLinksLocator: Locator
|
||||||
|
readonly articlesLocator: Locator
|
||||||
|
readonly continuationErrorLocator: Locator
|
||||||
|
readonly endOfFeedLocator: Locator
|
||||||
|
readonly loadingRailLocator: Locator
|
||||||
|
readonly mutationButtonsLocator: Locator
|
||||||
|
readonly mutationLinksLocator: Locator
|
||||||
|
|
||||||
|
constructor(readonly page: Page) {
|
||||||
|
const ambientLinkNames = /ホーム|おすすめ|トレンド|通知|履歴/
|
||||||
|
const mutationControlNames =
|
||||||
|
/投稿する|返信|いいね|再投稿|フォロー|ブックマーク/
|
||||||
|
|
||||||
|
this.ambientLinksLocator = page.getByRole('link', {
|
||||||
|
name: ambientLinkNames,
|
||||||
|
})
|
||||||
|
this.articlesLocator = page.locator('article')
|
||||||
|
this.continuationErrorLocator = page
|
||||||
|
.getByRole('alert')
|
||||||
|
.filter({ hasText: '続きの投稿を取得できませんでした。' })
|
||||||
|
this.endOfFeedLocator = page.getByText('これ以上の投稿はありません。')
|
||||||
|
this.loadingRailLocator = page.locator('.loading-rail')
|
||||||
|
this.mutationButtonsLocator = page.getByRole('button', {
|
||||||
|
name: mutationControlNames,
|
||||||
|
})
|
||||||
|
this.mutationLinksLocator = page.getByRole('link', {
|
||||||
|
name: mutationControlNames,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async navigateTo(path: string) {
|
||||||
|
await this.page.goto(path)
|
||||||
|
await this.page.waitForLoadState('networkidle')
|
||||||
|
}
|
||||||
|
|
||||||
|
async tabTo(target: Locator) {
|
||||||
|
await this.page.keyboard.press('Tab')
|
||||||
|
await expect(target).toBeFocused()
|
||||||
|
}
|
||||||
|
|
||||||
|
async retryContinuation() {
|
||||||
|
await this.continuationErrorLocator
|
||||||
|
.getByRole('button', { name: '再試行' })
|
||||||
|
.click()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import type { Locator, Page } from '@playwright/test'
|
||||||
|
import { Base } from './Base'
|
||||||
|
|
||||||
|
export class HomePage extends Base {
|
||||||
|
readonly handleInputLocator: Locator
|
||||||
|
readonly submitButtonLocator: Locator
|
||||||
|
|
||||||
|
constructor(page: Page) {
|
||||||
|
super(page)
|
||||||
|
this.handleInputLocator = page.getByLabel('ハンドルまたはプロフィール URL')
|
||||||
|
this.submitButtonLocator = page.getByRole('button', { name: '表示' })
|
||||||
|
}
|
||||||
|
|
||||||
|
async goTo() {
|
||||||
|
await this.navigateTo('/')
|
||||||
|
}
|
||||||
|
|
||||||
|
async displayUser(handle: string) {
|
||||||
|
await this.handleInputLocator.fill(handle)
|
||||||
|
await this.submitButtonLocator.click()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { Base } from './Base'
|
||||||
|
|
||||||
|
export class ListsPage extends Base {
|
||||||
|
async goTo() {
|
||||||
|
await this.navigateTo('/i/lists')
|
||||||
|
}
|
||||||
|
|
||||||
|
async openList(name: RegExp | string) {
|
||||||
|
await this.page.getByRole('link', { name }).click()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import type { Locator, Page } from '@playwright/test'
|
||||||
|
import { Base } from './Base'
|
||||||
|
|
||||||
|
export class SearchPage extends Base {
|
||||||
|
readonly followingOnlyLocator: Locator
|
||||||
|
readonly latestRankingLocator: Locator
|
||||||
|
readonly queryInputLocator: Locator
|
||||||
|
readonly searchButtonLocator: Locator
|
||||||
|
readonly topRankingLocator: Locator
|
||||||
|
|
||||||
|
constructor(page: Page) {
|
||||||
|
super(page)
|
||||||
|
this.followingOnlyLocator = page.getByLabel('フォロー中のみ')
|
||||||
|
this.latestRankingLocator = page.getByLabel('最新順')
|
||||||
|
this.queryInputLocator = page.getByLabel('検索語')
|
||||||
|
this.searchButtonLocator = page.getByRole('button', { name: '検索' })
|
||||||
|
this.topRankingLocator = page.getByLabel('人気順')
|
||||||
|
}
|
||||||
|
|
||||||
|
async goTo() {
|
||||||
|
await this.navigateTo('/search?q=&product=Latest&following=false')
|
||||||
|
}
|
||||||
|
|
||||||
|
async search(query: string) {
|
||||||
|
await this.queryInputLocator.fill(query)
|
||||||
|
await this.searchButtonLocator.click()
|
||||||
|
}
|
||||||
|
|
||||||
|
async searchTopFromFollowing(query: string) {
|
||||||
|
await this.queryInputLocator.fill(query)
|
||||||
|
await this.topRankingLocator.check()
|
||||||
|
await this.followingOnlyLocator.check()
|
||||||
|
await this.searchButtonLocator.click()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import type { Locator, Page } from '@playwright/test'
|
||||||
|
import { Base } from './Base'
|
||||||
|
|
||||||
|
export class ThreadPage extends Base {
|
||||||
|
readonly headingLocator: Locator
|
||||||
|
readonly selectedPostLabelLocator: Locator
|
||||||
|
|
||||||
|
constructor(page: Page) {
|
||||||
|
super(page)
|
||||||
|
this.headingLocator = page.getByRole('heading', { name: '会話' })
|
||||||
|
this.selectedPostLabelLocator = page.getByText('表示中の投稿')
|
||||||
|
}
|
||||||
|
|
||||||
|
async goTo(handle: string, tweetId: string) {
|
||||||
|
await this.navigateTo(`/${handle}/status/${tweetId}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { Base } from './Base'
|
||||||
|
|
||||||
|
export class UserPage extends Base {
|
||||||
|
async goTo(handle: string) {
|
||||||
|
await this.navigateTo(`/${handle}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async openPostDetails(postText: string) {
|
||||||
|
await this.page
|
||||||
|
.getByRole('article')
|
||||||
|
.filter({ hasText: postText })
|
||||||
|
.getByRole('link', { name: '詳細・スレッド' })
|
||||||
|
.click()
|
||||||
|
}
|
||||||
|
}
|
||||||
+65
-95
@@ -1,4 +1,4 @@
|
|||||||
import { expect, type Locator, test } from '@playwright/test'
|
import { expect, test } from './fixtures'
|
||||||
|
|
||||||
let consoleErrors: string[]
|
let consoleErrors: string[]
|
||||||
let pageErrors: string[]
|
let pageErrors: string[]
|
||||||
@@ -17,46 +17,22 @@ test.afterEach(() => {
|
|||||||
expect(pageErrors, 'uncaught browser errors').toEqual([])
|
expect(pageErrors, 'uncaught browser errors').toEqual([])
|
||||||
})
|
})
|
||||||
|
|
||||||
const ambientLinkNames = /ホーム|おすすめ|トレンド|通知|履歴/
|
|
||||||
const mutationControlNames = /投稿する|返信|いいね|再投稿|フォロー|ブックマーク/
|
|
||||||
|
|
||||||
async function submitSearch(
|
|
||||||
page: import('@playwright/test').Page,
|
|
||||||
query: string,
|
|
||||||
) {
|
|
||||||
await openReader(page, '/search?q=&product=Latest&following=false')
|
|
||||||
await expect(page.locator('article')).toHaveCount(0)
|
|
||||||
await page.getByLabel('検索語').fill(query)
|
|
||||||
await page.getByRole('button', { name: '検索' }).click()
|
|
||||||
}
|
|
||||||
|
|
||||||
async function openReader(page: import('@playwright/test').Page, path: string) {
|
|
||||||
await page.goto(path)
|
|
||||||
await page.waitForLoadState('networkidle')
|
|
||||||
}
|
|
||||||
|
|
||||||
async function tabTo(page: import('@playwright/test').Page, target: Locator) {
|
|
||||||
await page.keyboard.press('Tab')
|
|
||||||
await expect(target).toBeFocused()
|
|
||||||
}
|
|
||||||
|
|
||||||
test('requires intent and infinitely loads a user timeline', async ({
|
test('requires intent and infinitely loads a user timeline', async ({
|
||||||
|
homePage,
|
||||||
page,
|
page,
|
||||||
|
userPage,
|
||||||
}) => {
|
}) => {
|
||||||
await openReader(page, '/')
|
await homePage.goTo()
|
||||||
await expect(page).toHaveURL(/\/$/)
|
await expect(page).toHaveURL(/\/$/)
|
||||||
await expect(page.locator('article')).toHaveCount(0)
|
await expect(homePage.articlesLocator).toHaveCount(0)
|
||||||
await expect(page.getByRole('link', { name: ambientLinkNames })).toHaveCount(
|
await expect(homePage.ambientLinksLocator).toHaveCount(0)
|
||||||
0,
|
|
||||||
)
|
|
||||||
|
|
||||||
await page.getByLabel('ハンドルまたはプロフィール URL').fill('@yuta')
|
await homePage.displayUser('@yuta')
|
||||||
await page.getByRole('button', { name: '表示' }).click()
|
|
||||||
|
|
||||||
await expect(page).toHaveURL(/\/yuta$/)
|
await expect(page).toHaveURL(/\/yuta$/)
|
||||||
await expect(page.getByText('user page 1')).toBeVisible()
|
await expect(page.getByText('user page 1')).toBeVisible()
|
||||||
await expect(page.getByText('user page 2')).toBeVisible()
|
await expect(page.getByText('user page 2')).toBeVisible()
|
||||||
await expect(page.getByText('これ以上の投稿はありません。')).toBeVisible()
|
await expect(userPage.endOfFeedLocator).toBeVisible()
|
||||||
await expect(page).toHaveScreenshot('mist-user.png', {
|
await expect(page).toHaveScreenshot('mist-user.png', {
|
||||||
animations: 'disabled',
|
animations: 'disabled',
|
||||||
fullPage: true,
|
fullPage: true,
|
||||||
@@ -64,36 +40,36 @@ test('requires intent and infinitely loads a user timeline', async ({
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('selects an authenticated list and infinitely loads its timeline', async ({
|
test('selects an authenticated list and infinitely loads its timeline', async ({
|
||||||
|
listsPage,
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
await openReader(page, '/i/lists')
|
await listsPage.goTo()
|
||||||
await expect(page.locator('article')).toHaveCount(0)
|
await expect(listsPage.articlesLocator).toHaveCount(0)
|
||||||
|
|
||||||
await page.getByRole('link', { name: /My E2E List.*10 メンバー/ }).click()
|
await listsPage.openList(/My E2E List.*10 メンバー/)
|
||||||
|
|
||||||
await expect(page).toHaveURL(/\/i\/lists\/1234567890$/)
|
await expect(page).toHaveURL(/\/i\/lists\/1234567890$/)
|
||||||
await expect(page.getByText('list page 1')).toBeVisible()
|
await expect(page.getByText('list page 1')).toBeVisible()
|
||||||
await expect(page.getByText('list page 2')).toBeVisible()
|
await expect(page.getByText('list page 2')).toBeVisible()
|
||||||
await expect(page.getByText('これ以上の投稿はありません。')).toBeVisible()
|
await expect(listsPage.endOfFeedLocator).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('opens a card detail and infinitely loads its conversation', async ({
|
test('opens a card detail and infinitely loads its conversation', async ({
|
||||||
page,
|
page,
|
||||||
|
threadPage,
|
||||||
|
userPage,
|
||||||
}) => {
|
}) => {
|
||||||
await openReader(page, '/yuta')
|
await userPage.goTo('yuta')
|
||||||
const sourceCard = page
|
await userPage.openPostDetails('user page 1')
|
||||||
.getByRole('article')
|
|
||||||
.filter({ hasText: 'user page 1' })
|
|
||||||
await sourceCard.getByRole('link', { name: '詳細・スレッド' }).click()
|
|
||||||
|
|
||||||
await expect(page).toHaveURL(/\/yuta\/status\/1001$/)
|
await expect(page).toHaveURL(/\/yuta\/status\/1001$/)
|
||||||
await expect(page.getByRole('heading', { name: '会話' })).toBeVisible()
|
await expect(threadPage.headingLocator).toBeVisible()
|
||||||
await expect(page.getByText('表示中の投稿')).toBeVisible()
|
await expect(threadPage.selectedPostLabelLocator).toBeVisible()
|
||||||
await expect(page.getByText('user page 1')).toHaveCount(1)
|
await expect(page.getByText('user page 1')).toHaveCount(1)
|
||||||
await expect(page.getByText('thread root')).toBeVisible()
|
await expect(page.getByText('thread root')).toBeVisible()
|
||||||
await expect(page.getByText('thread page 1')).toBeVisible()
|
await expect(page.getByText('thread page 1')).toBeVisible()
|
||||||
await expect(page.getByText('thread page 2')).toBeVisible()
|
await expect(page.getByText('thread page 2')).toBeVisible()
|
||||||
await expect(page.getByText('これ以上の投稿はありません。')).toBeVisible()
|
await expect(threadPage.endOfFeedLocator).toBeVisible()
|
||||||
await expect(page).toHaveScreenshot('mist-thread.png', {
|
await expect(page).toHaveScreenshot('mist-thread.png', {
|
||||||
animations: 'disabled',
|
animations: 'disabled',
|
||||||
fullPage: true,
|
fullPage: true,
|
||||||
@@ -102,96 +78,90 @@ test('opens a card detail and infinitely loads its conversation', async ({
|
|||||||
|
|
||||||
test('resolves a reply root and retries only the failed continuation', async ({
|
test('resolves a reply root and retries only the failed continuation', async ({
|
||||||
page,
|
page,
|
||||||
|
threadPage,
|
||||||
}) => {
|
}) => {
|
||||||
await openReader(page, '/yuta/status/2001')
|
await threadPage.goTo('yuta', '2001')
|
||||||
|
|
||||||
await expect(page.getByText('retry focal')).toHaveCount(1)
|
await expect(page.getByText('retry focal')).toHaveCount(1)
|
||||||
await expect(page.getByText('thread root')).toBeVisible()
|
await expect(page.getByText('thread root')).toBeVisible()
|
||||||
await expect(page.getByText('thread page 1')).toBeVisible()
|
await expect(page.getByText('thread page 1')).toBeVisible()
|
||||||
const alert = page
|
await expect(threadPage.continuationErrorLocator).toHaveCount(1)
|
||||||
.getByRole('alert')
|
|
||||||
.filter({ hasText: '続きの投稿を取得できませんでした。' })
|
|
||||||
await expect(alert).toHaveCount(1)
|
|
||||||
await expect(page.getByText('retry focal')).toHaveCount(1)
|
await expect(page.getByText('retry focal')).toHaveCount(1)
|
||||||
|
|
||||||
await alert.getByRole('button', { name: '再試行' }).click()
|
await threadPage.retryContinuation()
|
||||||
|
|
||||||
await expect(page.getByText('thread page 2')).toBeVisible()
|
await expect(page.getByText('thread page 2')).toBeVisible()
|
||||||
await expect(alert).toHaveCount(0)
|
await expect(threadPage.continuationErrorLocator).toHaveCount(0)
|
||||||
await expect(page.getByText('これ以上の投稿はありません。')).toBeVisible()
|
await expect(threadPage.endOfFeedLocator).toBeVisible()
|
||||||
await expect(
|
await expect(threadPage.mutationButtonsLocator).toHaveCount(0)
|
||||||
page.getByRole('button', { name: mutationControlNames }),
|
|
||||||
).toHaveCount(0)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('searches Top posts from followed accounts', async ({ page }) => {
|
test('searches Top posts from followed accounts', async ({
|
||||||
await openReader(page, '/search?q=&product=Latest&following=false')
|
page,
|
||||||
await expect(page.locator('article')).toHaveCount(0)
|
searchPage,
|
||||||
await page.getByLabel('検索語').fill('AI lang:ja')
|
}) => {
|
||||||
await page.getByLabel('人気順').check()
|
await searchPage.goTo()
|
||||||
await page.getByLabel('フォロー中のみ').check()
|
await expect(searchPage.articlesLocator).toHaveCount(0)
|
||||||
await expect(page.getByLabel('フォロー中のみ')).toBeChecked()
|
await searchPage.searchTopFromFollowing('AI lang:ja')
|
||||||
await page.getByRole('button', { name: '検索' }).click()
|
await expect(searchPage.followingOnlyLocator).toBeChecked()
|
||||||
|
|
||||||
await expect(page).toHaveURL(/following=true/)
|
await expect(page).toHaveURL(/following=true/)
|
||||||
await expect(page.getByText('Top · follows page 1')).toBeVisible()
|
await expect(page.getByText('Top · follows page 1')).toBeVisible()
|
||||||
await expect(page.getByText('Top · follows page 2')).toBeVisible()
|
await expect(page.getByText('Top · follows page 2')).toBeVisible()
|
||||||
await expect(page.getByText('これ以上の投稿はありません。')).toBeVisible()
|
await expect(searchPage.endOfFeedLocator).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('retains the first page through a pagination error and retries explicitly', async ({
|
test('retains the first page through a pagination error and retries explicitly', async ({
|
||||||
page,
|
page,
|
||||||
|
searchPage,
|
||||||
}, testInfo) => {
|
}, testInfo) => {
|
||||||
await submitSearch(page, `retry-${testInfo.project.name}`)
|
await searchPage.goTo()
|
||||||
|
await expect(searchPage.articlesLocator).toHaveCount(0)
|
||||||
|
await searchPage.search(`retry-${testInfo.project.name}`)
|
||||||
|
|
||||||
await expect(page.getByText('Latest · all page 1')).toBeVisible()
|
await expect(page.getByText('Latest · all page 1')).toBeVisible()
|
||||||
const laterPageAlert = page
|
await expect(searchPage.continuationErrorLocator).toHaveCount(1)
|
||||||
.getByRole('alert')
|
|
||||||
.filter({ hasText: '続きの投稿を取得できませんでした。' })
|
|
||||||
await expect(laterPageAlert).toHaveCount(1)
|
|
||||||
await expect(page.getByText('Latest · all page 1')).toBeVisible()
|
await expect(page.getByText('Latest · all page 1')).toBeVisible()
|
||||||
await expect(page.getByText('Latest · all page 2')).toHaveCount(0)
|
await expect(page.getByText('Latest · all page 2')).toHaveCount(0)
|
||||||
|
|
||||||
await laterPageAlert.getByRole('button', { name: '再試行' }).click()
|
await searchPage.retryContinuation()
|
||||||
|
|
||||||
await expect(page.getByText('Latest · all page 2')).toBeVisible()
|
await expect(page.getByText('Latest · all page 2')).toBeVisible()
|
||||||
await expect(laterPageAlert).toHaveCount(0)
|
await expect(searchPage.continuationErrorLocator).toHaveCount(0)
|
||||||
await expect(page.getByText('これ以上の投稿はありません。')).toBeVisible()
|
await expect(searchPage.endOfFeedLocator).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('keeps keyboard focus intentional and discovery or mutation controls absent', async ({
|
test('keeps keyboard focus intentional and discovery or mutation controls absent', async ({
|
||||||
page,
|
searchPage,
|
||||||
}) => {
|
}) => {
|
||||||
await openReader(page, '/search?q=&product=Latest&following=false')
|
await searchPage.goTo()
|
||||||
|
|
||||||
await tabTo(page, page.getByRole('link', { name: 'ユーザー' }))
|
await searchPage.tabTo(
|
||||||
await tabTo(page, page.getByRole('link', { name: '検索' }))
|
searchPage.page.getByRole('link', { name: 'ユーザー' }),
|
||||||
await tabTo(page, page.getByRole('link', { name: 'リスト' }))
|
|
||||||
await tabTo(page, page.getByLabel('検索語'))
|
|
||||||
const ranking = page.getByLabel('最新順')
|
|
||||||
await expect(ranking).toBeChecked()
|
|
||||||
await tabTo(page, ranking)
|
|
||||||
await tabTo(page, page.getByLabel('フォロー中のみ'))
|
|
||||||
await tabTo(page, page.getByRole('button', { name: '検索' }))
|
|
||||||
|
|
||||||
await expect(page.getByRole('link', { name: ambientLinkNames })).toHaveCount(
|
|
||||||
0,
|
|
||||||
)
|
)
|
||||||
await expect(
|
await searchPage.tabTo(searchPage.page.getByRole('link', { name: '検索' }))
|
||||||
page.getByRole('button', { name: mutationControlNames }),
|
await searchPage.tabTo(searchPage.page.getByRole('link', { name: 'リスト' }))
|
||||||
).toHaveCount(0)
|
await searchPage.tabTo(searchPage.queryInputLocator)
|
||||||
await expect(
|
await expect(searchPage.latestRankingLocator).toBeChecked()
|
||||||
page.getByRole('link', { name: mutationControlNames }),
|
await searchPage.tabTo(searchPage.latestRankingLocator)
|
||||||
).toHaveCount(0)
|
await searchPage.tabTo(searchPage.followingOnlyLocator)
|
||||||
|
await searchPage.tabTo(searchPage.searchButtonLocator)
|
||||||
|
|
||||||
|
await expect(searchPage.ambientLinksLocator).toHaveCount(0)
|
||||||
|
await expect(searchPage.mutationButtonsLocator).toHaveCount(0)
|
||||||
|
await expect(searchPage.mutationLinksLocator).toHaveCount(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('removes loading rail animation for reduced motion', async ({
|
test('removes loading rail animation for reduced motion', async ({
|
||||||
page,
|
page,
|
||||||
|
searchPage,
|
||||||
}, testInfo) => {
|
}, testInfo) => {
|
||||||
await page.emulateMedia({ reducedMotion: 'reduce' })
|
await page.emulateMedia({ reducedMotion: 'reduce' })
|
||||||
await submitSearch(page, `slow-${testInfo.project.name}`)
|
await searchPage.goTo()
|
||||||
|
await expect(searchPage.articlesLocator).toHaveCount(0)
|
||||||
|
await searchPage.search(`slow-${testInfo.project.name}`)
|
||||||
|
|
||||||
const rail = page.locator('.loading-rail')
|
const rail = searchPage.loadingRailLocator
|
||||||
await expect(rail).toBeVisible()
|
await expect(rail).toBeVisible()
|
||||||
await expect
|
await expect
|
||||||
.poll(() =>
|
.poll(() =>
|
||||||
@@ -202,5 +172,5 @@ test('removes loading rail animation for reduced motion', async ({
|
|||||||
.toBe('none')
|
.toBe('none')
|
||||||
|
|
||||||
await expect(page.getByText('Latest · all page 2')).toBeVisible()
|
await expect(page.getByText('Latest · all page 2')).toBeVisible()
|
||||||
await expect(page.getByText('これ以上の投稿はありません。')).toBeVisible()
|
await expect(searchPage.endOfFeedLocator).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user