Verified Commit 6d210220 authored by Chocobozzz's avatar Chocobozzz
Browse files

Fix NSFW filter and add tests

parent 2ede0715
......@@ -281,6 +281,7 @@
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": [
"e2e/**/*.ts",
"src/**/*.ts",
"src/**/*.html"
]
......
import { browserSleep, go } from '../utils'
export class AdminConfigPage {
async navigateTo (tab: 'instance-homepage' | 'basic-configuration' | 'instance-information') {
const waitTitles = {
'instance-homepage': 'INSTANCE HOMEPAGE',
'basic-configuration': 'APPEARANCE',
'instance-information': 'INSTANCE'
}
await go('/admin/config/edit-custom#' + tab)
await $('.inner-form-title=' + waitTitles[tab]).waitForDisplayed()
}
updateNSFWSetting (newValue: 'do_not_list' | 'blur' | 'display') {
return $('#instanceDefaultNSFWPolicy').selectByAttribute('value', newValue)
}
updateHomepage (newValue: string) {
return $('#instanceCustomHomepageContent').setValue(newValue)
}
async save () {
await $('input[type=submit]').click()
await browserSleep(200)
}
}
import { go } from '../utils'
export class LoginPage {
async loginAsRootUser () {
await go('/login')
......@@ -8,7 +9,7 @@ export class LoginPage {
await browser.execute(`window.localStorage.setItem('no_welcome_modal', 'true')`)
await $('input#username').setValue('root')
await $('input#password').setValue('test1')
await $('input#password').setValue('test' + this.getSuffix())
await browser.pause(1000)
......@@ -19,7 +20,24 @@ export class LoginPage {
await expect(this.getLoggedInInfoElem()).toHaveText('root')
}
async logout () {
await $('.logged-in-more').click()
const logout = () => $('.dropdown-item*=Log out')
await logout().waitForDisplayed()
await logout().click()
await $('.login-buttons-block').waitForDisplayed()
}
private getLoggedInInfoElem () {
return $('.logged-in-display-name')
}
private getSuffix () {
return browser.config.baseUrl
? browser.config.baseUrl.slice(-1)
: '1'
}
}
......@@ -14,6 +14,24 @@ export class MyAccountPage {
return $('a[href="/my-library/history/videos"]').click()
}
// Settings
navigateToMySettings () {
return $('a[href="/my-account"]').click()
}
async updateNSFW (newValue: 'do_not_list' | 'blur' | 'display') {
const nsfw = $('#nsfwPolicy')
await nsfw.waitForDisplayed()
await nsfw.scrollIntoView(false) // Avoid issues with fixed header on firefox
await nsfw.selectByAttribute('value', newValue)
const submit = $('my-user-video-settings input[type=submit]')
await submit.scrollIntoView(false)
await submit.click()
}
// My account Videos
async removeVideo (name: string) {
......
......@@ -15,6 +15,9 @@ export class PlayerPage {
waitUntilPlaylistInfo (text: string, maxTime: number) {
return browser.waitUntil(async () => {
// Without this we have issues on iphone
await $('.video-js').click()
return (await $('.video-js .vjs-playlist-info').getText()).includes(text)
}, { timeout: maxTime })
}
......@@ -42,7 +45,7 @@ export class PlayerPage {
await browserSleep(2000)
await browser.waitUntil(async () => {
return (await this.getWatchVideoPlayerCurrentTime()) >= 2
return (await this.getWatchVideoPlayerCurrentTime()) >= waitUntilSec
})
await videojsElem().click()
......
import { browserSleep, go } from '../utils'
export class VideoListPage {
constructor (private isMobileDevice: boolean, private isSafari: boolean) {
}
async goOnVideosList () {
let url: string
// We did not upload a file on a mobile device
if (this.isMobileDevice === true || this.isSafari === true) {
url = 'https://peertube2.cpy.re/videos/local'
} else {
url = '/videos/recently-added'
}
await go(url)
// Waiting the following element does not work on Safari...
if (this.isSafari) return browserSleep(3000)
await this.waitForList()
}
async goOnLocal () {
await $('.menu-link[href="/videos/local"]').click()
await this.waitForTitle('Local videos')
}
async goOnRecentlyAdded () {
await $('.menu-link[href="/videos/recently-added"]').click()
await this.waitForTitle('Recently added')
}
async goOnTrending () {
await $('.menu-link[href="/videos/trending"]').click()
await this.waitForTitle('Trending')
}
async goOnHomepage () {
await go('/home')
await this.waitForList()
}
async goOnRootChannel () {
await go('/c/root_channel/videos')
await this.waitForList()
}
async goOnRootAccount () {
await go('/a/root/videos')
await this.waitForList()
}
async goOnRootAccountChannels () {
await go('/a/root/video-channels')
await this.waitForList()
}
getNSFWFilter () {
return $$('.active-filter').filter(async a => {
return (await a.getText()).includes('Sensitive')
}).then(f => f[0])
}
async getVideosListName () {
const elems = await $$('.videos .video-miniature .video-miniature-name')
const texts = await Promise.all(elems.map(e => e.getText()))
return texts.map(t => t.trim())
}
videoExists (name: string) {
return $('.video-miniature-name=' + name).isDisplayed()
}
async videoIsBlurred (name: string) {
const filter = await $('.video-miniature-name=' + name).getCSSProperty('filter')
return filter.value !== 'none'
}
async clickOnVideo (videoName: string) {
const video = async () => {
const videos = await $$('.videos .video-miniature .video-miniature-name').filter(async e => {
const t = await e.getText()
return t === videoName
})
return videos[0]
}
await browser.waitUntil(async () => {
const elem = await video()
return elem?.isClickable()
});
(await video()).click()
await browser.waitUntil(async () => (await browser.getUrl()).includes('/w/'))
}
async clickOnFirstVideo () {
const video = () => $('.videos .video-miniature .video-thumbnail')
const videoName = () => $('.videos .video-miniature .video-miniature-name')
await video().waitForClickable()
const textToReturn = await videoName().getText()
await video().click()
await browser.waitUntil(async () => (await browser.getUrl()).includes('/w/'))
return textToReturn
}
private waitForList () {
return $('.videos .video-miniature .video-miniature-name').waitForDisplayed()
}
private waitForTitle (title: string) {
return $('h1=' + title).waitForDisplayed()
}
}
export class VideoSearchPage {
async search (search: string) {
await $('#search-video').setValue(search)
await $('my-header .icon-search').click()
await browser.waitUntil(() => {
return $('my-video-miniature').isDisplayed()
})
}
}
import { join } from 'path'
import { clickOnCheckbox } from '../utils'
export class VideoUploadPage {
async navigateTo () {
......@@ -30,6 +31,10 @@ export class VideoUploadPage {
})
}
setAsNSFW () {
return clickOnCheckbox('nsfw')
}
async validSecondUploadStep (videoName: string) {
const nameInput = $('input#name')
await nameInput.clearValue()
......
import { FIXTURE_URLS } from '../urls'
import { browserSleep, go } from '../utils'
import { browserSleep, FIXTURE_URLS, go } from '../utils'
export class VideoWatchPage {
async goOnVideosList (isMobileDevice: boolean, isSafari: boolean) {
let url: string
// We did not upload a file on a mobile device
if (isMobileDevice === true || isSafari === true) {
url = 'https://peertube2.cpy.re/videos/local'
} else {
url = '/videos/recently-added'
}
await go(url)
// Waiting the following element does not work on Safari...
if (isSafari) return browserSleep(3000)
await $('.videos .video-miniature .video-miniature-name').waitForDisplayed()
}
async getVideosListName () {
const elems = await $$('.videos .video-miniature .video-miniature-name')
const texts = await Promise.all(elems.map(e => e.getText()))
constructor (private isMobileDevice: boolean, private isSafari: boolean) {
return texts.map(t => t.trim())
}
waitWatchVideoName (videoName: string, isMobileDevice: boolean, isSafari: boolean) {
if (isSafari) return browserSleep(5000)
waitWatchVideoName (videoName: string) {
if (this.isSafari) return browserSleep(5000)
// On mobile we display the first node, on desktop the second
const index = isMobileDevice ? 0 : 1
const index = this.isMobileDevice ? 0 : 1
return browser.waitUntil(async () => {
return (await $$('.video-info .video-info-name')[index].getText()).includes(videoName)
......@@ -58,42 +37,6 @@ export class VideoWatchPage {
return go(FIXTURE_URLS.HLS_PLAYLIST_EMBED)
}
async clickOnVideo (videoName: string) {
const video = async () => {
const videos = await $$('.videos .video-miniature .video-miniature-name').filter(async e => {
const t = await e.getText()
return t === videoName
})
return videos[0]
}
await browser.waitUntil(async () => {
const elem = await video()
return elem?.isClickable()
});
(await video()).click()
await browser.waitUntil(async () => (await browser.getUrl()).includes('/w/'))
}
async clickOnFirstVideo () {
const video = () => $('.videos .video-miniature .video-thumbnail')
const videoName = () => $('.videos .video-miniature .video-miniature-name')
await video().waitForClickable()
const textToReturn = await videoName().getText()
await video().click()
await browser.waitUntil(async () => (await browser.getUrl()).includes('/w/'))
return textToReturn
}
async clickOnUpdate () {
const dropdown = $('my-video-actions-dropdown .action-button')
await dropdown.click()
......
import { LoginPage } from './po/login.po'
import { MyAccountPage } from './po/my-account'
import { PlayerPage } from './po/player.po'
import { VideoUpdatePage } from './po/video-update.po'
import { VideoUploadPage } from './po/video-upload.po'
import { VideoWatchPage } from './po/video-watch.po'
import { FIXTURE_URLS } from './urls'
import { browserSleep, go, isIOS, isMobileDevice, isSafari } from './utils'
import { LoginPage } from '../po/login.po'
import { MyAccountPage } from '../po/my-account'
import { PlayerPage } from '../po/player.po'
import { VideoListPage } from '../po/video-list.po'
import { VideoUpdatePage } from '../po/video-update.po'
import { VideoUploadPage } from '../po/video-upload.po'
import { VideoWatchPage } from '../po/video-watch.po'
import { FIXTURE_URLS, go, isIOS, isMobileDevice, isSafari, waitServerUp } from '../utils'
function isUploadUnsupported () {
if (isMobileDevice() || isSafari()) {
......@@ -16,8 +16,9 @@ function isUploadUnsupported () {
return false
}
describe('Videos workflow', () => {
describe('Videos all workflow', () => {
let videoWatchPage: VideoWatchPage
let videoListPage: VideoListPage
let videoUploadPage: VideoUploadPage
let videoUpdatePage: VideoUpdatePage
let myAccountPage: MyAccountPage
......@@ -40,21 +41,17 @@ describe('Videos workflow', () => {
if (isUploadUnsupported()) return
await browser.waitUntil(async () => {
await go('/')
await browserSleep(500)
return $('<my-app>').isDisplayed()
}, { timeout: 20 * 1000 })
await waitServerUp()
})
beforeEach(async () => {
videoWatchPage = new VideoWatchPage()
videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
videoUploadPage = new VideoUploadPage()
videoUpdatePage = new VideoUpdatePage()
myAccountPage = new MyAccountPage()
loginPage = new LoginPage()
playerPage = new PlayerPage()
videoListPage = new VideoListPage(isMobileDevice(), isSafari())
if (!isMobileDevice()) {
await browser.maximizeWindow()
......@@ -80,11 +77,11 @@ describe('Videos workflow', () => {
})
it('Should list videos', async () => {
await videoWatchPage.goOnVideosList(isMobileDevice(), isSafari())
await videoListPage.goOnVideosList()
if (isUploadUnsupported()) return
const videoNames = await videoWatchPage.getVideosListName()
const videoNames = await videoListPage.getVideosListName()
expect(videoNames).toContain(videoName)
})
......@@ -95,10 +92,10 @@ describe('Videos workflow', () => {
await go(FIXTURE_URLS.WEBTORRENT_VIDEO)
videoNameToExcept = 'E2E tests'
} else {
await videoWatchPage.clickOnVideo(videoName)
await videoListPage.clickOnVideo(videoName)
}
return videoWatchPage.waitWatchVideoName(videoNameToExcept, isMobileDevice(), isSafari())
return videoWatchPage.waitWatchVideoName(videoNameToExcept)
})
it('Should play the video', async () => {
......
import { AdminConfigPage } from '../po/admin-config.po'
import { LoginPage } from '../po/login.po'
import { MyAccountPage } from '../po/my-account'
import { VideoListPage } from '../po/video-list.po'
import { VideoSearchPage } from '../po/video-search.po'
import { VideoUploadPage } from '../po/video-upload.po'
import { NSFWPolicy } from '../types/common'
import { isMobileDevice, isSafari, waitServerUp } from '../utils'
describe('Videos list', () => {
let videoListPage: VideoListPage
let videoUploadPage: VideoUploadPage
let adminConfigPage: AdminConfigPage
let loginPage: LoginPage
let myAccountPage: MyAccountPage
let videoSearchPage: VideoSearchPage
const seed = Math.random()
const nsfwVideo = seed + ' - nsfw'
const normalVideo = seed + ' - normal'
async function checkNormalVideo () {
expect(await videoListPage.videoExists(normalVideo)).toBeTruthy()
expect(await videoListPage.videoIsBlurred(normalVideo)).toBeFalsy()
}
async function checkNSFWVideo (policy: NSFWPolicy, filterText?: string) {
if (policy === 'do_not_list') {
if (filterText) expect(filterText).toContain('hidden')
expect(await videoListPage.videoExists(nsfwVideo)).toBeFalsy()
return
}
if (policy === 'blur') {
if (filterText) expect(filterText).toContain('blurred')
expect(await videoListPage.videoExists(nsfwVideo)).toBeTruthy()
expect(await videoListPage.videoIsBlurred(nsfwVideo)).toBeTruthy()
return
}
// display
if (filterText) expect(filterText).toContain('displayed')
expect(await videoListPage.videoExists(nsfwVideo)).toBeTruthy()
expect(await videoListPage.videoIsBlurred(nsfwVideo)).toBeFalsy()
}
async function checkCommonVideoListPages (policy: NSFWPolicy) {
const promisesWithFilters = [
videoListPage.goOnRootAccount,
videoListPage.goOnLocal,
videoListPage.goOnRecentlyAdded,
videoListPage.goOnTrending,
videoListPage.goOnRootChannel
]
for (const p of promisesWithFilters) {
await p.call(videoListPage)
const filter = await videoListPage.getNSFWFilter()
const filterText = await filter.getText()
await checkNormalVideo()
await checkNSFWVideo(policy, filterText)
}
const promisesWithoutFilters = [
videoListPage.goOnRootAccountChannels,
videoListPage.goOnHomepage
]
for (const p of promisesWithoutFilters) {
await p.call(videoListPage)
await checkNormalVideo()
await checkNSFWVideo(policy)
}
}
async function checkSearchPage (policy: NSFWPolicy) {
await videoSearchPage.search(normalVideo)
await checkNormalVideo()
await videoSearchPage.search(nsfwVideo)
await checkNSFWVideo(policy)
}
async function updateAdminNSFW (nsfw: NSFWPolicy) {
await adminConfigPage.navigateTo('instance-information')
await adminConfigPage.updateNSFWSetting(nsfw)
await adminConfigPage.save()
}
async function updateUserNSFW (nsfw: NSFWPolicy) {
await myAccountPage.navigateToMySettings()
await myAccountPage.updateNSFW(nsfw)
}
before(async () => {
await waitServerUp()
})
beforeEach(async () => {
videoListPage = new VideoListPage(isMobileDevice(), isSafari())
adminConfigPage = new AdminConfigPage()
loginPage = new LoginPage()
videoUploadPage = new VideoUploadPage()
myAccountPage = new MyAccountPage()
videoSearchPage = new VideoSearchPage()
await browser.maximizeWindow()
})
it('Should login and disable NSFW', async () => {
await loginPage.loginAsRootUser()
await updateUserNSFW('display')
})
it('Should set the homepage', async () => {
await adminConfigPage.navigateTo('instance-homepage')
await adminConfigPage.updateHomepage('<peertube-videos-list data-sort="-publishedAt"></peertube-videos-list>')
await adminConfigPage.save()
})
it('Should upload 2 videos (NSFW and classic videos)', async () => {
await videoUploadPage.navigateTo()
await videoUploadPage.uploadVideo()
await videoUploadPage.setAsNSFW()
await videoUploadPage.validSecondUploadStep(nsfwVideo)
await videoUploadPage.navigateTo()
await videoUploadPage.uploadVideo()
await videoUploadPage.validSecondUploadStep(normalVideo)
})
it('Should logout', async function () {
await loginPage.logout()
})
describe('Anonymous users', function () {
it('Should correctly handle do not list', async () => {
await loginPage.loginAsRootUser()
await updateAdminNSFW('do_not_list')