Fix NSFW filter and add tests
This commit is contained in:
parent
2ede07153c
commit
6d210220be
|
@ -281,6 +281,7 @@
|
||||||
"builder": "@angular-eslint/builder:lint",
|
"builder": "@angular-eslint/builder:lint",
|
||||||
"options": {
|
"options": {
|
||||||
"lintFilePatterns": [
|
"lintFilePatterns": [
|
||||||
|
"e2e/**/*.ts",
|
||||||
"src/**/*.ts",
|
"src/**/*.ts",
|
||||||
"src/**/*.html"
|
"src/**/*.html"
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import { go } from '../utils'
|
import { go } from '../utils'
|
||||||
|
|
||||||
export class LoginPage {
|
export class LoginPage {
|
||||||
|
|
||||||
async loginAsRootUser () {
|
async loginAsRootUser () {
|
||||||
await go('/login')
|
await go('/login')
|
||||||
|
|
||||||
|
@ -8,7 +9,7 @@ export class LoginPage {
|
||||||
await browser.execute(`window.localStorage.setItem('no_welcome_modal', 'true')`)
|
await browser.execute(`window.localStorage.setItem('no_welcome_modal', 'true')`)
|
||||||
|
|
||||||
await $('input#username').setValue('root')
|
await $('input#username').setValue('root')
|
||||||
await $('input#password').setValue('test1')
|
await $('input#password').setValue('test' + this.getSuffix())
|
||||||
|
|
||||||
await browser.pause(1000)
|
await browser.pause(1000)
|
||||||
|
|
||||||
|
@ -19,7 +20,24 @@ export class LoginPage {
|
||||||
await expect(this.getLoggedInInfoElem()).toHaveText('root')
|
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 () {
|
private getLoggedInInfoElem () {
|
||||||
return $('.logged-in-display-name')
|
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()
|
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
|
// My account Videos
|
||||||
|
|
||||||
async removeVideo (name: string) {
|
async removeVideo (name: string) {
|
||||||
|
|
|
@ -15,6 +15,9 @@ export class PlayerPage {
|
||||||
|
|
||||||
waitUntilPlaylistInfo (text: string, maxTime: number) {
|
waitUntilPlaylistInfo (text: string, maxTime: number) {
|
||||||
return browser.waitUntil(async () => {
|
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)
|
return (await $('.video-js .vjs-playlist-info').getText()).includes(text)
|
||||||
}, { timeout: maxTime })
|
}, { timeout: maxTime })
|
||||||
}
|
}
|
||||||
|
@ -42,7 +45,7 @@ export class PlayerPage {
|
||||||
await browserSleep(2000)
|
await browserSleep(2000)
|
||||||
|
|
||||||
await browser.waitUntil(async () => {
|
await browser.waitUntil(async () => {
|
||||||
return (await this.getWatchVideoPlayerCurrentTime()) >= 2
|
return (await this.getWatchVideoPlayerCurrentTime()) >= waitUntilSec
|
||||||
})
|
})
|
||||||
|
|
||||||
await videojsElem().click()
|
await videojsElem().click()
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
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()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
|
import { clickOnCheckbox } from '../utils'
|
||||||
|
|
||||||
export class VideoUploadPage {
|
export class VideoUploadPage {
|
||||||
async navigateTo () {
|
async navigateTo () {
|
||||||
|
@ -30,6 +31,10 @@ export class VideoUploadPage {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setAsNSFW () {
|
||||||
|
return clickOnCheckbox('nsfw')
|
||||||
|
}
|
||||||
|
|
||||||
async validSecondUploadStep (videoName: string) {
|
async validSecondUploadStep (videoName: string) {
|
||||||
const nameInput = $('input#name')
|
const nameInput = $('input#name')
|
||||||
await nameInput.clearValue()
|
await nameInput.clearValue()
|
||||||
|
|
|
@ -1,37 +1,16 @@
|
||||||
import { FIXTURE_URLS } from '../urls'
|
import { browserSleep, FIXTURE_URLS, go } from '../utils'
|
||||||
import { browserSleep, go } from '../utils'
|
|
||||||
|
|
||||||
export class VideoWatchPage {
|
export class VideoWatchPage {
|
||||||
async goOnVideosList (isMobileDevice: boolean, isSafari: boolean) {
|
|
||||||
let url: string
|
|
||||||
|
|
||||||
// We did not upload a file on a mobile device
|
constructor (private isMobileDevice: boolean, private isSafari: boolean) {
|
||||||
if (isMobileDevice === true || isSafari === true) {
|
|
||||||
url = 'https://peertube2.cpy.re/videos/local'
|
|
||||||
} else {
|
|
||||||
url = '/videos/recently-added'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await go(url)
|
waitWatchVideoName (videoName: string) {
|
||||||
|
if (this.isSafari) return browserSleep(5000)
|
||||||
// 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()))
|
|
||||||
|
|
||||||
return texts.map(t => t.trim())
|
|
||||||
}
|
|
||||||
|
|
||||||
waitWatchVideoName (videoName: string, isMobileDevice: boolean, isSafari: boolean) {
|
|
||||||
if (isSafari) return browserSleep(5000)
|
|
||||||
|
|
||||||
// On mobile we display the first node, on desktop the second
|
// 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 browser.waitUntil(async () => {
|
||||||
return (await $$('.video-info .video-info-name')[index].getText()).includes(videoName)
|
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)
|
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 () {
|
async clickOnUpdate () {
|
||||||
const dropdown = $('my-video-actions-dropdown .action-button')
|
const dropdown = $('my-video-actions-dropdown .action-button')
|
||||||
await dropdown.click()
|
await dropdown.click()
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { LoginPage } from './po/login.po'
|
import { LoginPage } from '../po/login.po'
|
||||||
import { MyAccountPage } from './po/my-account'
|
import { MyAccountPage } from '../po/my-account'
|
||||||
import { PlayerPage } from './po/player.po'
|
import { PlayerPage } from '../po/player.po'
|
||||||
import { VideoUpdatePage } from './po/video-update.po'
|
import { VideoListPage } from '../po/video-list.po'
|
||||||
import { VideoUploadPage } from './po/video-upload.po'
|
import { VideoUpdatePage } from '../po/video-update.po'
|
||||||
import { VideoWatchPage } from './po/video-watch.po'
|
import { VideoUploadPage } from '../po/video-upload.po'
|
||||||
import { FIXTURE_URLS } from './urls'
|
import { VideoWatchPage } from '../po/video-watch.po'
|
||||||
import { browserSleep, go, isIOS, isMobileDevice, isSafari } from './utils'
|
import { FIXTURE_URLS, go, isIOS, isMobileDevice, isSafari, waitServerUp } from '../utils'
|
||||||
|
|
||||||
function isUploadUnsupported () {
|
function isUploadUnsupported () {
|
||||||
if (isMobileDevice() || isSafari()) {
|
if (isMobileDevice() || isSafari()) {
|
||||||
|
@ -16,8 +16,9 @@ function isUploadUnsupported () {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Videos workflow', () => {
|
describe('Videos all workflow', () => {
|
||||||
let videoWatchPage: VideoWatchPage
|
let videoWatchPage: VideoWatchPage
|
||||||
|
let videoListPage: VideoListPage
|
||||||
let videoUploadPage: VideoUploadPage
|
let videoUploadPage: VideoUploadPage
|
||||||
let videoUpdatePage: VideoUpdatePage
|
let videoUpdatePage: VideoUpdatePage
|
||||||
let myAccountPage: MyAccountPage
|
let myAccountPage: MyAccountPage
|
||||||
|
@ -40,21 +41,17 @@ describe('Videos workflow', () => {
|
||||||
|
|
||||||
if (isUploadUnsupported()) return
|
if (isUploadUnsupported()) return
|
||||||
|
|
||||||
await browser.waitUntil(async () => {
|
await waitServerUp()
|
||||||
await go('/')
|
|
||||||
await browserSleep(500)
|
|
||||||
|
|
||||||
return $('<my-app>').isDisplayed()
|
|
||||||
}, { timeout: 20 * 1000 })
|
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
videoWatchPage = new VideoWatchPage()
|
videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
|
||||||
videoUploadPage = new VideoUploadPage()
|
videoUploadPage = new VideoUploadPage()
|
||||||
videoUpdatePage = new VideoUpdatePage()
|
videoUpdatePage = new VideoUpdatePage()
|
||||||
myAccountPage = new MyAccountPage()
|
myAccountPage = new MyAccountPage()
|
||||||
loginPage = new LoginPage()
|
loginPage = new LoginPage()
|
||||||
playerPage = new PlayerPage()
|
playerPage = new PlayerPage()
|
||||||
|
videoListPage = new VideoListPage(isMobileDevice(), isSafari())
|
||||||
|
|
||||||
if (!isMobileDevice()) {
|
if (!isMobileDevice()) {
|
||||||
await browser.maximizeWindow()
|
await browser.maximizeWindow()
|
||||||
|
@ -80,11 +77,11 @@ describe('Videos workflow', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should list videos', async () => {
|
it('Should list videos', async () => {
|
||||||
await videoWatchPage.goOnVideosList(isMobileDevice(), isSafari())
|
await videoListPage.goOnVideosList()
|
||||||
|
|
||||||
if (isUploadUnsupported()) return
|
if (isUploadUnsupported()) return
|
||||||
|
|
||||||
const videoNames = await videoWatchPage.getVideosListName()
|
const videoNames = await videoListPage.getVideosListName()
|
||||||
expect(videoNames).toContain(videoName)
|
expect(videoNames).toContain(videoName)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -95,10 +92,10 @@ describe('Videos workflow', () => {
|
||||||
await go(FIXTURE_URLS.WEBTORRENT_VIDEO)
|
await go(FIXTURE_URLS.WEBTORRENT_VIDEO)
|
||||||
videoNameToExcept = 'E2E tests'
|
videoNameToExcept = 'E2E tests'
|
||||||
} else {
|
} 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 () => {
|
it('Should play the video', async () => {
|
|
@ -0,0 +1,195 @@
|
||||||
|
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')
|
||||||
|
|
||||||
|
await loginPage.logout()
|
||||||
|
await checkCommonVideoListPages('do_not_list')
|
||||||
|
await checkSearchPage('do_not_list')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should correctly handle blur', async () => {
|
||||||
|
await loginPage.loginAsRootUser()
|
||||||
|
await updateAdminNSFW('blur')
|
||||||
|
|
||||||
|
await loginPage.logout()
|
||||||
|
await checkCommonVideoListPages('blur')
|
||||||
|
await checkSearchPage('blur')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should correctly handle display', async () => {
|
||||||
|
await loginPage.loginAsRootUser()
|
||||||
|
await updateAdminNSFW('display')
|
||||||
|
|
||||||
|
await loginPage.logout()
|
||||||
|
await checkCommonVideoListPages('display')
|
||||||
|
await checkSearchPage('display')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Logged in users', function () {
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
await loginPage.loginAsRootUser()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should correctly handle do not list', async () => {
|
||||||
|
await updateUserNSFW('do_not_list')
|
||||||
|
await checkCommonVideoListPages('do_not_list')
|
||||||
|
await checkSearchPage('do_not_list')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should correctly handle blur', async () => {
|
||||||
|
await updateUserNSFW('blur')
|
||||||
|
await checkCommonVideoListPages('blur')
|
||||||
|
await checkSearchPage('blur')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should correctly handle display', async () => {
|
||||||
|
await updateUserNSFW('display')
|
||||||
|
await checkCommonVideoListPages('display')
|
||||||
|
await checkSearchPage('display')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1 @@
|
||||||
|
export type NSFWPolicy = 'do_not_list' | 'blur' | 'display'
|
|
@ -28,10 +28,20 @@ async function go (url: string) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function waitServerUp () {
|
||||||
|
await browser.waitUntil(async () => {
|
||||||
|
await go('/')
|
||||||
|
await browserSleep(500)
|
||||||
|
|
||||||
|
return $('<my-app>').isDisplayed()
|
||||||
|
}, { timeout: 20 * 1000 })
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
isMobileDevice,
|
isMobileDevice,
|
||||||
isSafari,
|
isSafari,
|
||||||
isIOS,
|
isIOS,
|
||||||
|
waitServerUp,
|
||||||
go,
|
go,
|
||||||
browserSleep
|
browserSleep
|
||||||
}
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
function clickOnCheckbox (name: string) {
|
||||||
|
return $(`my-peertube-checkbox[inputname=${name}] label`).click()
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
clickOnCheckbox
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export * from './common'
|
||||||
|
export * from './elements'
|
||||||
|
export * from './urls'
|
|
@ -2,6 +2,8 @@
|
||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "../out-tsc/app",
|
"outDir": "../out-tsc/app",
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"esModuleInterop": true,
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"types": [
|
"types": [
|
||||||
|
|
|
@ -26,14 +26,16 @@ function buildBStackDesktopOptions (sessionName: string, resolution?: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildBStackMobileOptions (sessionName: string, deviceName: string, osVersion: string) {
|
function buildBStackMobileOptions (sessionName: string, deviceName: string, osVersion: string, appiumVersion?: string) {
|
||||||
return {
|
return {
|
||||||
'bstack:options': {
|
'bstack:options': {
|
||||||
...buildMainOptions(sessionName),
|
...buildMainOptions(sessionName),
|
||||||
|
|
||||||
realMobile: true,
|
realMobile: true,
|
||||||
osVersion,
|
osVersion,
|
||||||
deviceName
|
deviceName,
|
||||||
|
|
||||||
|
appiumVersion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +86,7 @@ module.exports = {
|
||||||
{
|
{
|
||||||
browserName: 'Safari',
|
browserName: 'Safari',
|
||||||
|
|
||||||
...buildBStackMobileOptions('Safari iPhone', 'iPhone 8 Plus', '11')
|
...buildBStackMobileOptions('Safari iPhone', 'iPhone SE', '11')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
browserName: 'Safari',
|
browserName: 'Safari',
|
||||||
|
@ -97,17 +99,20 @@ module.exports = {
|
||||||
connectionRetryTimeout: 240000,
|
connectionRetryTimeout: 240000,
|
||||||
waitforTimeout: 20000,
|
waitforTimeout: 20000,
|
||||||
|
|
||||||
|
specs: [
|
||||||
|
// We don't want to test "local" tests
|
||||||
|
'./src/suites-all/*.e2e-spec.ts'
|
||||||
|
],
|
||||||
|
|
||||||
services: [
|
services: [
|
||||||
[
|
[
|
||||||
'browserstack', { browserstackLocal: true }
|
'browserstack', { browserstackLocal: true }
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
|
||||||
after: function (result) {
|
onWorkerStart: function (_cid, capabilities) {
|
||||||
if (result === 0) {
|
if (capabilities['bstack:options'].realMobile === true) {
|
||||||
browser.executeScript('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"passed","reason": ""}}', [])
|
capabilities['bstack:options'].local = false
|
||||||
} else {
|
|
||||||
browser.executeScript('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"failed","reason": ""}}', [])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} as WebdriverIO.Config
|
} as WebdriverIO.Config
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { config as mainConfig } from './wdio.main.conf'
|
||||||
|
|
||||||
|
const prefs = {
|
||||||
|
'intl.accept_languages': 'en'
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
config: {
|
||||||
|
...mainConfig,
|
||||||
|
|
||||||
|
runner: 'local',
|
||||||
|
|
||||||
|
maxInstances: 1,
|
||||||
|
specFileRetries: 0,
|
||||||
|
|
||||||
|
capabilities: [
|
||||||
|
{
|
||||||
|
browserName: 'chrome',
|
||||||
|
acceptInsecureCerts: true,
|
||||||
|
'goog:chromeOptions': {
|
||||||
|
prefs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
services: [ 'chromedriver' ]
|
||||||
|
} as WebdriverIO.Config
|
||||||
|
}
|
|
@ -10,12 +10,11 @@ module.exports = {
|
||||||
|
|
||||||
runner: 'local',
|
runner: 'local',
|
||||||
|
|
||||||
maxInstances: 1,
|
maxInstances: 2,
|
||||||
|
|
||||||
capabilities: [
|
capabilities: [
|
||||||
{
|
{
|
||||||
browserName: 'chrome',
|
browserName: 'chrome',
|
||||||
acceptInsecureCerts: true,
|
|
||||||
'goog:chromeOptions': {
|
'goog:chromeOptions': {
|
||||||
prefs
|
prefs
|
||||||
}
|
}
|
||||||
|
@ -23,21 +22,20 @@ module.exports = {
|
||||||
{
|
{
|
||||||
browserName: 'firefox',
|
browserName: 'firefox',
|
||||||
'moz:firefoxOptions': {
|
'moz:firefoxOptions': {
|
||||||
// args: [ '-headless' ],
|
|
||||||
binary: '/usr/bin/firefox-developer-edition',
|
binary: '/usr/bin/firefox-developer-edition',
|
||||||
prefs
|
prefs
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
browserName: 'firefox',
|
|
||||||
'moz:firefoxOptions': {
|
|
||||||
// args: [ '-headless' ],
|
|
||||||
binary: '/usr/bin/firefox-esr',
|
|
||||||
prefs
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
services: [ 'chromedriver', 'geckodriver' ]
|
services: [ 'chromedriver', 'geckodriver' ],
|
||||||
|
|
||||||
|
beforeSession: function (config, capabilities) {
|
||||||
|
if (capabilities['browserName'] === 'chrome') {
|
||||||
|
config.baseUrl = 'http://localhost:9001'
|
||||||
|
} else {
|
||||||
|
config.baseUrl = 'http://localhost:9002'
|
||||||
|
}
|
||||||
|
}
|
||||||
} as WebdriverIO.Config
|
} as WebdriverIO.Config
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,8 @@ export const config = {
|
||||||
// will be called from there.
|
// will be called from there.
|
||||||
//
|
//
|
||||||
specs: [
|
specs: [
|
||||||
'./src/**/*.e2e-spec.ts'
|
'./src/suites-all/*.e2e-spec.ts',
|
||||||
|
'./src/suites-local/*.e2e-spec.ts'
|
||||||
],
|
],
|
||||||
// Patterns to exclude.
|
// Patterns to exclude.
|
||||||
exclude: [
|
exclude: [
|
||||||
|
@ -79,7 +80,7 @@ export const config = {
|
||||||
framework: 'mocha',
|
framework: 'mocha',
|
||||||
//
|
//
|
||||||
// The number of times to retry the entire specfile when it fails as a whole
|
// The number of times to retry the entire specfile when it fails as a whole
|
||||||
specFileRetries: 2,
|
specFileRetries: 1,
|
||||||
//
|
//
|
||||||
// Delay in seconds between the spec file retry attempts
|
// Delay in seconds between the spec file retry attempts
|
||||||
// specFileRetriesDelay: 0,
|
// specFileRetriesDelay: 0,
|
||||||
|
@ -105,6 +106,14 @@ export const config = {
|
||||||
|
|
||||||
tsNodeOpts: {
|
tsNodeOpts: {
|
||||||
project: require('path').join(__dirname, './tsconfig.json')
|
project: require('path').join(__dirname, './tsconfig.json')
|
||||||
|
},
|
||||||
|
|
||||||
|
tsConfigPathsOpts: {
|
||||||
|
baseUrl: './',
|
||||||
|
paths: {
|
||||||
|
'@server/*': [ '../../server/*' ],
|
||||||
|
'@shared/*': [ '../../shared/*' ]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
UserUpdateMe,
|
UserUpdateMe,
|
||||||
UserVideoQuota
|
UserVideoQuota
|
||||||
} from '@shared/models'
|
} from '@shared/models'
|
||||||
|
import { ServerService } from '../'
|
||||||
import { environment } from '../../../environments/environment'
|
import { environment } from '../../../environments/environment'
|
||||||
import { RestExtractor, RestPagination, RestService } from '../rest'
|
import { RestExtractor, RestPagination, RestService } from '../rest'
|
||||||
import { LocalStorageService, SessionStorageService } from '../wrappers/storage.service'
|
import { LocalStorageService, SessionStorageService } from '../wrappers/storage.service'
|
||||||
|
@ -32,6 +33,7 @@ export class UserService {
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private authHttp: HttpClient,
|
private authHttp: HttpClient,
|
||||||
|
private server: ServerService,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private restExtractor: RestExtractor,
|
private restExtractor: RestExtractor,
|
||||||
private restService: RestService,
|
private restService: RestService,
|
||||||
|
@ -298,9 +300,11 @@ export class UserService {
|
||||||
console.error('Cannot parse desired video languages from localStorage.', err)
|
console.error('Cannot parse desired video languages from localStorage.', err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const defaultNSFWPolicy = this.server.getHTMLConfig().instance.defaultNSFWPolicy
|
||||||
|
|
||||||
return new User({
|
return new User({
|
||||||
// local storage keys
|
// local storage keys
|
||||||
nsfwPolicy: this.localStorageService.getItem(UserLocalStorageKeys.NSFW_POLICY),
|
nsfwPolicy: this.localStorageService.getItem(UserLocalStorageKeys.NSFW_POLICY) || defaultNSFWPolicy,
|
||||||
webTorrentEnabled: this.localStorageService.getItem(UserLocalStorageKeys.WEBTORRENT_ENABLED) !== 'false',
|
webTorrentEnabled: this.localStorageService.getItem(UserLocalStorageKeys.WEBTORRENT_ENABLED) !== 'false',
|
||||||
theme: this.localStorageService.getItem(UserLocalStorageKeys.THEME) || 'instance-default',
|
theme: this.localStorageService.getItem(UserLocalStorageKeys.THEME) || 'instance-default',
|
||||||
videoLanguages,
|
videoLanguages,
|
||||||
|
|
|
@ -5,7 +5,6 @@ import { FormBuilder, FormGroup } from '@angular/forms'
|
||||||
import { AuthService } from '@app/core'
|
import { AuthService } from '@app/core'
|
||||||
import { ServerService } from '@app/core/server/server.service'
|
import { ServerService } from '@app/core/server/server.service'
|
||||||
import { UserRight } from '@shared/models'
|
import { UserRight } from '@shared/models'
|
||||||
import { NSFWPolicyType } from '@shared/models/videos'
|
|
||||||
import { PeertubeModalService } from '../shared-main'
|
import { PeertubeModalService } from '../shared-main'
|
||||||
import { VideoFilters } from './video-filters.model'
|
import { VideoFilters } from './video-filters.model'
|
||||||
|
|
||||||
|
@ -18,12 +17,7 @@ const logger = debug('peertube:videos:VideoFiltersHeaderComponent')
|
||||||
})
|
})
|
||||||
export class VideoFiltersHeaderComponent implements OnInit, OnDestroy {
|
export class VideoFiltersHeaderComponent implements OnInit, OnDestroy {
|
||||||
@Input() filters: VideoFilters
|
@Input() filters: VideoFilters
|
||||||
|
|
||||||
@Input() displayModerationBlock = false
|
@Input() displayModerationBlock = false
|
||||||
|
|
||||||
@Input() defaultSort = '-publishedAt'
|
|
||||||
@Input() nsfwPolicy: NSFWPolicyType
|
|
||||||
|
|
||||||
@Input() hideScope = false
|
@Input() hideScope = false
|
||||||
|
|
||||||
@Output() filtersChanged = new EventEmitter()
|
@Output() filtersChanged = new EventEmitter()
|
||||||
|
|
|
@ -74,6 +74,8 @@ export class VideoFilters {
|
||||||
}
|
}
|
||||||
|
|
||||||
setNSFWPolicy (nsfwPolicy: NSFWPolicyType) {
|
setNSFWPolicy (nsfwPolicy: NSFWPolicyType) {
|
||||||
|
console.log(nsfwPolicy)
|
||||||
|
|
||||||
this.updateDefaultNSFW(nsfwPolicy)
|
this.updateDefaultNSFW(nsfwPolicy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
<my-video-filters-header
|
<my-video-filters-header
|
||||||
*ngIf="displayFilters" [displayModerationBlock]="displayModerationBlock" [hideScope]="hideScopeFilter"
|
*ngIf="displayFilters" [displayModerationBlock]="displayModerationBlock" [hideScope]="hideScopeFilter"
|
||||||
[defaultSort]="defaultSort" [filters]="filters"
|
[filters]="filters"
|
||||||
(filtersChanged)="onFiltersChanged(true)"
|
(filtersChanged)="onFiltersChanged(true)"
|
||||||
></my-video-filters-header>
|
></my-video-filters-header>
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,4 @@ npm run clean:server:test
|
||||||
|
|
||||||
npm run concurrently -- -k -s first \
|
npm run concurrently -- -k -s first \
|
||||||
"cd client/e2e && ../node_modules/.bin/wdio run ./wdio.browserstack.conf.ts" \
|
"cd client/e2e && ../node_modules/.bin/wdio run ./wdio.browserstack.conf.ts" \
|
||||||
"NODE_ENV=test NODE_APP_INSTANCE=1 NODE_CONFIG='{ \"log\": { \"level\": \"warn\" }, \"signup\": { \"enabled\": false } }' node dist/server"
|
"NODE_ENV=test NODE_APP_INSTANCE=1 NODE_CONFIG='{ \"rates_limit\": { \"api\": { \"max\": 5000 }, \"login\": { \"max\": 5000 } }, \"log\": { \"level\": \"warn\" }, \"signup\": { \"enabled\": false } }' node dist/server"
|
||||||
|
|
|
@ -4,6 +4,14 @@ set -eu
|
||||||
|
|
||||||
npm run clean:server:test
|
npm run clean:server:test
|
||||||
|
|
||||||
|
config="{"
|
||||||
|
config+=" \"rates_limit\": { \"api\": { \"max\": 5000 }, \"login\": { \"max\": 5000 } }"
|
||||||
|
config+=", \"log\": { \"level\": \"warn\" }"
|
||||||
|
config+=", \"signup\": { \"enabled\": false }"
|
||||||
|
config+=", \"transcoding\": { \"enabled\": false }"
|
||||||
|
config+="}"
|
||||||
|
|
||||||
npm run concurrently -- -k -s first \
|
npm run concurrently -- -k -s first \
|
||||||
"cd client/e2e && ../node_modules/.bin/wdio run ./wdio.local.conf.ts" \
|
"cd client/e2e && ../node_modules/.bin/wdio run ./wdio.local.conf.ts" \
|
||||||
"NODE_ENV=test NODE_APP_INSTANCE=1 NODE_CONFIG='{ \"log\": { \"level\": \"warn\" }, \"signup\": { \"enabled\": false } }' node dist/server"
|
"NODE_ENV=test NODE_CONFIG='$config' NODE_APP_INSTANCE=1 node dist/server" \
|
||||||
|
"NODE_ENV=test NODE_CONFIG='$config' NODE_APP_INSTANCE=2 node dist/server"
|
||||||
|
|
|
@ -70,3 +70,18 @@ To run tests on browser stack:
|
||||||
```
|
```
|
||||||
$ BROWSERSTACK_USER=your_user BROWSERSTACK_KEY=your_key npm run e2e:browserstack
|
$ BROWSERSTACK_USER=your_user BROWSERSTACK_KEY=your_key npm run e2e:browserstack
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Add E2E tests
|
||||||
|
|
||||||
|
To add E2E tests and quickly run tests using a local Chrome, first create a test instance:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm run clean:server:test && NODE_APP_INSTANCE=1 NODE_ENV=test npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, just run your suite using:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cd client/e2e
|
||||||
|
$ ../node_modules/.bin/wdio wdio.local-test.conf.ts # you can also add --mochaOpts.grep to only run tests you want
|
||||||
|
```
|
||||||
|
|
Loading…
Reference in New Issue