"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": [
+ "e2e/**/*.ts",
"src/**/*.ts",
"src/**/*.html"
]
--- /dev/null
+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')
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)
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'
+ }
}
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) {
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 })
}
await browserSleep(2000)
await browser.waitUntil(async () => {
- return (await this.getWatchVideoPlayerCurrentTime()) >= 2
+ return (await this.getWatchVideoPlayerCurrentTime()) >= waitUntilSec
})
await videojsElem().click()
--- /dev/null
+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()
+ }
+}
--- /dev/null
+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 () {
})
}
+ 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)
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()) {
return false
}
-describe('Videos workflow', () => {
+describe('Videos all workflow', () => {
let videoWatchPage: VideoWatchPage
+ let videoListPage: VideoListPage
let videoUploadPage: VideoUploadPage
let videoUpdatePage: VideoUpdatePage
let myAccountPage: MyAccountPage
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()
})
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)
})
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 () => {
--- /dev/null
+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')
+ })
+ })
+})
--- /dev/null
+export type NSFWPolicy = 'do_not_list' | 'blur' | 'display'
})
}
+async function waitServerUp () {
+ await browser.waitUntil(async () => {
+ await go('/')
+ await browserSleep(500)
+
+ return $('<my-app>').isDisplayed()
+ }, { timeout: 20 * 1000 })
+}
+
export {
isMobileDevice,
isSafari,
isIOS,
+ waitServerUp,
go,
browserSleep
}
--- /dev/null
+function clickOnCheckbox (name: string) {
+ return $(`my-peertube-checkbox[inputname=${name}] label`).click()
+}
+
+export {
+ clickOnCheckbox
+}
--- /dev/null
+export * from './common'
+export * from './elements'
+export * from './urls'
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
+ "noImplicitAny": false,
+ "esModuleInterop": true,
"module": "commonjs",
"target": "es5",
"types": [
}
}
-function buildBStackMobileOptions (sessionName: string, deviceName: string, osVersion: string) {
+function buildBStackMobileOptions (sessionName: string, deviceName: string, osVersion: string, appiumVersion?: string) {
return {
'bstack:options': {
...buildMainOptions(sessionName),
realMobile: true,
osVersion,
- deviceName
+ deviceName,
+
+ appiumVersion
}
}
}
{
browserName: 'Safari',
- ...buildBStackMobileOptions('Safari iPhone', 'iPhone 8 Plus', '11')
+ ...buildBStackMobileOptions('Safari iPhone', 'iPhone SE', '11')
},
{
browserName: 'Safari',
connectionRetryTimeout: 240000,
waitforTimeout: 20000,
+ specs: [
+ // We don't want to test "local" tests
+ './src/suites-all/*.e2e-spec.ts'
+ ],
+
services: [
[
'browserstack', { browserstackLocal: true }
]
],
- after: function (result) {
- if (result === 0) {
- browser.executeScript('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"passed","reason": ""}}', [])
- } else {
- browser.executeScript('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"failed","reason": ""}}', [])
+ onWorkerStart: function (_cid, capabilities) {
+ if (capabilities['bstack:options'].realMobile === true) {
+ capabilities['bstack:options'].local = false
}
}
} as WebdriverIO.Config
--- /dev/null
+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
+}
runner: 'local',
- maxInstances: 1,
+ maxInstances: 2,
capabilities: [
{
browserName: 'chrome',
- acceptInsecureCerts: true,
'goog:chromeOptions': {
prefs
}
{
browserName: 'firefox',
'moz:firefoxOptions': {
- // args: [ '-headless' ],
binary: '/usr/bin/firefox-developer-edition',
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
}
// will be called from there.
//
specs: [
- './src/**/*.e2e-spec.ts'
+ './src/suites-all/*.e2e-spec.ts',
+ './src/suites-local/*.e2e-spec.ts'
],
// Patterns to exclude.
exclude: [
framework: 'mocha',
//
// 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
// specFileRetriesDelay: 0,
tsNodeOpts: {
project: require('path').join(__dirname, './tsconfig.json')
+ },
+
+ tsConfigPathsOpts: {
+ baseUrl: './',
+ paths: {
+ '@server/*': [ '../../server/*' ],
+ '@shared/*': [ '../../shared/*' ]
+ }
}
},
UserUpdateMe,
UserVideoQuota
} from '@shared/models'
+import { ServerService } from '../'
import { environment } from '../../../environments/environment'
import { RestExtractor, RestPagination, RestService } from '../rest'
import { LocalStorageService, SessionStorageService } from '../wrappers/storage.service'
constructor (
private authHttp: HttpClient,
+ private server: ServerService,
private authService: AuthService,
private restExtractor: RestExtractor,
private restService: RestService,
console.error('Cannot parse desired video languages from localStorage.', err)
}
+ const defaultNSFWPolicy = this.server.getHTMLConfig().instance.defaultNSFWPolicy
+
return new User({
// 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',
theme: this.localStorageService.getItem(UserLocalStorageKeys.THEME) || 'instance-default',
videoLanguages,
import { AuthService } from '@app/core'
import { ServerService } from '@app/core/server/server.service'
import { UserRight } from '@shared/models'
-import { NSFWPolicyType } from '@shared/models/videos'
import { PeertubeModalService } from '../shared-main'
import { VideoFilters } from './video-filters.model'
})
export class VideoFiltersHeaderComponent implements OnInit, OnDestroy {
@Input() filters: VideoFilters
-
@Input() displayModerationBlock = false
-
- @Input() defaultSort = '-publishedAt'
- @Input() nsfwPolicy: NSFWPolicyType
-
@Input() hideScope = false
@Output() filtersChanged = new EventEmitter()
}
setNSFWPolicy (nsfwPolicy: NSFWPolicyType) {
+ console.log(nsfwPolicy)
+
this.updateDefaultNSFW(nsfwPolicy)
}
<my-video-filters-header
*ngIf="displayFilters" [displayModerationBlock]="displayModerationBlock" [hideScope]="hideScopeFilter"
- [defaultSort]="defaultSort" [filters]="filters"
+ [filters]="filters"
(filtersChanged)="onFiltersChanged(true)"
></my-video-filters-header>
npm run concurrently -- -k -s first \
"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"
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 \
"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"
```
$ 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
+```